frontend
Frontend standards for atopile extension webviews: architecture, contracts, design system, and testing workflow.
Best use case
frontend is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Frontend standards for atopile extension webviews: architecture, contracts, design system, and testing workflow.
Teams using frontend should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/frontend/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How frontend Compares
| Feature / Agent | frontend | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Frontend standards for atopile extension webviews: architecture, contracts, design system, and testing workflow.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
Related Guides
AI Agents for Coding
Browse AI agent skills for coding, debugging, testing, refactoring, code review, and developer workflows across Claude, Cursor, and Codex.
Best AI Skills for Claude
Explore the best AI skills for Claude and Claude Code across coding, research, workflow automation, documentation, and agent operations.
ChatGPT vs Claude for Agent Skills
Compare ChatGPT and Claude for AI agent skills across coding, writing, research, and reusable workflow execution.
SKILL.md Source
# 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
```Related Skills
lsp
How the atopile Language Server works (pygls), how it builds per-document graphs for completion/hover/defs, and the invariants for keeping it fast and crash-proof.
solver
How the Faebryk parameter solver works (Sets/Literals, Parameters, Expressions), the core invariants enforced during mutation, and practical workflows for debugging and extending the solver. Use when implementing or modifying constraint solving, parameter bounds, or debugging expression simplification.
SEXP Benchmark Strategy
## Goal
sexp
How the Zig S-expression engine and typed KiCad models work, how they are exposed to Python (pyzig_sexp), and the invariants around parsing, formatting, and freeing. Use when working with KiCad file parsing, S-expression generation, or layout sync.
pyzig
How the Zig↔Python binding layer works (pyzig), including build-on-import, wrapper generation patterns, ownership rules, and where to add new exported APIs. Use when adding Zig-Python bindings, modifying native extensions, or debugging C-API interactions.
planning
Spec-driven planning for complex design tasks: when to plan, how to write specs as .ato files, and how to verify against requirements.
Package Agent
You are a package specialist.
library
How the Faebryk component library is structured, how `_F.py` is generated, and the conventions/invariants for adding new library modules. Use when adding or modifying library components, traits, or module definitions.
graph
How the Zig-backed instance graph works (GraphView/NodeReference/EdgeReference), the real Python API surface, and the invariants around allocation, attributes, and cleanup. Use when working with low-level graph APIs, memory management, or building systems that traverse the instance graph.
faebryk
How Faebryk's TypeGraph works (GraphView + Zig edges), how to traverse/resolve references, and how FabLL types/traits map onto edge types. Use when working with TypeGraph traversal, edge types, or building type-aware queries.
fabll
How FabLL (faebryk.core.node) maps Python node/trait declarations into the TypeGraph + instance graph, including field/trait invariants and instantiation patterns. Use when defining new components or traits, working with the Node API, or understanding type registration.
domain-layer
Instructions for electronics-specific logic and build processes: netlists, PCBs, build steps, and exporters. Use when implementing or modifying build steps, exporters, PCB generation, or BOM/netlist output.