Active migration. The legacy
apps/web Next.js runtime (port 7803) is being
replaced by apps/tanstack-web (TanStack Start) for the frontend and
apps/backend (Rust) for the API layer. See
TanStack Start And Rust Migration
for the migration contract and
apps/tanstack-web/migration/route-manifest.json for live route-by-route
progress. Treat the tRPC and Next.js REST sections below as the legacy
apps/web path; new read/write endpoints increasingly land in the Rust backend.Service Boundaries
Current Services
Additional product apps (
apps/chat, apps/drive, apps/mail, apps/cms,
apps/mind, apps/teach, apps/track, apps/storefront, and others) follow the
same conventional Next.js App Router shape and share the same Supabase project.
Shared Packages
All services share common infrastructure via workspace packages:Monorepo Architecture
Benefits
- Shared Code: Common utilities, UI components, types shared across services
- Atomic Changes: Change types in one commit, update all services
- Simplified Tooling: Single build system (Turborepo + Bun)
- Easy Refactoring: Move code between services, extract packages
- Consistent Standards: Shared linting, testing, deployment configs
Structure
Workspace Dependencies
Services declare dependencies on shared packages:Communication Patterns
1. Background Jobs (Trigger.dev v4)
When to use: Asynchronous workflows, background processing, scheduled work Implementation: Trigger.dev v4 (@trigger.dev/sdk ^4.4.5), using the
task() API. Task definitions live in packages/trigger/src.
The v2/v3 client.defineJob / eventTrigger / io.runTask APIs do not exist
in this repo. Define a task with task() and run it from app code with
tasks.trigger(...) (or <task>.trigger(...)):
The import path isCharacteristics:@trigger.dev/sdk/v3even though the installed SDK is the v4 line — that path is the current entrypoint for thetask()API.
- Loose coupling: producers fire-and-forget, tasks run out of band
- Resilient to failures, with built-in retries and queue concurrency limits
- Asynchronous processing
- Run history and replay in the Trigger.dev dashboard
2. Shared Database (Current)
When to use: Strong consistency requirements, complex queries across entities Implementation: Supabase PostgreSQL with RLS- Strong consistency
- ACID transactions
- Complex joins possible
- Shared schema (requires coordination)
- ✅ Simple implementation
- ✅ Strong consistency
- ❌ Tight coupling at data layer
- ❌ Schema changes affect multiple services
3. tRPC (legacy apps/web, currently a stub)
Status: The tRPC layer in apps/web/src/trpc is intentionally a stub. The
router (apps/web/src/trpc/routers/_app.ts) exports a single healthCheck
baseProcedure to keep the type system wired up:
createTRPCRouter, createTRPCContext, baseProcedure, and
createCallerFactory. There is no protectedProcedure, no auth middleware,
and no workspace/user/tasks/ai routers — the context is not a product data layer.
Product data flows through @tuturuuu/internal-api helpers and REST
/api/v1/* routes (below), not through tRPC. In apps/tanstack-web a guard
(check-tanstack-api-access) forbids /trpc calls entirely.
Do not document tRPC as the canonical internal API surface — it is a thin
compatibility shim that may be removed during the migration.
4. REST API (/api/v1, legacy apps/web) and the Rust backend
When to use: Public APIs, webhook endpoints, third-party integrations, and
product read/write endpoints.
Legacy implementation: Next.js App Router route handlers under
apps/web/src/app/api/v1/* (e.g. workspaces, inventory, nova, storage):
apps/backend, port 7820) is
progressively taking ownership of these endpoints. Route groups live in
apps/backend/src/*.rs (for example inventory.rs, nova.rs,
onboarding_progress.rs, aurora.rs), and the contract is documented in
apps/backend/api/openapi.yaml. Migration progress per endpoint is tracked in
apps/tanstack-web/migration/route-manifest.json.
Characteristics:
- Standard HTTP / JSON
- Versioned endpoints (
/api/v1/...) - Rate limiting and authentication
- OpenAPI documentation for the Rust backend (
apps/backend/api/openapi.yaml)
Service Communication Matrix
Most cross-surface coordination is not direct service-to-service RPC: apps
share the Supabase database (guarded by RLS) and hand off long-running work to
Trigger.dev. This keeps coupling at the data and job layers rather than in a
service mesh.
Deployment Strategies
Next.js apps: Vercel
Each Next.js app deploys independently to Vercel. CI builds the selected app, packages prebuilt artifacts, and deploys the production artifact through the matching GitHub Actions workflow. There is one Vercel workflow per app, named by product surface. For example,vercel-production-platform.yaml builds apps/web on pushes to the production
branch and deploys the prebuilt production artifact:
vercel-preview-*.yaml workflows run for pull requests. Node engines are
>=22 (CI uses Node 24) and Bun is pinned to 1.3.14.
Rust backend
apps/backend is built and validated by .github/workflows/rust-backend.yml.
It runs as a native container and keeps a Cloudflare Workers Rust entrypoint
(apps/backend/wrangler.jsonc) ready for edge preview deployment, per the
migration contract.
Independent Scaling
Each app scales independently on its hosting platform (Vercel autoscaling for the Next.js apps; container/edge scaling for the Rust backend). The per-appminInstances/maxInstances objects shown in earlier versions of this page were
illustrative, not a real config file in the repo — scaling is configured in the
Vercel project settings and the backend’s container/edge runtime, not in
versioned source.
Service Boundary Decisions
When to Create a New Service
✅ Extract to new service when:- Feature is logically independent (e.g., URL shortener)
- Different scaling requirements (high-traffic vs low-traffic)
- Different technology needs (Python for ML vs TypeScript for web)
- Team ownership boundary (separate team owns feature)
- Independent deployment cycle needed
- Shares most code with existing service
- Tight coupling to core domain
- Low complexity (< 1000 LOC)
- No special scaling or technology needs
Example: Why finance is a separate app
Data Ownership
Current: Shared Database Pattern
Pros:- Simple joins across entities
- Strong consistency
- ACID transactions
- Single source of truth
- Tight coupling at data layer
- Schema changes affect multiple services
- Harder to scale independently
Aspirational: Service-Specific Databases
This is not implemented today. Every app shares one Supabase project. The
following is a future option, not current architecture.
- A surface needs a specialized database (e.g., PostGIS for geolocation)
- Independent scaling requirements for specific data
- Strong service boundaries needed
Package Extraction Strategy
When to Extract to Package
The repo’s rootAGENTS.md carries the package-extraction decision matrix. As a
rough heuristic, extract when ≥3 HIGH signals:
Example extractions in Tuturuuu:
Testing Strategies
Unit Tests
Test individual services in isolation:Integration Tests
Test service interactions:End-to-End Tests
Test full user workflows across services (future):Monitoring & Observability
Service Health
Correlation IDs
There is no dedicated@tuturuuu/logging or @tuturuuu/observability package and
no event-store; the example below is an illustrative pattern. Runtime server
code should log diagnostics with the native console method matching severity.
Migration Paths
Current State → Future State
Current: A monorepo of Next.js apps over one shared Supabase project, with background work on Trigger.dev v4. In progress: The frontend is migrating fromapps/web (Next.js) to
apps/tanstack-web (TanStack Start), and the API layer to apps/backend (Rust).
This is the concrete, active migration — see
TanStack Start And Rust Migration.
Longer-term options (not committed):
-
Service-Specific Databases (when needed)
- Extract finance data to dedicated DB
- Communicate via events
- Maintain consistency with sagas
-
API Gateway Layer (if REST APIs grow)
- Single entry point for external clients
- Route to appropriate services
- Handle auth, rate limiting centrally
-
GraphQL Federation (if complex queries needed)
- Each service exposes GraphQL schema
- Gateway federates schemas
- Clients query unified graph
Related Documentation
- Architectural Decisions - Why microservices
- Event-Driven Architecture - Inter-service communication
- Monorepo Architecture - Turborepo setup
- Database Schema - Shared schema details