skillby atopile

frontend

Frontend standards for atopile extension webviews: architecture, contracts, design system, and testing workflow.

Installs: 0
Used in: 1 repos
Updated: 2w ago
$npx ai-builder add skill atopile/frontend

Installs to .claude/skills/frontend/

# Frontend Skill

Use this skill when building or modifying frontend features in atopile.
Default target is extension webviews (`ui-server` + `vscode-atopile`).

## Quick Start

Dependency install:

```bash
cd src/ui-server
bun install
```

Frontend-only loop (no backend integration):

```bash
cd src/ui-server
bun run dev
bun run test
bun run build
```

Webview integration loop (backend + Vite):

```bash
cd src/ui-server
./dev.sh
```

Extension package/install loop:

```bash
ato dev compile && ato dev install cursor
# or
ato dev compile && ato dev install vscode
```

Command reference:

- `bun install`: install/sync JS dependencies.
- `bun run dev`: start local Vite dev server (frontend-only iteration).
- `bun run test`: run local Vitest suite once.
- `bun run build`: run local `tsc && vite build`.
- `./dev.sh`: run backend + Vite for integration testing in browser.
- `ato dev compile`: build extension artifacts (default target `all`).
- `ato dev install cursor|vscode`: install latest built extension `.vsix`.
- `ato dev ui`: open a webpage for the user showing the shared component library components.

## Relevant Files

### Main Extension Webview App

- Root: `src/ui-server/src/`
- Transport: `src/ui-server/src/api/`
- Global state: `src/ui-server/src/store/`
- Feature hooks: `src/ui-server/src/hooks/`
- Feature components: `src/ui-server/src/components/`
- Shared components: `src/ui-server/src/components/shared/`
- Utilities: `src/ui-server/src/utils/`
- Styles/tokens: `src/ui-server/src/styles/`
- Contracts: `src/ui-server/src/types/`
- Tests: `src/ui-server/src/__tests__/`

### Extension Host Bridge

- Root: `src/vscode-atopile/src/`
- Use for IDE commands/webview wiring/host integration.
- Keep core React UI logic out of this layer.

### Specialized Standalone App Example

- Root: `src/atopile/visualizer/web/src/`
- Use as reference for compute/canvas/worker patterns.

### Layout Editor (Specialized)

- Root: `src/atopile/layout_server/frontend/src/`
- Specialized layout editor frontend; not default architecture for webviews.

## Dependants (Call Sites)

- Extension webviews are built from `src/ui-server` and loaded by `src/vscode-atopile`.
- `ato dev compile` and `ato dev install` are the common extension developer loop.
- `src/atopile/visualizer/web` is a separate app and reference pattern, not default target.

## How to Work With / Develop / Test

### Typical Change Paths

Use these patterns to keep changes scoped and predictable.

1. UI-only change (no contract changes)

- touch `components/`, `styles/`, small `hooks/` usage
- avoid transport/store churn unless required
- validate through browser-first flow + focused component tests

2. UI + state change

- add/adjust store fields/actions/selectors
- keep transport untouched if payload shape is unchanged
- add store transition tests and UI interaction tests

3. UI + contract/transport change

- update Pydantic contracts first
- regenerate TS types
- update `api/` mapping + store state transitions + UI
- add transport and state tests, then browser flow validation

### Architecture Standard

Default architecture:

- Backend: FastAPI (domain, APIs, events)
- Frontend: React + Vite
- Realtime: WebSocket-first transport

Layer boundaries:

- `api/`: HTTP + WS transport and payload mapping
- `store/`: typed app state, actions, selectors
- `components/`: rendering/composition
- `utils/lib`: pure transforms/logic

### Contract Standard (Required)

Schema-first contract workflow:

1. Define/modify backend Pydantic model.
2. Regenerate frontend TS schema/types.
3. Update frontend transport/store/components using generated types.
4. Add/update tests for changed contract behavior.

Do not:

- maintain duplicate handwritten interfaces if generated types exist
- use stringly-typed protocol payloads when typed contracts exist

### One-Flow Rule (Required)

Implement one canonical user flow per feature.

Do not introduce fallback flow branches.
If dependency/state is unavailable, surface a clear stop-state error in the same flow context.

### WebSocket Standard

Use WebSocket for:

- interactive state sync
- action dispatch + action results
- long-running workflow updates

