Skip to main content
This section contains tools, guides, and best practices for developing on the Tuturuuu platform.

Getting Started

Development Workflow

Documentation

  • Documenting - How to write and maintain documentation

Development Guidelines

Code Quality

  • Formatting and linting are handled by Oxc (.oxfmtrc.json and .oxlintrc.json), not ESLint or Prettier. Use bun ff to format, lint, and check in one pass.
  • Run focused tests, then the build-free bun check:changed gate before every push. bun validate is not run on agent machines because its Turbo graph can build workspace dependencies; it and app builds run in CI for the exact commit (see pre-push checks).
  • Default to Server Components in apps/web; add 'use client' only for state, browser APIs, or interactivity.
  • Prefer typed expected errors and dependency services via @tuturuuu/utils/effect for new server/service orchestration.

Git Workflow

  • Use Conventional Commits for commit messages and branch names.
  • The branch checker only accepts these prefixes: feature/, feat/, fix/, bugfix/, hotfix/, release/, chore/, docs/, style/, refactor/, perf/, dependabot/, and claude/.
  • Keep commits atomic and write descriptive PR descriptions.
  • Run bun check:changed before every push; it maps changed paths to the cheap CI gates without builds. See pre-push checks.
  • Do not manually bump TUTURUUU_PLATFORM_VERSION, package versions, or changelogs — Release Please owns version updates.

Testing

  • Tests run with Vitest. Use bun test for the full suite or filter to a single workspace (for example bun --filter @tuturuuu/web test).
  • Write unit tests for utilities and cover error scenarios.
  • Run focused tests before the full bun validate gate.

Performance

  • Default to server-side rendering and Server Components where possible.
  • Use TanStack Query for client-side fetching and caching; avoid useEffect for data fetching.
  • Minimize bundle size and profile performance regularly.

Tools and Scripts

Package Management

Dependencies are always installed from inside the owning workspace — never by hand-editing the root package.json and never with a --workspace flag.
For a broad refresh, also update Rust (cargo update in apps/backend), Python (uv lock --upgrade in apps/discord), and Flutter (flutter pub upgrade --major-versions in apps/mobile). Keep native CocoaPods locks aligned with Flutter plugins and retain stable versions when a registry’s latest tag points at a prerelease. The configured npm release-age policy still applies. Run bun check:changed locally and require bun validate and affected app builds to pass in CI for the exact commit. Keep React and React DOM aligned at 19.2.8 while React Three Fiber 9.7.0 requires versions below 19.3. The root overrides also prevent transitive peer dependencies from selecting a second runtime; revisit both overrides and Hive workspace constraints when Fiber supports the next React minor. Keep @types/react and @types/react-dom on the matching runtime minor as well. Other packages retain compatible consumer ranges so the repository overrides do not force a second React copy into published-package consumers. For a security patch, save the initial bun audit --json result and update direct dependencies with bun update <package>@<fixed-version> from the owning workspace. For transitive fixes, manage the root overrides with bun pm pkg set --json 'overrides=<merged JSON object>', preserving existing entries. Prefer selectors restricted to vulnerable versions, with the minimum fixed release on each major; test the consumer before crossing a major version. Re-run the audit after resolution because an initial fix can itself have a newer advisory. Verify the resulting lock with bun install --frozen-lockfile, run focused tests through the resource queue, and require applicable exact-commit CI. Builds remain CI-only, and paused runtimes remain excluded. Keep Vite+ and its core alias on the same published version; check the upstream release’s bundled Vite version separately from plain vite dependencies. Audit Python locks, Flutter/Pub advisories, and pinned Actions separately from Bun. An advisory without a published fix remains an explicit blocker, even when other packages are clean. Do not remove a used dependency or suppress an advisory merely to reduce the reported count. React-PDF 11 requires Node.js 22.13 or newer; CI uses Node.js 24. Its default Suspense behavior differs from version 10, so the shared PDF viewer explicitly keeps its existing loading and error handling with suspense={false}. Mermaid 12 also changes visual defaults; the chat renderers set layout: 'dagre' and look: 'classic' to preserve existing diagrams.

Development Commands

Database Commands

bun sb:push and bun sb:linkpush push migrations to the remote Supabase project and are reserved for the maintainer applying production changes. Do not run them — prepare migrations locally with bun sb:up and let the user apply production changes.

Troubleshooting

Common Issues

  1. Build / Check Failures: Run bun check:changed to surface TypeScript and Oxc errors in changed files, and confirm dependencies are installed with bun install
  2. Database Issues: Ensure the local Supabase stack is running (bun sb:start) and migrations are applied (bun sb:up)
  3. Test Failures: Check environment setup and re-run the focused Vitest workspace before bun check:changed; the full bun validate gate runs in CI
  4. Performance Issues: Use React DevTools and bundle analyzers

Getting Help

  • Check existing documentation
  • Search GitHub issues
  • Ask in team channels
  • Create detailed bug reports

Contributing

