Разделы документации
ОбзорБыстрый стартРедакции и возможностиМодели и поляРедактор контентаМедиатекаЛокализацияПубликация и работа командыAPI, SDK и генерация типовРасширения и инструментыРабочие проектыЗадания, вебхуки и наблюдаемостьАудит и управление даннымиСоветники и доверие к плагинамКорпоративный входПространства, квоты и масштабированиеCommerce и PortalПрава и безопасностьРазвёртывание и обновленияЛицензии и установка пакетовТекущие ограниченияПомощь и диагностикаДанные в кабинетеCore CMSDeveloper PlatformProduction UseWorkflowOperationsComplianceAI AssistantsPlugin TrustEnterprise IdentityEnterprise ScaleEnterprise DeploymentCommerce BundlePortal BundleNotty CMS DocumentationAuth & SecurityContent ModelingDeploymentEcosystem & Packaging ConventionsEditions and First-party ModulesExtensibilityGetting StartedMedia ManagementModule Extraction PathDraft & PublishUpgrade GuideWebhooks & IntegrationsCookbook: Blog with Next.jsCookbook: Custom PluginCookbook: Multilingual SiteOperations DocsBackup AutomationDeployment BlueprintsRunbook — Восстановление БД из бэкапаRunbook — Плановый деплойRunbook — Реакция на инцидентRunbook — Откат релизаRunbook — Горизонтальное масштабированиеRunbook — Ротация секретовRunbook — Major upgradeSecrets ManagementNotty CMS — Capability MapNotty Configuration ModelGenerated App ContractComponents and Dynamic ZonesMiddleware SystemPerformance & Scaling ToolkitDisaster Recovery PlaybookDistribution Model
Документация / Технический справочник

Distribution Model

Техническое руководство из исходного проекта Notty. Примеры, параметры и эксплуатационные ограничения.

Все редакцииОбновлено 2026-09-30

Status: accepted spec (Phase 5)

Purpose: formalize the installable distribution model, publish contract, upgrade path, and the boundary between platform runtime and user-land code.

Why This Exists

Notty must be delivered as a mature installable product, not as a copy of the monorepo source tree.

A user who runs npx @notty/create my-app must receive a self-contained project that:

  • installs from published npm packages
  • runs without building the platform from source
  • upgrades by bumping dependency versions
  • stays maintainable across version updates
  • keeps user code separate from platform internals

This document is the single source of truth for how Notty is shipped and consumed. Other specs handle what the generated app looks like inside (Generated App Contract) and how configuration works (Configuration Model). This spec owns the distribution pipeline end-to-end.

Package Architecture

Published Packages

Package Role Format Key Contents
@notty/server Runtime ESM Pre-built Nitro bundle (.output/server/), pre-built admin SPA (public/admin/), CLI executable (dist/cli.js)
@notty/core Engine CJS + ESM Config helpers (defineConfig), plugin system, registries, middleware engine
@notty/database Data layer CJS + ESM Drizzle ORM adapters (PostgreSQL, MySQL, SQLite), schema manager
@notty/types Type contracts CJS + ESM NottySchema, NottyField, ExtensionSource, all shared TS types
@notty/locales i18n CJS + ESM Locale bundles (./ru, ./en), translation utilities
@notty/ui Component library CJS + ESM Reusable UI components, CSS
@notty/plugin-api Plugin SDK CJS + ESM definePlugin, PluginContext, testing helpers
@notty/module-api Module SDK CJS + ESM defineNottyModuleManifest, module registry contract and validation
@notty/modules Module catalog CJS + ESM First-party module manifests for editions and add-ons
@notty/theme-api Theme SDK CJS + ESM defineTheme, token contracts, testing helpers
@notty/sdk Client SDK CJS + ESM Framework integrations (/react, /next, /nuxt)
@notty/codegen Code generation CJS + ESM TypeScript type generator from schemas
@notty/cli Developer tools ESM notty CLI: dev, start, build, check, doctor, diagnose, codegen, scaffold
@notty/create Scaffolder ESM Project generator, templates, version resolution

Edition Distribution Channels

Notty uses a hybrid distribution model:

