Skip to main content

Repository Map

This document defines the naming conventions and file organization rules for the GospeLib monorepo. For a walkthrough of the directory layout, see the Repository Tour. For monorepo tooling (Nx, pnpm, uv), see Monorepo & Tooling.

Top-Level Structure (Quick Reference)

gospelib/
├── apps/ # Frontend applications (Next.js, Expo)
├── services/ # Backend microservices (Go, Python)
├── packages/ # Shared TypeScript/Python libraries
├── infra/ # Docker Compose, Terraform, Kubernetes, Grafana
├── tools/ # Developer scripts and Nx generators
├── data/ # Book registry, corpus-v2, test fixtures
├── docs/ # Specifications, ADRs, guides
└── (root configs) # nx.json, package.json, tsconfig.base.json, etc.

For details on each directory, see the Repository Tour.


Naming Conventions

File Naming

ContextConventionExample
TypeScript / JavaScript fileskebab-case.tspassage-reader.tsx, use-auth.ts
React componentsPascalCase.tsxPassageReader.tsx, SearchBar.tsx
React component directoriesPascalCase/PassageReader/PassageReader.tsx
Go filessnake_case.gopassage_handler.go, rate_limiter.go
Python filessnake_case.pyscripture_text.py, batch_writer.py
Shell scriptskebab-case.shreset-db.sh, gen-types.sh
Terraform filessnake_case.tfmain.tf, variables.tf
YAML / JSON configkebab-case.yamldocker-compose.yml, plans.yaml
Markdown docsUPPER-KEBAB-CASE.md (specs) or kebab-case.md (guides)TECH-SPEC.md, getting-started.md
Test files (TS)*.test.ts or *.spec.tspassage-reader.test.tsx
Test files (Go)*_test.gopassage_handler_test.go
Test files (Python)test_*.pytest_scripture_text.py

Directory Naming

ContextConventionExample
Top-level concernskebab-case or singular nounapps/, services/, packages/
App/service sub-dirskebab-casecomponents/, hooks/, routes/
Component directoriesPascalCase (React)Button/, PassageReader/
Python packagessnake_casescripture_text/, db/
Go packageslowercase (single word preferred)handler/, middleware/, config/

Package and Service Naming

EntityConventionExample
npm packages@gospelib/<name>@gospelib/ui, @gospelib/sdk
Docker images / K8s servicesgospelib-<name>gospelib-content, gospelib-gateway
Python packagesgospelib_<name>gospelib_ingest
Go modulesgithub.com/gospelib/main/services/<name>github.com/gospelib/main/services/gateway

Environment Variable Naming

Pattern: GOSPELIB_<SERVICE>_<KEY>

CategoryExample
Service-specificGOSPELIB_CONTENT_DB_URL, GOSPELIB_BILLING_STRIPE_KEY
Shared infraGOSPELIB_PG_URL, GOSPELIB_REDIS_URL, GOSPELIB_FALKORDB_URL
Feature flagsGOSPELIB_FF_<FLAG_NAME>

Third-party variables use their standard names: CLERK_SECRET_KEY, STRIPE_SECRET_KEY, ANTHROPIC_API_KEY.

Database and Redis Naming

StoreConventionExample
PostgreSQL schemasgl_<name>gl_users, gl_subscriptions
FalkorDB graph namegospelib--
Redis key namespacesgl:<service>:<key>gl:content:passage:gen.1.1
Redis Streamsgl:events:<domain>gl:events:notifications

Data ID Conventions

EntityPatternExample
Passage IDs{bookId}.{chapter}.{verse}gen.1.1
JST Passage IDsjst-{bookId}.{chapter}.{verse}jst-gen.1.1
Translation IDs{bookId}.{chapter}.{verse}:{translation}gen.1.1:esv
Word IDs (Strong's){H|G}{NNNN} (zero-padded 4-digit)H0430, G0056
TG Entry IDstg:{slugified-title}tg:angels
BD Entry IDsbd:{slugified-title}bd:aaron
Person IDsperson:{slug}.{N}person:aaron.1
Place IDsplace:{slug}place:ammonihah
Index Topic IDstopic:{slug}topic:aaronic-priesthood
Section IDs{commentaryId}.t{XX}.s{XX}byu-ntc-revelation.t02.s01

File Organization Rules

When to Split a File

SignalAction
File exceeds 300 lines (TS/Python) or 500 lines (Go)Extract related functions into a new module
File handles more than one domain concernSplit by concern (e.g., separate auth from billing logic)
File has more than 5 exports that are unrelatedGroup related exports into sub-modules
A component has more than 3 sub-components inlineExtract sub-components to their own files

When to Create a New Directory

SignalAction
3+ related files that share a themeGroup into a named directory
A feature needs its own routes + components + hooksCreate a feature directory
A test fixture set is shared across multiple test filesMove to fixtures/ directory

When to Create a New Package vs. Module

Choose Package WhenChoose Module When
Code is consumed by 2+ apps or servicesCode is used by only one app or service
Code has its own versioning needsCode changes in lockstep with its consumer
Code could be open-sourced independentlyCode is tightly coupled to business logic

Co-location Principles

RuleRationale
Tests next to source (Go, TS components)Reduces navigation; makes coverage gaps visible
Types next to implementationKeeps contracts close to where they're enforced
Styles next to components (CSS Modules / Tailwind)Component is self-contained
Python tests in tests/Python convention; pytest discovery expects it
Fixtures near teststests/fixtures/ or data/fixtures/ -- never scattered

Index / Barrel File Policy

LanguagePolicy
TypeScriptOne index.ts per package as the public API surface. Internal directories may have index.ts only if they represent a clear module boundary. Do not create deeply nested barrel files.
Python__init__.py in every package (required). Keep imports minimal -- prefer explicit imports over from module import *.
GoNo barrel files. Use package-level exports directly.

Create on First Use

Do not create empty placeholder directories. Every directory is created when its first file is added. The structure is fully defined in this document and the Repository Tour, so contributors know where things go without empty directories as hints.


TopicPage
Directory walkthroughRepository Tour
Monorepo tooling (Nx, pnpm)Monorepo & Tooling
Service detailsServices Overview
Testing conventionsTesting
Port assignmentsPort Map
Architecture decisionsDecisions
Data schemasSchemas
Tech stackStack