Files
gerbeur/index.html
2026-11-08 21:22:53 +00:00

215 lines
11 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<title>gerbeur documentation</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="doc-current-file" content="">
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="page.css">
<link id="ddocResetStylesheet" rel="stylesheet" href="reset.css"><link href="comrak.css" rel="stylesheet" /><link href="prism.css" rel="stylesheet" /><script src="prism.js"></script><script src="script.js" defer></script>
<script src="darkmode_toggle.js"></script><script src="search_index.js" defer></script>
<script src="fuse.js" defer></script>
<script src="search.js" defer></script></head>
<body>
<div class="ddoc">
<div><nav id="topnav">
<div class="h-full">
<div class="flex items-center"><ul class="breadcrumbs">
<li>
<a href="" class="contextLink">gerbeur</a>
</li></ul>
</div>
<div class="flex items-center gap-2">
<button id="theme-toggle" type="button" aria-label="Toggle dark mode" style="display: none;"><svg
xmlns="http://www.w3.org/2000/svg"
width="14"
height="14"
viewBox="0 0 24 24"
fill="currentColor"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M12 1.992a10 10 0 1 0 9.236 13.838c.341 -.82 -.476 -1.644 -1.298 -1.31a6.5 6.5 0 0 1 -6.864 -10.787l.077 -.08c.551 -.63 .113 -1.653 -.758 -1.653h-.266l-.068 -.006l-.06 -.002z"
/>
</svg>
<svg
xmlns="http://www.w3.org/2000/svg"
width="14"
height="14"
viewBox="0 0 24 24"
fill="currentColor"
class="hidden"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M12 19a1 1 0 0 1 .993 .883l.007 .117v1a1 1 0 0 1 -1.993 .117l-.007 -.117v-1a1 1 0 0 1 1 -1z"
/>
<path
d="M18.313 16.91l.094 .083l.7 .7a1 1 0 0 1 -1.32 1.497l-.094 -.083l-.7 -.7a1 1 0 0 1 1.218 -1.567l.102 .07z"
/>
<path
d="M7.007 16.993a1 1 0 0 1 .083 1.32l-.083 .094l-.7 .7a1 1 0 0 1 -1.497 -1.32l.083 -.094l.7 -.7a1 1 0 0 1 1.414 0z"
/>
<path
d="M4 11a1 1 0 0 1 .117 1.993l-.117 .007h-1a1 1 0 0 1 -.117 -1.993l.117 -.007h1z"
/>
<path
d="M21 11a1 1 0 0 1 .117 1.993l-.117 .007h-1a1 1 0 0 1 -.117 -1.993l.117 -.007h1z"
/>
<path
d="M6.213 4.81l.094 .083l.7 .7a1 1 0 0 1 -1.32 1.497l-.094 -.083l-.7 -.7a1 1 0 0 1 1.217 -1.567l.102 .07z"
/>
<path
d="M19.107 4.893a1 1 0 0 1 .083 1.32l-.083 .094l-.7 .7a1 1 0 0 1 -1.497 -1.32l.083 -.094l.7 -.7a1 1 0 0 1 1.414 0z"
/>
<path
d="M12 2a1 1 0 0 1 .993 .883l.007 .117v1a1 1 0 0 1 -1.993 .117l-.007 -.117v-1a1 1 0 0 1 1 -1z"
/>
<path
d="M12 7a5 5 0 1 1 -4.995 5.217l-.005 -.217l.005 -.217a5 5 0 0 1 4.995 -4.783z"
/>
</svg>
</button>
<input
type="text"
id="searchbar"
style="display: none;"
class="py-2 px-2.5 mx-1 rounded text-sm border border-gray-300 bg-transparent dark:bg-gray-800 dark:border-gray-700"
/>
</div>
</div>
</nav>
<div id="searchResults"></div><div id="content">
<main><section>
<div class="space-y-2 flex-1"><div class="space-y-7" id="module_doc"><div class="markdown"><p>Documents gerbeur, a small invite-only social platform for sharing links and
files. The repository holds three parts: the backend in <code>api/</code>, the
frontend in <code>src/</code>, and in <code>shared/</code> whatever crosses the wire between them.
<a href="./all_symbols.html">Every module</a> is listed by path, so the list groups
them by part and layer.</p>
<h2 id="backend,-in-api/">
Backend, in <code>api/</code></h2>
<p>An Oak server over SQLite answers the API and the WebSocket, and serves the
built frontend. <code>api/main.ts</code> builds the application and listens. A request
goes to a route, which parses it, calls services and answers. The services
hold the logic and every SQL query, read rows through the model, and reach
other sites only through <code>remote/</code>. Each folder holds one kind of module,
and each file is named after its domain.</p>
<ul>
<li><code>routes/</code> holds the HTTP API, one router per resource. Each router's page
lists its endpoints, with their method and path, who may call them, and
what they do; <code>API.md</code> at the root sums them up, with the rule they all
follow.</li>
<li><code>middleware/</code> holds what runs around the routes, which is auth, errors and
the Open Graph tags.</li>
<li><code>services/</code> holds the logic and every SQL query, one module per domain.</li>
<li><code>model/</code> holds each table's row type, guard and mappers.</li>
<li><code>validators/</code> holds the guards of the request bodies.</li>
<li><code>remote/</code> is the only place that fetches from other sites, and its
<code>providers/</code> build the previews of each kind of site.</li>
<li><code>mail/</code> renders each email, one template per email on a shared layout
that takes every site style, its colors and fonts read from the themes'
stylesheets, and <code>services/email-service.ts</code> sends them.</li>
<li><code>lib/</code> holds the helpers that belong to no layer.</li>
<li><code>db/</code> opens, creates and migrates the database, and cleans it up at
startup. <code>db/migrations/</code> are applied in order, each once.</li>
<li><code>config.ts</code> reads the settings from the environment, and <code>scripts/</code> holds
the icon generator.</li>
</ul>
<h2 id="shared,-in-shared/">
Shared, in <code>shared/</code></h2>
<p>The types and constants both halves use sit here, one module per domain.
They are the API envelope, each domain's types and request bodies, the
socket protocol, the validation limits, the role permissions, and the page
paths and slugs (<code>paths.ts</code>, <code>slug.ts</code>) the client links with and the
server matches. <code>shared/</code> imports nothing from either half. The server
sends <code>Date</code>s, and the client reads the same types through <code>Wire&lt;T&gt;</code>, where
every <code>Date</code> is an ISO string.</p>
<p>Beside it, <code>locales/</code> holds one Lingui catalogue per language for the whole
app: the interface's messages, and the emails' that <code>api/mail/i18n.ts</code>
loads compiled. The interface writes its English in place (<code>t</code>, <code>Trans</code>)
and Lingui keys the message by it. A message with a named id, which every
email's is, along with the labels the interface shares with them, has its
English in <code>locales/en.po</code> alone and the code names only the id; the build
fails when a language lacks one.</p>
<h2 id="frontend,-in-src/">
Frontend, in <code>src/</code></h2>
<p>The React app is built with Vite and translated with Lingui. <code>main.tsx</code>
mounts it, <code>App.tsx</code> holds the providers and the route table, and <code>i18n.ts</code>
sets the language. A page reads the API and the socket through contexts and
hooks, and draws with components, while utils hold what isn't React at all.</p>
<ul>
<li><code>pages/</code> holds one component per route, each naming its route, and the two
guards that keep routes to signed-in or signed-out visitors.</li>
<li><code>config/</code> holds the settings read at startup.</li>
<li><code>contexts/</code> holds, for each domain, a <code>FooContext</code> with its state and the
<code>FooProvider</code> that fills it.</li>
<li><code>hooks/</code> holds every hook, and <code>components/</code> only components.</li>
<li><code>utils/</code> holds every module that isn't React.</li>
</ul>
<p>Every layer but <code>pages/</code> and <code>config/</code> is split into the same domains (auth,
category, chat, comment, dump, editor, feed, form, layout, player, playlist,
profile, social, theme, ws, and shared for what belongs to no one domain), so
the chat lives in <code>components/chat/</code>, <code>contexts/chat/</code>, <code>hooks/chat/</code> and
<code>utils/chat/</code>.</p>
</div></div>
</div>
</section>
</main><div class="toc">
<div><nav class="topSymbols">
<h3>Symbols</h3>
<ul><li>
<a href=".&#x2F;api&#x2F;middleware&#x2F;auth.ts&#x2F;~&#x2F;AuthState.html" title="AuthState"><div class="docNodeKindIcon"><div class="text-Interface bg-Interface/15 dark:text-InterfaceDark dark:bg-InterfaceDark/15" title="Interface">I</div></div>
<span class="hover:bg-Interface/15 hover:bg-InterfaceDark/15">
AuthState
</span>
</a>
</li><li>
<a href=".&#x2F;api&#x2F;middleware&#x2F;auth.ts&#x2F;~&#x2F;AuthContext.html" title="AuthContext"><div class="docNodeKindIcon"><div class="text-TypeAlias bg-TypeAlias/15 dark:text-TypeAliasDark dark:bg-TypeAliasDark/15" title="Type Alias">T</div></div>
<span class="hover:bg-TypeAlias/15 hover:bg-TypeAliasDark/15">
AuthContext
</span>
</a>
</li><li>
<a href=".&#x2F;api&#x2F;middleware&#x2F;auth.ts&#x2F;~&#x2F;authMiddleware.html" title="authMiddleware"><div class="docNodeKindIcon"><div class="text-Function bg-Function/15 dark:text-FunctionDark dark:bg-FunctionDark/15" title="Function">f</div></div>
<span class="hover:bg-Function/15 hover:bg-FunctionDark/15">
authMiddleware
</span>
</a>
</li><li>
<a href=".&#x2F;api&#x2F;middleware&#x2F;auth.ts&#x2F;~&#x2F;requirePermission.html" title="requirePermission"><div class="docNodeKindIcon"><div class="text-Function bg-Function/15 dark:text-FunctionDark dark:bg-FunctionDark/15" title="Function">f</div></div>
<span class="hover:bg-Function/15 hover:bg-FunctionDark/15">
requirePermission
</span>
</a>
</li><li>
<a href=".&#x2F;api&#x2F;middleware&#x2F;error.ts&#x2F;~&#x2F;errorMiddleware.html" title="errorMiddleware"><div class="docNodeKindIcon"><div class="text-Function bg-Function/15 dark:text-FunctionDark dark:bg-FunctionDark/15" title="Function">f</div></div>
<span class="hover:bg-Function/15 hover:bg-FunctionDark/15">
errorMiddleware
</span>
</a>
</li></ul><a class="flex items-center gap-0.5" href=".&#x2F;all_symbols.html">
<span class="leading-none">view all 1307 symbols</span><svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M5.76748 11.8159C5.5378 11.577 5.54525 11.1972 5.78411 10.9675L8.93431 8L5.78411 5.0325C5.54525 4.80282 5.5378 4.423 5.76748 4.18413C5.99715 3.94527 6.37698 3.93782 6.61584 4.1675L10.2158 7.5675C10.3335 7.68062 10.4 7.83679 10.4 8C10.4 8.16321 10.3335 8.31938 10.2158 8.4325L6.61584 11.8325C6.37698 12.0622 5.99715 12.0547 5.76748 11.8159Z"
fill="currentColor"
/>
</svg>
</a></nav><nav class="documentNavigation">
<h3>Document Navigation</h3><ul><li><a href="#backend,-in-api/" title="Backend, in api/">Backend, in api/</a></li><li><a href="#shared,-in-shared/" title="Shared, in shared/">Shared, in shared/</a></li><li><a href="#frontend,-in-src/" title="Frontend, in src/">Frontend, in src/</a></li></ul></nav></div>
</div></div>
</div>
</div>
</body>
</html>