When contributing to the platform:
  1. Read the relevant documentation
  2. Follow the established patterns
  3. Write tests for new features
  4. Update documentation
  5. Submit a pull request with a clear description

Task-owned temporary files for check stages

When an admitted runner has a constrained /tmp user quota, prepare a unique, existing current-user directory with mode 0700 on a filesystem with freshly verified quota and free-space capacity. Set TUTURUUU_CHECK_CHILD_TMPDIR to its absolute real path when invoking normal bun validate through ttr resources run. The option changes TMPDIR, TMP, and TEMP only for validation children. Keep the check runner’s own TMPDIR, HOME, and TTR_RESOURCES_HOME unchanged; both shared queues remain in their original locations. Directory validation alone does not establish capacity or authorize cleanup. Invalid directories fail without falling back to /tmp. Child processes carry a sentinel preserved through Turbo strict mode that rejects a nested bun validate CLI before it creates a queue; imports of the check module remain allowed. Run another broad check separately through the original queues. This option does not skip checks, change resource limits, or turn an incomplete or failing check into a pass.

Aggregate validation and native Bun type checking

bun validate is the repository aggregate (formerly the custom bun check script). bun validate:now retains the explicit --force-now queue behavior. Both invoke the same scripts/check.js; flags, fail-fast handling, mandatory Oxc follow-through, queues and child-temp isolation are unchanged. The legacy tuturuuu-bun-check queue directory and environment names stay stable so old and new runner processes coordinate during the rename. The aggregate still covers workspace tests, Turbo type-checking, blocking Oxc format/lint, source size, public SEO, server console, internal-app-auth, satellite cookie auth, offline Worker wiring, multi-account vault ownership, legacy API wrappers, mobile iOS settings and API mappings, script tests, next-intl setup, translation validity/key parity/sorting/namespaces and migration timestamps. Platform release alignment runs for release files; Discord Python validation runs for Discord changes. No component was replaced with a type-only command. bun check:changed remains the separate build-free pre-push gate; other check:* commands retain their roles. ttr resources run -- bun check --no-script -p <project> explicitly invokes Bun’s native type-only checker. A package script named check takes precedence over native checking; scripts/validate-command.test.js rejects that name in the root and every workspace, including retained inactive workspaces. The test is discovered by the existing script-test gate. Native checking is not a substitute for bun validate, app builds, guards, tests, or declaration generation. The ban on local aggregate/build execution applies to bun validate; native qualification still requires resource admission and a bounded thread count. The resource wrapper injects --threads=<lane buildJobs> when absent and clamps explicit values to that lane limit, preserving smaller requests. The aggregate rejects unknown arguments, including --help and --dry-run, before starting work, prints one usage line to stderr and exits 1; neither flag provides an aggregate preview. The inventory recognizes both wrangler types and cf types as declaration generators, including scripts with custom names. It reads package manifests without executing generators. The legacy detector and its data-only regression fixture have an explicit producer-inventory Wrangler-gap admission.

Native checker qualification

The required gate remains tsc 7.0.2, including run-tsc-build.js and its cache invalidation. PR #6468 supplies optional tsrs 7.1-dev shadow/advisory pre-push comparison; it is not the required CI baseline. Keep both until a replacement proves all existing semantics. Do not remove TypeScript: declaration producers and editor tooling still require it. Bun 1.4.4 reports TypeScript 7.0.2 through bun -p process.versions.typescript, matching the repository compiler version. It embeds its own compiler and standard library; matching versions alone is not proof of diagnostic or build equivalence. The repository Bun pin remains owned by the separate Bun upgrade/security lane; this change does not update it. Native execution requires Bun 1.4.4, while validate works with the existing pin. See Bun’s native checker. There are 89 root/workspace manifests; only the root defined check before the rename. Active scripts invoke tsc from TypeScript 7.0.2, often through run-tsc-build.js. No active manifest invokes a separate tsgo binary; that name is recognized by the changed-files project resolver. tsrs is installed externally for shadow/pre-push use, not as a workspace dependency. Run node scripts/ci/bun-check-inventory.js to inventory root/workspace scripts, resolved type-check projects, inactive workspaces and custom emit/generation producers. Turbo’s type-check still depends on ^build and ^type-check. Meet has a custom declaration producer; Calendar/Mail split app, boundary and Worker configs; several services generate Wrangler ambient declarations before checking. Those steps must survive any future switch. The opt-in Linux harness is scripts/ci/bun-check-qualification.js --out <private-dir> --threads 6 --runs 5 [--tsrs <pinned-binary>]. Invoke it with node inside the existing fenced exact-SHA runner after frozen dependency installation. It does not create another CI gate. Each report records source SHA, lock hash, versions, host/load, exact commands, resolved configs/references, file closures and hashes, full diagnostics, exit status, wall time and peak RSS. --all disables native diagnostic grouping. The known-invalid control adds a fresh TS2322 assignment under packages/types/src, requires every checker to report it, and removes the file in finally; the mutation and source hash are recorded separately. This harness compares the same no-emit projection used by the existing shadow: noEmit=true, incremental=false, composite=false. This alone does not prove the original build/reference/emit semantics. First runs are process cold; subsequent runs use fresh processes with warm OS caches. It does not evict shared host caches or claim cold filesystem results. Alternate checker order, report all five observations and errors, and compare diagnostic multisets before comparing performance. Real diagnostic differences or unverified generated closures prohibit gate promotion. Preserve declaration/emit tasks even after future diagnostic equivalence is established.