Use HTTP for:

- bootstrap reads
- direct idempotent reads
- file/artifact retrieval

Required WS client behavior:

- reconnect with bounded backoff
- explicit connected/disconnected state in store
- pending request timeout/cancel handling
- post-reconnect resync

Recommended WS client behavior:

- centralize WS connection in `api/` module
- keep message decoding/type-guarding out of components
- record minimal telemetry/logging for reconnect and parse failures
- guard against stale async results when reconnecting

Example envelope shape:

```ts
type WsMessage =
  | { type: "state"; data: AppState }
  | { type: "event"; event: EventType; data: EventPayload }
  | {
      type: "action_result";
      action: string;
      requestId?: string;
      result: { success: boolean; error?: string };
    };
```

### Reuse Rules

Before creating new primitives:

1. Check `src/ui-server/src/components/shared/`.
2. Check `src/ui-server/src/utils/` for existing logic.
3. If adding compute/canvas behavior, check `src/atopile/visualizer/web/src/lib/` and `src/atopile/visualizer/web/src/workers/`.
4. If behavior is IDE-host specific, keep it in `src/vscode-atopile/src/`.

Promote to shared when:

- used by 2+ feature surfaces, or
- repeated interaction semantics would drift if duplicated.

## Shared Assets Reference

### Shared Components (ui-server)

Prefer reusing the components in `src/ui-server/src/components/shared/` before creating equivalents.
If a new component is needed, create it in `src/ui-server/src/components/shared/` and reuse it in the feature.
If possible, compose complex components from existing shared components.

### Shared Utilities (ui-server)

Prefer extending these utilities:

- `src/ui-server/src/utils/codeHighlight.tsx`
- `src/ui-server/src/utils/nameValidation.ts`
- `src/ui-server/src/utils/packageUtils.ts`
- `src/ui-server/src/utils/searchUtils.ts`

### Specialized Utility Reference (visualizer)

Useful standalone reference:

- `src/atopile/visualizer/web/src/lib/exportUtils.ts`

## Best Practices

### Frontend Code Quality

- Keep strict TS and typed state transitions.
- Isolate side effects in transport/hooks, not leaf components.
- Use selectors, not broad full-store subscriptions.
- Implement explicit loading/error/empty states.

Example typed API boundary:

```ts
export async function fetchBuilds(
  projectRoot: string,
): Promise<BuildSummary[]> {
  const res = await fetch(
    `/api/builds?project_root=${encodeURIComponent(projectRoot)}`,
  );
  if (!res.ok) throw new APIError(res.status, "Failed to fetch builds");
  const data = (await res.json()) as { builds: BuildSummary[] };
  return data.builds;
}
```

### Design System

Apply across all surfaces:

- host-native typography/colors first
- brand accents only where semantically useful
- complete interaction states (`default/hover/focus-visible/active/disabled/loading`)
- consistent spacing/row-height/typography rhythm
- tokenized colors/spacing/radius/z-index, no ad-hoc semantic hardcoding

Example tokenized control:

```css
.btn-default {
  background: var(--accent);
  color: var(--text-on-accent);
  border: 1px solid var(--accent);
  border-radius: var(--radius-md);
  padding: 0 var(--spacing-md);
}
.btn-default:hover:not(:disabled) {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}
.btn-default:focus-visible {
  outline: 2px solid var(--info);
  outline-offset: 1px;
}
.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
```

### Accessibility Baseline

Required:

- keyboard-operable controls
- deterministic focus order
- ARIA only where native semantics are insufficient
- visible focus states
- readable contrast in light/dark modes

### Performance Baseline

Required:

- memoize expensive derived data/callbacks in hot paths
- use `requestAnimationFrame` for drag/resize animation paths
- move heavy layout/geometry/compute work to workers where needed
- keep WS update handling efficient under active event streams

Operational checks:

- avoid full-store subscriptions in high-frequency components
- memoize derived collections used in render loops
- verify no avoidable setState chains during drag/scroll/update streams
- keep long-running transformations out of component render bodies

## Implementation Playbooks

### Playbook A: New Extension Webview Panel (`ui-server`)

1. Add/confirm contracts

- if backend shape changes: update Pydantic + regenerate types

2. Add transport mapping

- implement data/action methods in `src/ui-server/src/api/`

3. Add store state/actions

