Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/wtyler2505/ProtoPulse/llms.txt

Use this file to discover all available pages before exploring further.

ProtoPulse is a TypeScript-first codebase with strict mode enabled across all layers — client, server, and shared. The conventions below are not preferences; most are enforced by ESLint, the TypeScript compiler, or the test suite. A contribution that violates any of them will fail CI.

TypeScript and imports

  • strict: true is set in tsconfig.jsonnoImplicitAny, strict null checks, and strict function types are all active.
  • All type-only imports must use import type. This is enforced by the eslint-plugin-import-x rule import/consistent-type-specifier-style.
// correct
import type { BomItem } from '@shared/schema';
import { useState } from 'react';

// incorrect — will fail lint
import { BomItem } from '@shared/schema';
  • Public API functions (exported hooks, context values, utility functions) must have explicit return types.
  • as any is an ESLint error. Use type narrowing, discriminated unions, or generics instead.

State management

All server state is managed by TanStack React Query (@tanstack/react-query). There is no Redux, no Zustand, and no useState for remote data.
// correct — server state via React Query
const { data: bomItems } = useQuery({
  queryKey: ['bom', projectId],
  queryFn: () => apiRequest('GET', `/api/projects/${projectId}/bom`),
});

// incorrect — server state in local state
const [bomItems, setBomItems] = useState([]);
Use Wouter for client-side routing. Do not add React Router.

Component conventions

  • Every interactive element must have a data-testid attribute.
<button data-testid="export-gerber-btn" onClick={handleExport}>
  Export Gerber
</button>
  • Wrap every top-level view component in an ErrorBoundary. ProjectWorkspace renders each view lazily inside its own boundary so that one crashing view does not take down the whole app.
  • Use shadcn/ui primitives from client/src/components/ui/ for all UI building blocks. Do not reach for a new UI library.
  • Use Tailwind CSS v4 utility classes for all styling. No inline style props except for dynamic values that cannot be expressed as utilities (e.g., canvas coordinates).

Naming

ThingConventionExample
Fileskebab-casebom-diff-panel.tsx
React componentsPascalCaseBomDiffPanel
Functions and variablescamelCasehandleExport, bomItems
CSS classesTailwind utilitiesflex items-center gap-2
data-testidkebab-casedata-testid="bom-export-btn"

Path aliases

AliasResolves to
@/*client/src/*
@shared/*shared/*
Use these aliases for all cross-directory imports. Never use ../../.. relative paths to cross the client/shared boundary.

Vertical slice pattern

Every feature — no matter how small — is implemented as a complete vertical slice across all layers. This is the only allowed development pattern:
shared/schema.ts       ← 1. Add/modify Drizzle table + Zod schema
server/storage.ts      ← 2. Add IStorage method + DatabaseStorage implementation
server/routes/         ← 3. Add route with asyncHandler + Zod validation
project-context.tsx    ← 4. Add React Query hook
client/src/components/ ← 5. Build UI component with data-testid attributes
__tests__/             ← 6. Write test covering the new behavior
Do not implement step 5 before step 2. A UI component that calls a non-existent API route will always produce a runtime error.

File organization

shared/                 # Code shared between client and server
  schema.ts             # All Drizzle tables + Zod validators (source of truth)
  component-types.ts    # Component editor type system
  drc-engine.ts         # Design rule check engine (runs on both sides)
  bom-diff.ts           # BOM snapshot comparison logic

server/
  routes.ts             # Barrel — registers all 21 domain routers
  circuit-routes.ts     # Barrel — registers all 13 circuit routers
  routes/               # One file per domain (auth, projects, bom, ...)
  circuit-routes/       # One file per circuit domain (designs, instances, nets, ...)
  storage.ts            # IStorage interface + DatabaseStorage
  ai-tools/             # 11 AI tool modules (barrel: ai-tools.ts)
  export/               # 16 export format modules

client/src/
  components/
    views/              # Top-level view components (one per workspace tab)
    panels/             # Sidebar panels (ChatPanel, ExportPanel)
    circuit-editor/     # Schematic, breadboard, PCB canvas components
  lib/
    project-context.tsx # ProjectProvider — all React Query hooks
    circuit-editor/     # Wire router, ERC engine, view sync
    simulation/         # SPICE generator, circuit solver
    component-editor/   # Constraint solver, diff engine, snap engine
New barrel files for routes go in server/routes.ts or server/circuit-routes.ts. New shared utilities go in shared/. Do not add new top-level directories without discussion.

Testing conventions

  • Tests live in __tests__/ subdirectories co-located with the source they test.
  • Vitest 4 is the test runner, configured as a workspace with separate server (Node.js environment) and client (happy-dom environment) projects.
  • Use @testing-library/react for all component tests — assert on what the user sees, not on internal state.
  • Name tests descriptively: "should display error message when BOM item creation fails".
  • The v8 coverage provider is available via npm run test:coverage.
// good test name
it('should show a toast error when the API returns 400', async () => { ... });

// poor test name
it('handles error', async () => { ... });

Prettier configuration

Prettier is enforced project-wide. The .prettierrc settings are:
OptionValue
semitrue
singleQuotetrue
tabWidth2
trailingComma"all"
printWidth120
bracketSpacingtrue
arrowParens"always"
Run npx prettier --write . before committing. The CI check will fail on unformatted files.

Build docs developers (and LLMs) love