Skip to content
CADCAMFUN
Docs

Documentation

Local development

Choose the API process, data directory, and client mode explicitly.

Development processes

A full desktop development session runs a Rust shell, a Bun sidecar, and Vite. The shell supplies native features and supervises the sidecar; Vite supplies webview assets and hot reload. bun run desktop:dev prepares the binary and migration resources before starting those processes.

For faster screen work, run the desktop dev script alone. App.tsx selects the in-memory preview API only outside Tauri and only when VITE_SIDECAR_URL is absent. Preview failures for unsupported API collections are expected to return 501. Use a live sidecar for persistence, authorization, streaming AI, and server services.

Manual sidecar, in an interactive terminal at the repository root
CADCAMFUN_TOKEN=local-development-token CADCAMFUN_DATA_DIR=/tmp/cadcamfun-development CADCAMFUN_MIGRATIONS_DIR="$PWD/packages/db/drizzle" bun --no-env-file apps/sidecar/src/main.ts

The token above is an example for an isolated local development process. Choose your own value. Keep stdin open: closing it stops the sidecar. The server prints one JSON ready event with its ephemeral port after /api/health responds; logs go to stderr.

Second terminal: browser connected to that sidecar
VITE_SIDECAR_URL=http://127.0.0.1:43111 VITE_SIDECAR_TOKEN=local-development-token bun run --filter @cadcamfun/desktop dev

Replace port 43111 with the ready-event port and use the token supplied to that sidecar before running. Vite uses port 1420 with strict port selection, matching the Tauri development URL. The sidecar allows browser CORS origins on HTTP localhost/loopback and the supported Tauri origins; it still requires the appropriate authorization for protected routes.

Data directories and migrations

The sidecar opens <CADCAMFUN_DATA_DIR>/cadcamfun.db. Tauri chooses its own application data directory and passes it to the child. A manual process uses the directory you provide. These databases are independent even when their filename is identical.

The CLI migration script reads DATABASE_URL and otherwise uses ./data/cadcamfun.db relative to its working directory. Root db:migrate runs inside packages/db. Choose an absolute file URL for deliberate CLI operations; do not infer the target from a relative filename shown in a log.

Migrate an explicitly selected disposable database
DATABASE_URL=file:/tmp/cadcamfun-cli/cadcamfun.db bun run db:migrate

Schema changes originate in packages/db/src/schema.ts. Run bun run db:generate, review the generated migration, and apply it to an isolated database first. The sidecar uses CADCAMFUN_MIGRATIONS_DIR when provided; packaged builds stage the generated directory as a resource.

The database layer enables WAL and foreign keys. When an existing file needs a migration, the upgrade path creates a backup beside it under backups/ and retains the latest five matching automatic backups. First creation, an unchanged schema, and in-memory databases do not create an upgrade backup. Preserve data independently before manual recovery operations.

Targeted checks

From the repository root
bun run --filter @cadcamfun/core typecheck
bun test packages/core
bun run --filter @cadcamfun/desktop typecheck
bun test apps/desktop/src/viewport
bun run --cwd packages/web check
bun run --cwd packages/web build

Select checks by the boundary changed. Pure geometry changes need geometry assertions; API contract changes need generated-client checks and affected handlers; persistence changes need repository and migration tests; UI interaction changes need the relevant component and runtime flow. The root test script includes packages, apps, and scripts.

Native shell checks run from apps/desktop/src-tauri with cargo clippy --all-targets -- -D warnings and cargo test. Stage the target sidecar and migrations first, since Tauri's build context includes those resources. Operating-system integration tests can require a native desktop and keychain.

Runtime configuration

apps/sidecar/src/config.ts owns the sidecar configuration layer. Required inputs are CADCAMFUN_TOKEN and CADCAMFUN_DATA_DIR. CADCAMFUN_MIGRATIONS_DIR selects migration resources. The default AI host is nikcli; CADCAMFUN_AI_HOST=direct selects direct calls, and CADCAMFUN_AI_OFFLINE supports offline/test operation.

