A local-first electrical network editor for modeling, validating, and documenting electrical networks.
The app treats connectors, splices, nodes, segments, and wires as a graph, computes routes deterministically, and keeps canvas preferences and export outputs aligned with the current workspace state.
- Live Demo & Status
- Product
- Technical Overview
- AI Agent Workspace
- Getting Started
- Available Scripts
- Deployment
- Project Structure
- Quality and CI
- Contributing
- License
- Production: https://e-plan-editor.onrender.com
- Hosting: Render Static Site (Blueprint via
render.yaml) - Current version:
1.22.0 - CI status: see the GitHub Actions badge above
- Electrical modeling for connectors, splices, nodes, segments, and wires, with occupancy rules and wire-side connection / seal references.
- Automatic route computation, forced-route locking, and live wire-length recomputation after segment edits.
- Interactive 2D workspace with drag-and-drop nodes, zoom/pan controls, selectable segments, sub-network filtering, configurable callouts, wire-linked pin highlighting, and quick navigation between
Modeling,Analysis,Statistics,Harness, andSettings. - Connector and splice callouts with tabular wire details, optional wire-name columns, draggable positions, and catalog connector drawings when a physical layout was edited.
- Optional callout columns for the effective connection (contact) and seal references of each wire, for this side (the callout's own endpoint) and/or the opposite side (the other end of the same wire). Four global checkboxes in
Settings > Canvas tools preferences(all off by default) control them; codes come from the wire's manual value, otherwise the connector cavity/catalog material, wrap instead of truncating, show—when missing, and are included in SVG/PNG/PDF exports. - Catalog-backed connector physical layout editor with reusable way geometry, keying features, shell shape controls, and physical connector analysis views.
- Harness assembly workflows for multi-network grouping, master connector references, inter-harness connector links, saved assembly graphs, current-network functional graphs, and contextual assembly help.
- Analysis workflows with targeted
Go toactions, including navigation fromNode analysistoSegment analysis, fromSegment analysistoWire analysis, and from connector analysis into physical views. - Statistics workspace for active-network KPIs, manual multi-network comparison, wire-length metrics, section/color distributions, and utilization tables.
- Network-scoped catalog management with catalog-first connector flows, optional splice linkage, seeded starter items, usage analysis, and pricing context settings.
- Home workspace hub with Quick start actions, active-network context, changelog feed, and rich recent-change rows that can navigate back to changed objects when possible.
- Themed toast notifications for important workspace actions, including undo/redo and connector/splice occupancy changes.
- Export tooling for operational handoff:
SVG/PNG/PDFnetwork-plan export with optional frame and metadata cartouche (network, author, code, plan revision, plan issue date, manufacturer and supplier plan references, creation date, notes)BOM CSVexport with pricing context and a dedicatedWire terminationssection- wire CSV export with explicit begin/end connection and seal reference columns
- Network metadata authoring for export identity: creation date, author, project code, plan revision (
planRevision, free text up to 40 characters such asA,B02,03), plan issue date (planIssueDate, a calendar dateYYYY-MM-DDdistinct from the creation date), logo URL, and export notes. Plan revision and issue date are set manually per network and are never inferred or updated automatically (Save, export, recompute, versions); unset values are omitted from the cartouche like other optional metadata. - Manufacturer and supplier plan references: two fixed roles per network, each with an editable company name (
planManufacturerName/planSupplierName, up to 80 characters) and the reference that company gives this network plan (planManufacturerReference/planSupplierReference, up to 120 characters). All four values are optional, single-line and kept literally (case, punctuation, leading zeroes); blank values are unset. They identify the whole network plan and are unrelated to component catalogmanufacturerReference, wire endpoint material references or BOM references. In the export cartouche each role shows asManufacturer (Manufacturer A): MFG-001/Supplier (Supplier B): SUP-009(localized role label, literal name and reference), asManufacturer: MFG-001with only a reference, asManufacturer (Manufacturer A)with only a name, and is omitted when both values are unset. Long values wrap, and the cartouche grows the export height when needed. - Local-first persistence so workspace state, settings, and export preferences survive reloads.
- Validation center with grouped issues, issue navigation, and catalog integrity checks, plus a read-only Routing consistency check that warns when
Network Scope > Recompute routeswould change stored routes, lengths, endpoint details or directional splice sides (checked 500 ms after the latest routing edit, in idle-time slices; never applied automatically). - Built-in onboarding flow plus contextual help entry points to guide first-time usage.
- Accessibility-oriented interactions across dialogs, tables, keyboard navigation, and assistive-technology semantics.
- Theme, language, canvas, export, and onboarding preferences persisted per workspace.
- PWA support with install prompt, offline shell, and update readiness in production.
- React 19 + TypeScript in strict mode.
- Vite for dev, preview, and production builds.
- Domain/state split:
src/coreholds graph, routing, layout, and domain primitives.src/storeholds reducers, selectors, and action orchestration.src/appholds screen composition, controller wiring, and UI modules.
- Persistence and portability:
- local storage uses versioned schema migrations
- import/export payloads are normalized and guarded against unsupported future versions
- storage failures surface visible runtime warnings instead of silently corrupting state
- Test and quality stack:
- Vitest + Testing Library for unit and integration coverage
- Playwright for E2E smoke coverage
- ESLint for linting
- explicit quality gates for UI modularization, timeout governance, store modularization, segmented test ownership, and PWA artifacts
- Delivery workflow:
- Logics-backed request/backlog/task tracking under
logics/ - CI runs the same blocking validation pipeline locally and in GitHub Actions
- Logics-backed request/backlog/task tracking under
The Modeling AI Agent workspace supports controlled, reversible AI-assisted plan edits. The agent is not allowed to patch raw application state. It receives scoped electrical-plan context, asks the configured provider for a structured plan change, then lets the app derive, validate, preview, and apply bounded operations through the same domain rules as manual Modeling.
flowchart LR
Agent[AI Agent instruction] --> Permission{Permission enabled?}
Permission -- add --> Add[Add entities]
Add --> AddConnector[Connector]
Add --> AddSplice[Splice]
Add --> AddNode[Routing node]
Add --> AddSegment[Segment]
Add --> AddWire[Wire]
Permission -- move --> Move[Move layout]
Move --> MoveSingle[Move one entity]
Move --> MoveRelative[Place relative to another entity]
Move --> MoveBatch[Batch move selected entities]
Permission -- update --> Update[Update data]
Update --> Labels[Names and technical IDs]
Update --> WireFields[Wire section, material, color, protection]
Update --> Catalog[Catalog assignment and connector layout]
Update --> Terminals[Connector terminal material]
Permission -- route --> Route[Route operations]
Route --> Regenerate[Regenerate wire routes]
Route --> Lock[Lock forced route segments]
Permission -- delete --> Delete[Delete entities]
Delete --> DeleteGate[Blocked by default unless explicitly enabled]
Add --> Validate[Local validation]
Move --> Validate
Update --> Validate
Route --> Validate
Delete --> Validate
Validate --> Result[Accepted, rejected, unsupported, warnings]
- Node.js 20+
- npm
- Python 3 with
logics-manageravailable aspython3 -m logics_manager
npm ci
python3 -m pip install logics-managerCreate local env values from the tracked template:
cp .env.example .envSupported variables and defaults:
APP_HOST=127.0.0.1APP_PORT=5284PREVIEW_PORT=5285E2E_BASE_URL=http://127.0.0.1:5284VITE_STORAGE_KEY=electrical-plan-editor.state- optional local maintenance credentials:
RENDER_API_KEY,RENDER_SERVICE_ID,OPENAI_API_KEY,GEMINI_API_KEY
Env fallback behavior:
- Invalid/empty
APP_PORTorPREVIEW_PORTfalls back to documented defaults. - Invalid/empty
E2E_BASE_URLfalls back tohttp://{APP_HOST}:{APP_PORT}. - Invalid/empty
VITE_STORAGE_KEYfalls back toelectrical-plan-editor.state. - Keep secrets out of
VITE_*variables (they are client-visible at build/runtime). - Non-
VITE_*variables are for local tooling only and are not bundled into the client app.
npm run devThen open http://127.0.0.1:5284 (unless overridden).
npm run dev: start local dev servernpm run build: typecheck + production buildnpm run preview: preview production buildnpm run lint: run ESLintnpm run typecheck: run TypeScript checksnpm run test: run Vitest in watch modenpm run test:ci: run Vitest with coveragenpm run test:ci:segmentation:check: validate explicit segmented-lane contract (scripts/quality/run-vitest-segmented.mjs)npm run test:ci:fast: run non-UI lane via explicit segmented contract (complementary totest:ci; keepspwa.*in fast lane)npm run test:ci:ui: run UI lane via explicit segmented contractnpm run test:ci:slow-top: print top-10 slowest tests from a Vitest run (informational)npm run test:ci:ui:slow-top: print top-10 slowest UI-lane tests from explicit segmented contract (informational)npm run coverage:ui:report: emitsrc/app/**coverage report (informational, non-blocking)npm run bundle:metrics:report: report main JS chunk + total JS gzip with non-blocking warning budgetsnpm run build:bundle:report: run production build then bundle metrics reportnpm run ci:blocking: run the canonical blocking CI pipeline shared with GitHub Actionsnpm run ci:local: alias ofnpm run ci:blockingnpm run test:e2e: run Playwright E2E smoke testsnpm run quality:dependency-audit: run the npm audit allowlist gatenpm run quality:ui-modularization: enforce UI modularization line-budget gatenpm run quality:ui-timeout-governance: enforce UI test timeout-override governance (no explicit per-test timeout override unless allowlisted)npm run quality:store-modularization: enforce store modularization line-budget gatenpm run quality:exceljs-boundary: enforce that ExcelJS stays behind the tabular-export boundarynpm run quality:pwa: validate generated PWA build artifacts (manifest,sw.js,workbox-*)
This repository includes a ready-to-use render.yaml for static hosting on Render.
- Push your latest changes to GitHub.
- In Render, create a new service with Blueprint from this repository.
- Render will build with
npm ci && npm run buildand publishdist/.
The app is a SPA and can be hosted from dist/ on any static server/CDN.
- Build:
npm run build - Serve over HTTPS in production (required for full PWA behavior).
- Configure SPA fallback rewrite to
/index.html.
src/
app/ # React app shell, UI, controller wiring, PWA integration
app/pwa/ # PWA registration and update/install UX helpers
config/ # Runtime env resolution and defaults
core/ # Domain entities, graph and pathfinding
store/ # State management, reducer, selectors, actions
store/reducer/ # Reducer handlers split by domain concern
adapters/persistence/ # Local storage persistence + migrations
adapters/portability/ # Network import/export payload adapters
tests/ # Unit + integration tests
tests/e2e/ # Playwright end-to-end smoke
logics/ # Product requests, backlog, tasks, architecture
This repository uses the standalone logics-manager CLI for Logics workflow operations.
python3 -m logics_manager flow ...creates, promotes, and finishes workflow docs.python3 -m logics_manager lint --require-statusvalidates Logics document structure.python3 -m logics_manager audit ...checks workflow consistency.
The app uses explicit versioned payload contracts for both local storage and network export files.
-
Current schema versions:
- local persistence:
3 - network import/export file:
3
- local persistence:
-
Local workspace persistence:
- primary key: configured
VITE_STORAGE_KEY(defaultelectrical-plan-editor.state) - backup key:
<storage-key>.backup(written before destructive migration replacement or unsupported/failed payload fallback) - payload includes:
payloadKindschemaVersionappVersionappSchemaVersion- timestamps + serialized
state
- primary key: configured
-
Network export/import files:
- include explicit file
schemaVersion+ source metadata (appVersion,appSchemaVersion) - legacy file payloads are normalized on import
- unsupported future file versions are rejected safely (no workspace mutation)
- include explicit file
-
Named workspace lineages (working copy, numbered immutable versions, supplier handoff archives, folder/ZIP portability, legacy adoption): see
docs/workspace-lineages.mdfor the user workflow, the portable format contract and failure semantics.- workspace file (
*.epe.json): schema2(schema1still readable) - lineage manifest / supplier handoff record: schema
1
- workspace file (
Migration authoring workflow (future schema evolution):
- Add/adjust payload shape support in
src/adapters/persistence/migrations.ts(local storage) and/orsrc/adapters/portability/networkFile.ts(file import/export). - Keep migration steps incremental and deterministic (
vN -> vN+1), with a single entry point for runtime hydration/import. - Add regression fixtures/tests for:
- legacy/unversioned payload
- current payload
- unsupported future version
- malformed payload
- Run the full validation pipeline (
npm run ci:local).
Primary validation commands:
npm run ci:blockingEquivalent expanded command list:
python3 -m logics_manager lint --require-status
python3 -m logics_manager sync close-eligible-requests
git diff --exit-code -- logics/request
python3 -m logics_manager audit --legacy-cutoff-version 1.1.0 --group-by-doc --skip-ac-traceability
npm run lint
npm run typecheck
npm run quality:dependency-audit
npm run test:ci:segmentation:check
npm run quality:ui-modularization
npm run quality:ui-timeout-governance
npm run quality:store-modularization
npm run quality:exceljs-boundary
npm run test:ci:fast -- --coverage
npm run test:ci:ui
npm run test:e2e
npm run build
npm run quality:pwaCI runs the same main blocking pipeline in .github/workflows/ci.yml on push and pull_request.
Additional non-blocking CI observability:
coverage:ui:reportforsrc/app/**coverage visibilitytest:ci:ui:slow-topfor top-N slow UI test reportingbundle:metrics:reportfor main-chunk and total-gzip size visibility- these signals are informational and do not replace blocking CI gates
- in CI,
coverage:ui:reportandtest:ci:ui:slow-topare configured withif: success()so they run only when prior blocking steps pass - in CI,
bundle:metrics:reportstays informational and runs only when the production build step succeeds
Segmented test contract:
- explicit lane ownership is defined in
scripts/quality/run-vitest-segmented.mjs test:ci:segmentation:checkverifies the lane contract and fails on drift- CI uses
test:ci:fast+test:ci:uias required lanes;test:ciremains available as a full-suite local command
Form validation doctrine (current targeted scope):
- native HTML validation guards simple required/number constraints first (
catalog,wire) - inline custom errors remain for business and cross-field rules (catalog URL policy, uniqueness, endpoint/business integrity)
UI reliability note:
- explicit per-test UI timeout overrides are disallowed by default and enforced by
npm run quality:ui-timeout-governance - temporary exceptions, if strictly necessary, must be explicitly allowlisted in
scripts/quality/check-ui-timeout-governance.mjswith rationale and retirement plan
Local E2E note:
npm run test:e2erequires a Playwright browser install first (CI runsnpx playwright install --with-deps chromium).
PWA caveats:
- Service worker registration is production-only (
build/preview) and remains disabled during normalnpm run dev. - Install prompt availability depends on browser capability and secure context (
httpsorlocalhost). - Offline behavior is guaranteed after the first successful online load of production assets.
Contribution guidelines are available in CONTRIBUTING.md.
This project is licensed under the MIT License. See LICENSE.