# {{projectName}} / {{appName}}

Voltro web app scaffold (template: **frontend-dashboard**) — an
authenticated dashboard shell with a public marketing area.

## Boot

```bash
pnpm install
pnpm --filter @{{projectName}}/{{appName}} dev
# → http://localhost:{{port}}
```

Open `/dashboard` while signed out → you're redirected to `/login`. Click
**Continue as Demo User** → the gate lets you in.

## What this shows

- **Route groups** — `src/pages/(marketing)/` is a *silent* route group:
  the parens organise files + scope a layout WITHOUT adding a URL segment,
  so its pages are `/` and `/login`. The `/dashboard` area is a real dir
  (real prefix) by contrast.
- **A nested layout loader as an auth gate** — `dashboard/layout.tsx`
  exports a `loader` that runs once for every page beneath it, server-side,
  before render. It checks the session and `throw`s `RedirectError('/login')`
  when there's none. On SSR that's a `303`; on client navigation it's a
  `replace` redirect.
- **`renderMode: 'ssr'`** on the dashboard pages — required so the gate runs
  per request. A `static` page can't redirect per-visitor, and the build
  rejects a `RedirectError` there.
- **Scoped special files** — `dashboard/error.tsx` (error boundary),
  `dashboard/loading.tsx` (opt-in skeleton), `dashboard/not-found.tsx`
  (scoped 404). Each applies to every page under `/dashboard`.

## The demo gate

`src/lib/auth.ts` is a cookie-only stand-in so the template boots with **no
backend**: `login` writes a `demo_session` cookie, the dashboard loader
reads it (from the request `Cookie` header on SSR, or `document.cookie` on
client nav). Swap `isSignedIn` for a real check — verify a signed session,
or call an api — when you wire auth for real. See AGENTS.md › *Auth*.

## Wire a backend

Add an api and an `apis:` entry in `app.config.ts`, then read live data in
the dashboard pages with `useSubscription`. The gate stays the same — only
its session check moves from a demo cookie to your real session.

## Build + serve

```bash
voltro build .     # static marketing pages + an SSR bundle for /dashboard
voltro start .     # serve: / + /login are static; /dashboard renders per request
```
