Understanding the oblien/openship Project Structure: A Monorepo Architecture Guide

The oblien/openship project is organized as a TypeScript monorepo using pnpm workspaces, separating reusable libraries in packages/ from deployable applications in apps/, with centralized configuration via pnpm-workspace.yaml.

The oblien/openship repository follows a scalable monorepo pattern that isolates shared business logic from application-specific implementations. Grasping the oblien/openship project structure is essential for contributors navigating the codebase, as it dictates how the web UI, API server, and database layers interact through workspace-scoped packages and adapter-based architecture.

Monorepo Organization Strategy

The repository employs pnpm workspaces to manage multiple packages within a single version-controlled tree. This approach enables atomic changes across the stack while maintaining clear boundaries between infrastructure, business logic, and presentation layers.

Workspace membership is declared in pnpm-workspace.yaml at the repository root, which identifies all directories containing package.json files under packages/* and apps/*. This configuration allows shared dependencies to be hoisted to the root node_modules, reducing installation time and ensuring version consistency across the oblien/openship ecosystem.

Directory Structure Deep Dive

The packages/ Directory (Shared Libraries)

The packages/ folder contains versioned libraries that expose functionality to applications via workspace imports. Each package maintains its own package.json and extends the shared TypeScript configuration from tsconfig.base.json.

  • packages/adapters/ – Runtime adapters for various deployment targets (Docker, Systemd, Vercel). Contains implementation code in src/ and type definitions in packages/adapters/src/types.ts.
  • packages/core/ – Central business logic for application routing, plugin systems, and workflow orchestration. Reference packages/core/src/apps/README.md for architectural documentation.
  • packages/db/ – Database schema definitions and migration tooling using Drizzle ORM. Configuration lives in packages/db/drizzle.config.ts, while the schema is consumed via packages/db/src/index.ts.
  • packages/db-email/ – Specialized database utilities for email processing and queue management.
  • packages/ui/ – React component library and styling utilities consumed by the web frontend.

The apps/ Directory (Deployable Applications)

Standalone executables reside in apps/, each importing specific packages from the workspace to compose complete services.

  • apps/web/ – Next.js-based frontend UI. Entry point at apps/web/src/index.tsx with page components and business logic connectors in apps/web/src/lib/source.ts.
  • apps/api/ – HTTP API server exposing OpenShip endpoints. Implements route handlers and middleware layers for the core business logic.
  • apps/email/ – Background workers for SMTP processing and LDAP synchronization. Core engine logic resides in apps/email/engine/.

Infrastructure and Documentation

Supporting resources are grouped at the repository root for discoverability:

  • docker/ – Container orchestration files including docker/docker-compose.yml for multi-service local development.
  • scripts/ – Automation helpers such as scripts/release.ts for versioning and deployment pipelines.
  • docs/ – Markdown documentation, installation guides (docs/installation.md), and architecture diagrams.
  • fixtures/ – Sample datasets and deployment configurations used in integration tests.

Key Configuration Files

Understanding these entry points clarifies how the oblien/openship project structure wires together:

File Purpose
pnpm-workspace.yaml Declares workspace glob patterns enabling cross-package imports
tsconfig.base.json Shared TypeScript compiler options extended by all packages
packages/core/src/apps/README.md Core application utilities documentation
packages/db/drizzle.config.ts ORM configuration for database migrations
docker/docker-compose.yml Local development environment definition
scripts/release.ts Automated release and changelog generation

Practical Code Integration Examples

Importing Core Services in Applications

Applications consume domain logic through workspace-scoped imports. The web interface initializes the execution engine as follows:

// apps/web/src/lib/source.ts
import { ShipRunner } from '@openship/core';

export const runner = new ShipRunner({
  db: /* injected DB client */,
  adapters: /* loaded adapters */
});

Adapter Testing Patterns

The adapters package exposes runtime-specific builders for testing deployment plans:

// packages/adapters/test/docker-build-plan.test.ts
import { DockerAdapter } from '@openship/adapters';

test('Docker build plan is generated correctly', async () => {
  const plan = await DockerAdapter.buildPlan({
    image: 'openship/web',
    context: './apps/web'
  });
  expect(plan).toContain('docker build');
});

Database Client Initialization

The schema package configures Drizzle ORM with Bun runtime compatibility:

// packages/db/src/index.ts
import { drizzle } from 'drizzle-orm/bun';
import { schema } from './schema';

export const db = drizzle('sqlite:openship.db', { schema });

Summary

  • oblien/openship organizes code as a pnpm workspace monorepo with strict separation between packages/ (libraries) and apps/ (executables).
  • Configuration is centralized in pnpm-workspace.yaml and tsconfig.base.json, ensuring consistent tooling across TypeScript projects.
  • Database layer resides in packages/db/ using Drizzle ORM, exported for consumption by API and worker applications.
  • Runtime adapters in packages/adapters/ abstract deployment targets, allowing the same core logic to run on Docker, Vercel, or systemd.
  • Entry points such as apps/web/src/index.tsx and apps/email/engine/ demonstrate how applications compose shared packages into runnable services.

Frequently Asked Questions

How is the oblien/openship project structure organized?

The repository follows a monorepo pattern using pnpm workspaces. Code is bifurcated into packages/ (reusable TypeScript libraries for adapters, core logic, and database schemas) and apps/ (standalone deployables like the Next.js web UI, API server, and email workers). This structure enables shared code ownership while maintaining distinct deployment boundaries.

Where is the database configuration located in oblien/openship?

Database schema definitions and Drizzle ORM configuration reside in packages/db/. The main configuration file is packages/db/drizzle.config.ts, while the runtime client is instantiated in packages/db/src/index.ts using Bun-compatible SQLite drivers.

How do applications import shared code in the oblien/openship monorepo?

Applications reference packages via workspace-scoped imports (e.g., import { ShipRunner } from '@openship/core'). The pnpm-workspace.yaml file maps these specifiers to local directories, allowing TypeScript to resolve modules across the repository boundary without publishing to npm.

What purpose does the packages/adapters/ directory serve?

The packages/adapters/ directory contains abstraction layers for various deployment runtimes including Docker, Systemd, and Vercel. It exposes a common interface defined in packages/adapters/src/types.ts, enabling the core business logic to remain agnostic of where it is ultimately deployed.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →