-
v0.12.0
Stablereleased this
2026-04-27 18:43:57 +02:00 | 2 commits to main since this releasev0.12.0 - Public Launch
This release makes Piruetas publicly presentable:
unauthenticated visitors now land on a product page instead of being bounced straight to the login form.What's new
Landing page
The root route (/) now serves a full marketing page for visitors who aren't logged in. Authenticated users are
still redirected directly to today's journal entry as before. The landing page includes:- Animated headline and hero section
- Desktop + mobile screenshots (light and dark)
- Feature highlights and "try it" block with demo credentials
- Self-hosting instructions (one-liner and docker-compose)
- Language switcher (EN/ES) and theme toggle
Self-hosted fonts
EB Garamond and JetBrains Mono are now bundled as self-hosted
.woff2files so the landing page loads cleanly without any external font CDN requests.
Full i18n coverage for all new landing page strings in both English and Spanish.Polish
- Admin tasks page "Run now" button now uses the shared
.btn.btn-accentstyle instead of one-off inline CSS - Account data and security pages: minor typography alignment fixes
- Login page: added a styled "back to landing" link
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
v0.11.0
Stablereleased this
2026-04-25 12:55:01 +02:00 | 3 commits to main since this releasev0.11.0
Product landing page
Added a public-facing landing page at / for unauthenticated visitors.
Previously the root redirected straight to login.What's new:
- New landing page (
app/templates/index.html) with light/dark product screenshots, marketing copy, and a clear
call-to-action to sign up / log in - Dedicated stylesheet (
app/static/css/landing.css) — scoped to the landing page, no impact on the app shell - Self-hosted EB Garamond and JetBrains Mono fonts (
app/static/fonts/) with a shared fonts.css manifest;
reduces third-party font requests across the app i18nstrings extended (app/i18n.py) to cover all landing page copy in EN and ES- Minor form CSS tweak (
forms.css) and template polish across account, admin, and login pages - Security tests updated to account for the new unauthenticated root route
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- New landing page (
-
v0.10.0
Stablereleased this
2026-04-24 16:11:16 +02:00 | 4 commits to main since this releasev0.10.0: Data Management & Editor Links
New features
Data Management tab (
/account/data)A new tab in the account settings gives you full control over your journal data.
- Export entries: download a ZIP of your entries scoped to all time, a specific year, or a specific month.
Exports are available in plain text (Markdown) or JSON. A preview step shows the entry count before the
download begins. - Delete entries: bulk-delete entries by scope with the same preview flow, including a warning to export
first. Destructive actions require explicit confirmation. - Export current entry: a quick-download button in the journal toolbar (and the slide-out sheet) lets you
download the entry you're currently editing without leaving the page.
Hyperlink support in the editor
The Tiptap toolbar now includes a link button. Clicking it (or activating via the toolbar when text is
selected) opens a modal to insert, edit, or remove a hyperlink. Keyboard shortcuts work: Enter to confirm,
Escape to cancel, clicking the backdrop to dismiss.Changes
- The account page is now split into two tabs: Security (password change) and Data (new data management).
- The admin Users page has a cleaner UX: the reset-password form is hidden behind a click-to-reveal button,
and delete confirmations are handled inline via JS rather than a blocking browser dialog. Page-level tab
navigation now links Users ↔ Tasks.
Internals
- Added markdownify dependency for HTML→Markdown conversion in text exports.
- New i18n strings for all added UI (EN + ES).
- New unit test suite for account data routes (tests/test_account.py, 412 lines) and a new e2e suite for the
data management tab (tests/e2e/test_data_management.py, 189 lines).
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Export entries: download a ZIP of your entries scoped to all time, a specific year, or a specific month.
-
v0.9.0
Stablereleased this
2026-04-23 10:27:04 +02:00 | 5 commits to main since this releasev0.9.0
Features
- Admin task scheduler: new
/admin/tasksUI for running maintenance tasks on demand; tasks are defined inapp/tasks.pyand triggered from the admin panel - Self-hosted fonts and Tiptap: all web fonts (Inter, Lora, Cormorant Garamond) and the Tiptap editor bundle
are now served locally; no external CDN requests at runtime - Share links: "Publish" renamed to "Share" consistently across the UI and codebase; clearer copy and improved share flow in the editor
- Mobile improvements: new mobile-specific CSS (
components/mobile.css), responsive calendar adjustments, and
logo visibility fixes on small screens - Modal polish: dedicated
components/modal.css, improved modal close behavior, and fixes for elements
obscured behind open modals
Improvements
- Editor JS refactored for better async button handling and modal interaction safety
- Responsive layout refined across breakpoints (nav, calendar, editor)
i18nstrings extended and corrected for both en and es locales
Testing
- Test coverage raised to 100%
- Playwright e2e suite now runs on both Chromium and Firefox in CI
- New e2e tests covering the share/publish flow
Infrastructure
- Tiptap bundled via esbuild (
scripts/build-tiptap.mjs); rebuild withjust build-js package.json/package-lock.jsonadded for JS tooling- Docker image updated to copy bundled fonts and vendor JS
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Admin task scheduler: new
-
v0.8.0
StableAll checks were successfulTest and publish Docker image / test (pull_request) Successful in 46sTest and publish Docker image / e2e (pull_request) Successful in 3m11sTest and publish Docker image / build (pull_request) Has been skippedTest and publish Docker image / test (push) Successful in 45sTest and publish Docker image / e2e (push) Successful in 1m52sTest and publish Docker image / build (push) Successful in 45sreleased this
2026-04-21 22:36:03 +02:00 | -7 commits to main since this releasev0.8.0
Features
Mobile navigation overhaul
Replaced the cluttered mobile header with a clean minimal bar (logo + Publish button + "…" menu).
Tapping "…" opens a native-style bottom sheet containing: copy link, theme toggle, language switcher, account, delete entry, and sign out.
Desktop is unchanged.Delete modal
Replaced the browser
confirm()dialog with a proper in-page modal.
If the entry is currently published, the modal warns that deleting will also remove the public link
and handles the unpublish automatically before deleting.Alpha logo
The Piruetas alpha logo image now appears alongside the wordmark in the header.
On mobile, only the image is shown to conserve space.Playwright E2E test suite
Full end-to-end coverage added: authentication (login, logout, rate limiting), journal (CRUD, images, share
tokens), account (password change), and admin (user management, access control).CI: E2E job in Forgejo workflow
The Forgejo CI pipeline now runs the Playwright E2E suite on every push.
Fixes
- Copy link button correctly hidden on mobile when entry is not published
- Sign-out button properly hidden from mobile header (was leaking through an inline style)
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
v0.7.0
Stablereleased this
2026-04-21 16:55:26 +02:00 | 16 commits to main since this releaseWhat's new in 0.7.0
Delete entries
A trash icon now appears in the toolbar whenever the current day has a saved entry.
One click (with a confirmation prompt) permanently deletes the entry and updates the calendar immediately.
No more empty days showing as having content.Calendar legend
A
?button in the bottom corner of the calendar expands an inline legend explaining the three visual states:
today, shared entry, and days with content.Sidebar stats
The left column now shows a writing streak (consecutive days with entries) and a monthly summary (entry count
and word count) on every journal page.License
Piruetas is now officially licensed under
AGPL-3.0.
A commercial license is available for proprietary use: contactpatillacode (at) gmail (dot) comFrontend code quality
Theme toggle, locale picker, and mobile navigation logic have been moved out of HTML templates into proper
static JS files (ui.js,calendar.js), making the frontend easier to maintain.Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
Source code (ZIP)
-
v0.6.0
Stablereleased this
2026-04-20 18:11:48 +02:00 | 17 commits to main since this releaseSecurity hardening, publishing flow redesign, and polish
Security (9 fixes)
HSTS+Permissions-Policyheaders added to all responses;HSTSonly sent whenSECURE_COOKIES=true- Session versioning:
session_versioncolumn onUser; token format updated to include version; stale tokens
rejected on every request - Session invalidation on password change: admin reset and self-change both increment
session_version,
logging out all other devices; self-change re-issues cookie so the current session stays valid - Login
CSRF: double-submit cookie pattern onGET /login→POST /login; requests without a matching token get
403 - Image magic byte validation: upload endpoint validates actual file bytes, not the client-supplied
Content-Type TRUST_PROXYsetting: opt-inX-Forwarded-Forsupport for correct IP detection behind nginx/Caddy/Traefik; rate limiter uses real IP when enabled- CSP nonces: per-request nonces replace unsafe-inline on script-src; Google Fonts and esm.sh (Tiptap) whitelisted
- Image access control:
/uploads/{user_id}/{filename}requires auth or a valid?share_tokenlinked to an entry owned by that user - Share token revocation:
DELETE /journal/{date}/shareendpoint clears the token; images embedded in shared entries are rewritten to include?share_tokenso they load for unauthenticated viewers
Publishing flow redesign
Replaced the fragile share popup with a clean two-action model:
- Publish/Unpublish toggle in the toolbar: primary action, clear state label
- Copy link icon button: appears inline only when the entry is published, copies directly to clipboard with a
toast; no popup, no URL input field - Both buttons work dynamically without page reload
- Mobile nav button mirrors the same publish toggle
UI & calendar polish
- Calendar now distinguishes four day states: today (dot below number), written (accent strikethrough),
shared/published (accent ring), active/current (solid fill); states stack, active overrides all - CSS split into modular component files
i18n
- All templates fully wired to the translation system (account page, admin users table, journal toolbar)
- New keys: account, publish, unpublish, copy_link, change_password, admin_role, user_role, stop_sharing,
delete_confirm
Docs & CI
- README rewritten with inline Docker Compose quick-start
CONFIGURATION.mdadded with full prose-style config reference- CI pipeline updated to run tests on every push to main, build and push Docker image only on version tags (v*)
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
v0.5.0
Stablereleased this
2026-04-18 18:50:43 +02:00 | 20 commits to main since this releaseBug fixes
- Share link privacy fix: shared journal entries were exposing all entries to the viewer instead of only the intended one
- Database path misconfiguration warning:
DATABASE_URLwith three slashes (sqlite:///) resolves relative to
the app working directory, silently bypassing the volume mount and losing data on container restarts;
the app now logs a warning at startup if the DB path falls outsideDATA_DIR
Other changes
- Updated logo: optimised alpha PNG (5 MB → 478 KB) and added dark variant
READMElogo link fix
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
v0.4.0
Stablereleased this
2026-04-18 11:36:25 +02:00 | 24 commits to main since this releaseMobile improvements
Shared entries with images now load correctly on Android
Images in shared entries were served behind authentication, causing Android browsers (Telegram, Firefox) to
receive a redirect to the login page when loading the image, making the page appear blank.
Images are now public; UUID filenames remain the security boundary.Share button accessible in portrait mode
The share button was hidden off-screen in portrait mode.
It now lives in the header nav on mobile and is always reachable regardless of screen width or orientation.Date picker on mobile
Tapping the date in the mobile navigation bar opens a slide-up calendar sheet. Tap any day to navigate to it,
or tap the backdrop to dismiss.Language selector
Replaced the ambiguous EN/ES text toggle with a flag<select>(🇬🇧 / 🇪🇸) clearer at a glance and visible on
mobile (the previous link was hidden by the nav collapse rule).Editor toolbar
Replaced text labels (Link, Undo, Redo, Image) with minimal SVG icons.
Buttons are now evenly distributed across the full toolbar width on both desktop and mobile; separators removed.Bug fixes
- Fixed webmanifest href pointing to a
404path
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Fixed webmanifest href pointing to a
-
v0.3.0
Stablereleased this
2026-04-18 03:36:31 +02:00 | 26 commits to main since this releaseWhat's new
Demo mode
A built-in demo user can now be enabled via environment variables. When active, the demo account is
auto-created at startup and its content is wiped on a configurable interval (default: every 30 minutes) via an
asyncio background loop, no cron jobs or external schedulers needed.Try it at piruetas.patilla.es, log in with
demo/mysupersecretpassword.README
Added screenshots of both light and dark themes, a live demo link, and the full demo configuration reference.
Bug fixes
- Fixed a startup crash where
appusercouldn't write to.venvdue to/appownership - Disabled
uvcache to resolve a non-root runtime error in Docker
Configuration (new env vars)
Variable Default Description DEMO_ENABLED false Enable demo user and content reset loop DEMO_USERNAME demo Demo account username DEMO_PASSWORD demo Demo account password DEMO_RESET_INTERVAL 1800 Seconds between content wipes Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Fixed a startup crash where