Optional configuration includes the application URL and development auth links, Stripe credentials and price identifiers, administrator/cron settings, and OTEL_EXPORTER_OTLP_ENDPOINT. Billing is unavailable without the relevant provider configuration; telemetry export is off without its collector endpoint. Supply only the inputs needed for your flow.

Browser endpoint variables are Vite configuration, not sidecar configuration. A companion pairing contains a different token and HTTPS address. A standalone action-bridge token has its own scope and lifetime. Do not substitute these credentials for each other.

Use explicit process configuration or application settings. The sample sidecar command disables Bun's environment-file loading. Never print actual tokens, model keys, pairing links, or signing material in logs or documentation examples.

Effect and resource ownership

The repository pins Effect to 4.0.0-rc.112. Services use Context.Service, implementations are supplied through layers, and operations return typed Effects. Use the installed effect/ai-docs/src documentation when changing this API, including its unstable HTTP modules.

Decode external input at boundaries. Map foreign exceptions into typed errors, preserve stable error tags, and let a scoped layer own database handles, workers, streams, and server resources. The sidecar's shutdown flow handles a parent shutdown event, stdin closure, and runtime interruption; logs and protocol stdout have different destinations.

Core CAD/CAM calculations remain plain functions in computational hot paths. Wrapping validation at the boundary does not require putting every geometry operation inside an Effect. Use the core geometry unit conventions and perform display/export conversions at the appropriate edge. Drawing angles use radians; some feature parameters and CAM rotary-axis values explicitly use degrees.

Startup troubleshooting

  • Vite port occupied: free port 1420 or stop the existing development server; strict port mode does not silently choose another port.
  • Boot keeps retrying: inspect the sidecar ready/error output and migration path. The app re-resolves the endpoint while its connection budget remains.
  • Server exits immediately: check required configuration and whether the launching process closed stdin.
  • Projects missing: confirm the data directory, API endpoint, and whether the app is using the fake client.
  • 401 responses: verify the client is using the token of the current process rather than a previous launch.
  • 501 in browser preview: use a real sidecar for that API collection.
  • Native context build fails: stage the sidecar binary and migration resources for the correct target.

Documentation and companion development

bun run --cwd packages/web start runs Astro alone. bun run --cwd packages/web dev starts Astro plus the local Studio API. The documentation check validates the route index; the build validates Astro compilation and prerendering.

For iOS, bun run --cwd apps/mobile start starts Metro for a custom development client. bun run --cwd apps/mobile ios builds/runs the native app; build exports JavaScript only. Native pinning requires the local Swift module and cannot run in Expo Go.

bun scripts/build.ts --help lists the release pipeline's options. --only=resources restages migrations without rebuilding, and --dry-run prints the plan without writing anything.

Process configuration reference

VariableDefault/requirementUse
CADCAMFUN_TOKENRequiredBearer token supplied by the shell or development launcher.
CADCAMFUN_DATA_DIRRequiredSidecar database and application service state.
CADCAMFUN_MIGRATIONS_DIROptionalFolder of generated migrations. The database layer skips migrations when no folder is supplied.
CADCAMFUN_AI_HOSTnikclinikcli embedded host or direct AI calls.
CADCAMFUN_AI_OFFLINEFalseOffline/test AI operation; not a local substitute model.
CADCAMFUN_AI_MINIMAX_BASE_URLUnsetOptional embedded-host MiniMax endpoint override.
CADCAMFUN_APP_URLUnsetApplication origin used in authentication links.
CADCAMFUN_DEBUG_LINKSFalseDevelopment auth responses can expose reset/magic links.
OTEL_EXPORTER_OTLP_ENDPOINTUnsetEnables telemetry export when configured.
VITE_SIDECAR_URL, VITE_SIDECAR_TOKENUnsetBrowser webview connection; both are needed for a real sidecar.
DATABASE_URLCLI-specific defaultDatabase migration/generation tool target, independent of sidecar configuration.

Boolean inputs are decoded by Effect configuration, not arbitrary string truthiness. Use explicit true/false values. Unknown AI host literals fail decoding. Supply configuration before creating the process; changing a parent terminal variable does not update an already running sidecar.

