Make Docker bind mounts actually work; refresh homepage feature grid

App/, cache/, uploads/, and data/ are now bind-mounted by default, so
docker-entrypoint.sh seeds an empty App/ from a build-time backup and
re-chowns the mounted paths to http:http on every start (a bind mount
doesn't inherit a named volume's ownership or get seeded from the image
the way COPY does). Also fixes AllowOverride never actually being
enabled (the sed pattern didn't account for httpd.conf's indentation,
so only DirectoryIndex-served routes worked) and pins Apache/PHP/SQLite
to a dated Arch Linux Archive snapshot for reproducible builds.

Homepage's feature grid was six cards behind what's actually shipped;
brought it in line with the features blog post.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
code
2026-07-17 02:43:03 +00:00
parent d1ce803412
commit 15b32ed256
9 changed files with 146 additions and 35 deletions
+30 -2
View File
@@ -56,8 +56,36 @@
<p>Meta description, canonical links, Open Graph, and Twitter Card tags ship by default, all overridable per page.</p>
</article>
<article class="feature-card">
<h2>Matomo &amp; admin auth</h2>
<p>Built-in analytics tracking and a multi-user session login for <code>/admin/*</code> — both off until you turn them on in <code>App/config.php</code>.</p>
<h2>Admin authentication</h2>
<p>A multi-user session login gates every <code>/admin/*</code> route, with email verification for new accounts. Off by default in <code>App/config.php</code>.</p>
</article>
<article class="feature-card">
<h2>Access control &amp; drafts</h2>
<p>Gate a page to a user or group with one <code>Lib\Access</code> call in its sidecar, or preview an unfinished page as an admin-only draft.</p>
</article>
<article class="feature-card">
<h2>Media manager &amp; comments</h2>
<p>An upload/browse/delete UI at <code>/admin/media</code>, and <code>Lib\Comments</code> for a moderated comment thread on any page.</p>
</article>
<article class="feature-card">
<h2>Database, zero setup</h2>
<p><code>Lib\Db</code> wraps PDO for SQLite or MySQL, multiple named connections at once, migrating automatically on first use.</p>
</article>
<article class="feature-card">
<h2>Search, sitemap &amp; tags</h2>
<p>One content index backs full-text <code>/search</code>, <code>/sitemap.xml</code>, and blog tag browsing — reindexed lazily, no extra steps.</p>
</article>
<article class="feature-card">
<h2>Blog RSS feed</h2>
<p><code>/blog/feed</code> is built from the same hand-written post list <code>App/pages/blog/index.php</code> renders from — no database required.</p>
</article>
<article class="feature-card">
<h2>Matomo &amp; dark/light theme</h2>
<p>Built-in analytics tracking, off by default, alongside a nav toggle that swaps every color via CSS custom properties.</p>
</article>
<article class="feature-card">
<h2>Form security by default</h2>
<p><code>Lib\Csrf</code>, <code>Lib\SpamGuard</code>'s honeypot check, and cleaning input accessors — wired into the contact form and every admin form.</p>
</article>
<article class="feature-card">
<h2>Override anything</h2>