Packages
Every workspace package has exactly one responsibility, and dependencies only point downward, which keeps the monorepo free of cycles.
Dependency Direction
Code may only depend on packages "below" it:
apps (server, web, desktop, plugin-runtime)
→ packages
→ shared, contracts (the floor)
server and web depend on packages; packages depend at most on shared
and contracts. Cyclic dependencies are forbidden. When you add new code,
put it in the narrowest package that can host it: shared helpers go to
@neotavern/shared, API shapes go to @neotavern/contracts, and anything database
related goes to @neotavern/db.
Package Responsibilities
@neotavern/shared— isomorphic utilities with zero runtime dependencies: UUIDv7 IDs,Result, theAppErrorenvelope, a structured logger with secret redaction, timeout and signal helpers, and prompt macros.@neotavern/contracts— TypeBox schemas for every API input and output. The single source of truth shared by server and web; never duplicated by hand.@neotavern/db— SQLite: the Drizzle schema, migrations, repositories, and FTS5 search. The only package that talks to the database.@neotavern/ui— headless base components built on Radix primitives, design tokens, and thedata-*hooks that themes rely on.@neotavern/i18n— i18next setup, namespaces,enandruresources, and the error-code localizer that maps machine error codes to localized text.@neotavern/plugin-sdk— the versioned Plugin SDK: manifest schema, permissions and capability grants, and the frontend and backend API contracts that plugins compile against.@neotavern/theme-sdk— the Theme SDK: manifest schema, the token/component/shell levels, and inheritance resolution.@neotavern/provider-sdk— the unified provider adapter contract plus the built-in adapters for LLM, TTS, STT, and image providers, and the adapter registry.@neotavern/legacy-compat— the legacy compatibility layer:windowglobals, the event bus, and unmanaged DOM islands for SillyTavern-era scripts.@neotavern/gestures— framework-agnostic row gestures: context menus (right-click and long-press) and drag-and-drop reorder recognition.@neotavern/plugin-build— the plugin build and publish pipeline: analyze, sign, and build plugin packages.
What Lives Where
- API shapes always come from
@neotavern/contracts. Backend and frontend never declare the same type twice. - Database access happens only through
@neotavern/dbrepositories. Plugin code never receives a SQLite connection. - Provider behavior lives in
@neotavern/provider-sdkadapters. The server core is not coupled to any single provider's SDK, with one documented exception: the Anthropic adapter uses the official SDK for beta surfaces. - UI building blocks come from
@neotavern/ui; application screens compose them. Framework-agnostic gestures stay in@neotavern/gesturesso they can be reused outside React.
Adding a Package
A new package needs a README.md that states its purpose, public entry
points, dependencies, and constraints — documentation is part of the
implementation. Before creating one, check whether the code fits an existing
package; the default answer is no new package.