This guide is developer material for contributors. It describes the code organization of Marinara Engine: shared foundations, feature systems, mode ownership, and where each piece of code belongs. It also lists the current large files and the direction for future refactor work.
Scope: packages/client/src, packages/server/src, and packages/shared/src. The repo keeps no conventional .test.ts suite. Tracked regression scripts and Playwright smoke coverage provide automated validation; temporary .test.ts proof files are gitignored and removed after use.
File counts, line counts, and route counts drift as the repo changes. This map gives approximate shapes and names. Always check the current tree for exact numbers.
Use these codes when planning moves, labeling issues, or adding a short file header to code that cannot be moved yet.
| Code | Meaning | Primary home |
|---|---|---|
CORE-CONTRACT |
Types, schemas, constants, pure helpers shared by client and server | packages/shared/src |
CLIENT-APP |
React app bootstrap, layout shell, global UI wiring | packages/client/src/App.tsx, main.tsx, components/layout |
CLIENT-SHARED |
Client-only UI primitives, common hooks, common browser helpers, global stores | packages/client/src/components/ui, hooks, lib, stores |
SERVER-APP |
Fastify app bootstrap, middleware, route registration, runtime config | packages/server/src/app.ts, index.ts, middleware, config |
SERVER-SHARED |
Server-only storage, DB, LLM, prompt, lorebook, import, and integration foundations | packages/server/src/services, db, utils, lib |
MODE-CONVERSATION |
Conversation-only UI and server behavior | conversation components, /api/conversation, conversation services |
MODE-ROLEPLAY |
Roleplay UI, scenes, sprites, encounter helpers | roleplay chat components, /api/scene, /api/encounter, /api/sprites |
MODE-GAME |
Game-mode UI, GM prompts, dice, party, map, combat, assets, sessions | components/game, /api/game, game services |
FEATURE-AGENTS |
Agent definitions, execution, debug state, knowledge routing | agent components, agent store, agent routes/services |
FEATURE-ASSETS |
Backgrounds, avatars, gallery, generated images, sprites, game assets | asset routes, gallery storage, image services |
FEATURE-SIDECAR |
Local model runtime, scene analysis, downloads, process control | sidecar store, /api/sidecar, sidecar services |
FEATURE-TTS |
TTS config, voice routing, cache keys, audio playback | TTS settings/hooks/routes/services |
FEATURE-IMPORT |
SillyTavern and Marinara importers and migration helpers | import routes/services |
TEST |
Tracked regression and browser smoke coverage, plus temporary proof tests when needed | scripts/regressions, e2e, and temporary packages/server/src/**/__tests__/ files removed after use |
Prefer making the path communicate the section. A comment like // Section: MODE-GAME is only useful while a file still sits in a mixed directory.
CORE-CONTRACT. This package should stay runtime-agnostic.
Current contents:
types: chat, character, game, game state, combat, scene, sidecar, TTS, agents, prompts, lorebooks, exports, themes.schemas: Zod schemas for persisted and shared entities.constants: providers, defaults, chat modes, model lists, agent prompts.utils: pure helpers such as macro expansion, XML wrapping, and music scoring.features: agent manifests and registry, function-call definitions, folder packages, and turn-game engines for UNO, Chess, and Poker.
Rules:
- No React, DOM, Fastify, server storage, filesystem, network, or provider SDK code.
- Move code here only when both client and server need the same contract or pure algorithm.
- Do not turn
sharedinto a general dumping ground for client-only helpers.
React 19 and Vite PWA. It currently holds several hundred source files.
Current top-level shape:
App.tsx,main.tsx: app bootstrap, React Query, PWA, global effects.components/layout: app shell, sidebars, top bar, modal renderer.components/ui: reusable UI primitives.components/chat: mixed common chat, conversation, roleplay, scene, sprite, and encounter UI.components/game: game-mode surface and panels.components/panels,components/modals, entity editors: settings and resource management.features: extracted feature modules, currently including chat-settings sections and tracker-panel pieces.hooks: React Query hooks and runtime hooks for most API features.lib: browser and client helpers. This currently mixes common helpers with mode-specific game helpers.stores: Zustand stores for UI, chat runtime, agents, game state, game mode, assets, sidecar, translation, gallery, encounters, and the turn games.styles: global stylesheet and theme-specific CSS.
Important current crossovers:
components/gameimportscomponents/chatfor shared visual pieces such as weather and gallery drawers.components/chatimports game-state and encounter state for roleplay features.hooks/use-generate.tstouches chat state, agent state, game state, game mode state, translation state, and UI settings.lib/game-*helpers are game-only but live beside global helpers.
Fastify API, file-native storage, and provider integrations. It currently holds several hundred source files.
Current top-level shape:
app.ts,index.ts: app factory, bootstrap, static serving, file-storage hydration, and seeders.routes: many route files. Most are thin CRUD APIs, butgenerate.routes.tsandgame.routes.tsare large orchestration files. Aroutes/generate/folder holds the first extracted pieces of the generation path.services/storage: storage facade layer for chats, characters, prompts, lorebooks, settings, assets, themes, game state.services/llm: provider registry, base provider contract, OpenAI-compatible providers, local sidecar bridge.services/prompt: shared prompt assembly for non-game generation.services/conversation: schedules, autonomous messages, awareness, conversation profiles, conversation command handling.services/game: GM prompts, dice, combat, state machine, party prompts, maps, weather, time, sessions, checkpoints, reputation, assets.services/sidecar: local runtime, model management, scene analysis, scene postprocessing.services/agents: agent execution and knowledge routing.- Feature foundations:
services/import,services/lorebook,services/image,services/haptic,services/tools,services/regex,services/professor-mari,services/mari-db,services/turn-games,services/spotify,services/video,services/generation,services/chat-summary,services/achievements,services/prompt-overrides,services/setup,services/noodle,services/memory-recall, anddiscord-webhook.ts. db/schema: file-table definitions for data stored underDATA_DIR/storage.db/file-schema.ts,db/file-query.ts: native table metadata and query expressions.db/file-backed-store.ts: in-memory table store, transaction boundary, crash recovery, and JSON snapshot persistence. See File-Native Storage (Developers).
Important current crossovers:
- Routes import storage, LLM, prompt, lorebook, game, sidecar, and feature services directly.
generate.routes.tsserves the main conversation and roleplay generation path plus the agent pipeline.game.routes.tsowns game orchestration and also reaches into LLM, sidecar, lorebook, image, storage, and Discord webhook behavior.- Scene analysis lives in sidecar services, but game mode can run it through either the sidecar or a selected LLM connection.
These are global foundations:
- Chat and message persistence:
packages/server/src/routes/chats.routes.ts,packages/server/src/services/storage/chats.storage.ts, shared chat types and schemas. - Characters and personas: character routes, storage, schemas, and client character hooks and editors.
- Connections and providers: connection routes, storage, shared provider constants, and
services/llm. - Prompt presets, lorebooks, regex, custom tools: shared authoring and prompt-injection foundations.
- Generation transport:
packages/client/src/hooks/use-generate.ts,packages/server/src/routes/generate.routes.ts, and the provider registry. - TTS, translation, gallery, themes, settings, imports, backups.
Primary code:
- Client:
components/chat/ChatConversationSurface.tsx,ConversationView.tsx,ConversationMessage.tsx,ConversationInput.tsx, and conversation quick-start wiring inChatArea.tsx. - Client hooks:
use-autonomous-messaging.ts,use-background-autonomous.ts. - Server:
/api/conversation,services/conversation/*. - Shared metadata:
conversationSchedulesEnabled,characterSchedules,scheduleWeekStart, and day and week summaries.
Expected boundary:
- Conversation should own schedules, autonomous check-ins, conversation activity, and non-roleplay message display.
- Conversation should not know about game dice, GM tags, quick-time events, game maps, or game combat.
Primary code:
- Client:
components/chat/ChatRoleplaySurface.tsx,ChatMessage.tsx,ChatInput.tsx, theRoleplayHUDcomponents,SpriteOverlay.tsx,SceneBanner.tsx,CyoaChoices.tsx, andEncounterModal.tsx. - Server:
/api/scene,/api/encounter,/api/sprites, and parts of/api/generate. - Shared contracts:
scene, roleplay-related chat metadata fields, and sprite placement types.
Expected boundary:
- Roleplay should own scenes, sprite display, CYOA choices, the roleplay HUD, and roleplay encounter helper flows.
- Shared visual effects that game mode also uses should move out of
components/chat.
Primary code:
- Client:
components/game/*,hooks/use-game.ts,hooks/use-scene-analysis.ts,stores/game-mode.store.ts,stores/game-state.store.ts,stores/game-asset.store.ts,lib/game-*,lib/party-dialogue-parser.ts. - Server:
/api/game,/api/game-assets,services/game/*, and game portions ofservices/sidecar/scene-analyzer.tsandscene-postprocess.ts. - Shared contracts:
types/game.ts,types/game-state.ts,types/combat-encounter.ts, and game fields inChatMetadata.
Expected boundary:
- Game should own GM prompts, party prompts, dice, skill checks, quick-time events, game combat, maps, travel and rest, weather and time, NPC reputation, game session summaries, generated game assets, and game logs.
- Game should not depend on chat-mode UI except through shared primitives or explicitly shared feature components.
These files are the most likely to slow future work because they mix many concerns in one place. Line counts change often, so this list gives rough order and the concern rather than exact sizes.
| File | Section | Concern |
|---|---|---|
packages/server/src/routes/generate.routes.ts |
shared generation and agents | Route, streaming, prompt, agents, storage, and side effects live in one file. |
packages/server/src/routes/game.routes.ts |
MODE-GAME |
API handlers, GM flow, scene analysis, assets, combat, and persistence are coupled. |
packages/client/src/components/game/GameSurface.tsx |
MODE-GAME |
Rendering, state orchestration, assets, logs, narration, combat, and effects are coupled. |
packages/client/src/components/chat/ChatSettingsDrawer.tsx |
mixed chat settings | Section extraction is underway in features/chat-settings, but the drawer is still large. |
packages/client/src/components/game/GameNarration.tsx |
MODE-GAME |
Display rendering and command formatting are tightly coupled. |
packages/client/src/components/game/GameCombatUI.tsx |
MODE-GAME |
Combat display, controls, and logs can become smaller panels and hooks. |
packages/client/src/components/chat/RoleplayHUD.tsx |
MODE-ROLEPLAY |
A split is partly done via RoleplayHUDActionsMenu.tsx and RoleplayHUDPanels.tsx. |
This is the direction for future refactors. It does not require moving everything at once.
packages/client/src/
app/ # App bootstrap, shell integration, providers
shared/
components/ # UI primitives and mode-agnostic widgets
hooks/ # cross-feature client hooks
lib/ # browser/runtime helpers
stores/ # global client stores only
features/
agents/
assets/
gallery/
sidecar/
tts/
translation/
modules/
conversation/
components/
hooks/
lib/
roleplay/
components/
hooks/
lib/
game/
components/
hooks/
lib/
stores/
packages/server/src/
app/ # Fastify setup, route registration, middleware
shared/
db/
storage/
llm/
prompt/
lorebook/
utils/
features/
agents/
assets/
haptic/
image/
import/
sidecar/
tts/
modules/
chat/
conversation/
roleplay/
scene/
encounter/
sprites/
game/
routes/
services/
prompts/
packages/shared/src/
contracts/
chat/
conversation/
roleplay/
game/
providers/
constants/
utils/
The old flat types, schemas, and constants layout is no longer the whole story. packages/shared/src/features/ now hosts agents, function calls, folder packages, and turn games. The first shared cleanup should still be type-level and incremental, not a mass file move.
-
Place new code in the narrowest correct section.
-
If two or more modes use a client component, move it to
CLIENT-SHAREDbefore adding more mode-specific behavior. -
If client and server both need a type, schema, or pure helper, move it to
CORE-CONTRACT. -
If only the server needs it, keep it out of
packages/shared. -
Route files should validate HTTP input and call services. Domain decisions should move into services.
-
Stores should be either global (
ui,chat,sidecar) or mode-specific (game-mode,encounter). Avoid one store quietly owning multiple modes. -
Metadata should become discriminated by
ChatMode: base metadata plus conversation, roleplay, and game fields. -
Move one feature at a time. Leave compatibility exports or wrappers when a broad import path would otherwise churn the repo.
-
After each move, run lint:
pnpm lint
Then run a targeted Prettier check on the touched files.
These are good first cleanup passes because they reduce coupling without changing behavior.
- Split
components/chatinto common, conversation, and roleplay groups.- Common candidates:
ChatCommonOverlays,ChatBranchSelector,ChatGalleryDrawer,WeatherEffects, and shared message and input primitives. - Conversation candidates:
ChatConversationSurface,ConversationView,ConversationMessage,ConversationInput. - Roleplay candidates:
ChatRoleplaySurface,SpriteOverlay,SceneBanner,CyoaChoices,EncounterModal. The roleplay HUD split is partly done inRoleplayHUDActionsMenu.tsxandRoleplayHUDPanels.tsx.
- Common candidates:
- Move game-only client helpers under a game module.
- Candidates:
game-audio,game-tag-parser,game-full-body-pose,game-character-name-match,game-segment-edits,party-dialogue-parser.
- Candidates:
- Split
GameSurface.tsxinto runtime hooks and smaller containers.- Candidate hooks: narration runtime, asset runtime, scene-analysis runtime, combat runtime, log and history runtime, audio runtime.
- Split
GameNarration.tsxinto command parsing and formatting plus display components. - Split
game.routes.tsby handler group.- Candidate groups: setup and session, turn generation, dice and skill and quick-time events, journal and inventory, map and travel and weather, combat, assets and scene analysis.
- Split
generate.routes.tsinto generation transport, agent pipeline handling, retry routes, and command and postprocess helpers. - Split
ChatMetadatainto mode-specific metadata contracts. - Move shared roleplay and game visuals out of
components/chatbefore game imports more chat internals.
For the next cleanup PR, use this order:
-
Create the target directories for one area only.
-
Move pure helpers first.
-
Move leaf components next.
-
Leave the large orchestrator in place until its imports mostly point at the new module.
-
Add compatibility re-exports only where import churn would distract from the real change.
-
Run lint:
pnpm lint
Then run targeted Prettier checks on the touched files.