Skip to main content

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, the AppError envelope, 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 the data-* hooks that themes rely on.
  • @neotavern/i18n — i18next setup, namespaces, en and ru resources, 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: window globals, 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/db repositories. Plugin code never receives a SQLite connection.
  • Provider behavior lives in @neotavern/provider-sdk adapters. 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/gestures so 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.