Project Structure

An annotated directory tree of the Nebutra-Sailor monorepo — categorized packages, backends split, infra/workflows/e2e/tests directories.

The Nebutra-Sailor monorepo is organized by purpose at the top level (apps/, backends/, packages/, infra/, workflows/, e2e/, tests/), and packages are categorized by domain (packages/<category>/<name>/).

Top-level layout

nebutra-sailor/
├── apps/                User-facing apps (Next.js / Hono / Storybook / docs)
├── backends/            Non-UI backends — split by language (gateway/, python/)
├── packages/            Shared TypeScript libraries — categorized by domain
├── infra/               iac/ + runtime/ + data/ + ops/  (Wave 2.2)
├── workflows/           inngest/ + n8n/ + pusher/        (Wave 2.3)
├── e2e/                 smoke/ + golden/ + sleptons/     (Wave 2.1)
├── tests/               architecture/ + load/            (vitest + k6)
├── docs/                Internal architecture ADRs (source repo only)
├── scripts/             Repo-level utility scripts
├── docker-compose.infra.yml
├── turbo.json
├── pnpm-workspace.yaml
└── package.json

apps/ — user-facing apps

AppFrameworkPurpose
apps/landingNext.js 16 + Tailwind v4Public marketing site (7 locales)
apps/webNext.js 16 + Tailwind v4Authenticated SaaS dashboard
apps/storybookStorybook 8.xComponent library documentation
apps/design-docsNext.js + FumadocsInternal design system docs
apps/sailor-docsNext.js + FumadocsPublic product docs (this site)
apps/studioSanity Studio v4CMS — content management
apps/docsMintlifyPublic product docs (Mintlify variant)
apps/idpNext.jsSelf-hosted identity provider
apps/mail-previewNext.jsReact Email template preview
apps/sleptonsAuxiliary product surface

backends/ — non-UI services

backends/
├── gateway/             TypeScript / Hono — BFF, auth, tenancy, rate-limit, routing
│                        DEFAULT for new backend work per ADR 2026-05-10
└── python/              Python / FastAPI — batch / ML / specialized libs only
    ├── _shared/         Cross-service utilities (active)
    └── ai/              LLM, embeddings, agent orchestration (active)

The TS/Python split mirrors vercel/vercel's pkg/ layout. New backend work goes in backends/gateway unless the TS-by-Default ADR exception applies.

Each Python module has exactly one of three lifecycle tiers — active (has real callers, builds in CI), stub (interface preserved, src/ empty), or incubator (excluded from workspaces and CI).

packages/ — categorized libraries

Every package lives under packages/<category>/<name>/:

CategoryPurposeExample packages
design/UI, tokens, brand, icons, themeui, tokens, design-tokens, brand, theme, icons, design-sync
iam/Identity, auth, tenancy, secrets, audit, permissionsauth, audit, vault, tenant, permissions, identity
commerce/Billing, marketing, license, metering, contracts, waitlistbilling, contracts, license, marketing, metering, waitlist
integrations/Queue, search, notifications, webhooks, uploads, storage, email, sagaqueue, search, notifications, webhooks, uploads, storage, email, saga
platform/Lower-level platform primitivesdb, logger, config
ai/AI primitives and provider metadatamcp, ai-providers, agents
ops/CLI, scaffolding, presets, Sanity helperscli, create-sailor, sanity, preset

Design system note

@nebutra/design-system has been merged into @nebutra/ui. The layout wrappers it used to export now live at @nebutra/ui/layout:

import { Button, Input, Card } from "@nebutra/ui/components";
import { PageHeader, EmptyState, LoadingState } from "@nebutra/ui/layout";

Icon governance (three-tier)

Three icon libraries are allowed; each has a single, well-defined slot:

TierPackageWhere to use
1 — default@nebutra/icons (Geist 541)All product / app / dashboard surfaces
2 — marketing@phosphor-icons/react/lightOnly inside packages/design/ui/src/marketing/** for thin/duotone AI-brand emphasis
3 — deprecatedlucide-reactZero new imports allowed — existing references will be migrated

See Linting rules for details.

infra/, workflows/, e2e/, tests/

infra/
├── iac/                 Terraform / Pulumi
├── runtime/             Cloud Run / ECS / Vercel runtime configs
├── data/                Migration / seeding pipelines
└── ops/                 Operational runbooks

workflows/
├── inngest/             Durable workflow functions
├── n8n/                 Self-hosted n8n workflow JSON exports
└── pusher/              Realtime channels

e2e/
├── smoke/               Critical-path smoke tests
├── golden/              Golden-path visual regressions
├── sleptons/            Sleptons product flows
├── playwright.config.ts
├── playwright.golden.config.ts
└── playwright.sleptons.config.ts

tests/
├── architecture/        Architecture conformance tests (vitest)
└── load/                Load tests (k6)

nebutra workflow init <provider> scaffolds a starter into workflows/<provider>/. nebutra e2e <suite> runs the matching Playwright config.

File naming conventions

PatternExamplePurpose
kebab-case.tsxuser-avatar.tsxReact component files
kebab-case.tsformat-date.tsUtility and helper files
*.test.ts / *.test.tsxbilling.test.tsVitest tests
*.stories.tsxbutton.stories.tsxStorybook stories
route.tsapp/api/webhooks/route.tsNext.js App Router API route
page.tsx / layout.tsxapp/dashboard/page.tsxApp Router page / layout

Where to add new things

You want to...Where to put it
Add a new dashboard pageapps/web/src/app/(dashboard)/
Add a new marketing pageapps/landing/src/app/[lang]/
Add a new API routebackends/gateway/src/routes/
Add a new Python servicebackends/python/<name>/ (must cite ADR justification)
Add a new UI componentpackages/design/ui/src/components/ + Storybook story
Add a new layout wrapperpackages/design/ui/src/layout/
Add a new design tokenpackages/design/tokens/styles.css
Add a new email templatepackages/integrations/email/src/templates/
Add a new Prisma modelpackages/platform/db/prisma/schema.prisma
Add a queue handlerpackages/integrations/queue/src/handlers/
Add a workflowworkflows/<provider>/ (scaffold via nebutra workflow init)
Add an e2e teste2e/<suite>/

Turborepo task pipeline

The turbo.json at the repo root defines how tasks depend on each other:

{
  "tasks": {
    "build":     { "dependsOn": ["^build"], "outputs": [".next/**", "dist/**"] },
    "typecheck": { "dependsOn": ["^typecheck"] },
    "lint":      { "dependsOn": [] },
    "test":      { "dependsOn": ["^build"] },
    "dev":       { "cache": false, "persistent": true }
  }
}

Use --filter to scope tasks to a single workspace:

pnpm turbo run build --filter=@nebutra/ui
pnpm turbo run typecheck --filter=apps/web

How is this guide?

Edit on GitHub

Last updated on

On this page