Files
novaconium/App/pages/index.twig
T
code 15b32ed256 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>
2026-07-17 02:43:03 +00:00

106 lines
5.8 KiB
Twig

{% extends layout %}
{% block title %}Home{% endblock %}
{% block description %}A tiny, Hugo-flavored PHP micro-framework: file-based routing, Twig templates, and static caching.{% endblock %}
{# Every block below is optional — the layout already supplies a sensible
default for each (see /admin/docs/seo). Shown here uncommented as a
reference for every override a page can make; delete what you don't
need. #}
{% block robots %}index, follow{% endblock %}
{% block canonical %}{{ request_path|default('/') }}{% endblock %}
{% block og_type %}website{% endblock %}
{% block og_title %}{{ block('title') }}{% endblock %}
{% block og_description %}{{ block('description') }}{% endblock %}
{% block og_url %}{{ block('canonical') }}{% endblock %}
{% block twitter_card %}summary{% endblock %}
{% block twitter_title %}{{ block('title') }}{% endblock %}
{% block twitter_description %}{{ block('description') }}{% endblock %}
{% import '_layout/icons.twig' as icons %}
{% block content %}
<section class="hero">
<span class="hero-eyebrow">novaconium</span>
<h1>You're up and running.</h1>
<p class="hero-lede">A tiny, Hugo-flavored PHP micro-framework: file-based routing, Twig templates, and static caching — no Composer, no build step. This page lives at <code>App/pages/index.twig</code>; start editing there.</p>
<div class="hero-actions">
<a class="button-link" href="/admin/docs">Read the docs</a>
<a class="button-link button-link--ghost" href="https://git.4lt.ca/4lt/novaconium">{{ icons.git() }}View source</a>
</div>
<ul class="hero-badges">
<li class="badge">PHP 8.1+</li>
<li class="badge">No Composer</li>
<li class="badge">Twig vendored</li>
<li class="badge">Static caching</li>
</ul>
</section>
<section class="feature-grid">
<article class="feature-card">
<h2>File-based routing</h2>
<p>A directory under <code>App/pages/</code> <em>is</em> a route. <code>[param]</code> segments capture into <code>$params</code>. No route table to maintain.</p>
</article>
<article class="feature-card">
<h2>Optional sidecars</h2>
<p>Drop an <code>index.php</code> next to any <code>index.twig</code> for real logic, or return a <code>Response</code> to short-circuit templating entirely.</p>
</article>
<article class="feature-card">
<h2>Static caching</h2>
<p>Sidecar-less pages render once and get served straight from Apache afterwards — this page included.</p>
</article>
<article class="feature-card">
<h2>SEO out of the box</h2>
<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>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>
<p><code>App/</code> is checked before <code>novaconium/</code> for every page, layout, and <code>Lib\</code> class — override by dropping a file at the same relative path.</p>
</article>
</section>
<section class="next-steps">
<h2>Where to next</h2>
<ul>
<li><a href="/admin/docs/getting-started">Getting started</a> — requirements, running locally, deploying on Apache.</li>
<li><a href="/admin/docs/routing">Routing</a> and <a href="/admin/docs/sidecars">sidecars</a> — how pages and logic fit together.</li>
<li><a href="/blog">The blog example</a> — a listing sidecar, individual posts, and a layout override.</li>
<li><a href="/admin">Admin</a> — clear the cache and browse these docs live.</li>
</ul>
</section>
{% endblock %}