feat: phase 2 content model + cache — SQLite schema, markdown, TTL
Stand up the full SQLite content layer: all 7 tables from the authoritative schema with WAL + foreign-keys enforced per-connection, entity dataclasses plus row mappers, hand-rolled versioned migrations tracked in schema_migrations, and an idempotent Python seed (system user + welcome post + About page). Add a Markdown->HTML service using markdown-it-py with a strict bleach allowlist (tables intentionally omitted on both sides). Add a typed in-process TTLCache[K,V] and wire it into real DB-backed PostService and PageService, both exposing invalidate_all() for Phase 4 admin writes. Rewire / and /about to read from the DB; homepage renders the seeded welcome post, About renders page.title + sanitized body_html_cached. Update the Phase 1 route tests accordingly. Mark Phase 2 complete in docs/ROADMAP.md.
This commit is contained in:
@@ -1,42 +1,37 @@
|
||||
{#
|
||||
About page — static placeholder copy. Head Hen will replace this via
|
||||
the Phase 4 admin CMS, so the prose below is deliberately generic and
|
||||
free of lorem ipsum. Per CLAUDE.md, the physical address is not shown
|
||||
anywhere on the site — only the town name.
|
||||
About page. Phase 2: body comes from the ``pages`` row with
|
||||
slug='about', rendered via the Markdown pipeline (markdown-it-py →
|
||||
bleach allowlist) at write time and cached on the row. The cached
|
||||
HTML has already been sanitized against an allowlist that forbids
|
||||
scripts, styles, iframes, etc., so it is safe to emit with the
|
||||
``| safe`` filter (Jinja autoescape is explicitly disabled for the
|
||||
body only). Head Hen edits this content through the Phase 4 admin.
|
||||
|
||||
Per CLAUDE.md, the physical address is not shown anywhere on the
|
||||
site — only the town name.
|
||||
|
||||
Context:
|
||||
- page : app.models.entities.Page
|
||||
- active_nav : str "about"
|
||||
#}
|
||||
{% extends "public/base.html" %}
|
||||
|
||||
{% block title %}About — Chicken Babies R Us{% endblock %}
|
||||
{% block title %}{{ page.title }} — Chicken Babies R Us{% endblock %}
|
||||
{% block meta_description %}About Chicken Babies R Us — a small family farm in Morrison, Tennessee raising chickens, ducks, and geese.{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<article class="page-article">
|
||||
<header class="page-article__header">
|
||||
<h1 class="page-article__title">About the farm</h1>
|
||||
<h1 class="page-article__title">{{ page.title }}</h1>
|
||||
</header>
|
||||
|
||||
<p>
|
||||
Chicken Babies R Us is a small family farm tucked into the rolling
|
||||
hills of Morrison, Tennessee. What started as a handful of chicks
|
||||
in a backyard brooder has grown into a flock of chickens, ducks, and
|
||||
geese that keep us busy (and entertained) year round.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The operation is run by Head Hen — the chief wrangler, egg
|
||||
gatherer, waterfowl-whisperer, and unofficial chicken photographer.
|
||||
She handles the day-to-day care of the birds and does most of the
|
||||
writing you'll find on this site. Expect updates on hatching plans,
|
||||
new arrivals, the occasional coop mishap, and whatever the geese
|
||||
decided to get into this week.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
We're a hobby farm at heart, not a commercial one, which means we
|
||||
can take the time to know our birds and raise them the way we think
|
||||
they ought to be raised. If you're curious about what we've got
|
||||
going on — or just want to say hello — pop over to the
|
||||
contact page.
|
||||
</p>
|
||||
{#
|
||||
body_html_cached is the output of the bleach-sanitized
|
||||
Markdown pipeline. It contains only tags / attributes /
|
||||
protocols from our allowlist (p, strong, em, a, ul, ol, li,
|
||||
h1-h4, blockquote, code, pre, img, hr + href/src/etc.), so
|
||||
rendering with ``| safe`` does not reintroduce XSS risk.
|
||||
#}
|
||||
{{ page.body_html_cached | safe }}
|
||||
</article>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user