Skip to main content
Mind lives in apps/mind, runs locally on port 7816, and is served in production from https://mind.tuturuuu.com. Local development should use Portless at https://mind.tuturuuu.localhost; the legacy direct fallback is http://localhost:7816. Mind is available to signed-in Tuturuuu users, not only internal @tuturuuu.com accounts. The satellite app accepts the Tuturuuu cross-app login handoff through /verify-token, stores a host-local tuturuuu_app_session cookie for the mind app target, and keeps workspace data behind membership checks. Mind must not create a local Supabase Auth session. Mind consumes /verify-token in the proxy and requires the coordinated cookie pair on protected routes: the Mind-local app-session cookie for route guards and the Web-issued app-session cookie for forwarded central APIs. If only the Mind-local cookie remains, route users through local /login to refresh the pair. Expired access tokens should rotate through /api/auth/refresh-app-session on the Mind origin while refresh cookies are valid. Mind AI also follows the shared AI credit contract instead of an employee-only allowlist. The /api/ai/mind route resolves the selected personal or workspace credit source, checks the caller’s membership for workspace credits, preflights model availability and remaining credits, and deducts usage from that same billing workspace after a successful stream. Mind AI uses the stable google/gemini-3.1-flash-lite model entry for its Flash Lite default/fallback surface. Stored preferences and old clients that still send google/gemini-3.1-flash-lite-preview are normalized to the stable ID before credit model resolution and provider streaming. The model selector reads from the paginated infrastructure model catalog with server-side search and “load more” pages. Do not reintroduce first-page-only catalog fetches or local-only filtering; matching models must remain reachable even when they are outside the initial response.

Dual-Host Parity

Mind is available through both the standalone satellite host and the main web dashboard. The standalone route shape stays /{wsId} and /{wsId}/boards/{boardId}. Inside apps/web, the route shape is /{wsId}/mind and /{wsId}/mind/boards/{boardId}. Both hosts must render the same shared UI and use the same client logic from @tuturuuu/mind-ui. Keep apps/mind and the apps/web Mind routes as thin host wrappers for auth, workspace resolution, and route prefixing only. Future Mind feature work belongs in packages/mind-ui or the centralized Mind APIs so the standalone app and web-hosted app stay 1:1. Board route-segment layouts that render Mind board routes must load @xyflow/react/dist/style.css, and the shared Mind shell must keep a concrete dashboard embed height. Keep that stylesheet out of root app layouts and the Mind index so it is only loaded when users enter a canvas route. Without both pieces, React Flow can mount but render as a blank or collapsed canvas inside embedded dashboard routes.

Board library vs studio

The workspace index route is a board library, not the canvas studio:
  • Web: /{wsId}/mind lists boards (search, create, pick). Selecting or creating a board navigates to /{wsId}/mind/boards/{boardId} for the studio.
  • Satellite: /{wsId} is the same board library; /{wsId}/boards/{boardId} is the studio.
MindBoardIndex from @tuturuuu/mind-ui owns the index experience. Do not auto-select the first board on the index route. MindDashboard only mounts on board routes and receives initialBoardId; it must not fall back to boards[0]. If a board route loads without a selected board, prompt the user to return to the index instead of showing an infinite loading state.

API Ownership

Protected Mind data stays behind apps/web APIs:
  • /api/v1/workspaces/:wsId/mind/boards
  • /api/v1/workspaces/:wsId/mind/boards/:boardId
  • /api/v1/workspaces/:wsId/mind/boards/:boardId/graph
  • /api/v1/workspaces/:wsId/mind/boards/:boardId/patches
  • /api/v1/workspaces/:wsId/mind/search
  • /api/v1/workspaces/:wsId/mind/ai/patches/:patchId/apply
  • /api/v1/hive/servers/:serverId/mind-simulations for importing a Mind board into Hive as agents plus a saved interaction workflow
  • /api/ai/mind
  • /api/ai/chat/upload-url, /api/ai/chat/delete-file, and /api/ai/chat/file-urls for Mind chat attachments
