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 insrc/and type definitions inpackages/adapters/src/types.ts.packages/core/– Central business logic for application routing, plugin systems, and workflow orchestration. Referencepackages/core/src/apps/README.mdfor architectural documentation.packages/db/– Database schema definitions and migration tooling using Drizzle ORM. Configuration lives inpackages/db/drizzle.config.ts, while the schema is consumed viapackages/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 atapps/web/src/index.tsxwith page components and business logic connectors inapps/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 inapps/email/engine/.
Infrastructure and Documentation
Supporting resources are grouped at the repository root for discoverability:
docker/– Container orchestration files includingdocker/docker-compose.ymlfor multi-service local development.scripts/– Automation helpers such asscripts/release.tsfor 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) andapps/(executables). - Configuration is centralized in
pnpm-workspace.yamlandtsconfig.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.tsxandapps/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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →