Pansy is a self-hostable garden planner (Go backend + embedded React frontend, single static binary). This issue creates the web app skeleton in web/ that all frontend issues build on. It matches the stack of the sibling cdfview project: React + TypeScript + Vite + Tailwind.
Scope
web/: Vite + React 19 + TypeScript (strict mode).
Tailwind 4 via @tailwindcss/vite.
@tanstack/react-router with placeholder routes: /login, /register, /gardens, /gardens/$gardenId, /plants. Each renders a stub page.
@tanstack/react-query provider at the root; zod installed.
web/src/lib/api.ts: small typed fetch wrapper for /api/v1 (JSON in/out, throws a typed error carrying HTTP status and response body — later issues rely on reading 409 conflict bodies from it).
Vite dev proxy: /api → http://localhost:8080.
Basic layout shell: top nav with app name + placeholder nav links, viewport meta for mobile, sensible base styles.
Out of scope
Real pages, auth logic, and the canvas (issues #6, #8, #9+).
cd web && npm run dev serves the shell; client-side navigation between all five routes works.
npx tsc --noEmit is clean.
npm run build emits web/dist without warnings that matter.
Shell renders sensibly at 375px width (phone) and desktop.
Part of epic #20 · Design: [DESIGN.md](https://gitea.stevedudenhoeffer.com/steve/pansy/src/branch/main/DESIGN.md)
## Context
Pansy is a self-hostable garden planner (Go backend + embedded React frontend, single static binary). This issue creates the web app skeleton in `web/` that all frontend issues build on. It matches the stack of the sibling `cdfview` project: React + TypeScript + Vite + Tailwind.
## Scope
- [ ] `web/`: Vite + React 19 + TypeScript (strict mode).
- [ ] Tailwind 4 via `@tailwindcss/vite`.
- [ ] `@tanstack/react-router` with placeholder routes: `/login`, `/register`, `/gardens`, `/gardens/$gardenId`, `/plants`. Each renders a stub page.
- [ ] `@tanstack/react-query` provider at the root; `zod` installed.
- [ ] `web/src/lib/api.ts`: small typed fetch wrapper for `/api/v1` (JSON in/out, throws a typed error carrying HTTP status and response body — later issues rely on reading `409` conflict bodies from it).
- [ ] Vite dev proxy: `/api` → `http://localhost:8080`.
- [ ] Basic layout shell: top nav with app name + placeholder nav links, `viewport` meta for mobile, sensible base styles.
## Out of scope
- Real pages, auth logic, and the canvas (issues #6, #8, #9+).
- Embedding into the Go binary (#3).
## Key files & patterns
- Stack reference: `/Users/steve/Projects/cdfview` (sibling repo on this machine) — React/TS/Vite/Tailwind conventions.
- Route/state plan: `DESIGN.md` § Frontend layout.
## Dependencies
None — parallel to #1.
## Acceptance criteria
- `cd web && npm run dev` serves the shell; client-side navigation between all five routes works.
- `npx tsc --noEmit` is clean.
- `npm run build` emits `web/dist` without warnings that matter.
- Shell renders sensibly at 375px width (phone) and desktop.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Part of epic #20 · Design: DESIGN.md
Context
Pansy is a self-hostable garden planner (Go backend + embedded React frontend, single static binary). This issue creates the web app skeleton in
web/that all frontend issues build on. It matches the stack of the siblingcdfviewproject: React + TypeScript + Vite + Tailwind.Scope
web/: Vite + React 19 + TypeScript (strict mode).@tailwindcss/vite.@tanstack/react-routerwith placeholder routes:/login,/register,/gardens,/gardens/$gardenId,/plants. Each renders a stub page.@tanstack/react-queryprovider at the root;zodinstalled.web/src/lib/api.ts: small typed fetch wrapper for/api/v1(JSON in/out, throws a typed error carrying HTTP status and response body — later issues rely on reading409conflict bodies from it)./api→http://localhost:8080.viewportmeta for mobile, sensible base styles.Out of scope
Key files & patterns
/Users/steve/Projects/cdfview(sibling repo on this machine) — React/TS/Vite/Tailwind conventions.DESIGN.md§ Frontend layout.Dependencies
None — parallel to #1.
Acceptance criteria
cd web && npm run devserves the shell; client-side navigation between all five routes works.npx tsc --noEmitis clean.npm run buildemitsweb/distwithout warnings that matter.