Files
novaconium/novaconium/pages/admin/docs/caching/index.twig
T
codeandClaude Sonnet 5 6ae05da6de debug config also drives Twig debug + bypasses static cache
When debug is true: enable Twig debug mode (dump(), auto_reload,
DebugExtension), and stop caching sidecar-less pages — Renderer skips
the cache write, the dev router skips serving cache files, and
bootstrap clears stale cache on the first request that reaches PHP.

Also update docs: new Debug mode section on the config page, cache-
opt-out notes (debug + empty index.php sidecar) on the caching page,
and correct the Sass build target to App/css/main.css in AGENTS.md
and the styling page.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011FZQHKxu24mvojrJDwhWVS
2026-09-09 18:30:48 +00:00

31 lines
3.5 KiB
Twig

{% extends 'admin/docs/_layout/layout.twig' %}
{% import '_layout/icons.twig' as icons %}
{% block title %}Static caching{% endblock %}
{% block description %}How sidecar-less pages are pre-rendered and served as static HTML.{% endblock %}
{% block robots %}noindex, nofollow{% endblock %}
{% block docs_content %}
<h1>Static caching</h1>
<p>If a page has <strong>no</strong> sidecar, its rendered HTML is written to <code>public/cache/&lt;path&gt;/index.html</code> after the first request. <code>.htaccess</code> checks for that file before PHP ever runs, so repeat visits are served straight by Apache with zero PHP/Twig overhead. Pages with a sidecar are never cached this way, since their output can vary per request.</p>
<p>Two kinds of route are excluded from the cache unconditionally, regardless of whether they have a sidecar: every <a class="icon-link" href="/admin/docs/drafts">{{ icons.lock() }}draft page</a> and every <code>/admin/*</code> route. Both are gated by the <a class="icon-link" href="/admin/docs/admin-auth">{{ icons.lock() }}admin login</a>, and a cached copy would bypass that check entirely — <code>.htaccess</code> serves a cached file before PHP (and therefore any auth check) ever runs, so a cached admin or draft page would be served to anyone, unauthenticated, forever after the first authenticated view. See <a class="icon-link" href="/admin/docs/drafts">{{ icons.lock() }}Draft pages</a> for the full write-up.</p>
<p>To opt a single page out of caching permanently, give it a sidecar — presence is all that's checked, so an <strong>empty <code>index.php</code></strong> is enough (<code>&lt;?php return [];</code> if you'd rather it read as deliberate). The page then re-renders through PHP/Twig on every request. Reach for this when a sidecar-less page's output actually varies (a current-time stamp, a random pick) but you don't otherwise need sidecar logic.</p>
<p>The whole mechanism is disabled while <a href="/admin/docs/config">debug mode</a> is on: sidecar-less pages are re-rendered on every request and nothing is written to or served from <code>public/cache/</code>. Set <code>'debug' =&gt; false</code> in <code>App/config.php</code> for production so static caching takes effect.</p>
<p>To force a single page to re-render, delete its file under <code>public/cache/</code>. To clear everything at once, there are two equivalent options:</p>
<ul>
<li><strong>CLI:</strong> <code>php novaconium/bin/clear-cache.php</code> — a standalone script for deploys, cron jobs, or anywhere you'd rather not go through a browser. Prints <code>Cache cleared.</code> and exits.</li>
<li><strong>Web:</strong> <a href="/admin/clear-cache">/admin/clear-cache</a> — a POST form under <code>/admin</code>, covered by the same <a href="/admin/docs/admin-auth">admin login gate</a> as the rest of <code>/admin/*</code> once admin auth is enabled.</li>
</ul>
<p>Both end up calling the same underlying <code>Cache::clear()</code> — see <code>/admin/docs/config</code>'s "For developers: using <code>Cache.php</code> directly" section for how each entry point constructs it. Clearing the cache only deletes the generated static HTML; it doesn't affect <code>App/pages/</code> or any other source. Any project change that should show up on an already-cached page — a new <code>site_name</code>, a new Sass color, a new admin toggle — needs a cache clear before it's visible, since the old <code>index.html</code> would otherwise keep being served as-is.</p>
{% endblock %}