The Mind app forwards /api/v1/* and /api/ai/* to apps/web and consumes them through @tuturuuu/internal-api. Do not add direct client Supabase reads or client-local raw fetch('/api/...') calls for protected Mind data. Workspace routes must normalize aliases such as personal, verify workspace membership with the request-scoped auth context, and then perform private-schema reads or writes through the centralized server repository. Mind repositories must not use ad-hoc raw SQL from application code. Keep data operations in private-schema Postgres RPCs and call them through a service-role Supabase admin client with .schema('private').rpc(...). apps/database/supabase/config.toml exposes the private schema to PostgREST so these RPCs are callable, but table/function grants stay service-role-only. Changing that config requires a local Supabase restart or bun sb:up before the Mind APIs stop returning Invalid schema: private. The canvas should load from the graph-only snapshot path, while generated draft patch artifacts load from the patch-list path. Do not couple canvas rendering to recent AI patch serialization: a failed patch-artifact refresh should stay inside the assistant panel and must not replace the board canvas with a board load error. The legacy full snapshot can still return graph data plus patches for backward compatibility. Mind graph handles use loose React Flow connections with one visible connection point per side. Cluster and children frames are synthetic canvas nodes used only for interaction: manual links to a frame persist as normal node edges with frame endpoint metadata, so saved graph payloads still satisfy the node-only edge schema while rendering the relationship to the group boundary. Nodes, relationships, clusters, and child-group frames should all be selectable from the canvas. Node and relationship selections open editable properties, while synthetic group or cluster frame selections open a compact read-only properties island that identifies the anchor node and child count.

Hive Integration

Inside apps/web, a Mind board can be sent to Hive from the compact top-right canvas controls. The import API reads the saved Mind graph, verifies workspace membership through the request-scoped client, requires Hive admin access, and creates Hive NPC agents from the highest-signal Mind nodes. Mind edges become Hive agent interaction pairs, and the generated Hive workflow first stamps the Mind source context into the world before running the agent-interaction node. Keep this integration hosted in apps/web: the standalone apps/mind surface should stay a shared Mind canvas and must not assume that the Hive satellite is available in the same host. Client code should call createHiveMindSimulation() from @tuturuuu/internal-api/hive; do not add client-local raw fetch calls or duplicate graph-to-agent conversion logic.

Data Model

Mind product tables live in the private schema. User access goes through the central web API; direct table access is service-role only.
  • private.mind_boards
  • private.mind_nodes
  • private.mind_edges
  • private.mind_tags
  • private.mind_node_tags
  • private.mind_groups
  • private.mind_group_nodes
  • private.mind_node_links
  • private.mind_ai_threads
  • private.mind_ai_messages
  • private.mind_ai_patches
mind_node_links is the first integration seam for Tasks, Calendar, documents, projects, and external URLs. Live pickers can attach to this link contract later without changing the core graph schema. Nodes carry a first-class workflow status: backlog, planned, in_progress, in_review, blocked, completed, deferred, and cancelled. The canvas and AI tools should treat status as a planning signal, not just decoration: blocked nodes need dependencies, in-review nodes need validation criteria, and completed nodes should remain available for historical context and dependency tracing.

AI Patch Safety

Mind AI chats default to review mode. In review mode, tools can inspect mindboards, load graph chunks, search nodes, and store proposed patches, but the user applies the patch explicitly from the Mind UI. Direct-write mode is scoped to the current chat. In direct-write mode, the apply_mind_patch tool can write the structured patch transactionally and the repository records the patch status, applied_at, and applying user for audit. Structured patches should stay small enough to review. Prefer multiple focused patches over a single broad rewrite when consolidating large graphs. For normal structure-generation requests, a patch should still be complete enough to be useful: include the major clusters, concrete child nodes, and the relationship edges that connect them to the root goal or to each other. Avoid AI drafts that expand only one branch while leaving related top-level systems as isolated nodes. The existing board is authoritative. AI drafts should reuse and extend relevant existing node IDs first, then create missing child nodes and relationships around those anchors. Do not draft a detached replacement root when the current mindboard already contains a matching goal, system, cluster, or milestone. The patch tool normalizes generated aliases and stores operations in apply-safe order: newly-created parent and child nodes are inserted before relationship edges or updates that reference them. Existing draft patches are normalized again just before application so older edge-first drafts do not fail foreign-key checks. For large boards, the assistant should inspect structure first, then search or load neighborhoods/chunks instead of requesting a full graph by default. Keep responses action-oriented: suggest follow-up passes, propose draft patches when they are useful, and only implement graph writes when the chat is explicitly in Implement mode. After a draft patch is applied from the Mind UI, the client closes the assistant panel, reloads the board, runs the smart canvas organizer, saves the resulting positions, and refreshes board queries. The organizer should keep true same-level sequence nodes in a compact horizontal lane, place explicit children under their parent, and anchor supporting or dependency nodes near the higher-level node they affect. Applying a draft and refreshing layout are separate phases: once the patch application RPC returns, patch artifacts should show Applied immediately. If the follow-up auto-layout save fails, keep the patch applied and show a retryable layout-refresh warning instead of treating the graph patch as failed. Mind boards auto-save canvas edits. The board title, canvas tools, tag filter, and save status live in one compact top-left island. The title is editable from that island, the tag filter uses an icon-only ghost dropdown, and the save icon shows saved, saving, unsaved, or retryable error state and can be clicked to force a save. In the web-hosted board route, the compact top-right island owns the Hive simulation launcher and the assistant toggle. Autosave signatures, tag indexing, group-frame layout, and relationship routing obstacle scans are intentionally debounced so dragging stays responsive on dense boards; keep direct node movement immediate and move only derived calculations onto short debounce windows. React Flow canvas routes should pan with two-finger trackpad movement while preserving pinch-to-zoom. Do not switch trackpad scrolling back to zoom-only behavior; use explicit canvas controls or pinch gestures for zoom. Generated plans and patch drafts should be treated as artifacts. The newest artifact can open in the proposal island, while every message keeps a compact artifact row for reopening it. When a generated visual plan and a draft patch belong to the same assistant response, render them as one centralized draft proposal pending approval: the structured patch preview is the review context, and the single Apply action belongs to the proposal shell. Do not show the visual plan and draft patch as duplicated stacked content. Tool-call and artifact sections default to collapsed compact rows; while the assistant is working, the row should show a spinner and the latest tool or artifact name without expanding the full debug list. When a draft is applied, the applied patch should render as Applied in those artifact views instead of staying visually draft-only. The canvas toolbar can copy the current board as Markdown or JSON. This export uses the local in-canvas graph state, including unsaved position edits, so it is useful for sharing a planning snapshot or debugging AI patch output.

Deployment

Mind has dedicated Vercel workflows:
  • .github/workflows/vercel-preview-mind.yaml
  • .github/workflows/vercel-production-mind.yaml
Store VERCEL_TOKEN, VERCEL_ORG_ID, and VERCEL_MIND_PROJECT_ID in the workflow environments vercel-preview-mind and vercel-production-mind. Deployment should rely on Vercel project environment variables pulled by vercel pull; do not add provider AI keys, production Supabase service keys, TURBO_TOKEN, or TURBO_TEAM at workflow scope.

Verification

After changing Mind schema, API, or UI code, run the most relevant focused checks first, then the repo-required checks:
bunx vitest run packages/internal-api/src/mind.test.ts packages/ai/src/mind/patch.test.ts
bun i18n:sort
bun type-check:mind
bun check
After applying the local Supabase migration, run bun sb:typegen and consume database shapes through @tuturuuu/types/db.