Monorepo & Tooling
GospeLib uses a polyglot monorepo orchestrated by Nx with three package managers for three language ecosystems.
Why Nx?
Nx was chosen over Turborepo and Bazel because:
- Mixed language support — first-class plugins for TypeScript, Python, Go, React Native, and Next.js
- Project graph — visual dependency graph helps onboard contributors
- Affected commands — only build/test/lint what changed (
nx affected -t test) - Remote caching — Nx Cloud for CI cache sharing across branches
- Generators — scaffolding for new services and packages
Package Managers
| Ecosystem | Manager | Why |
|---|---|---|
| TypeScript/JS | pnpm 9.15.0 | Strict hoisting prevents phantom dependency bugs; disk-efficient |
| Python | uv (latest) | 10–100× faster than pip; built-in venv; Rust-native lockfile |
| Go | Go modules | Standard, no alternative needed |
Workspace Layout
gospelib/
├── apps/ # Deployable applications
│ ├── web/ # Next.js 15 — web reader (port 3002)
│ ├── admin/ # Next.js 15 — admin dashboard (port 3001)
│ └── mobile/ # Expo 52 / React Native
│
├── services/ # Backend microservices
│ ├── gateway/ # Go — API gateway (port 8080)
│ ├── content/ # Python — graph queries (port 8100)
│ ├── auth/ # Go — Clerk wrapper (port 8200)
│ ├── billing/ # Go — Stripe (port 8300)
│ ├── ai/ # Python — LLM features (port 8400)
│ ├── notifications/ # Go — push + email (port 8500)
│ ├── plugin-registry/ # Python — plugin manifest registry (port 8500)
│ └── ingest/ # Python — CLI data pipeline
│
├── packages/ # Shared code packages
│ ├── core/ # Shared domain logic (book registry, events, navigation)
│ ├── ui/ # Cross-platform React Native components
│ ├── types/ # Shared TypeScript types (OpenAPI-generated)
│ ├── sdk/ # Client SDK (openapi-fetch)
│ ├── config/ # ESLint/TSConfig presets + Zod env schemas
│ ├── schemas/ # Shared Pydantic schema models (Python services)
│ ├── scripture-ref/ # Scripture reference parser and formatter
│ ├── plugin-sdk/ # Plugin authoring SDK for plugin ecosystem
│ └── testing/ # Shared test fixtures, mocks, helpers
│
├── infra/ # Infrastructure as code
│ ├── terraform/ # Terraform modules + environments
│ ├── k8s/ # Kubernetes manifests (Kustomize)
│ ├── docker/ # Docker Compose files
│ └── grafana/ # Dashboards + provisioning
│
├── tools/ # Developer tooling
│ ├── scripts/ # Shell scripts (setup, health-check, etc.)
│ └── generators/ # Nx generators for scaffolding
│
├── data/ # Scripture corpus + fixtures
│ ├── book_registry.json # Canonical book metadata
│ └── fixtures/ # Test fixture data
│
└── docs/ # Project documentation
Dependency Graph
graph TB
subgraph apps["Apps (TypeScript)"]
web["apps/web"]
admin["apps/admin"]
mobile["apps/mobile"]
end
subgraph pkgs["Packages (TypeScript)"]
sdk["@gospelib/sdk"]
types["@gospelib/types"]
ui["@gospelib/ui"]
config["@gospelib/config"]
testing["@gospelib/testing"]
core["@gospelib/core"]
scripref["@gospelib/scripture-ref"]
pluginsdk["@gospelib/plugin-sdk"]
end
subgraph svcs["Services (Go/Python)"]
gateway["gateway"]
content["content"]
auth["auth"]
billing["billing"]
ai["ai"]
notif["notifications"]
end
web --> sdk & ui & config & core & scripref
admin --> sdk & ui & config
mobile --> sdk & ui & config & core
sdk --> types
core --> types & scripref
pluginsdk --> types
gateway --> content & auth & billing & ai & notif
Dependency rules:
- Apps import all packages
@gospelib/sdkimports only@gospelib/types- Services never import TypeScript packages at runtime
- Services communicate only via HTTP or Redis Streams
Task Caching
Nx caches results for build, test, lint, and typecheck targets. The dev target is not cached.
// nx.json (simplified)
{
"targetDefaults": {
"build": { "dependsOn": ["^build"], "cache": true },
"test": { "cache": true },
"lint": { "cache": true },
"typecheck": { "cache": true }
}
}
Affected Commands
Only run tasks for projects affected by your changes:
# Test only what changed since main
pnpm nx affected -t test
# Lint affected projects in parallel
pnpm nx affected -t lint --parallel=4
# See which projects are affected
pnpm nx show projects --affected
Naming Conventions
| Category | Convention | Example |
|---|---|---|
| npm packages | @gospelib/<name> | @gospelib/ui |
| Python packages | gospelib_<name> | gospelib_content |
| Service containers | gospelib-<name> | gospelib-content |
| Env vars | GOSPELIB_<SERVICE>_<KEY> | GOSPELIB_CONTENT_DB_URL |
| DB schemas/tables | gl_<name> | gl_users |
| Redis keys | gl:<service>:<key> | gl:content:passage:gen.1.1 |
| API routes | /api/v1/<resource> | /api/v1/passages |
| Docker tags | <registry>/<service>:<semver> | ecr/gospelib-content:1.2.3 |
Related Pages
- Technology Stack — Pinned versions and rationale
- Architecture Overview — Core principles