Blog RSS feed (novaconium/ISSUES.md):
- App/pages/blog/feed/index.php - main feed, built from the same
hand-written $posts array App/pages/blog/index.php renders from, so it
works with content_index_enabled left at its default false. Added a
published date field per post entry.
- App/pages/blog/tag/[tag]/feed/index.php - per-tag feed, gated on
content_index_enabled the same way blog/tag/[tag]/index.php is.
- novaconium/lib/Rss.php - shared RSS 2.0 envelope builder both feeds
use, generic (title/link/description/items in, XML string out).
- New head_extra block in the root layout (empty by default) so
App/pages/blog/_layout/layout.twig can add feed auto-discovery scoped
to /blog/* only.
Footer:
- New content_index_enabled Twig global (Renderer/bootstrap.php), same
pattern as admin_auth_enabled.
- Right-aligned footer menu linking to /sitemap.xml (only shown when
content_index_enabled, so it never links to a 404) and /blog/feed
(always shown, no content-index dependency).
Docs:
- New /admin/docs/rss page: Lib\Rss API, the two shipped feeds, a worked
example of adding a feed for another content collection, and how to
advertise multiple feeds via head_extra.
- New /admin/docs/sitemap page: changefreq/priority blocks, what's
included/excluded, an honest callout on the relative-<loc>-URL spec
deviation (consistent with how canonical/og:url already work) with an
override path for strict compliance, and submitting it to search
engines.
- /admin/docs (Overview) gains a Requirements section: minimum
requirements, then optional requirements for the database/content-index
features (pdo_sqlite, optional pdo_mysql, FTS5) - and a Documentation
heading separating it from the doc links list.
- /admin/docs/getting-started's Requirements line was stale (missing
pdo_sqlite entirely, unlike README) - fixed and cross-linked to the
Overview page's fuller list.
- /admin/docs/content-index trimmed to point at the new RSS/sitemap pages
instead of duplicating their detail.
Also adds an "In-house comments" entry to novaconium/ISSUES.md's Backlog
- a Lib\ class for sidecar-attached comments on any page, depending on
the not-yet-built Admin login & user management for real user accounts.
Closes the "Blog RSS feed" backlog item.
Ships Blog tags/categories, Internal search, and XML sitemap together as
one shared mechanism, plus a new meta keywords request, rather than three
separate ones - the "worth deciding together" call ISSUES.md made when
XML sitemap was first written.
Content stays in files. Per-page metadata is four Twig blocks in the
root layout, the same override mechanism already used for
title/description/og_* - keywords (rendered), tags/changefreq/priority
(not rendered, harvested only). App\ContentIndexer crawls every routable
page (Overlay::listPageDirs(), new) and pulls each block via
Renderer::renderForIndex() (new) calling Twig's own renderBlock() API,
not regex-parsing .twig source, so overrides and layout inheritance
resolve exactly like a real render. Rendered HTML is stripped and
indexed into a SQLite FTS5 table for search.
Off by default (content_index_enabled) - same posture as Matomo/admin
auth, since this is a real SQLite dependency plenty of sites won't want.
Verified true zero footprint when disabled: no data/novaconium.sqlite
gets created, all three consumer routes 404 like they don't exist.
content_index_auto (default true) reindexes lazily on first stale touch
of a consumer route, never on a normal page view; both that path and the
explicit `php novaconium/bin/index-content.php` share one reindex().
Two real bugs caught by testing, not review: a reentrancy bug where
/search's own sidecar calling ensureFresh() during the crawl triggered a
nested reindex() mid-transaction (fixed with a static re-entrancy guard),
and a wrong PDO constant in the search sidecar. Also fixed two unrelated
pre-existing bugs found while building this: an unescaped {{ }} in
admin/docs/sidecars that fataled Twig on any real render of that page,
and a stale "no database layer yet" claim there and in Lib\Input's
docblock, left over from before Lib\Db shipped.
Lib\Db's migrations_dir now accepts an ordered list of roots, not just
one path, so the content index's schema could ship as a framework
migration (novaconium/migrations/) without colliding with project
migrations in App/migrations/ - the two-root extension point flagged in
AGENTS.md when SQLite groundwork shipped. Migrations are tracked by path
relative to the repo root rather than bare filename so two roots with a
same-named file can't shadow each other.
New consumer routes: novaconium/pages/sitemap.xml/ and
novaconium/pages/search/ (framework defaults), App/pages/blog/tag/[tag]/
(project-owned, since blog/ is project content - the existing hand
-written post array in App/pages/blog/index.php is untouched). Added
tags to the 4 existing blog posts as a real demonstration.
Closes the Blog tags/categories, Internal search, and XML sitemap
backlog items in novaconium/ISSUES.md.
Full rewrite: swap out the v1 framework (src/, controllers/, views/,
twig/, sass/, skeleton/) for the working v2 codebase from phpproject
(App/, novaconium/, public/).