-
v0.20.0
Stablereleased this
2026-05-25 21:29:31 +02:00 | 0 commits to main since this releasev0.20.0
This release is all about security visibility and keeping bots out.
Security notifications
Piruetas can now ping you in real time when things happen on your instance, things like admin logins, new signups, and rate limit hits.
Both ntfy and Telegram are supported; configure whichever you prefer (or both) viaNTFY_URL,NTFY_TOPIC,NTFY_TOKEN,TELEGRAM_BOT_TOKEN, andTELEGRAM_CHAT_ID.
All optional, all off by default.Sharing age gate
New accounts have to wait 7 days (by default) before they can share journal entries publicly.
The share button is disabled in the meantime and tells you exactly how many days are left.
Admins are exempt.
If 7 days doesn't fit your setup,SHARING_WAIT_DAYSlets you change it. Set to zero0if don't want to enable this feature.Bug fix
Corrected a template block placement in the admin users page that was causing page scripts to load incorrectly.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
Source code (ZIP)
-
v0.19.0
Stablereleased this
2026-05-06 21:56:48 +02:00 | 5 commits to main since this releasev0.19.0
Admin: User Stats & Banner Messages
The admin panel now shows per-user statistics and lets you set a banner for individual users.
New User fields (applied via safe ALTER TABLE migration on startup):
last_login: timestamp of the user's most recent loginstorage_bytes: disk usage across all uploaded images, recalculated on a schedulebanner_message: a warning or notice shown to the user on every page
Admin user modal now surfaces: last login date, total storage used, entry count, and days written.
Admins can set or clear a banner per user directly from the modal.
The demo account gets a default banner explaining the periodic data reset.New scheduled task (
recalculate_storage) runs alongside the existing cleanup and vacuum jobs, keeping
storage_bytesup to date.All new strings are translated in both English and Spanish.
Fix: Self-hosted Ko-fi Badge
The Ko-fi support badge image is now served from
/static/img/kofi1.pnginstead of the external CDN, avoiding a
third-party request on the landing page.
README description of the admin panel was also corrected.E2E Test Suite Refactor
The flat
tests/e2e/directory has been reorganized into focused subdirectories:test_auth/: login, logout, registration, rate limiting, demo user, password recoverytest_account/: password change, data management, recovery codes, demo restrictionstest_admin/: banner management, user deletion, admin tasks, user list, user statstest_journal/: entry CRUD, image upload, navigation, sharingjourneys/multi-feature end-to-end journeys: admin lifecycle, orphan image cleanup, recovery flow, share flow, user stats
Also adds locale-switching tests and fixes an
admin_pagefixture leak (now uses an isolated browser context).Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
v0.18.0
Stablereleased this
2026-05-03 14:25:13 +02:00 | 8 commits to main since this releasev0.18.0
arm64 support & GHCR publishing
What's new
-
Raspberry Pi support: Docker images are now built for both linux/amd64 (standard servers and desktops) and linux/arm64 (Raspberry Pi 4/5, Apple Silicon).
-
Images on GitHub Container Registry: images are now published to GHCR (ghcr.io/patillacode/piruetas) in addition to the Forgejo registry.
GHCR requires no authentication to pull and is the recommended source for new deployments.
Upgrading
Existing users on Forgejo registry:
docker compose pull && docker compose up -d(no changes needed)New users or those switching to GHCR, update your compose.yml:
image: ghcr.io/patillacode/piruetas:latestDownloads
-
Source code (ZIP)
1 download
-
Source code (TAR.GZ)
1 download
-
-
v0.17.0
Stablereleased this
2026-05-03 05:16:25 +02:00 | 9 commits to main since this releasev0.17.0
Features
- Proxy headers middleware: When
TRUST_PROXY=true, the app now enablesProxyHeadersMiddlewareso that real client IPs are correctly resolved when behind a reverse proxy (nginx, Traefik, etc.). - robots.txt: Added a
/robots.txtendpoint that allows crawlers on public-facing pages only (/,/about,/terms,/privacy,/login,/signup,/forgot-password) and disallows everything else, keeping journal content and private routes out of search indexes.
Internal
- CI/CD: Split the single
docker.ymlworkflow into separateci.yml(tests/lint) andrelease.yml(build/push image) workflows for cleaner pipeline separation.
Downloads
-
Source code (ZIP)
1 download
-
Source code (TAR.GZ)
1 download
- Proxy headers middleware: When
-
v0.16.0
Stablereleased this
2026-05-02 15:23:40 +02:00 | 11 commits to main since this releasev0.16.0
Bug fixes
- Demo account hardening: the demo user can no longer change their own password, access or regenerate recovery codes, or use the forgot-password flow.
This closes a troll trend where anyone with demo access could lock other visitors out.
Downloads
-
Source code (ZIP)
1 download
-
Source code (TAR.GZ)
1 download
-
v0.15.0
StableAll checks were successfulTest and publish Docker image / test (pull_request) Successful in 36sTest and publish Docker image / e2e (pull_request) Successful in 4m45sTest and publish Docker image / build (pull_request) Has been skippedTest and publish Docker image / test (push) Successful in 34sTest and publish Docker image / e2e (push) Successful in 4m41sTest and publish Docker image / build (push) Successful in 47sreleased this
2026-05-02 11:58:36 +02:00 | 4 commits to main since this releasev0.15.0
Features
- Demo user banner: Demo accounts now display a persistent banner showing a live countdown to the next
scheduled data reset. The banner usesrole=statusfor accessibility and updates in real time. - Clock-aligned demo resets: The demo cleanup loop now aligns to clock half-hours (:00 and :30) rather than
running on a fixed interval from startup. The next reset timestamp is exposed to the frontend for accurate
countdown display.
Fixes
- Editor link insertion: Selecting text and inserting a link via the toolbar now correctly preserves the
selection. Previously, focus shifting to the URL input lost the selected range; the selection is now saved
before the modal opens and restored on confirm. The Enter key is also scoped to the URL input to prevent
keystrokes from leaking into the editor after the modal closes. - Editor link styles: Inserted links in the editor are now visually underlined (
.ProseMirror a). - Skip link: Fixed unreliable positioning by switching from
position:absolute; top:-100%toposition:fixed; translateY(-100%). - Ko-fi button: Added
width:auto; display:inline-blockto prevent the button image from stretching to fill its container. - Signup form links: Links now use accent color + underline instead of muted text with no decoration.
- Demo banner stability: Cleared the countdown interval before triggering a reload to avoid double-fire.
Guarded againstNaNtimestamps from missing or malformeddata-*attributes. - Demo banner layout: Corrected a duplicate vertical offset that pushed the banner too far down on pages using the app layout.
- Half-hour boundary condition: Fixed an off-by-one in
_seconds_until_next_half_hourthat could return0seconds exactly on the boundary. - Demo reset timestamp:
demo_next_reset_tsis now only computed whenis_demois true, avoiding unnecessary work on every request.
Tests
- Unit tests for
_seconds_until_next_half_hourcovering boundary and midpoint cases. - E2E tests for the demo banner (visibility, countdown display, role attribute).
Downloads
-
Source code (ZIP)
1 download
-
Source code (TAR.GZ)
1 download
- Demo user banner: Demo accounts now display a persistent banner showing a live countdown to the next
-
v0.14.0
Stablereleased this
2026-05-01 20:41:29 +02:00 | 13 commits to main since this releasev0.14.0
Accessibility
- Full WCAG AA contrast audit across all UI components
- Improved keyboard focus styles and focus management throughout the app
- Focus trap for modal overlays
- Semantic HTML improvements on auth, layout, and editor templates
Code quality & internals
- Extracted export logic into dedicated
app/export.pymodule - Renamed
app/auth.pytoapp/session_token.pyfor clarity - Extracted Jinja2 macros into app/templates/macros.html
- Theme switching logic moved to dedicated app/static/js/theme.js
- Added CSS export bundle (app/static/css/export-bundle.css)
- Router cleanup across account.py, auth.py, and journal.py
Bug fixes (QA)
- Fixed form layout and styling issues on mobile
- Auth JS improvements (signup/login edge cases)
- Recovery codes page polish
- i18n string additions for missing UI labels
Tests
- Expanded e2e suite: new test files for account, auth, registration, and sharing flows
- Reorganised e2e test structure (test_data_management.py → test_data.py)
- New unit tests for account, entries, and security
Docker / CI
.dockerignoreandcompose.ymlimprovements- Docker workflow updated
Landing page
- Replaced old landing screenshots with new feature-specific screenshots
- Added
scripts/take_screenshots.pyfor automated screenshot generation - Landing page CSS and copy updates for public release
Downloads
-
Source code (ZIP)
1 download
-
Source code (TAR.GZ)
1 download
-
v0.13.0
Stablereleased this
2026-04-28 16:23:03 +02:00 | 17 commits to main since this releasev0.13.0 - Security & Account Recovery
New features
- Recovery codes: Users can now generate a set of 12 one-time recovery codes from their account security
page. Codes are bcrypt-hashed at rest and can be used to regain access to an account when the password is
lost. - Forgot password flow: New forgot-password page and supporting auth routes let users request a password
reset without admin intervention. - User self-registration: Signup is now a proper auth route (
/auth/signup), replacing the old top-level page. - Privacy Policy and Terms of Service pages: Static
/privacyand/termspages added.
Improvements
- Security page (
/account/security) redesigned to surface recovery code management alongside existing
password-change controls. - Admin user management table updated for clarity.
- i18n dictionaries extended with translations for all new flows (en/es).
- Landing page and form styles polished.
Tests
- New test modules:
test_recovery.pyandtest_recovery_routes.pycovering code generation, consumption, and
all new auth endpoints.
Downloads
-
Source code (ZIP)
1 download
-
Source code (TAR.GZ)
1 download
- Recovery codes: Users can now generate a set of 12 one-time recovery codes from their account security
-
v0.12.0
Stablereleased this
2026-04-27 18:43:57 +02:00 | 20 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)
1 download
-
Source code (TAR.GZ)
1 download
-
v0.11.0
Stablereleased this
2026-04-25 12:55:01 +02:00 | 21 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)
1 download
-
Source code (TAR.GZ)
1 download
- New landing page (