Bun 1.4.4 evaluation: initial declaration closure

The first exact-source run at b56c8fde67b487ee07961004feb92930f121b945 used a Linux build host (x86_64, 20 CPUs), the fenced early-merge-validate.sh runner, Bun 1.4.4 and Node 24.22.1. Both Bun’s embedded compiler and the baseline reported TypeScript 7.0.2; the tsrs pin reported 7.1.0-dev.20260930.4. The frozen bun.lock SHA256 was c4687dadb08c5aa33a132d860f8d44a0b7ee2c032ec11c09e5724a4d864999e2. All checkers used a six-thread budget (--threads 6, GOMAXPROCS=6, RAYON_NUM_THREADS=6 as applicable). The four standard Types/Supabase/Internal API/Masonry declaration prerequisites were built first. Each paired comparison used identical source/dependencies and effective no-emit flags; all 11 recorded input closure hashes stayed unchanged. There was one process-cold pass and four warm passes per checker, with alternating order, plus five error-control runs. The host was shared (initial load averages 9.57/34.93/31.40); these are observations, not an adoption or speedup claim. Source-loading inventory had already warmed filesystem caches before the first timed compiler process. Totals above sum the 11 project checks sequentially. Peak RSS is the maximum single checker process, not summed memory. Warm values summarize four totals; error values summarize five runs of the injected Types control only. tsrs and Bun did not perform identical validation work on this initial closure, so the timing columns must not be used as an equivalence-adjusted performance ratio. Every checker reported the injected TS2322 at the same file, line, column and message in all five runs; the control was removed afterward. Existing real checkout diagnostics also matched exactly: Calendar Worker reported TS2307 for the absent generated #calendar-handler alias, and Web plus SDK reported TS2307 for absent @tuturuuu/devbox declarations. These are genuine checkout diagnostics, but they are missing generated inputs rather than evidence of a fully prepared production type gate. Meet’s Worker config has disableSourceOfProjectReferenceRedirect: true and references its app declaration producer. With those declarations absent, tsc reported two TS6305 diagnostics for token.d.ts and handler.d.ts; Bun reported none. This is consistent with Bun’s documented use of referenced source instead of prebuilt declarations. Removing the current gate at this point would lose an existing generated-output assertion. tsrs also differed from the 7.0.2 baseline (20 UI diagnostics and 20 Web diagnostics versus 0 and 2). Native gate promotion remains unqualified. Retain the authoritative producers, emit/declaration validation and existing baseline. The follow-up uses --all-projects --runs 1 after running the existing complete Turbo type gate, including Meet/Calendar boundary producers, to distinguish missing-output differences from source diagnostic differences. This mode covers all active inventoried projects and expands Meet’s solution root into its two concrete configs; inactive TanStack remains excluded. It is coverage evidence, not a second performance benchmark or an automatic rollout decision.

Prepared-closure coverage result

At 612429d21223b91018e632ebd84b6044c19d00ec, the unchanged authoritative Turbo type graph passed on the same Linux host (72 seconds, concurrency 2, GOMAXPROCS=6). Its declaration and boundary producers prepared the complete closure. The subsequent one-pass comparison covered 86 concrete configs from 79 active workspaces: all had exact diagnostic parity, zero diagnostics and unchanged input-closure hashes. The additional TS2322 negative control also matched exactly and failed in both checkers as intended. The lock hash and compiler versions matched the earlier run. Inactive TanStack was not executed. This qualifies the observed prepared no-emit projection of those configs. It does not establish drop-in equivalence for the complete current gate: composite/incremental behavior was disabled for the paired measurements, Bun intentionally does not enforce the same missing-reference-output behavior, and it does not provide emit or the existing producer/cache receipts. Keep the TypeScript gate and tsrs shadow; no checker dependency was removed. Before a switch, compare unmodified config semantics and preserve the producer/output assertions explicitly, including a missing/stale-output regression. Do not interpret the prepared all-green result as permission to discard those checks. The complete build-free pre-push gate passed on Linux for the implementation commit, including the changed SDK/Devbox tests and type checks; focused Node coverage passed 92 tests on the Mac through resource admission. The installed Mac shim and nested workspace CLI had incompatible admission behavior, so that owned full-gate invocation was stopped and the remaining checks ran on Linux. No installed scheduler was modified. Exact-head hosted CI and independent review remain separate delivery gates; no merge or production sync is part of this change.