Use Studio against an explicit database

The local Studio API listens on loopback port 4396. Its path precedence is CADCAMFUN_DB, then DATABASE_URL with a file: prefix removed, then repository-root data/cadcamfun.db. This differs from the database package's default CLI working-directory path. It opens only an existing database and does not create/migrate one automatically.

Use the same disposable file for migrations and Studio
DATABASE_URL=file:/tmp/cadcamfun-studio/cadcamfun.db   bun run db:migrate

CADCAMFUN_DB=/tmp/cadcamfun-studio/cadcamfun.db   bun run --cwd packages/web dev

The first command initializes the file. The second starts Studio plus Astro against that path. A fresh migrated schema does not contain a user/password session merely because it exists; Studio sign-in requires a suitable account. Its authenticated requests use the Studio session cookie and return 401 without a valid session.

When the file is missing, the Studio API returns 503 with the selected path. When Astro runs without the companion Studio process, proxied /studio/api requests cannot reach port 4396. Documentation pages themselves can be developed with packages/web start without starting Studio.

Implementation anchors: packages/web/script/dev.ts, script/studio-server.ts, astro.config.mjs, packages/db/src/migrate.ts, and apps/sidecar/src/config.ts.

A repeatable development loop

  1. Choose a disposable sidecar data directory and explicit migration folder.
  2. Start the sidecar in an interactive terminal and record the port from its ready event.
  3. Start Vite in another terminal with the matching URL/token, or open the native app with its supervised sidecar.
  4. Reproduce one action and inspect its response and persisted state.
  5. For backend changes, restart the sidecar, update the browser endpoint if its port changed, and repeat the action.
  6. Stop the process with its normal interrupt or parent shutdown path so resources finalize.

The sidecar drains HTTP scopes briefly, checkpoints WAL, and closes SQLite on normal scoped shutdown. Killing a process without that path can interrupt in-flight work. A source edit does not replace the compiled binary already supervised by Tauri; rebuild the sidecar when testing compiled behavior.

For compiled-runtime validation, scripts/smoke-sidecar.ts can run a selected binary with an isolated home/data directory and offline AI. It measures readiness/health/action behavior and exercises a kernel job. Without --binary it first compiles a temporary executable, so plan for the build cost; its result is separate from source-level tests.

Which process runs where

CommandStartsData directoryDatabase
bun run desktop:devCompiled sidecar + Tauri dev windowApplication data directory chosen by Tauri<dataDir>/cadcamfun.db
Manual sidecar (bun apps/sidecar/src/main.ts)Sidecar only, on an ephemeral loopback portCADCAMFUN_DATA_DIR<dataDir>/cadcamfun.db
bun run db:migrateMigration script—DATABASE_URL or packages/db/data/cadcamfun.db
bun run --filter @cadcamfun/web studioLocal Studio—CADCAMFUN_DB, DATABASE_URL or data/cadcamfun.db
bun run --filter @cadcamfun/web devDocs site——

Four different database defaults

These entry points do not share a default path. Set the path explicitly when you need two tools to look at the same file.

Inner loop by change type

You changedRun
Kernel code in packages/corebun test packages/core
A contract in packages/apibun run generate, bun run generate:check, the sidecar tests, then the docs generate:api-reference
A sidecar handler or servicebun test apps/sidecar
The schemabun run db:generate, commit the new migration folder, bun scripts/build.ts --only=resources
Rust in src-tauricargo clippy and cargo test in apps/desktop/src-tauri
Docs pagesbun run typecheck and bun run build in packages/web

In 3D

What runs when you develop locally Drag to orbit · scroll to zoom · right-drag to pan
Processes at run time. The Tauri shell spawns the sidecar and waits for its {”event”:”ready”,”port”:N} line on stdout (sidecar.rs); the webview then talks HTTP to 127.0.0.1 on that port with the bearer token. The sidecar owns the SQLite database, the embedded nikcli AI host (CADCAMFUN_AI_HOST=nikcli, the default) and plugins; the mobile app reaches it through companion pairing.