Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions config/autoload/local.php.dist
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,14 @@ return [
// and is routed in Light\App\RoutesDelegator. Re-adding it here registers the path twice.
'routes' => [
'page' => [
'contact' => 'contact',
'api' => 'api',
'admin' => 'admin',
'queue' => 'queue',
'light' => 'light',
'frontend' => 'frontend',
'dotboost' => 'dotboost',
'contact' => 'contact',
'api' => 'api',
'admin' => 'admin',
'queue' => 'queue',
'light' => 'light',
'frontend' => 'frontend',
'dotboost' => 'dotboost',
'architecture' => 'architecture',
],
],
'twig' => [
Expand Down
2 changes: 1 addition & 1 deletion public/css/app.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/js/app.js

Large diffs are not rendered by default.

73 changes: 73 additions & 0 deletions src/App/assets/scss/components/_custom.scss
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,79 @@ html[data-theme="light"] .theme-toggle {
}
}

/* ============================================================
Hero artwork

Per-page line-art figure stacked above the pipeline box. The SVG is
inlined in each template so it inherits the theme through currentColor
and the shared tokens - an <img>-loaded SVG cannot follow the
data-theme toggle.
============================================================ */

.hero-visual {
display: flex;
flex-direction: column;
gap: 18px;
}

.hero-art {
position: relative;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 16px;
padding: 22px 24px 18px;
margin: 0;
color: var(--text-dim);

figcaption {
font-family: var(--mono);
font-size: 11px;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--text-dim);
margin-bottom: 14px;
}

svg {
display: block;
width: 100%;
height: auto;
overflow: visible;
stroke: currentColor;
fill: none;
stroke-width: 1.25;
stroke-linecap: round;
stroke-linejoin: round;
}

.art-accent {
stroke: var(--teal);
}

.art-hot {
stroke: var(--brand-red);
}

.art-fill {
fill: var(--teal-dim);
stroke: var(--teal);
}

.art-dot {
fill: var(--teal);
stroke: none;
}

.art-dash {
stroke-dasharray: 4 4;
opacity: 0.75;
}

.art-faint {
opacity: 0.45;
}
}

/* ============================================================
Pipeline
============================================================ */
Expand Down
45 changes: 35 additions & 10 deletions src/Page/templates/page/admin.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,41 @@
</div>
</div>

<div class="pipeline">
<div class="pipeline-label"><span>Request lifecycle</span></div>
<div class="pipeline-track">
<div class="pl-packet" aria-hidden="true"></div>
<div class="pl-step"><span class="name">Session</span><span class="tag">dot-session</span></div>
<div class="pl-step"><span class="name">Router</span><span class="tag">dot-router</span></div>
<div class="pl-step"><span class="name">Authentication</span><span class="tag">laminas-authentication</span></div>
<div class="pl-step"><span class="name">RBAC guard</span><span class="tag">dot-rbac-guard</span></div>
<div class="pl-step"><span class="name">Your handler</span><span class="tag">PSR-15</span></div>
<div class="pl-step"><span class="name">Response</span><span class="tag">Twig template</span></div>
<div class="hero-visual">
<figure class="hero-art">
<figcaption>Guarded record table</figcaption>
<svg viewBox="0 0 360 170" role="img" aria-label="A record table where one row is gated by a role check">
<rect x="14" y="24" width="332" height="122" rx="10"/>
<rect class="art-fill" x="14" y="90" width="332" height="28"/>
<line x1="14" y1="56" x2="346" y2="56"/>
<line class="art-faint" x1="14" y1="90" x2="346" y2="90"/>
<line class="art-faint" x1="14" y1="118" x2="346" y2="118"/>
<line class="art-faint" x1="104" y1="24" x2="104" y2="146"/>
<line class="art-faint" x1="206" y1="24" x2="206" y2="146"/>
<line class="art-faint" x1="286" y1="24" x2="286" y2="146"/>
<line class="art-faint" x1="30" y1="41" x2="76" y2="41"/>
<line class="art-faint" x1="120" y1="41" x2="176" y2="41"/>
<line class="art-faint" x1="222" y1="41" x2="262" y2="41"/>
<line class="art-faint" x1="302" y1="41" x2="330" y2="41"/>
<path class="art-accent" d="M46 96 l10 3.4 v7.6 c0 6 -4 10.4 -10 12.4 c-6 -2 -10 -6.4 -10 -12.4 v-7.6 z"/>
<line class="art-accent" x1="120" y1="104" x2="176" y2="104"/>
<line class="art-accent" x1="222" y1="104" x2="262" y2="104"/>
<line class="art-faint" x1="30" y1="132" x2="76" y2="132"/>
<line class="art-faint" x1="120" y1="132" x2="176" y2="132"/>
</svg>
</figure>

<div class="pipeline">
<div class="pipeline-label"><span>Request lifecycle</span></div>
<div class="pipeline-track">
<div class="pl-packet" aria-hidden="true"></div>
<div class="pl-step"><span class="name">Session</span><span class="tag">dot-session</span></div>
<div class="pl-step"><span class="name">Router</span><span class="tag">dot-router</span></div>
<div class="pl-step"><span class="name">Authentication</span><span class="tag">laminas-authentication</span></div>
<div class="pl-step"><span class="name">RBAC guard</span><span class="tag">dot-rbac-guard</span></div>
<div class="pl-step"><span class="name">Your handler</span><span class="tag">PSR-15</span></div>
<div class="pl-step"><span class="name">Response</span><span class="tag">Twig template</span></div>
</div>
</div>
</div>
</div>
Expand Down
70 changes: 57 additions & 13 deletions src/Page/templates/page/api.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,40 @@
</div>
</div>

