Releases: Promptly-Technologies-LLC/fastapi-jinja2-postgres-webapp
Release list
v0.1.11
v0.1.10
Summary
- Enable Open Graph and Twitter Card meta tags via
_quarto.ymlfor rich link previews on social media - Add
site-urlfor canonical URLs and automatic sitemap generation - Add
descriptionfrontmatter to all.qmdpages for<meta name="description">tags - Improve alt text on homepage screenshot image
Closes #37
Test plan
- Verify Quarto renders successfully with
quarto render - Inspect generated HTML for
<meta name="description">,og:tags, andtwitter:tags - Confirm
sitemap.xmlis generated in_docs/
🤖 Generated with Claude Code
v0.1.9
Annotate FastAPI routes for better OpenAPI documentation
v0.1.8
Resequenced deployment documentation to clarify that Modal requires separate Postgres deployment, but Hetzner does not.
- Digital Ocean PostgreSQL deployment is nested under Modal
- Removed a Supabase-related example since Supabase is not an explicit deployment target (yet)
v0.1.7
Template changes (templates/base/partials/header.html):
- Added a mobile-only
- with plain Profile and Logout links inside the collapsible
- Wrapped the desktop avatar dropdown in d-none d-lg-flex so it's hidden on mobile
- Kept Login/Register links visible on all screen sizes (not wrapped in d-none)
section (only for authenticated users)
The result: on mobile, authenticated users see Profile and Logout as regular nav items in the hamburger menu (no
dropdown, no avatar thumbnail). On desktop, the avatar dropdown works as before.
v0.1.6
- The Register page now clearly states the requirements for passwords
- The error toast, if the user submits an invalid password, restates the requirements
- Using a suggested password on Chrome now auto-populates both password fields, not just one.
v0.1.5
- Add Hetzner Cloud deployment docs and deployment branch note
- Add hcloud CLI installation to devcontainer setup
- Update all dependencies and pin dev postgres to v17
- Replace mypy with ty type checker and fix ruff lint issues
- chore: release v0.1.2 [skip ci]
- Error messaging standardization
- Type checks and lints
- Bugfixes for modal cleanup
v0.1.4
OOB Toast (HTMX error handlers)
These all fire through the exception handlers in main.py.
-
CredentialsError (401 toast)
- Go to /account/login
- Enter a valid email format but wrong credentials
- Submit — toast renders: "Invalid email or password"
-
RequestValidationError (422)
- Go to /account/login
- Leave both fields blank, submit
- Toast is rendered with validation messages
-
PasswordValidationError (422)
- Go to /account/register
- Fill in name/email, enter a weak password like abc, different confirm password
- Submit — toast renders: "The passwords you entered do not match"
-
RateLimitError (429 toast)
- Go to /account/login
- Submit wrong credentials rapidly ~6 times (depends on your limiter config)
- Eventually toast renders: "Too many attempts..." with Retry-After
-
HTTPException (business logic errors)
- Log in, go to an org page
- Try to create a role with a name that already exists (e.g. "Owner")
- Toast: "A role with that name already exists"
-
StarletteHTTPException (404 toast via HTMX)
- Harder to trigger naturally. You can use browser devtools to fire an HTMX request to a
non-existent route:
htmx.ajax('GET', '/nonexistent', {target: 'body', headers: {'HX-Request': 'true'}})
- Harder to trigger naturally. You can use browser devtools to fire an HTMX request to a
OOB Toasts (HTMX success — append_toast)
These return the partial content + an appended toast in the same response.
-
Profile update
- Log in, go to /user/profile
- Click Edit, change your name, Save
- Toast: "Profile updated successfully."
-
Role CRUD
- Go to an org page where you're Owner
- Create a new role — toast: "Role created successfully."
- Edit that role's name — toast: "Role updated successfully."
- Delete that role — toast: "Role deleted successfully."
-
[] User role update
- On the org page, edit a member's roles (check/uncheck roles)
- Save — toast: "User role updated successfully."
-
[] Remove member
- On the org page, remove a non-owner member
- Toast: "User removed from organization."
-
[] Send invitation
- On the org page, invite a new email address
- Toast: "Invitation sent successfully."
-
Email update (HTMX path)
- On /user/profile, enter a new email in the Update Email form
- Submit — toast: "Confirmation email sent. Check your inbox."
Flash Cookie (PRG redirects — full page load)
These set a flash_message cookie that the JS in base.html reads on the next page load.
-
Confirm email update
- Trigger an email update from profile
- Click the confirmation link from the email
- You'll be redirected to /user/profile — toast: "Your email address has been successfully
updated."
-
[] Forgot password
- Go to /account/forgot_password (or use the Change Password section on profile)
- Submit your email
- Redirected to ?show_form=false — toast: "If an account exists with this email, a password reset
link will be sent."
-
Update organization name
- On the org page, edit the org name and save
- Page redirects via HX-Redirect — toast: "Organization updated successfully."
-
Delete organization
- On the org page, delete the organization
- Redirected to /user/profile — toast: "Organization deleted successfully."
JS showToast() (client-side validation)
-
Avatar file validation
- Go to /user/profile, click Edit
- Try uploading a file that's too large — toast: "File size must be less than X MB"
- Try uploading a .txt file — toast: "File format must be one of: ..."
- Try a very small image (e.g. 1x1 px) — toast: "Image dimensions must be at least ..."
Quick checklist
┌────────────────┬─────────────────────────────────────────────┬────────────────────────────────┐
│ Mechanism │ Trigger │ Where to look │
├────────────────┼─────────────────────────────────────────────┼────────────────────────────────┤
│ toast_response │ Any HTMX error (login, register, │ Bottom-right toast │
│ │ validation) │ │
├────────────────┼─────────────────────────────────────────────┼────────────────────────────────┤
│ append_toast │ Any HTMX success mutation (profile, roles, │ Bottom-right toast alongside │
│ │ members, invitations) │ updated partial │
├────────────────┼─────────────────────────────────────────────┼────────────────────────────────┤
│ Flash cookie │ PRG redirects (email confirm, forgot │ Bottom-right toast after page │
│ │ password, org update/delete) │ load │
├────────────────┼─────────────────────────────────────────────┼────────────────────────────────┤
│ showToast() JS │ Avatar file picker validation │ Bottom-right toast, no network │
│ │ │ request │
└────────────────┴─────────────────────────────────────────────┴────────────────────────────────┘
v0.1.3
Summary
- Set
follow_redirects=Falseon allTestClientinstances inconftest.pyinstead of passing it per API call - Removed ~90 redundant
follow_redirects=Falsearguments from individual test calls - Added redirect location assertions (
response.headers["location"]) to all tests that check 3xx status codes but previously didn't verify the redirect target - Fixed
InsecureKeyLengthWarningby using a testSECRET_KEYlonger than 32 bytes
Closes #101
Test plan
- All 348 tests pass with zero warnings
🤖 Generated with Claude Code
v0.1.2
Summary
- Add Hetzner Cloud deployment documentation to deployment.qmd with instructions for provisioning, DNS setup, configuration, and management
- Add callout note explaining that deployment artifacts live on per-target branches (
modal,hetzner) - Add
DOMAINenv var to.env.examplefor Caddy TLS configuration - Install
hcloudCLI in devcontainer setup
Closes #151
🤖 Generated with Claude Code