1# Web apps
2
3Default to a light server-rendered stack unless the product is clearly
4frontend-heavy.
5
6## Default light web stack
7
8- `net/http`
9- `html/template` or `text/template` as appropriate
10- `embed.FS` for templates and static assets
11- plain CSS with semantic variables
12- semantic HTML forms and links before client-side JavaScript
13- small Node toolchain only for things like Prettier/template formatting when
14 needed
15
16This is the default for admin panels, dashboards, release trackers, internal
17tools, and server-rendered apps with modest interaction.
18
19## Light web layout
20
21```text
22cmd/<app>/main.go
23internal/config/...
24internal/db/...
25internal/<domain>/...
26internal/web/ or web/
27├── handler.go
28└── static/
29 ├── head.html.tmpl
30 ├── page.html.tmpl
31 ├── styles.css
32 └── reset.css
33```
34
35Use `template.ParseFS` with named shared templates. Keep handlers thin: parse
36input, call domain code, render or redirect.
37
38## CSS and accessibility
39
40- Use semantic HTML and real form controls.
41- Include viewport and colour-scheme metadata.
42- Use CSS custom properties as semantic design tokens. OKLCH is preferred for
43 colour palettes when browser support is acceptable.
44- Support dark mode by overriding semantic tokens under `prefers-color-scheme`.
45- Use spacing, radius, type, and measure scales instead of one-off values.
46- Prefer simple responsive layouts with CSS grid/flex.
47- Use accessible fonts when bundling fonts; include licence metadata when the
48 project is REUSE-compliant.
49- Do not use ARIA to compensate for avoidable non-semantic markup.
50
51## Security
52
53- Treat form/query values as untrusted.
54- Use `bluemonday` when rendering user-provided HTML or Markdown-derived HTML.
55- Keep auth/session logic in a domain package; handlers should not duplicate
56 password or token handling.
57- Prefer `database/sql` with explicit migrations for small SQLite-backed apps.
58
59## Escalate to frontend-heavy only when needed
60
61Escalate to a frontend-heavy stack only when the UI needs rich local state,
62complex component composition, desktop integration, drag/drop, long-running
63event streams, or substantial client-side interaction. For Wails, prefer Svelte
645 + TypeScript + Vite; Tailwind and shadcn-svelte remain explicit project
65choices. If the page can remain a form and a template, keep it light.