# Web apps

Default to a light server-rendered stack unless the product is clearly
frontend-heavy.

## Default light web stack

- `net/http`
- `html/template` or `text/template` as appropriate
- `embed.FS` for templates and static assets
- plain CSS with semantic variables
- semantic HTML forms and links before client-side JavaScript
- small Node toolchain only for things like Prettier/template formatting when
  needed

This is the default for admin panels, dashboards, release trackers, internal
tools, and server-rendered apps with modest interaction.

## Light web layout

```text
cmd/<app>/main.go
internal/config/...
internal/db/...
internal/<domain>/...
internal/web/ or web/
├── handler.go
└── static/
    ├── head.html.tmpl
    ├── page.html.tmpl
    ├── styles.css
    └── reset.css
```

Use `template.ParseFS` with named shared templates. Keep handlers thin: parse
input, call domain code, render or redirect.

## CSS and accessibility

- Use semantic HTML and real form controls.
- Include viewport and colour-scheme metadata.
- Use CSS custom properties as semantic design tokens. OKLCH is preferred for
  colour palettes when browser support is acceptable.
- Support dark mode by overriding semantic tokens under `prefers-color-scheme`.
- Use spacing, radius, type, and measure scales instead of one-off values.
- Prefer simple responsive layouts with CSS grid/flex.
- Use accessible fonts when bundling fonts; include licence metadata when the
  project is REUSE-compliant.
- Do not use ARIA to compensate for avoidable non-semantic markup.

## Security

- Treat form/query values as untrusted.
- Use `bluemonday` when rendering user-provided HTML or Markdown-derived HTML.
- Keep auth/session logic in a domain package; handlers should not duplicate
  password or token handling.
- Prefer `database/sql` with explicit migrations for small SQLite-backed apps.

## Escalate to frontend-heavy only when needed

Escalate to a frontend-heavy stack only when the UI needs rich local state,
complex component composition, desktop integration, drag/drop, long-running
event streams, or substantial client-side interaction. For Wails, prefer Svelte
5 + TypeScript + Vite; Tailwind and shadcn-svelte remain explicit project
choices. If the page can remain a form and a template, keep it light.
