This repository is a Bespoke application: the Geometry Plane, an interactive 2D coordinate plane with point, line, ray, segment, angle, circle, and intersection tools. For the Bespoke framework contract (layout, design system, conventions), see BESPOKE.md.
This application provides:
- CodeSignal Design System integration
- Consistent layout (header, sidebar, main content area)
- Help modal (content from
help-content.html) - Local development server with WebSocket support and operation logging
- Geometry plane state and operation log for validation
-
Run the application
npm run dev
Server runs at
http://localhost:3000. TypeScript is compiled viatsc; usenpm run typecheckto type-check without emitting. -
Production:
npm run build(compiles TypeScript toclient/), thennpm start(or use your preferred production server setup).
- CSS files: kebab-case (e.g.
geometry-plane.css) - JavaScript/TypeScript files: kebab-case (e.g.
geometry-plane.ts) - Data files: kebab-case (e.g.
solution.json) - Image files: kebab-case (e.g.
overview.png)
- Wrap all async operations in try-catch blocks
- Provide meaningful error messages to users
- Log errors to console for debugging
- Implement retry logic for network operations where appropriate
- Handle localStorage quota exceeded errors when persisting
- Validate data before saving operations
The geometry plane and app entry use TypeScript (.ts). The browser loads the compiled JavaScript (client/*.js); editing a .ts file does not update the .js until you recompile.
- Type-check only:
npm run typecheck - Compile once:
npm run build(runstsc; writesclient/*.jsandvalidate/*.js). Run this after changing any.tsfile so the app uses your changes. - Compile on save:
npm run build:watch— runstsc --watchso that saving a.tsfile automatically updates the corresponding.js. Use this in a separate terminal while developing.
The server provides POST /message for real-time alerts:
curl -X POST http://localhost:3000/message \
-H "Content-Type: application/json" \
-d '{"message": "Your message here"}'Requires ws package: npm install.
POST /log– Accepts{ "message": "string" }. Appends the message as one line tologs/user_actions.log. The server creates thelogs/directory at startup if missing. Used for operation logging and optional state snapshots.
logAction(message)– Defined inclient/logger.jsand exposed onwindow.logAction. Sends the string toPOST /log(fire-and-forget). The geometry plane calls it for every mutation (add, remove, intersection, clear, and optionally label) with a JSON-serialized payload (one object per line) so validators can parse line-by-line.
There is no validation API or server endpoint. Validation is log-based: run npm run validate (or node run-validate.mjs); the script reads logs/user_actions.log, replays operations via validate/replay.ts, and runs a validator (see run-validate.mjs and validate/tasks.ts). Set LOG_FILE to override log path. Snapshot file or stdin: node run-validate.mjs snapshot.json or pipe JSON. Exit code 0 = valid, 1 = invalid. Replay lives in validate/replay.ts (canonical operation replay). Validators and registry in validate/tasks.ts; geometry helpers in validate/geometry.ts. To add a validator, implement it in validate/tasks.ts and register it. Validators can use either or both of:
-
Final state – Call
getPlaneStateSnapshot()(exported fromgeometry-plane.js). Returns an array of{ geom, name?, labelAngle? }in the same form as saved state. Compare to an expected construction (e.g. same set of objects, coordinate tolerance). -
Operation log – Call
getOperationLog()(exported fromgeometry-plane.js) to get the in-memory sequence of operations, or readlogs/user_actions.logserver-side. Each line can be a JSON object withop,tool,geom,index, etc. Check that the user performed an allowed sequence of steps.
For design system usage, layout components, and CSS/JS conventions, see BESPOKE.md.
client/
├── index.html # Main HTML
├── app.js # WebSocket, help modal, logger bootstrap
├── logger.js # logAction() for POST /log
├── bespoke.css # Bespoke layout and utilities
├── geometry-plane.ts # Plane logic, state, operation log
├── geometry-math.ts # Geometry math utilities
├── geometry-objects.ts # Point, Line, Ray, Segment, Angle, Circle
├── help-content.html # Help modal content
└── design-system/ # CodeSignal Design System
validate/
├── types.ts # GeomObject, SnapshotEntry, OperationLogEntry
├── geometry.ts # distToLine, segmentLength, areParallel, etc.
├── replay.ts # Full operation replay (replayLogToSnapshot, replayLogFromString)
└── tasks.ts # Validators + registry
run-validate.mjs # CLI: log/file/stdin -> replay -> run validator
server.js # Static server, WebSocket, POST /message, POST /log
When working on this application:
- Reference BESPOKE.md for layout, design system, and implementation details.
- Follow the conventions above for file naming and error handling.
- Use Design System components as documented in BESPOKE.md.
- Logging: Use
logAction(JSON.stringify({ op, ... }))for any new user actions that should be validated; keep one JSON object per call for line-by-line parsing. - Validation: Use
getPlaneStateSnapshot()andgetOperationLog()for task/validation features; do not mutate state from validators.