Web App
SolidJS resume builder structure, stores, components, and WASM integration.
The Rustume web app (apps/web/) is a SolidJS single-page
application (SPA) built with
Vite. It runs offline-first with WASM +
IndexedDB local storage. In
connected Cloud mode, signed-in persistence synchronizes through authenticated server storage.
Tech stack
| Layer | Technology |
|---|---|
| Framework | SolidJS (signals, fine-grained reactivity) |
| Build | Vite + bun |
| Styling | Tailwind CSS |
| Rich text | TipTap editor |
| Local storage | WASM → IndexedDB |
| API client | Fetch wrappers in api/ — see Cloud endpoints |
| Tests | Vitest + jsdom |
Directory structure
apps/web/src/
├── index.tsx App entry + router
├── App.tsx Root component, auth probe on mount
├── pages/
│ ├── Home.tsx Resume list, create/import
│ ├── Editor.tsx Main builder + preview split view
│ └── NotFound.tsx 404 page
├── components/
│ ├── builder/ Section editors (basics, experience, skills)
│ ├── preview/ Live PDF/PNG preview panel
│ ├── templates/ Template picker, theme editor
│ ├── import/ Import modal (JSON, LinkedIn, Reactive Resume)
│ ├── export/ PDF/JSON export modal
│ ├── Auth/ Sign-in menu, cloud import prompt
│ ├── layout/ AppShell, Sidebar, SplitPane
│ └── ui/ Buttons, modals, inputs, toast
├── stores/
│ ├── resume.ts Active resume state, validation, auto-save
│ ├── persistence.ts Local/cloud storage routing
│ ├── cloudStorage.ts Cloud API wrappers
│ ├── auth.ts Session state, sign-in/out
│ ├── ui.ts Modals, sidebar, loading states
│ └── editorTheme.ts Code editor theme preference
├── api/
│ ├── client.ts Base fetch with error handling
│ ├── resumes.ts Cloud CRUD endpoints
│ ├── auth.ts Auth probe, logout
│ └── render.ts PDF/preview API calls
├── hooks/
│ ├── useOnline.ts Offline detection
│ ├── useDebounce.ts Debounced auto-save
│ └── useHotkeys.ts Keyboard shortcuts
└── wasm/
├── index.ts WASM module loader
└── types.ts ResumeData TypeScript types
State management
SolidJS stores use createStore and createSignal — no external state
library.
resume.ts — central resume editing state:
loadResume(id)— fetch from persistence layer- Auto-save on debounced changes (500ms)
validateResumeData()— client-side schema check before save
persistence.ts — storage abstraction:
// Routes to cloud or local based on auth
if (isCloudAuthenticated()) {
await saveCloudResume(id, data);
} else {
await saveToWasmStorage(id, data);
}
auth.ts — probes GET /auth/me on app load, exposes user and plan.
WASM integration
The rustume-wasm crate compiles to apps/web/wasm/ via
wasm-pack:
make wasm
# cd bindings/wasm && wasm-pack build --release --target web
WASM provides:
- IndexedDB read/write for resume JSON
- Resume list enumeration
- ID generation
Falls back to localStorage when WASM fails
to load (with user notice).
Routing
Client-side routing via @solidjs/router:
| Path | Page |
|---|---|
/ | Home (resume list) |
/editor/:id | Editor for resume UUID |
* | NotFound |
The Rust server serves index.html for all non-API routes (SPA
fallback).
Preview and export
Preview panel calls POST /api/render/preview for PNG rendering — see Core
endpoints. Skips requests when offline (shows cached preview or
message).
Export modal offers:
- PDF via
POST /api/render/pdf - JSON download (client-side blob)
Development
cd apps/web
bun install
bun run dev # :5173, proxies API to :3000
bun run test # Vitest
bun run build # production bundle → dist/
Production build output is copied into the Docker image at /app/web
and served by the Rust server.
Cloud components
When RUSTUME_CLOUD=true on the server:
AuthMenu.tsx— sign-in and sign-out controls when Cloud mode is enabled — see AuthenticationCloudImportPrompt.tsx— one-time local → cloud migration — see Getting startedcloudStorage.ts— typed wrappers for/api/resumes/*
The web app detects cloud mode by probing /auth/me — no build-time flag required.
Testing
cd apps/web && bun run test
Tests cover stores (persistence, auth, cloud storage), API client, hooks, and key components.
Coverage reports are generated in CI by the Coverage Reports workflow
(reusable-test-node with coverage: true).
See also
- Development setup —
make devworkflow - Cloud storage — API the web app calls
- Architecture overview — full crate map
- Import formats — JSON Resume, LinkedIn, Reactive Resume