<div class="pipeline">
<div class="pipeline-label"><span>Request lifecycle</span></div>
<div class="pipeline-track">
<div class="pl-packet" aria-hidden="true"></div>
<div class="pl-step"><span class="name">CORS</span><span class="tag">mezzio-cors</span></div>
<div class="pl-step"><span class="name">Router</span><span class="tag">FastRoute</span></div>
<div class="pl-step"><span class="name">Authentication</span><span class="tag">OAuth 2.0</span></div>
<div class="pl-step"><span class="name">RBAC guard</span><span class="tag">per route name</span></div>
<div class="pl-step"><span class="name">Your handler</span><span class="tag">PSR-15</span></div>
<div class="pl-step"><span class="name">Response</span><span class="tag">HAL / problem+json</span></div>
<div class="hero-visual">
<figure class="hero-art">
<figcaption>One resource, its links</figcaption>
<svg viewBox="0 0 360 170" role="img" aria-label="A resource envelope whose links branch out to embedded resources">
<rect x="14" y="28" width="164" height="114" rx="10"/>
<line class="art-faint" x1="14" y1="62" x2="178" y2="62"/>
<line x1="32" y1="45" x2="86" y2="45"/>
<rect class="art-fill" x="32" y="80" width="9" height="9" rx="2"/>
<line class="art-faint" x1="50" y1="84.5" x2="120" y2="84.5"/>
<rect class="art-fill" x="32" y="108" width="9" height="9" rx="2"/>
<line class="art-faint" x1="50" y1="112.5" x2="146" y2="112.5"/>
<path class="art-accent" d="M178 84 C 224 84 232 42 286 42"/>
<path class="art-accent" d="M178 90 C 230 90 240 88 286 88"/>
<path class="art-accent" d="M178 112 C 226 112 236 134 286 134"/>
<circle class="art-accent" cx="298" cy="42" r="11"/>
<circle class="art-accent" cx="298" cy="88" r="11"/>
<circle class="art-accent" cx="298" cy="134" r="11"/>
</svg>
</figure>

<div class="pipeline">
<div class="pipeline-label">
<span>Request lifecycle</span>
<span><a href="{{ url('page::architecture') }}">All 19 stages →</a></span>
</div>
<div class="pipeline-track">
<div class="pl-packet" aria-hidden="true"></div>
<div class="pl-step"><span class="name">CORS</span><span class="tag">mezzio-cors</span></div>
<div class="pl-step"><span class="name">Router</span><span class="tag">FastRoute</span></div>
<div class="pl-step"><span class="name">Authentication</span><span class="tag">OAuth 2.0</span></div>
<div class="pl-step"><span class="name">RBAC guard</span><span class="tag">per route name</span></div>
<div class="pl-step"><span class="name">Your handler</span><span class="tag">PSR-15</span></div>
<div class="pl-step"><span class="name">Response</span><span class="tag">HAL / problem+json</span></div>
</div>
</div>
</div>
</div>
Expand Down Expand Up @@ -227,9 +251,22 @@
</div>
<p class="lede">Scheduled work that refuses to trample itself.</p>
<p class="desc">
Console commands are registered through <code>dot-cli</code> on top of Symfony Console. The file
locker, enabled by default, writes a lock file per command so a second instance cannot start
while the previous run is still going - the safeguard cron jobs usually lack.
Console commands are registered through <code>dot-cli</code> on top of Symfony Console, and
<code>php ./bin/cli.php route:list</code> prints every endpoint the application exposes. The
file locker, enabled by default, writes a lock file per command so a second instance cannot
start while the previous run is still going - the safeguard cron jobs usually lack.
</p>
</div>

<div class="card" style="--accent:var(--brand-red)">
<div class="card-top">
<div><span class="kicker">Operations · Mail</span><h3>Transactional email</h3></div>
</div>
<p class="lede">Account mail that works before you configure anything.</p>
<p class="desc">
<code>dot-mail</code> wraps Symfony Mailer with templated messages, so account activation and
password reset send out of a fresh install. It joins the request flow only where it is needed -
the rest of the pipeline is unchanged whether a route sends mail or not.
</p>
</div>

Expand Down Expand Up @@ -305,12 +342,19 @@
API versions. The same codebase evolves gradually and clients are given notice, instead of every
change forking into another branch you have to keep alive.
</p>
<p class="lede">
The mechanism is <code>DeprecationMiddleware</code>: mark a handler with the
<code>#[ResourceDeprecation]</code> attribute and the response carries <code>sunset</code> and
<code>link</code> headers, so a client learns an endpoint is retiring from the endpoint itself
rather than from a changelog it never read.
</p>
<p class="lede">
Full versioning stays reserved for major, format-level changes - the cases where it genuinely earns
its maintenance cost. The two approaches are not mutually exclusive.
</p>
<div class="hero-ctas">
<a class="btn btn-ghost" href="https://docs.dotkernel.org/api-documentation/v6/tutorials/api-evolution/" target="_blank" rel="noopener">API evolution guide</a>
<a class="btn btn-ghost" href="{{ url('page::architecture') }}">Where it sits in the pipeline</a>
</div>
</div>
<div class="callout">
Expand Down
Loading