Sidecar-less page bundles whose directory ends in a MediaType extension
(.txt/.css/.xml/.json/.js) now render raw (no HTML layout, autoescape off),
are served with that extension's Content-Type, and cache as a flat file
(public/cache/<path>) so Apache serves them directly via a new .htaccess
rule. They're excluded from the content index.
CSS becomes one of these: novaconium/pages/css/main.css/ holds index.twig
({{ sass('main.sass') }}), main.sass, and _colors.sass. App\SassExtension's
sass() Twig function resolves the entry file through the overlay and shells
out to Dart Sass on a cache miss; Lib\SassCompiler wraps the CLI. This
drops the committed App/css/main.css build artifact and the public/css
bind mount. Override styling by copying the whole bundle to App/pages/.
Also ship robots.txt and humans.txt as framework bundles, and drop the
php -S dev router (public/router.php) - Docker/Apache only now.
New: novaconium/src/MediaType.php, SassExtension.php, lib/SassCompiler.php.
Moved: novaconium/sass/ -> novaconium/pages/css/main.css/ (+ App/sass merged).
Docs: AGENTS.md, new /admin/docs/text-pages, and styling/caching/docker/
design-notes/getting-started/project-layout/config docs updated.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Q9cAXC9xcXYnmP7qjsnw7
53 lines
5.1 KiB
Twig
53 lines
5.1 KiB
Twig
{% extends 'admin/docs/_layout/layout.twig' %}
|
|
|
|
{% block title %}Project layout{% endblock %}
|
|
|
|
{% block description %}A map of the whole project tree.{% endblock %}
|
|
|
|
{% block robots %}noindex, nofollow{% endblock %}
|
|
|
|
{% block docs_content %}
|
|
<h1>Project layout</h1>
|
|
|
|
<pre><code>public/ Apache document root
|
|
index.php thin front controller — just requires novaconium/bootstrap.php
|
|
.htaccess cache short-circuit, canonical redirects, rewrite to index.php
|
|
cache/ generated static output — HTML pages plus css/main.css, robots.txt etc. (safe to delete anytime)
|
|
App/ your project — the only directory you're expected to edit
|
|
pages/ your routes — directory tree = URL tree, checked before novaconium/pages/ so you can add or override pages/layouts
|
|
lib/ your PHP classes (Lib\), checked before novaconium/lib/ so you can override defaults
|
|
config.php your config overrides — ships as an empty, commented placeholder; shallow-merged over novaconium/config.php
|
|
novaconium/ the framework itself — boilerplate, not meant to be edited per-project
|
|
pages/ default pages: _layout/layout.twig (root layout), 404/index.twig, and the css/main.css/ + robots.txt/ + humans.txt/ bundles (all overridable from App/pages/)
|
|
css/main.css/ the site stylesheet as a page bundle — index.twig + main.sass + _colors.sass, compiled on demand (see Styling / Typed text pages)
|
|
lib/ default Lib\ classes (used when App/lib/ doesn't override them)
|
|
src/ Router, Route, Renderer, Response, Cache, Overlay (the App/-over-novaconium/ lookup used for both pages and lib)
|
|
vendor/twig/ vendored Twig source (no Composer)
|
|
bin/
|
|
clear-cache.php standalone CLI entry point — `php novaconium/bin/clear-cache.php`
|
|
create-static-page.php scaffolds a new page from the SEO starter template — `php novaconium/bin/create-static-page.php <path>`
|
|
autoload.php manual PSR-4 autoloader
|
|
config.php paths and settings
|
|
bootstrap.php wires everything together for each request</code></pre>
|
|
|
|
<h2>How a request flows through these files</h2>
|
|
|
|
<p>There's no framework "kernel" class — just a plain chain of <code>require</code>s, each handing off to the next, deliberately kept flat enough to read top-to-bottom in one sitting:</p>
|
|
|
|
<ol>
|
|
<li><strong><code>public/.htaccess</code></strong> runs first, before PHP does anything. If <code>public/cache/<path>/index.html</code> exists for the requested URL, Apache serves that file directly and nothing below this line ever executes — see <a href="/admin/docs/caching">Static caching</a>. Otherwise it strips a trailing slash (301 redirect) and rewrites everything else to <code>public/index.php</code>.</li>
|
|
<li><strong><code>public/index.php</code></strong> is intentionally one line: <code>require __DIR__ . '/../novaconium/bootstrap.php';</code>.</li>
|
|
<li><strong><code>novaconium/bootstrap.php</code></strong> is where the real wiring happens, top-to-bottom:
|
|
<ol>
|
|
<li>Requires <strong><code>novaconium/autoload.php</code></strong>, registering the <code>Twig\</code>/<code>App\</code>/<code>Lib\</code> class autoloader (see <a href="/admin/docs/libraries">Libraries</a>) before anything below tries to instantiate a class.</li>
|
|
<li>Requires <strong><code>novaconium/config.php</code></strong>, then shallow-merges <strong><code>App/config.php</code></strong> over it if that file exists — see <a href="/admin/docs/config">Configuration</a>.</li>
|
|
<li>Constructs a <strong><code>Router</code></strong> (<code>novaconium/src/Router.php</code>) and calls <code>resolve()</code> to turn the URL into a <strong><code>Route</code></strong> (<code>novaconium/src/Route.php</code>) — see <a href="/admin/docs/routing">Routing</a>.</li>
|
|
<li>If the resolved route is under <code>admin</code>/<code>admin/*</code> (except <code>admin/login</code> itself), calls <strong><code>AdminAuth::requireLogin()</code></strong> (<code>novaconium/src/AdminAuth.php</code>), reading that same <code>Route</code>.</li>
|
|
<li>Constructs a <strong><code>Cache</code></strong> (<code>novaconium/src/Cache.php</code>) and a <strong><code>Renderer</code></strong> (<code>novaconium/src/Renderer.php</code>), then calls <code>renderNotFound()</code> or <code>render($route, ...)</code> depending on <code>$route->found</code> — see <a href="/admin/docs/sidecars">Sidecars</a> for what happens inside <code>Renderer</code> itself (running the matched directory's <code>index.php</code>, if any; resolving the nearest layout; rendering <code>index.twig</code>; writing the static cache for sidecar-less pages).</li>
|
|
</ol>
|
|
</li>
|
|
</ol>
|
|
|
|
<p>Every step after step 1 is plain PHP you can read start to finish in <code>novaconium/bootstrap.php</code> itself — the comments there walk through the same five sub-steps in more detail than this page does.</p>
|
|
{% endblock %}
|