Install Dependencies
This guide covers machine prerequisites (PHP, Node, mobile SDKs) and per-package installs (composer, yarn). You do not need every toolchain if you only work in one package — see What you need below.
What you need
Section titled “What you need”| If you work in… | Install |
|---|---|
api/ | PHP 8.4+, Composer, Node (for Vite assets in api/) |
ui/, www/, docs/ | Node.js 22+ (nvm) |
mobile/ | JDK 17, Android Studio; Xcode on macOS for iOS |
| Any contribution | Git, Sign Off Commits configured, git setup (hooks) |
Production planning targets PostgreSQL and Redis (Deployment); the API scaffold defaults to SQLite locally so you can run without Docker on day one.
Local dev stack (recommended)
Section titled “Local dev stack (recommended)”The repo ships bin/setup, bin/start, bin/stop, and bin/check to run a production-like stack locally:
| Layer | How it runs |
|---|---|
| API, Postgres, Redis, Traefik (TLS) | Docker Compose (compose.dev.yml) |
ui/, docs/, www/ (optional) | Native yarn dev on the host |
Default URLs (HTTPS) — add hosts once (see below), run bin/setup, then bin/start:
| Service | URL |
|---|---|
| API | https://api.garrison.test |
| Web app | https://app.garrison.test |
| WebSocket (Reverb) | wss://ws.garrison.test |
| Docs site | https://docs.garrison.test |
Marketing (--www) | https://www.garrison.test (apex https://garrison.test redirects here) |
Traefik terminates TLS on port 443 using mkcert certs in .certs/ (generated by bin/setup). Frontends listen on 5173 / 4322 / 4321; Traefik proxies to them via host.docker.internal.
bin/setup also creates ui/.env from ui/.env.example with VITE_API_URL=https://api.garrison.test so the SPA calls the API host directly (required for Sanctum cookies on .garrison.test). Override that value if your API origin differs.
Commands
Section titled “Commands”bin/check # prerequisites only; exit 1 if anything missingbin/setup # once: mkcert, Docker build, composer, migratebin/start # foreground: docker compose + ui + docsbin/start --preview # ui: production build + vite preview (no HMR)bin/start --www # also start www/bin/stop # docker compose downbin/stop --purge # down + remove postgres volumeOn Windows (PowerShell from the repo root), use the same flags with the bin\*.ps1 scripts: bin\check.ps1, bin\setup.ps1, bin\start.ps1, bin\stop.ps1, bin\lint.ps1, and bin\install-git-hooks.ps1. The hosts file is %SystemRoot%\System32\drivers\etc\hosts (the setup/start scripts can append the dev hostnames when you confirm, with elevation).
| Flag | Effect |
|---|---|
--no-prompt | Fail with instructions instead of interactive install offers (bin/start, bin/setup) |
--preview | Build ui/ once, then vite preview on port 5173 (no HMR; recommended for Playwright) |
--http | Skip TLS checks / Traefik; use http://localhost:8000, :5173, :4322 (OAuth and Secure cookies may not work) |
--www | Include marketing site |
bin/start runs everything in one terminal via concurrently; Ctrl+C stops Docker and frontends. Compose services use restart: unless-stopped; the API container is watched for api/.env.docker and docker/api image changes (composer.lock is bind-mounted — run composer install in the container after lockfile updates). Frontends restart automatically if their dev server exits.
Prerequisites checked by bin/check / bin/start
Section titled “Prerequisites checked by bin/check / bin/start”- Docker + Compose v2 (
docker compose), daemon running - Node 22 (
.nvmrc) and npm ui/node_modules,docs/node_modules(andwww/node_moduleswith--www) — prompts foryarn installwhen missing- mkcert,
.certs/(afterbin/setup) - hosts file (
/etc/hostson Unix;%SystemRoot%\System32\drivers\etc\hostson Windows) — one line mapping dev hostnames to127.0.0.1(scripts can append when you confirm)
Not required on the host for Docker dev: PHP and Composer (run inside the api container via bin/setup).
Hosts file (one-time)
Section titled “Hosts file (one-time)”Add to /etc/hosts (macOS/Linux) or C:\Windows\System32\drivers\etc\hosts (Windows, edit as Administrator):
127.0.0.1 garrison.test api.garrison.test app.garrison.test docs.garrison.test www.garrison.test ws.garrison.testWeb E2E tests (Playwright)
Section titled “Web E2E tests (Playwright)”Browser tests live in tests/web/ and target the running SPA at https://app.garrison.test (same stack as bin/start).
cd tests/webyarn installyarn install:browsersyarn testRequires bin/start (or equivalent) so the API and UI are reachable. Copy tests/web/.env.example to .env only if you need a non-default BASE_URL. See tests/web/README.md for project layout (setup, smoke, chromium) and worktree workflow.
Native API (without Docker)
Section titled “Native API (without Docker)”Contributors can still run the API on the host with SQLite:
cd api && composer run setup && composer run devSee PHP and Composer below.
Sample data (local only)
Section titled “Sample data (local only)”When APP_ENV=local, seed a dev account and sample studies:
docker compose -f compose.dev.yml run --rm --no-deps api php artisan db:seed| Field | Value |
|---|---|
dev@garrison.test | |
| Password | password |
Re-running the seeder resets that user’s studies, log entries, and notes. The web sign-in page (yarn dev) shows Use dev account to fill these credentials. Not run in production.
Clone the repository
Section titled “Clone the repository”git clone https://gitlab.com/ChurchTechHelp/garrison.gitcd garrisonRecommended next steps for contributors: Git setup (once per clone), then sign off commits (Git identity and commit.signoff), then install only the toolchains you need below.
Git setup
Section titled “Git setup”The repository ships shared pre-commit hooks under .githooks/. They call bin/pre-commit, which inspects staged files and runs checks only for the packages you touched.
Install hooks (once per clone)
Section titled “Install hooks (once per clone)”From the repository root:
bin/install-git-hooksThis sets core.hooksPath to .githooks for this clone only (stored in .git/config, not committed). Re-run the installer after cloning again or if hooks stop running.
Confirm hooks are active:
git config core.hooksPath # should print: .githooksWhat runs on commit
Section titled “What runs on commit”| Staged paths | Check | Requires |
|---|---|---|
api/**/*.php | Laravel Pint (--test, staged files only) | cd api && composer install |
ui/**/*.{vue,ts,tsx,js,mjs,cjs} | ESLint (staged files) | cd ui && npm install |
ui/**/*.{vue,ts,tsx,js,mjs,cjs,css,json,md,html} | Prettier --check (staged files) | cd ui && npm install |
ui/** with any .vue or .ts change | vue-tsc (full UI typecheck) | cd ui && npm install |
| Any path | Block .env and common key files (allow *.example) | — |
api/routes/**, api/graphql/schema.graphql, api/app/GraphQL/**, api/app/Models/**, api/database/migrations/**, ui/graphql/** | CodeSight wiki regen + stage .codesight/ | npx (Node.js) on the host |
Changes under www/, docs/, or mobile/ do not trigger package linters yet; install hooks anyway so secret checks and future rules still apply.
Run checks manually
Section titled “Run checks manually”Same script Git invokes on commit:
bin/pre-commitWith nothing staged, it prints No staged files and exits successfully. Stage changes first to mirror a real commit:
git add ui/src/App.vuebin/pre-commitLint from the repository root (package name first; remaining args go to the linter):
bin/lint uibin/lint ui --fix src/pages/index.vuebin/lint apibin/lint api --test app/Models/User.phpSupported packages: api (Pint), ui (ESLint). With no extra args, bin/lint api runs pint --test . and bin/lint ui runs eslint ..
Other checks (run inside the package directory):
cd ui && npm run format:check && npm run typecheckcd api && ./vendor/bin/pint # fix style (omit --test)If a commit is blocked
Section titled “If a commit is blocked”- Read the
pre-commit:message — it names the failing tool. - Fix formatting or lint issues, or run the package commands above.
- Ensure dependencies are installed for the package you changed (see Troubleshooting).
To skip hooks in exceptional cases (not for routine use):
git commit --no-verifyImplementation details live in bin/pre-commit and bin/lib/common.sh in the repository root. Policy summary: CONTRIBUTING.
Local dev stack
Section titled “Local dev stack”Run the API in Docker (PostgreSQL + Redis) with native frontends (ui, docs). HTTPS is provided by Traefik and certificates from mkcert so local dev matches production TLS, Sanctum cookies, OAuth, and WebSockets.
Prerequisites
Section titled “Prerequisites”| Tool | Purpose |
|---|---|
| Docker + Compose v2.22+ | API, Postgres, Redis, Traefik; Compose Watch for API rebuilds |
| Node.js 22+ (nvm) | ui, docs, optional www |
| mkcert | Trusted local TLS certificates |
/etc/hosts | Map *.garrison.test to 127.0.0.1 (scripts can prompt to append) |
bin/start and bin/setup check these tools and can offer interactive installs (Homebrew on macOS where available). Use bin/check or bin/start --no-prompt in CI.
Commands
Section titled “Commands”| Script | Purpose |
|---|---|
bin/setup | Once per clone: mkcert certs, Docker image, Composer, migrations |
bin/start | One terminal: Docker + ui + docs (Ctrl+C stops everything) |
bin/stop | Stop containers (--purge removes Postgres volume) |
bin/check | Verify prerequisites only (exit 1 if missing) |
bin/setupbin/startHTTPS URLs (default):
| Service | URL |
|---|---|
| API | https://api.garrison.test |
| Web app | https://app.garrison.test |
| WebSocket (Reverb) | wss://ws.garrison.test |
| Docs site | https://docs.garrison.test |
Marketing (--www) | https://www.garrison.test (apex https://garrison.test redirects here) |
Options: bin/start --www (marketing site); bin/start --http (plain localhost ports, no Traefik — limited OAuth/cookie testing); bin/setup --http (skip mkcert).
Resilience: bin/start brings Compose up detached (up -d) with restart: unless-stopped, then runs docker compose watch api so changes to api/.env.docker restart the API and changes under docker/api/ rebuild the image — without stopping ui/docs. After api/composer.lock changes (e.g. git pull), run docker compose -f compose.dev.yml run --rm --no-deps api composer install (or restart the API once vendor is updated). Vite/Astro still need a manual restart after yarn install when lockfiles change.
Native API (no Docker): use SQLite and composer run dev in api/ as documented under PHP and Composer below.
Node.js (nvm)
Section titled “Node.js (nvm)”JavaScript packages (ui/, www/, docs/, and Laravel Vite assets in api/) use Yarn (via Corepack). CI and www/package.json expect Node 22 (LTS).
Install nvm
Section titled “Install nvm”Follow the official nvm install guide. On macOS with Homebrew:
brew install nvmAdd nvm to your shell profile as described in the install output, then open a new terminal.
Use the project Node version
Section titled “Use the project Node version”The repo root includes .nvmrc (Node 22). From the repository root:
nvm install # reads .nvmrcnvm usenode -v # should report v22.xnpm -vWithout nvm, install Node 22 from nodejs.org or your system package manager and ensure node and npm are on your PATH.
Install JavaScript dependencies
Section titled “Install JavaScript dependencies”Run yarn install inside each package you work on:
cd ui && yarn install && cd ..cd www && yarn install && cd ..cd docs && yarn install && cd ..cd api && yarn install && cd ..Use yarn install --immutable in CI and Docker when you want a clean reproducible tree from the committed lockfile.
PHP and Composer
Section titled “PHP and Composer”The API requires PHP ^8.4 (see api/composer.json).
macOS (Homebrew)
Section titled “macOS (Homebrew)”brew install php@8.4 composerEnsure php on your PATH is 8.4+ (php -v). You may need to link the formula or adjust your shell PATH per Homebrew’s post-install notes.
Use your distribution’s packages, phpbrew, or asdf with the PHP plugin. Install Composer globally or use the composer phar.
API setup
Section titled “API setup”cd apicomposer installcp .env.example .env # skip if .env already existsphp artisan key:generatephp artisan migrateyarn install # Vite / Tailwind for Laravel assetsQuick bootstrap (copies .env, generates key, migrates, installs Yarn deps, builds assets):
cd apicomposer run setupRun the API locally:
php artisan serveFor the full dev stack (server, queue, logs, Vite) after dependencies are installed:
composer run devRun tests:
php artisan test# orcomposer testOptional: PostgreSQL and Redis
Section titled “Optional: PostgreSQL and Redis”Not required for the default SQLite scaffold. When you work against production-like services:
| Service | Typical local install |
|---|---|
| PostgreSQL | brew install postgresql@16 (macOS) or distro packages |
| Redis | brew install redis (macOS) or distro packages |
Update api/.env (DB_CONNECTION, QUEUE_CONNECTION, CACHE_STORE, REDIS_*) per Laravel’s configuration. See Deployment for v1 infrastructure choices.
Mobile (mobile/)
Section titled “Mobile (mobile/)”Kotlin Multiplatform uses the Gradle wrapper (./gradlew); you do not install Gradle globally.
| Requirement | Version / notes |
|---|---|
| JDK | 17 (see shared/build.gradle.kts jvmToolchain(17)) |
| Android SDK | Via Android Studio; compileSdk 34 |
| Xcode | macOS only, for iosApp/ builds and simulator |
| Kotlin / AGP / Compose | Pinned in mobile/gradle.properties; wrapper uses Gradle 8.2.1 |
macOS:
brew install openjdk@17Set JAVA_HOME to JDK 17. Android Studio’s embedded JBR also works when launched from the IDE.
Build commands
Section titled “Build commands”From mobile/:
./gradlew :androidApp:assembleDebug./gradlew :desktopApp:runOpen the mobile/ directory in Android Studio for device selection, iOS targets, and run configurations. iOS builds require Xcode and CocoaPods/tooling as prompted by the IDE.
Verify your setup
Section titled “Verify your setup”| Check | Command |
|---|---|
| Node | node -v → v22.x |
| PHP | php -v → 8.4+ |
| Composer | composer -V |
| API | cd api && php artisan test |
| UI | cd ui && npm run typecheck |
| Docs site | cd docs && npm run build |
| Hooks | bin/pre-commit (with staged files, or expect “No staged files”) |
| Dev stack | bin/check |
Package commands (reference)
Section titled “Package commands (reference)”Each package’s AGENTS.md lists day-to-day commands. Common entry points:
| Package | Dev server | Build |
|---|---|---|
api/ | php artisan serve or composer run dev | yarn run build (in api/) |
ui/ | npm run dev | npm run build |
www/ | yarn dev | yarn build |
docs/ | npm run dev | npm run build |
mobile/ | Android Studio / ./gradlew :desktopApp:run | ./gradlew :androidApp:assembleDebug |
Troubleshooting
Section titled “Troubleshooting”- Hooks not running — Run
bin/install-git-hooksfrom the repo root; confirmgit config core.hooksPathis.githooks. - Pre-commit: Pint missing — Run
composer installinapi/. - Pre-commit: ui dependencies missing — Run
npm installinui/. - Pre-commit: ESLint or Prettier failed — Run
npm run lint/npm run format:checkinui/; fix withnpm run lint:fixandnpm run formatas needed. - Pre-commit: TypeScript failed — Run
npm run typecheckinui/. - Wrong Node version — Run
nvm usefrom the repo root (with.nvmrcpresent). - Permission errors on
vendor/ornode_modules/— Avoidsudowith Composer/npm; fix directory ownership instead. - Do not commit secrets — Use
.env.exampletemplates; real.envfiles are blocked by pre-commit. - bin/start: certificates missing — Run
bin/setup(ormkcert -installand re-run setup). - bin/start: /etc/hosts — Add
127.0.0.1 garrison.test api.garrison.test app.garrison.test docs.garrison.test www.garrison.test ws.garrison.testor accept the script’s sudo prompt. - Vite HMR over HTTPS — If hot reload fails, try
bin/start --httpfor UI-only work or see Traefik websocket notes in the repo.