Lalabase
티켓·문서·근무시간·고객대화를 한 곳에 모아 KI로 검색, 소프트웨어 기업 고객 프로젝트용, 오픈소스로 자체 서버·독일 클라우드에 배포
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
A comprehensive children's ministry management system designed to streamline registration, check-in/out processes, incident management, and administrative oversight for church ministries.README 전문 보기 ↗A comprehensive children's ministry management system designed to streamline registration, check-in/out processes, incident management, and administrative oversight for church ministries.
/check-in, /ministries, /reports, etc.; legacy /dashboard/* redirects to the flat path/help and /help/releases/reports export of today’s roster with allergies and contactsNEXT_PUBLIC_SENTRY_DSN is setdbAdapterBefore you begin, ensure you have the following installed:
>=22.22.2, see package.json engines)git clone <your-repository-url>
cd gather-kids
npm install
# or
yarn install
The app is Supabase-only. There is no demo mode, IndexedDB backend, DATABASE_MODE, or in-app demo users. Local development uses a disposable local Supabase stack, or the UAT Supabase project. Stakeholder demos use UAT.
See DATABASE_ENV_SETUP_GUIDE.md for UAT/production project setup, GitHub Actions secrets, and Vercel env vars.
.env.local (never commit secrets or real family data).supabase start
npm run gen:types
npm run seed:dev
npm run seed:dev is safe to run repeatedly: households, guardians, emergency
contacts, children and incidents are keyed on stable ids derived from their
natural keys, so a second run reports already exists and changes nothing. Each
run does still create a new registration cycle (and the enrollments belonging to
it), which is deliberate — the newest cycle becomes the active one.
If your local database was seeded before this was fixed, it holds several copies of the Smith and Johnson families. Reseeding will not clean those up. Start over on the disposable local stack instead:
supabase db reset
npm run seed:dev
.env.local at that local instance (URLs and keys are printed by supabase start):# Application Configuration
NEXT_PUBLIC_APP_NAME=gatherKids
NEXT_PUBLIC_APP_VERSION=1.11.0
NODE_ENV=development
NEXT_PUBLIC_LOGIN_MAGIC_ENABLED=false
NEXT_PUBLIC_LOGIN_PASSWORD_ENABLED=true
NEXT_PUBLIC_LOGIN_GOOGLE_ENABLED=false
# Local Supabase (from `supabase start`)
NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321
NEXT_PUBLIC_SUPABASE_ANON_KEY=<local-anon-key>
SUPABASE_SERVICE_ROLE_KEY=<local-service-role-key>
NEXT_PUBLIC_SENTRY_DSN=
NEXT_PUBLIC_SITE_URL=http://localhost:9002
The factory always returns SupabaseAdapter. Missing NEXT_PUBLIC_SUPABASE_URL or NEXT_PUBLIC_SUPABASE_ANON_KEY is an error, not a fallback to IndexedDB.
Point .env.local at the UAT Supabase project instead of local:
NEXT_PUBLIC_SUPABASE_URL=https://<your-uat-ref>.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=<your-uat-anon-key>
SUPABASE_SERVICE_ROLE_KEY=<your-uat-service-role-key>
NEXT_PUBLIC_SITE_URL=http://localhost:9002
Do not reset or reseed UAT unless an issue explicitly authorizes it.
npm run dev
# or
yarn dev
The application will be available at http://localhost:9002 (note the custom port).
Open your browser and navigate to http://localhost:9002
There are no in-app demo users. After npm run seed:dev (local) or an authorized UAT seed, log in with the synthetic accounts those scripts create. See docs/ADMIN_USER_GUIDE.md to create an admin in a Supabase project.
For UAT (User Acceptance Testing) environments using Supabase, the application includes a comprehensive seeding script that populates the database with deterministic test data:
is_active# Idempotent seeding (safe to re-run, upserts existing data)
npm run seed:uat
# Reset mode (destructive - deletes existing UAT data first)
RESET=true npm run seed:uat
# or use the shortcut:
npm run seed:uat:reset
.env.localNEXT_PUBLIC_SUPABASE_URL or SUPABASE_UAT_URLSUPABASE_SERVICE_ROLE_KEY or SUPABASE_UAT_SERVICE_ROLE_KEYThe script includes schema compatibility verification and detailed error reporting to help diagnose issues.
# Development
npm run dev # Start development server on port 9002
npm run build # Build for production
npm run start # Start production server
npm run lint # Run ESLint
npm run typecheck # Run TypeScript type checking
# Testing
npm test # Run Jest test suite
npm run test:watch # Run tests in watch mode
# Database & Type Generation
npm run gen:types # Generate TypeScript types from Supabase schema
npm run gen:types:prod # Generate types from production environment
# Data Management
npm run seed:scriptures # Seed scripture references
npm run seed:dev # Seed local disposable Supabase
npm run seed:uat # Seed UAT database with test data (idempotent; authorized use only)
npm run seed:uat:reset # Reset and re-seed UAT database (destructive; authorized use only)
# Documentation (in-app /help)
npm run docs:validate # Validate help markdown, links, screenshots, changelog
npm run help:parse-changelog # Smoke-test CHANGELOG.md parser
npm run help:capture-screenshots # Playwright baseline PNGs (local seeded dev only)
# AI Development (Genkit)
npm run genkit:dev # Start Genkit AI development server
npm run genkit:watch # Start Genkit with file watching
Quick helpers added for UAT and migration validation:
scripts/db/snapshot_uat.sh - create a pg_dump snapshot of a target DATABASE_URL (read-only)scripts/test/uat_smoke.sh - small curl-based smoke checks (assumes app running)scripts/db/check_fks.sh - FK integrity checker used by CIsupabase db push). See docs/CI_CD.md.See docs/PROD_PROMOTION_RUNBOOK.md for the promotion runbook.
gather-kids/
├── src/
│ ├── app/ # Next.js App Router
│ │ ├── (admin)/ # Flat staff routes: /check-in, /ministries, /reports, …
│ │ ├── dashboard/ # Legacy /dashboard/* → flat-route redirects
│ │ ├── help/ # In-app user guide + /help/releases
│ │ ├── household/ # Guardian household portal
│ │ ├── login/ # Authentication
│ │ └── register/ # Family registration
│ ├── components/ # Reusable UI components
│ │ ├── ui/ # Base UI components (Radix)
│ │ └── gatherKids/ # Application-specific components
│ ├── contexts/ # React contexts (auth, features)
│ ├── hooks/ # Custom React hooks
│ ├── lib/ # Utilities and data access
│ │ ├── database/ # Database abstraction layer (SupabaseAdapter)
│ │ │ ├── types.ts # Database adapter interface
│ │ │ ├── factory.ts # Always returns SupabaseAdapter
│ │ │ └── supabase-adapter.ts
│ │ ├── dal/ # Domain DAL helpers (cycle scoping, exports, …)
│ │ └── ai/ # AI/Genkit integration
├── content/help/ # Markdown sources for /help
├── supabase/ # Raw SQL migrations and Supabase config
│ ├── migrations/ # SQL migration files
│ └── seeds/ # Project seed scripts and SQL
├── docs/ # Developer / ops documentation
├── public/ # Static assets
└── tailwind.config.ts # Tailwind CSS configuration
Runtime storage is Supabase (PostgreSQL) in every environment. The factory always returns SupabaseAdapter. There is no DATABASE_MODE and no IndexedDB/demo backend.
supabase start) or the UAT projectThe database schema is managed as raw PostgreSQL SQL migrations stored in supabase/migrations/. Apply them locally with supabase db push. UAT and production go through the GitHub DB deploy workflows only. See docs/CI_CD.md.
Run npm run gen:types to generate TypeScript types from the Supabase schema.
The application uses Tailwind CSS with a custom design system:
mainsrc/components/src/lib/types.ts as neededAll data access goes through the DAL (@/lib/dal) and dbAdapter. Do not import @supabase/supabase-js outside the DAL and allowed API/script paths. See DATABASE_ADAPTERS.md.
The application uses raw SQL migrations stored in supabase/migrations/ for database schema management:
# Local disposable database only
supabase start
supabase db push
# Generate TypeScript types from schema
npm run gen:types
supabase db push)supabase db push)scripts/db/apply_migrations_safe.sh is quarantined. It does not update supabase_migrations.schema_migrations.
# Local disposable Supabase
supabase start
npm run seed:dev
npm run dev
# Or point .env.local at UAT (do not reset/reseed UAT unless authorized)
npm run dev
For detailed Supabase setup instructions, see DATABASE_ENV_SETUP_GUIDE.md.
useAuth hook for authentication statedbAdapter) for all data operations@supabase/supabase-js outside the DAL and allowed API/script paths# Type checking
npm run typecheck
# Code linting
npm run lint
# Test suite
npm test
# Build verification
npm run build
gatherKids uses a multi-environment deployment strategy with strong isolation between development, UAT (preview), and production environments.
npm ci), put local or UAT Supabase values in .env.local.supabase start, npm run gen:types, npm run seed:dev.npm run dev — app at http://localhost:9002.See DATABASE_ENV_SETUP_GUIDE.md for UAT/production credentials and Vercel env vars.
uat branch.github/workflows/uat-deploy.yml.github/workflows/prod-deploy.ymlMigrations use raw PostgreSQL SQL files in supabase/migrations/:
# UAT (automatic on branch push)
git push origin uat
# Production (manual with approval)
# Trigger via GitHub Actions > Workflows > "PROD deploy"
Required environment variables for each deployment target:
NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321
NEXT_PUBLIC_SUPABASE_ANON_KEY=<local-anon-key>
SUPABASE_SERVICE_ROLE_KEY=<local-service-role-key>
NEXT_PUBLIC_SITE_URL=http://localhost:9002
NEXT_PUBLIC_LOGIN_MAGIC_ENABLED=true
NEXT_PUBLIC_LOGIN_PASSWORD_ENABLED=true
NEXT_PUBLIC_LOGIN_GOOGLE_ENABLED=true
NEXT_PUBLIC_SUPABASE_URL=https://<prod-ref>.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=<prod-anon-key>
SUPABASE_SERVICE_ROLE_KEY=<prod-service-role-key>
NEXT_PUBLIC_SITE_URL=https://your-production-domain.com
For complete setup instructions including Supabase project creation, GitHub environment configuration, and Vercel deployment settings, see DATABASE_ENV_SETUP_GUIDE.md.
This repository is configured with GitHub Actions and Vercel to provide automated CI and preview deployments.
.github/workflows/ci.yml — runs test suite on pull requests (and on push for branches if enabled). The CI job checks out the code, installs dependencies, and runs npm test.Notes about how PR runs are chosen
main) when evaluating pull_request events. That means a workflow added only on a feature branch will not run for PRs targeting main until the workflow exists on main. If you need immediate CI on a branch push, enable push triggers in .github/workflows/ci.yml.What happens after a PR is merged
main Vercel will deploy the merge commit to your production environment (depending on your Vercel project settings)..github/workflows/delete-branch.yml will attempt to delete the source branch after the PR is merged into main (this uses the repository token by default). If your organization blocks marketplace actions, the workflow contains an API fallback that uses GITHUB_TOKEN to remove the branch.main Vercel will deploy the merge commit to your production environment (depending on your Vercel project settings).Branch cleanup after merge
If you prefer automation in workflows (instead of the native setting), you can add a workflow that calls the GitHub API to delete the merged branch — but the native setting is simpler and recommended.
If you need to change CI behavior
.github/workflows/ci.yml to add steps (lint, typecheck, build) or to enable push: triggers so pushes to feature branches also run CI.peter-evans/delete-branch) in organization settings or rely on the API fallback step in the workflow.Sentry is integrated via @sentry/nextjs. Init files:
src/instrumentation-client.ts — browser-side error capture (keep onRouterTransitionStart)sentry.server.config.ts — server-side error capturesentry.edge.config.ts — edge runtime error captureDo not add sentry.client.config.ts. That file is deprecated under Turbopack; browser init lives only in src/instrumentation-client.ts.
Sentry initializes only when NODE_ENV=production and NEXT_PUBLIC_SENTRY_DSN is set. Shared DSN / environment / release helpers live in src/lib/sentry/runtime.ts.
| Variable | Purpose |
|---|---|
NEXT_PUBLIC_SENTRY_DSN | Public DSN. Do not commit a real value. |
NEXT_PUBLIC_DEPLOY_ENV | Preferred environment tag (production or uat) |
VERCEL_ENV | Fallback (production, preview, or development) |
release is the app version already stamped at build time (package.json / src/lib/build-info.ts), the same value /api/version reports.
The Sentry tunnel is /monitoring (tunnelRoute in next.config.ts). Middleware excludes that path so client events are not intercepted.
CI dummy builds must not upload source maps. .github/workflows/ci.yml must not set SENTRY_AUTH_TOKEN. Uploads are for Vercel/production builds only (see #260).
Turbopack sourcemaps: Local npm run dev uses Turbopack. Production stays on webpack (next build without --turbopack). The repo is on Next.js 16 and @sentry/nextjs ^10.73; keep production on webpack unless Turbopack production sourcemaps are explicitly validated for this stack.
Sample rates, Replay policy, and PII scrubbing are shared from src/lib/sentry/ (do not copy magic numbers into each init file):
tracesSampleRate is 0.05 in production and 0.2 in UAT (NEXT_PUBLIC_DEPLOY_ENV=uat or Sentry environment === 'uat'). It is not 1.0 in production. Local/dev may use a higher rate if Sentry is initialized there.replaysSessionSampleRate is 0 (no session recordings). replaysOnErrorSampleRate is 1.0 (record only sessions that error). Replay uses default masking: maskAllText, maskAllInputs, blockAllMedia.enableLogs is false so log volume does not consume the free-plan quota.beforeSend (src/lib/sentry/scrub.ts) strips emails, obvious name fields, and request/response bodies. Stack traces are kept. Do not call Sentry.setUser with guardian email or child identifiers. Sentry is an error-monitoring tool, not a store of family records.Core Web Vitals (CLS, FID, LCP, INP, FCP, TTFB) are reported via src/components/analytics/web-vitals.tsx using the Next.js useReportWebVitals hook. The component is rendered in src/app/layout.tsx and logs metrics to the console in production. To forward metrics to an analytics backend, edit the useReportWebVitals callback in that file.
A lightweight health endpoint is available at:
GET /api/health
Response (HTTP 200):
{ "status": "ok", "timestamp": "2026-03-22T12:00:00.000Z" }
Use this URL for uptime monitors, load balancer health checks, and smoke tests. The endpoint has no external dependencies and always returns 200 while the process is running.
Dependabot is configured in .github/dependabot.yml to open weekly pull requests for npm dependency updates. Minor and patch updates are grouped into a single PR to reduce noise. Major version bumps create individual PRs.
npm test # Run Jest test suite
npm run test:watch # Watch mode
npm run build # Production build (ESLint + TypeScript gate)
npm run typecheck # TypeScript check only
npm run lint # ESLint only
Both npm test and npm run build must pass before merging any PR. CI enforces this via .github/workflows/ci.yml.
For detailed E2E test status — including the login → check-in → roster coverage gap — see docs/testing.md.
The application underwent a comprehensive audit in March 2026. Key documents:
Humans: docs/CONTRIBUTING.md (conventional commits, trunk-based main).
Coding agents: AGENTS.md is the operating contract. Thomas’s GitHub inbox and notification setup: docs/AGENT_WORKFLOW.md.
/help on any deployed app (same origin as gatherKids)/help/releases (from CHANGELOG.md)docs/HELP_DOCS.mddocs/FEATURES.md, docs/blueprint.mdpackage.json if needed.npm installnpm run typecheck to identify TypeScript issuessupabase db reset and npm run seed:dev on a disposable local stackNEXT_PUBLIC_SUPABASE_URL and API keys in .env.local>=22.22.2 (package.json engines)This project is proprietary software. All rights reserved.
Happy coding! 🎉