← All technical documents

CARULY / TECHNICAL REPORT

Caruly — Internal Architecture

How the browser, Node server, SQLite database, and file storage work together.

Updated: September 13, 2026
Scope: source-based prototype snapshot
Code baseline: d23f62e plus this local documentation change
5SQLite tables
7Index entries
5Runtime / utility JS files
2JS test files

Source snapshot counts; categories measure different things and are not added together.

Browser
Forms · Photos · Listings
↓ same-origin requests
Node HTTP server
Routing · Validation · Ownership
Storage layer
SQLite ↔ Private image files

Simplified request flow, not a complete dependency graph. Tech serves curated files through a separate read-only route.

1. System Overview

Back to contents ↑

Caruly is a car-selling prototype. A single HTML document implements the seller experience with inline CSS and JavaScript. A Node HTTP server serves the application and JSON APIs. SQLite stores drafts, photo metadata, damage reports, inspections, and demo verification state. Photo bytes live on disk outside the static web surface.

2. Data Flow

Back to contents ↑

Plate and state -> sample Toyota match -> vehicle/contact details -> POST /api/draft -> sample $4,375 estimate -> demo code verification -> listing review -> photos -> damages -> self-inspection -> Documents placeholder.
Returning verified browsers call GET /api/session. My Listings opens My Vehicles, displays server-derived progress and routes Continue Listing to the next incomplete implemented step.

3. Server Boundaries

Back to contents ↑

server.js handles routes, request limits, origin checks, cookies, and responses. storage.js owns SQLite queries, owner-scoped photos, completion validation, disk quota, and backups. inspection.js defines the 12 inspection groups and validates answers. tech.js serves the curated document library separately from seller uploads.

4. Persistence

Back to contents ↑

Local default: data/caruly.sqlite, data/photos, data/backups. Render default: the corresponding files under /var/data on the attached 5 GB persistent disk. DATA_DIR overrides the directory. Local and deployed data do not synchronize.
SQLite tables: drafts, photos, damage_reports, inspections, verified_drafts. The draft cookie contains a random bearer token; only its SHA-256 hash is stored. The cookie lasts 30 days. This is browser ownership, not a production identity system.

5. Routing

Back to contents ↑

The seller UI uses hash routes: vehicle-information, instant-estimate, dashboard, upload-photos, damage-photos, self-inspection, my-vehicles. On a fresh visit, an existing verified demo session restores My Vehicles. Tech uses /tech, so it is directly linkable without seller session restoration.

6. Deployment And Limits

Back to contents ↑

GitHub main deploys to one Render web service. The disk is attached to that service. There is no shared storage layer for multiple replicas. Node runs the server directly; no frontend build is required. Technical documents are curated repository files and are deployed with code. They are not seller documents.

7. Database Catalog And Relationships

Back to contents ↑

Five application tables, verified by initializing a fresh database from the current storage.js schema. No production customer rows were read for this catalog.
- drafts: id TEXT primary key; token_hash unique; details JSON text; created_at and updated_at epoch milliseconds.
- photos: id TEXT primary key; draft_id foreign key; slot, name, mime, size, created_at, deleted_at. Files are stored separately under the photo UUID.
- damage_reports: draft_id primary/foreign key; answers JSON text. One report per draft.
- inspections: draft_id primary/foreign key; answers JSON text. One inspection per draft.
- verified_drafts: draft_id primary/foreign key; verified_at epoch milliseconds. Demonstration verification only.
Each child belongs to a draft. photos_owner indexes (draft_id, deleted_at). The schema uses CREATE TABLE IF NOT EXISTS and user_version=4, without an explicit migration runner. File-write and SQL operations are coordinated but cannot form a single filesystem/database transaction across a crash.

8. Screen Catalog

Back to contents ↑

Nine seller page families in index.html: Sell My Car, Vehicle Information, Instant Estimate, Vehicle Review, Upload Photos, Damage Photos, Self-Inspection, My Vehicles; plus the Tech library as a separate server-rendered page family. Tech document previews add a tenth family. Two native dialogs: Create Your Account and Confirm No Damage. This counting rule excludes inline help, placeholders and every individual document URL. These are a source catalog, not a page registry implemented in the application.

9. Three Concrete Request Paths

Back to contents ↑

Save inspection: browser PUT /api/inspection -> server body/origin/owner checks -> storage.saveInspection -> inspection.validateInspection -> SQLite upsert -> JSON saved result.
Upload image: browser validates image -> POST /api/photos/slot/:slot -> server size bound -> storage signature/quota/owner checks -> UUID file write -> metadata transaction -> saved ID -> browser preview.
Return to website: browser GET /api/session with owning cookie -> hash lookup -> verified_drafts check -> persisted answers and photo metadata -> progress calculation -> My Vehicles. Tech links bypass this hash-route restoration because /tech is served independently.

10. Sources And Maintenance

Back to contents ↑

Prepared from the Caruly source tree and recorded development work on September 13, 2026. Reference report structure supplied by the owner. Update this snapshot when routes, schema, security, or deployment behavior changes. Do not copy unrelated project findings into this report.