Skip to content

pyvelm v0.14.0

Release date: 2026-05-27

UX pass on the page shell and error surface, plus a development-only "nuke the database and re-run everything" command.


Highlights

Filament-style heading

The page title now renders as a prominent <h1> directly under the breadcrumbs in the main column — the same shape Filament panels use. The sidebar brand area shows only the logo + app name; the per-page subtitle that used to sit there is gone.

┌───────────┬─────────────────────────────────────────┐
│  pyvelm   │  Settings ▸ Workflows ▸ Email templates │
│           │  Email templates                        │  ← h1
│  Nav      │  ──────────────────────────────────────│
│  …        │  [list / form / kanban here]            │
└───────────┴─────────────────────────────────────────┘

Pages override the title with {% block page_title %}…{% endblock %} as before; the layout's default page_heading block emits the h1 + optional subtitle. The handful of templates that overrode page_heading themselves (none currently in-tree) are unaffected.

No record-count subtitle on list / kanban

The pager footer already shows the record total, so the heading region no longer renders 5 records underneath the title. List views pass subtitle="" and the OOB #pv-count-label swap in list_rows.html / kanban_cards.html is gone. Pivot (R rows × C columns) and graph (N groups) subtitles stay — they describe the visualisation's structure, not a record count.

Styled error pages

Every 4xx / 5xx that hits a browser navigation now renders the same shaped card:

  • One template pyvelm/templates/error.html (centered card, status code badge, title, message, optional Retry-After countdown, Back / Home buttons).
  • render_error_page(env, *, status_code, …) with per-status defaults for 400, 401, 403, 404, 405, 422, 429, 500, 501, 502, 503, 504. Unlisted codes roll up to a generic 4xx / 5xx flavour.
  • Two global FastAPI handlers in pyvelm/web.py: @app.exception_handler(StarletteHTTPException) for raised HTTPExceptions (including router 404s); a last-resort @app.exception_handler(Exception) for uncaught errors that becomes a styled 500 (with the traceback logged server-side).
  • The login throttle's 429 now returns the styled card with a live countdown instead of text/plain.

API / JSON / HTMX callers still get the same status code plus a short text body (with Retry-After etc. preserved) — only browser GETs under /web/... swap to HTML.

pyvelm db nuke — development-only reset

PYVELM_ENV=development \
PYVELM_DSN=postgresql://user:pass@localhost/dev \
pyvelm db nuke           # interactive
pyvelm db nuke --yes     # scripted
pyvelm db nuke --schema my_schema --yes
  • Refuses to run when PYVELM_ENV=production (pyvelm db nuke is disabled in production. Aborting.).
  • Prints the plan (DSN, schema, modules), prompts Type nuke to continue: — anything else aborts. --yes skips the prompt.
  • DROP SCHEMA public CASCADE; CREATE SCHEMA public; (override with --schema X) + re-grant on CURRENT_USER and PUBLIC.
  • Runs the same install pass as pyvelm db migrate so every module's 0_x_to_0_y.py migration re-executes from scratch.

Use it on local dev databases, not anything you care about. There is no undo.


Upgrade

pip install -U pyvelm==0.14.0

No schema or migration changes. After pip install -U:

  1. Hard-refresh your browser — the page heading shape changed and the layout template needs a fresh load.
  2. If you have a project that overrode {% block page_heading %}, review it. The default now renders the h1 itself; you may want to drop your duplicate.

Also in this release

  • The db subparser help mentions nuke in its summary so pyvelm db --help discoverability is correct.
  • pyvelm/cli.py docstring lists the new command alongside migrate and migrate-fresh.
  • docs/cli.md ships a dedicated paragraph on db nuke with the full warning and a sample invocation.

Docs