# Add Page

> Adds a React page and feature folder with routes and API client calls wired to existing backend endpoints in a dotnet-vite-webapp-template app. Use when the user invokes /add-page, asks for a new screen/route/UI only, or the API already exists and needs a frontend.

- Skill: `manifold-works/add-page` (Agent Skill)
- Install (CLI): `npx skillmds@latest add manifold-works/add-page`
- Raw SKILL.md: https://api.skillmd.com/api/skills/manifold-works/add-page/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: Manifold-Works (https://skillmd.com/u/manifold-works)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/manifold-works/add-page

---


# Add Page

Frontend-only: route + feature UI + API client. Assumes backend endpoints already exist.

**Read first:** [`~/.cursor/skills/webapp-shared/reference.md`](../webapp-shared/reference.md)

**Mirror:** `frontend/src/features/auth/` and routing in `frontend/src/app/`.

## Prerequisites

- [ ] Backend endpoints exist and are documented (paths, DTO shapes, auth requirements)
- [ ] Dev stack running (`docker compose up`) or Vite dev with API reachable
- [ ] Shared HTTP client in `frontend/src/shared/` handles Bearer + refresh

## Gather inputs

| Input | Example |
|-------|---------|
| Feature/page name | `todos` |
| Route path(s) | `/todos`, `/todos/:id` |
| API endpoints | `GET /api/todos`, `POST /api/todos` |
| Auth required | yes (default) |
| Page type | list, detail, form, dashboard |

## Checklist

```
Add-page progress:
- [ ] 1. Confirm API contract (paths, JSON shapes)
- [ ] 2. Add types.ts matching DTOs
- [ ] 3. Add {feature}Api.ts using shared client
- [ ] 4. Build page components
- [ ] 5. Register routes in src/app
- [ ] 6. Add nav link (if requested)
- [ ] 7. Loading + error states
- [ ] 8. Vitest smoke test
- [ ] 9. Manual verify in browser
```

## Step 1: Confirm API contract

Before coding, verify against running API or OpenAPI/README:

```bash
curl -sf http://localhost:8080/api/health
# Login if needed; test target endpoint with Bearer token
```

Record request/response JSON for each call the page will make.

## Step 2: Types

Create `frontend/src/features/{feature}/types.ts`:

```typescript
// Match backend DTO property names (camelCase in JSON if API serializes that way)
export interface TodoItem { id: string; title: string; isDone: boolean }
export interface CreateTodoRequest { title: string }
```

Check existing auth types for serialization conventions.

## Step 3: API module

Create `frontend/src/features/{feature}/{feature}Api.ts`:

- Import shared HTTP helper from `src/shared/` (same as auth feature)
- Export typed functions: `listTodos()`, `createTodo(body)`, etc.
- Do **not** duplicate refresh logic — shared client handles 401 → refresh → retry
- Do **not** put access tokens in `localStorage`

Mirror `features/auth/` API module structure.

## Step 4: Pages and components

```
frontend/src/features/{feature}/
├── pages/
│   ├── {Feature}ListPage.tsx
│   └── {Feature}DetailPage.tsx   # if needed
├── components/
│   └── {Feature}Form.tsx
├── {feature}Api.ts
└── types.ts
```

Each page should handle:

- **Loading:** skeleton or spinner
- **Error:** user-visible message (network, 401 → redirect to login via auth provider)
- **Empty:** sensible empty state

Use existing shared UI primitives from `src/shared/` when available.

## Step 5: Routes

In `frontend/src/app/` router configuration:

```typescript
// Example pattern — match existing router library (react-router, etc.)
{ path: '/todos', element: <ProtectedRoute><TodoListPage /></ProtectedRoute> }
```

- Wrap with auth guard if endpoints require `[Authorize]`
- Follow how `/login`, `/register`, and home routes are registered in auth feature

## Step 6: Navigation

If user wants nav entry, add link in app layout/sidebar — same component auth uses for post-login navigation.

## Step 7: Tests

Add Vitest + Testing Library test in `frontend/tests/` or colocated `*.test.tsx`:

- Render page with mocked API
- Assert key heading or list item appears

Keep smoke-level — mirror auth form tests.

## Step 8: Verify

```bash
docker compose up -d web    # if only frontend changed
cd frontend && npm test -- --run
```

Browser check at `http://localhost:5173`:

- [ ] Route loads without console errors
- [ ] Authenticated calls succeed (login first if needed)
- [ ] 401 redirects to login

## If API missing

Stop and tell user to run `/add-entity` or `/add-feature` first. Do not invent backend endpoints from the frontend skill.

## Do not

- Create backend files in this skill
- Store access tokens in `localStorage`
- Bypass shared HTTP client for authenticated calls
- Invent routes outside `src/app/` + `src/features/` layout

## Related skills

- Need backend too → `add-feature` or `add-entity`
- Local dev issues → `dev-webapp`