- add minimal new fields/actions in `store/`
- expose selectors for component use

4. Compose UI

- build panel in `components/`
- reuse `components/shared/` primitives where possible

5. Validate

- run tests
- run browser-first flow
- capture screenshot + inspect ui logs

### Playbook B: Compute/Canvas-heavy Feature

1. Put core transforms into `utils/` or specialized `lib/` module.
2. Add worker offload if main-thread latency becomes visible.
3. Keep render components thin and memoized.
4. Validate interaction smoothness under active updates.

### Playbook C: Long-running Workflow UI

Use one canonical flow:

- trigger
- in-progress
- completion or error in same context

Required:

- disable conflicting controls during in-progress state
- emit progress updates via typed WS events
- provide deterministic terminal state in store

## Detailed Testing Notes

### Testing Scope by Layer

1. Unit tests

- pure utils/lib transforms

2. Store tests

- action transitions and derived selector correctness

3. Transport tests

- API/WS mapping, error handling, request correlation behavior

4. UI tests

- user interaction + state rendering behavior

5. Browser automation checks

- key flow interaction + screenshot + ui logs

### WebSocket Feature Test Cases

At minimum test:

- initial connect path
- disconnect state update
- reconnect and resync path
- pending request timeout/cancel path

Recommended:

- late or duplicate event tolerance
- malformed message handling without UI crash

## Testing Standard

Minimum per feature:

1. Store/action test
2. API/transport test
3. UI interaction test
4. Error/loading/empty-state test

Example matrix (build queue):

- store: enqueue + complete transitions
- API: build start error -> typed API error
- UI: cancel click dispatches cancel action
- state: disconnected WS state is visible

### Browser-First Dev Viewer Flow (Required)

Agents should self-test in browser flow first:

```bash
cd src/ui-server
./dev.sh
```

Then:

1. Validate interaction flow in browser webview page.
2. Capture key-state screenshots.
3. Inspect UI logs.
4. Fix issues.
5. Ask user to test in extension host only after browser flow is clean.

Relevant pages:

- `http://127.0.0.1:5173/`
- `http://127.0.0.1:5173/log-viewer.html`
- `http://127.0.0.1:5173/migrate.html`
- `http://127.0.0.1:5173/test-explorer.html`

### Puppeteer + Vite Screenshot APIs

Use these built-in dev endpoints:

```bash
curl -sS -X POST http://127.0.0.1:5173/api/screenshot \
  -H 'Content-Type: application/json' \
  -d '{"path":"/","name":"default","waitMs":1200}'
```

```bash
curl -sS -X POST http://127.0.0.1:5173/api/screenshot \
  -H 'Content-Type: application/json' \
  -d '{"path":"/","name":"projects-expanded","uiActions":[{"type":"openSection","sectionId":"projects"}],"uiActionWaitMs":600}'
```

```bash
curl -sS http://127.0.0.1:5173/api/ui-logs
```

Automation guardrails:

- stable selectors (`data-testid` or semantic roles)
- fixed viewport for diffs
- readiness-based waits preferred over arbitrary sleep
- runtime errors treated as failures unless allowlisted

## Definition of Done

A feature is done only when all are true:

- [ ] one canonical flow implemented (no fallback branch)
- [ ] contract changes modeled in Pydantic + regenerated TS consumed
- [ ] WS behavior validated (connect/reconnect/resync)
- [ ] tests added/updated (store + transport + UI + state handling)
- [ ] browser-first dev viewer checks complete
- [ ] user asked to test extension host only after browser validation
- [ ] build/test commands pass for touched app
- [ ] component/util placement follows repo structure and reuse rules

## PR Checklist (Copy/Paste)

```md
- [ ] Single canonical flow preserved (no fallback path added)
- [ ] Pydantic models updated for API/WS changes
- [ ] Generated TS schema/types regenerated and committed
- [ ] WS reconnect/resync behavior verified
- [ ] Browser dev viewer flow validated (`./dev.sh`)
- [ ] Screenshots + UI logs reviewed (no unapproved runtime errors)
- [ ] Added/updated: store test, transport test, UI interaction test
- [ ] Asked user to test in extension host only after browser checks passed
```

Quick Install

$npx ai-builder add skill atopile/frontend

Details

Type
skill
Author
atopile
Slug
atopile/frontend
Created
2w ago

More by atopile