Skip to content

Commit 0fb46dc

Browse files
authored
Add glossary page (#142)
* refactor: extract backlink component * feat: first draft of glossary page * feat: add remaining glossary sections * fix: minor fixes * feat: add glossary to navbar * style: harmonize maxwidth * refactor: use new layout and style structure * style: apply optimal line length readabilty https://baymard.com/blog/line-length-readability * style: add a link styles
1 parent 4a469d2 commit 0fb46dc

7 files changed

Lines changed: 299 additions & 27 deletions

File tree

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
3+
---
4+
5+
<a href="/" class="back-link">← All frameworks</a>
6+
7+
<style>
8+
.back-link {
9+
display: inline-block;
10+
margin-bottom: 1.5em;
11+
color: var(--ft-accent);
12+
text-decoration: none;
13+
font-weight: 500;
14+
transition: color 0.2s;
15+
}
16+
17+
.back-link:hover {
18+
color: var(--ft-accent-hover);
19+
text-decoration: underline;
20+
}
21+
</style>

packages/docs/src/components/FrameworkDetail.astro

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
---
22
import type { CollectionEntry } from 'astro:content'
33
import { formatBytesToMB, formatTimeMs } from '../lib/utils'
4+
import '../styles/shared.css'
5+
import BackLink from './BackLink.astro'
46
import DevTimeChart from './DevTimeChart.astro'
57
import MethodologyTag from './MethodologyTag.astro'
6-
import MethodologyNotes from './MethodologyNotes.astro'
7-
import '../styles/shared.css'
88
import PageHeader from './PageHeader.astro'
99
import SSRStatsMethodologyNotes from './SSRStatsMethodologyNotes.astro'
1010
@@ -25,7 +25,7 @@ const measuredDateDisplay = (() => {
2525
---
2626

2727
<div class="detail">
28-
<a href="/" class="back-link">← All frameworks</a>
28+
<BackLink />
2929

3030
<header class="detail-header">
3131
<PageHeader>{devtime.name}</PageHeader>
@@ -193,20 +193,6 @@ const measuredDateDisplay = (() => {
193193
line-height: 1.5;
194194
}
195195

196-
.back-link {
197-
display: inline-block;
198-
margin-bottom: 1.5em;
199-
color: var(--ft-accent);
200-
text-decoration: none;
201-
font-weight: 500;
202-
transition: color 0.2s;
203-
}
204-
205-
.back-link:hover {
206-
color: var(--ft-accent-hover);
207-
text-decoration: underline;
208-
}
209-
210196
.detail-header {
211197
margin-bottom: 2em;
212198
}

packages/docs/src/components/Navbar.astro

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ const pathname = Astro.url.pathname
2020
class={`nav-link${pathname === '/run-time' ? ' nav-link--active' : ''}`}
2121
>Run Time</a
2222
>
23+
<a
24+
href="/glossary"
25+
class={`nav-link${pathname === '/glossary' ? ' nav-link--active' : ''}`}
26+
>Glossary</a
27+
>
2328
<a href="https://e18e.dev" class="nav-link">e18e.dev</a>
2429
<a href="https://e18e.dev/blog" class="nav-link">Blog</a>
2530
</nav>

packages/docs/src/layouts/Layout.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ const { title = 'Framework Tracker' } = Astro.props
6969

7070
.page-content {
7171
width: 100%;
72-
max-width: 1200px;
72+
max-width: 75ch;
7373
}
7474

7575
@media screen and (max-width: 768px) {

packages/docs/src/pages/framework/[slug].astro

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
import { getCollection } from 'astro:content'
3-
import Layout from '../../layouts/Layout.astro'
43
import FrameworkDetail from '../../components/FrameworkDetail.astro'
4+
import Layout from '../../layouts/Layout.astro'
55
import { getFrameworkSlug } from '../../lib/utils'
66
77
export async function getStaticPaths() {
@@ -35,11 +35,3 @@ const { devtime, runtime, baseline } = Astro.props
3535
<FrameworkDetail devtime={devtime} runtime={runtime} baseline={baseline} />
3636
</section>
3737
</Layout>
38-
39-
<style>
40-
.framework-page-section {
41-
width: 100%;
42-
max-width: 900px;
43-
margin: 0 auto;
44-
}
45-
</style>
Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
---
2+
import BackLink from '../components/BackLink.astro'
3+
import PageHeader from '../components/PageHeader.astro'
4+
import Layout from '../layouts/Layout.astro'
5+
---
6+
7+
<Layout title="Glossary — Framework Tracker">
8+
<BackLink />
9+
10+
<header>
11+
<PageHeader>Glossary</PageHeader>
12+
<p>
13+
This site describes the terminology and concepts used in the framework
14+
tracker.
15+
</p>
16+
</header>
17+
18+
<section>
19+
<h2 id="application-architecture">Application architecture</h2>
20+
<p>
21+
<strong>MPA (Multi-Page Application)</strong> and
22+
<strong>SPA (Single-Page Application)</strong>
23+
are the two foundational architectures for web applications. The choice between
24+
them shapes how pages are rendered, how navigation works, and how state is managed.
25+
In practice, many modern frameworks blur the line by supporting hybrid approaches
26+
— for example, combining server-rendered pages with client-side navigation.
27+
</p>
28+
<p>The key aspects that distinguish an application architecture are:</p>
29+
<ul>
30+
<li>
31+
<strong>Navigation model</strong> — Does the browser perform a full page load
32+
for each route (MPA), or does JavaScript intercept navigation and update the
33+
page in-place (SPA)?
34+
</li>
35+
<li>
36+
<strong>Content loading and processing</strong> — Is HTML assembled on the
37+
server and sent ready-to-display (MPA), or is it generated in the browser
38+
by a JavaScript framework consuming raw data fetched from an API (SPA)?
39+
</li>
40+
<li>
41+
<strong>State lifetime</strong> — Is in-memory state reset on every navigation
42+
(MPA), or does it persist across route changes within the same session (SPA)?
43+
</li>
44+
<li>
45+
<strong>JavaScript dependency</strong> — Is JavaScript required for the page
46+
to be meaningful, or is it an optional progressive enhancement on top of server-rendered
47+
HTML?
48+
</li>
49+
<li>
50+
<strong>SEO and initial load</strong> — Is content present in the first HTML
51+
response (MPA), or does meaningful content only appear after JS downloads
52+
and executes (SPA)?
53+
</li>
54+
</ul>
55+
56+
<h3 id="mpa">Multi-Page Application (MPA)</h3>
57+
<p>
58+
In an MPA, each navigation triggers a full browser request and the server
59+
responds with a complete HTML document. HTML is generated on the server
60+
per request, so the browser always receives ready-to-display content.
61+
JavaScript is optional and typically used only for progressive
62+
enhancement. In-memory state is lost on every navigation. Because content
63+
is present in the initial HTML response, MPAs are naturally SEO-friendly.
64+
The server must be capable of rendering and serving a full page for every
65+
route.
66+
</p>
67+
68+
<h3 id="spa">Single-Page Application (SPA)</h3>
69+
<p>
70+
In an SPA, the browser loads a single HTML shell once and all subsequent
71+
navigation is handled client-side by JavaScript, without full page
72+
reloads. HTML is generated in the browser, typically by a JavaScript
73+
framework rendering components on demand. On initial load the browser
74+
receives a minimal document and must download and execute JS before
75+
content appears. Subsequent navigations fetch only data (e.g. via API
76+
calls), keeping the page transition fast. In-memory state persists across
77+
navigation. Because the initial HTML shell contains little content, SPAs
78+
require extra effort (SSR, prerendering) for good SEO. The server only
79+
needs to serve static assets.
80+
</p>
81+
</section>
82+
83+
<section>
84+
<h2 id="rendering-patterns">Rendering Patterns</h2>
85+
<p>
86+
A rendering pattern describes how and when content is generated and
87+
delivered to the client, typically the browser. The rendering process can
88+
happen on the client or on a server, and at different stages of the
89+
application lifecycle.
90+
</p>
91+
<p>
92+
Each pattern has different tradeoffs in terms of performance, SEO, UX,
93+
resource usage, robustness, and complexity. The choice of rendering
94+
pattern can have a significant impact on the overall experience and
95+
maintainability of the application.
96+
</p>
97+
98+
<h3 id="ssg">Static Site Generation (SSG)</h3>
99+
<p>
100+
All pages are pre-built into static HTML files at build time (ahead of
101+
time) by a build tool or framework. The output is a set of ready-to-serve
102+
files — one per route — that can be delivered directly from a CDN with no
103+
server needed at runtime. Because every response is a pre-built file, load
104+
times are fast and infrastructure is simple. Best suited for content that
105+
doesn't change per request.
106+
</p>
107+
108+
<h3 id="ssr">Server-Side Rendering (SSR)</h3>
109+
<p>
110+
HTML is generated on a server for each incoming request (just in time).
111+
This allows dynamic content and per-request logic such as authentication,
112+
personalization, or A/B testing. Unlike SSG, SSR requires a running server
113+
at runtime.
114+
</p>
115+
<p>
116+
The term SSR is often used together with
117+
<a href="#hydration">hydration</a>. However, classic SSR works without
118+
hydration — the server sends functional HTML that relies on native browser
119+
capabilities (links, forms) rather than a JavaScript framework. This is
120+
the traditional web model where JavaScript is only used for progressive
121+
enhancement, not for rendering core content.
122+
</p>
123+
124+
<h3 id="csr">Client-Side Rendering (CSR)</h3>
125+
<p>
126+
Instead of receiving ready-made HTML from a server, the browser receives a
127+
minimal HTML skeleton and a JavaScript bundle. The JS framework then
128+
fetches data, builds the DOM, and controls all rendering on the client
129+
side.
130+
</p>
131+
<p>
132+
This enables highly dynamic interfaces where the page can update without
133+
full reloads. The tradeoff is a slower initial load — nothing meaningful
134+
appears until the JavaScript has downloaded and executed — and weaker SEO
135+
by default, since the initial HTML response contains little content.
136+
</p>
137+
138+
<h3 id="hydration">Hydration</h3>
139+
<p>
140+
Hydration is the process of making server-rendered HTML interactive on the
141+
client. After the browser receives the static HTML produced by
142+
<a href="#ssr">SSR</a>, a JavaScript framework re-attaches event handlers,
143+
restores component state, and wires up reactivity — turning an inert
144+
document into a fully interactive application. During hydration the
145+
framework typically re-executes the component tree against the existing
146+
DOM rather than replacing it.
147+
</p>
148+
<p>
149+
What happens after hydration depends on the
150+
<a href="#application-architecture">application architecture</a>. For a
151+
<a href="#spa">SPA</a>, once hydration completes the JavaScript framework
152+
takes over routing and rendering — subsequent navigations are handled
153+
client-side. In <a href="#mpa">MPA</a> setups, hydration only activates specific
154+
components without changing the navigation model - page transitions still trigger
155+
full server requests.
156+
</p>
157+
<p>
158+
The tradeoff is that hydration requires downloading and executing the same
159+
component code that was already run on the server, which can delay
160+
interactivity on slow devices or large pages. Techniques like
161+
<a href="#partial-hydration">partial hydration</a>,
162+
<a href="#progressive-hydration">progressive hydration</a>, and
163+
<a href="#islands">islands architecture</a> aim to reduce this cost.
164+
</p>
165+
166+
<h3 id="partial-hydration">Partial Hydration</h3>
167+
<p>
168+
Partial hydration is a technique where only specific components on a page
169+
are hydrated on the client, rather than hydrating the entire component
170+
tree. Static parts of the page remain as plain HTML and never load any
171+
JavaScript, while interactive components are selectively hydrated. This
172+
reduces the amount of JavaScript the browser needs to download, parse, and
173+
execute.
174+
</p>
175+
176+
<h3 id="progressive-hydration">Progressive Hydration</h3>
177+
<p>
178+
Progressive hydration defers the hydration of individual components until
179+
they are actually needed, rather than hydrating everything at once on page
180+
load. Components can be hydrated based on triggers such as the component
181+
scrolling into the viewport, the browser becoming idle, or the user
182+
interacting with the component for the first time. This spreads the cost
183+
of <a href="#hydration">hydration</a> over time.
184+
</p>
185+
186+
<h3 id="islands">Islands Architecture</h3>
187+
<p>
188+
Islands architecture is a pattern where interactive UI components — called
189+
"islands" — are hydrated independently within an otherwise static HTML
190+
page. The static content is rendered at build time or on the server with
191+
zero JavaScript, and only the islands ship client-side code. Each island
192+
hydrates on its own, without depending on a top-level application shell.
193+
</p>
194+
195+
<h3 id="isr">Incremental Static Regeneration (ISR)</h3>
196+
<p>
197+
ISR is a hybrid of <a href="#ssg">SSG</a> and <a href="#ssr">SSR</a>
198+
where statically generated pages are regenerated in the background after a configured
199+
time interval or on-demand trigger, without requiring a full site rebuild. When
200+
a request arrives for a stale page, the cached version is served immediately
201+
while a fresh version is generated in the background for subsequent requests.
202+
</p>
203+
204+
<h3 id="ppr">Partial Prerendering (PPR)</h3>
205+
<p>
206+
Partial prerendering splits a single route into a static shell that is
207+
served instantly and dynamic holes that are streamed in at request time.
208+
The static parts of the page — any content known at build time — are
209+
prerendered and cached, while personalized or data-dependent sections are
210+
rendered on-demand and streamed into the page via Suspense boundaries.
211+
</p>
212+
213+
<h3 id="streaming">Streaming</h3>
214+
<p>
215+
Streaming is a rendering approach where server-rendered HTML is sent to
216+
the browser in chunks as each part becomes ready, rather than waiting for
217+
the entire page to finish rendering. The browser can begin parsing and
218+
displaying content as soon as the first bytes arrive, improving
219+
time-to-first-byte and perceived performance.
220+
</p>
221+
222+
<h3 id="rsc">Server Components (RSC)</h3>
223+
<p>
224+
Server Components are components that execute exclusively on the server.
225+
Unlike traditional <a href="#ssr">SSR</a>, where component code is sent to
226+
the client for <a href="#hydration">hydration</a>, Server Components send
227+
only their rendered output — never their source code — to the client. They
228+
can directly access server-side resources such as databases and file
229+
systems without exposing those details to the browser.
230+
</p>
231+
232+
<h3 id="esr">Edge-Side Rendering (ESR)</h3>
233+
<p>
234+
Edge-side rendering moves the rendering step from a central origin server
235+
to edge servers distributed geographically close to the user. Instead of
236+
every request traveling to a single data center, the nearest edge node
237+
renders the HTML, reducing latency and improving time-to-first-byte.
238+
</p>
239+
</section>
240+
</Layout>

packages/docs/src/styles/shared.css

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,31 @@ h3 {
4747
font-size: 18px;
4848
}
4949
}
50+
51+
/* ── Section & paragraphs ─────────────────────────────────────── */
52+
53+
section {
54+
margin-top: 2em;
55+
}
56+
57+
p,
58+
ul {
59+
font-size: 16px;
60+
color: var(--ft-muted);
61+
line-height: 1.6;
62+
margin-bottom: 1em;
63+
}
64+
65+
a[href^='#'] {
66+
color: var(--ft-accent);
67+
text-decoration: none;
68+
border-bottom: 1px solid transparent;
69+
transition:
70+
color 0.2s ease,
71+
border-color 0.2s ease;
72+
}
73+
a[href^='#']:hover,
74+
a[href^='#']:focus-visible {
75+
color: var(--ft-accent);
76+
border-bottom-color: var(--ft-accent);
77+
}

0 commit comments

Comments
 (0)