Channel Intended use Access model
Public npm Community installs and evaluation Public @notty/* packages required by Community
Private npm registry Paid self-hosted installs Token-gated Pro, Business, Enterprise and module access
Portable tarball distro On-prem/offline-friendly delivery Edition-specific bundle generated from packed tarballs
Docker image per edition Fast server deployment Public Community image, private paid edition images
NottyPortal customer access License and entitlement management Seller-owned portal outside the product repository

The Community stack is public. Commercial packages publish with restricted access and are granted by NottyPortal through registry tokens, private Docker access or downloadable portable distributions.

Portable distributions are generated with:

./scripts/local-publish.sh
pnpm release:dist -- --edition=community
pnpm release:dist -- --edition=pro
pnpm release:dist -- --edition=business
pnpm release:dist -- --edition=enterprise

Each generated directory under dist/editions/ contains only the @notty/* tarballs for that edition, a runtime package.json, notty.config.ts, .env.example, install.sh, manifest and Docker Compose reference. Higher-tier package tarballs are not present in lower-tier distributions.

Docker images are built with:

pnpm release:docker -- community
pnpm release:docker -- pro
pnpm release:docker -- business
pnpm release:docker -- enterprise

The Docker build passes NOTTY_EDITION into deployment/Dockerfile and copies only the package layer for that edition into the runtime image.

Dependency Graph

@notty/types                  (zero deps, foundation)
    |
    +-- @notty/module-api     (types)
    |       |
    |       +-- @notty/modules
    |               |
    |               +-- @notty/server  (module catalog + core + Nitro + pre-built admin)
    |
    +-- @notty/database       (types + Drizzle ORM)
    |       |
    |       +-- @notty/core   (database + types)
    |
    +-- @notty/plugin-api     (types)
    +-- @notty/theme-api      (types)
    +-- @notty/sdk            (types)
    +-- @notty/codegen        (types)
    +-- @notty/locales        (standalone)
    +-- @notty/ui             (standalone)
    +-- @notty/cli            (standalone tooling, shells out to project runtime)
    +-- @notty/create         (standalone, resolves versions at scaffold time)

What the User Installs

A generated project's package.json depends on:

{
  "dependencies": {
    "@notty/server": "^0.16.0",
    "@notty/core": "^0.16.0",
    "better-sqlite3": "^12.4.1"
  }
}

@notty/server transitively pulls in @notty/core, @notty/database, @notty/types, @notty/locales, @notty/module-api, @notty/modules, and @notty/ui. The user does not need to install these directly.

Database drivers (better-sqlite3, pg, mysql2) are direct dependencies because they contain native binaries that must match the user's platform.

@notty/cli is optional. Generated apps do not install it by default; teams invoke it on demand via pnpm dlx @notty/cli <command> (or npx @notty/cli <command>) when they need diagnostics, validation, or scaffolding helpers.

Pre-built Artifacts

Server Bundle

@notty/server ships a complete Nitro pre-build in .output/server/:

  • index.mjs — the server entry point
  • chunks/ — code-split server modules
  • node_modules/ — vendored pure-JS dependencies (native modules excluded)

Native database drivers (better-sqlite3, pg-native) are explicitly removed from the vendored node_modules/ during the post-build step. This prevents cross-platform binary mismatches between the CI build environment and the user's machine.

Admin SPA

@notty/admin builds into @notty/server's public/admin/ directory. The admin is a React + Vite SPA served at /admin by Nitro's static route handler with SPA fallback.

Users never build the admin themselves. They get it pre-built inside @notty/server.

Library Packages

All other packages ship dist/ with:

  • .cjs + .mjs dual format (or ESM-only for CLI tools)
  • .d.ts type declarations
  • No vendored node_modules

Build tool: tsup with --format cjs,esm --dts.

Publish Contract

Version Policy

During the 0.x pre-release phase:

Bump Meaning Example
Patch (0.16.1) Bug fixes, fully backwards compatible Fix SQLite adapter edge case
Minor (0.17.0) New features, deprecations possible, breaking changes documented with migration path Add new field type
Major (1.0.0) Stable API contract, breaking changes only in major bumps GA release

Version Synchronization

Core runtime packages (@notty/server, @notty/core, @notty/database, @notty/locales, @notty/ui, @notty/admin) share the same version line and must be released together. A change to any one of them bumps all of them.

SDK packages (@notty/plugin-api, @notty/theme-api) may move on an independent version line. They declare compatibility via engines.notty in their manifest.

@notty/create must stay in sync with the core version line. When core packages are bumped, @notty/create must be bumped too, because it uses its own version to resolve dependency versions for generated projects.

Compatibility Matrix

Notty Version Node.js Plugin API Theme API
0.16.x >= 20 ^0.14.0 ^0.14.0
0.15.x >= 20 ^0.14.0 ^0.14.0
0.14.x >= 20 ^0.14.0 ^0.14.0

Package Contents (files field)

Every published package explicitly declares its files field:

Package files
@notty/server ["dist", ".output", "public"]
@notty/create ["dist", "templates"]
All other libs ["dist"]

No package should ship src/, test/, or monorepo config files.

Exports Contract

Every library package provides conditional exports:

{
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    }
  }
}

Additional sub-path exports (e.g., @notty/locales/ru, @notty/sdk/react, @notty/plugin-api/testing) follow the same pattern and are part of the public API contract.

Generated App Skeleton

See Generated App Contract for the full canonical structure.

Key Distribution Properties

  1. No build step required. A generated project runs with pnpm dev immediately after pnpm install. The platform is pre-built inside @notty/server. Teams that prefer the developer CLI can invoke the same flow explicitly via pnpm dlx @notty/cli dev.

  2. No monorepo artifacts. Generated projects never contain turbo.json, pnpm-workspace.yaml, tsup configs, or other monorepo tooling.

  3. No platform source code. Generated projects consume compiled packages from node_modules/. They do not copy or transpile platform internals.

  4. Starter templates are data, not code. Templates in @notty/create generate schemas (JSON) and thin plugin wrappers (TS/JS). They never generate platform-level logic.

  5. Version resolution at scaffold time. @notty/create queries the npm registry for the latest published versions of @notty/server and @notty/core. If the registry is unreachable, it falls back to its own version number.

Platform vs User-Land Separation

Platform Code (owned by @notty/*)

Everything inside node_modules/@notty/:

  • Server runtime, admin SPA, database adapters
  • Plugin/theme APIs and lifecycle
  • Configuration engine and validators
  • CLI tooling

This code is immutable from the user's perspective. Users cannot and should not patch it directly.

User-Land Code (owned by the project)

Everything outside node_modules/:

Zone Ownership Upgrade-safe
notty.config.ts User-owned Yes
schemas/, components/ User-owned Yes
src/plugins/, src/routes/, src/controllers/, src/services/, src/policies/, src/hooks/, src/middlewares/ User-owned Yes
public/ User-owned Yes
migrations/, seeds/ User-owned Yes
.env, .env.example User-owned Yes
data/ Runtime-owned N/A (not source)
.notty/ Platform-managed Regenerated by tooling
.output/ Platform-managed Regenerated by build

Boundary Rule

User-land code extends the platform only through supported contracts:

  1. Schema-driven — JSON schemas in schemas/ and components/
  2. App-local plugin — src/plugins/app.ts registered in notty.config.ts
  3. Reusable plugin/theme — npm packages using @notty/plugin-api or @notty/theme-api
  4. Configuration — notty.config.ts and environment variables

There is no "eject" mechanism. If a user needs behavior that cannot be achieved through these contracts, it is a signal that the platform needs a new extension point, not that the user should fork platform internals.

Upgrade Path

Standard Upgrade Flow

1. Read CHANGELOG for target version
2. pnpm update @notty/server @notty/core
3. pnpm dlx @notty/cli doctor
4. pnpm dlx @notty/cli check
5. pnpm dev (auto-syncs database)
6. Test custom routes, hooks, middleware

Upgrade Tooling

Generated apps call these commands through @notty/cli, typically via pnpm dlx @notty/cli <command> (or pnpm exec notty <command> if the CLI is installed locally).

Command Purpose
notty doctor Comprehensive project health check: dependency versions, config validity, schema compatibility, file structure
notty check Validate schemas and components against the current runtime version
notty diagnose Detailed diagnostics report for troubleshooting
notty validate-plugin <path> Validate a plugin manifest and structure

Database Migrations on Upgrade

Notty uses Drizzle ORM with automatic schema synchronization:

  • Adding fields — the column is added automatically on next boot
  • Removing fields — the column is kept in the database but ignored by the ORM; drop it manually via custom SQL if needed
  • Renaming fields — create the new field, migrate data via a custom script, then remove the old field

For complex data migrations, users create scripts in migrations/ and run them before starting the server.

Breaking Change Protocol

When a version introduces breaking changes:

  1. The CHANGELOG documents what changed and why
  2. notty doctor detects the incompatibility and prints actionable guidance
  3. If the change affects schemas, notty check flags affected files
  4. If the change affects config, notty doctor reports the outdated config shape
  5. Migration guidance is published in the upgrade guide

Rollback

  1. Stop the server
  2. Restore previous package.json and lock file from git
  3. Run pnpm install to restore previous versions
  4. If a database migration has already run, restore from the latest backup

Build Pipeline (Monorepo → npm)

Build Order

@notty/types         (tsup)
       ↓
@notty/module-api    (tsup)
       ↓
@notty/modules       (tsup)
       ↓
@notty/database      (tsup)
       ↓
@notty/core          (tsup)
       ↓
@notty/admin         (vite → ../server/public/admin/)
       ↓
@notty/server        (nitro build → postbuild → tsup)
       ↓
@notty/cli           (tsup)
@notty/create        (tsup)
@notty/locales       (tsup)
@notty/ui            (tsup)
@notty/plugin-api    (tsup)
@notty/theme-api     (tsup)
@notty/sdk           (tsup)
@notty/codegen       (tsup)

Orchestrated by Turbo with topological dependency resolution.

Server Post-Build

After the Nitro build:

  1. Remove native modules from .output/server/node_modules/ (better-sqlite3, pg-native)
  2. Build CLI executable via tsup (dist/cli.js)

This ensures the published package does not ship platform-specific binaries.

Release Pipeline

  1. pnpm changeset — create changeset describing the change
  2. pnpm changeset version — apply version bumps to package.json files
  3. pnpm release:verify:pre — verify internal dependency consistency
  4. pnpm release:readiness — unified quality gate
  5. git commit && git push — CI publishes to npm via Changesets Action

Invariants

These invariants must always hold:

  1. A generated project must work without building platform source. All platform code is pre-built and shipped in npm packages.

  2. @notty/server is self-contained. It includes the Nitro server bundle and the pre-built admin SPA. No other build step is needed.

  3. Version sync is enforced. Core runtime packages share a version line. A mismatch between @notty/server and @notty/core versions must produce a startup warning.

  4. Native modules are user-side. Database drivers are installed by the user's pnpm install, not vendored by the platform.

  5. User-land files survive upgrades. An pnpm update @notty/server @notty/core must never modify files outside node_modules/, .notty/, or .output/.

  6. No monorepo leakage. Published packages must not reference workspace paths, monorepo-only scripts, or unpublished internal packages.

  7. @notty/create produces the canonical skeleton. The scaffolder generates exactly the structure defined in the Generated App Contract, nothing more.

Non-Goals

This spec does not cover:

  • Internal monorepo development workflow (see CLAUDE.md)
  • Admin UI architecture or component design
  • Content API specification
  • Plugin marketplace infrastructure
  • Cloud hosting or managed service offering
Document Scope
Generated App Contract Canonical project structure, ownership model, resolution order
Configuration Model 3-tier configuration, env precedence, locking
Ecosystem & Packaging Plugin/theme naming, versioning, publishing conventions
Upgrade Guide Step-by-step upgrade instructions for users
Deployment Production configuration, Docker, security
Release Workflow (./claude/release-workflow.md в исходном проекте) Internal release process (Changesets, CI/CD)
Capability Map Feature matrix with implementation status

Источник: docs/distribution-model.md. Снимок документации исходного проекта. Технический справочник сохраняет язык оригинала.