- Home header shows a running sum of impacted people across all matching records (respects the current search filter), next to the record count - Letters can be deleted from the table (trash button next to Download), which unlinks the pastor and removes the upload doc so a new file can be uploaded in its place Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|---|---|---|
| .claude | ||
| .vscode | ||
| data | ||
| src | ||
| .env.example | ||
| .gitignore | ||
| .npmrc | ||
| .prettierrc.json | ||
| Dockerfile | ||
| README.md | ||
| ecosystem.config.cjs | ||
| eslint.config.mjs | ||
| next.config.ts | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| postcss.config.mjs | ||
| tsconfig.json | ||
README.md
DB Ministerial
A Payload CMS 3 content platform with a Next.js frontend, styled with Tailwind CSS v4 and daisyUI v5, backed by SQLite (zero-setup).
The CMS admin, REST/GraphQL API, and the public React frontend all live in a single Next.js app.
Requirements
- Node.js 20.9+ (22 recommended)
- pnpm 9, 10, or 11 (
npm install -g pnpm)
Getting started
pnpm install # install dependencies
cp .env.example .env # then set a real PAYLOAD_SECRET
pnpm dev # start the dev server at http://localhost:3000
On first boot, SQLite creates ministerial.db automatically and pushes the schema.
Open http://localhost:3000/admin and create your first admin user.
Optional: seed sample content
pnpm seed
Creates an admin user (admin@example.com / changeme123 — change these via
SEED_ADMIN_EMAIL / SEED_ADMIN_PASSWORD), three tags, and three published posts so
the home page has something to render. Safe to re-run; it skips if any user exists.
Import pastors from the CSV
The pastors collection is populated from data/pastores_unificado.csv. On a new
server, run this once after the first boot (the schema is created automatically):
pnpm import:pastors
Maps the CSV columns to the collection: codigo_iso → country (ISO alpha-2),
nombre → name, ciudad → city, estado → state, telefono → telephone[] (numbers
split on ||), email, notas → notes, and fuente → source.
Environment flags:
DRY_RUN=1— parse and report the row count without writing anything.CLEAR=1— delete existing pastors first, then reimport (clean re-run).FORCE=1— import even if pastors already exist (appends).
Without a flag the script skips if any pastors already exist, so it is safe to leave in a provisioning script — it will not create duplicates on a second run.
Project structure
src/
├── app/
│ ├── (frontend)/ # Public site (Tailwind + daisyUI)
│ │ ├── layout.tsx # Navbar, footer, daisyUI theme (Spanish)
│ │ ├── page.tsx # Home page — pastors data table
│ │ ├── PastorsTable.tsx # Client table + create/edit/upload modals
│ │ ├── actions.ts # Server actions (create/update/upload letter)
│ │ └── styles.css # @import "tailwindcss" + @plugin "daisyui"
│ └── (payload)/ # Payload admin + API (do not edit — generated)
├── collections/
│ ├── Users.ts # Auth-enabled admin users
│ ├── Posts.ts # Title, slug, status, excerpt, cover, tags, richtext
│ ├── Pastors.ts # Name, church, location, phones[], Telegram, letter
│ ├── PastorLetters.ts # Letter uploads (PDF / Word only)
│ ├── Media.ts # File uploads
│ └── Tags.ts
├── payload.config.ts # Payload config (SQLite adapter, collections)
├── import-pastors.ts # CSV → pastors importer (pnpm import:pastors)
└── seed.ts # Sample-content seeder
How the frontend gets content
src/app/(frontend)/page.tsx uses Payload's Local API directly on the server —
no HTTP round-trip:
const payload = await getPayload({ config })
const { docs: posts } = await payload.find({
collection: 'posts',
where: { status: { equals: 'published' } },
sort: '-publishedDate',
})
Content is also available over REST (/api/posts) and GraphQL (/api/graphql).
Styling
Tailwind v4 + daisyUI are configured entirely in CSS (no tailwind.config.js):
postcss.config.mjsenables@tailwindcss/postcsssrc/app/(frontend)/styles.cssimports Tailwind and registers daisyUI themes (corporatelight /businessdark)
The Payload admin (route group (payload)) uses its own styles and is not affected
by Tailwind/daisyUI, because the Tailwind stylesheet is only imported in the frontend
layout.
Change the theme by editing the data-theme attribute in
src/app/(frontend)/layout.tsx, or add more daisyUI themes in styles.css.
Production build
pnpm build
pnpm start
For production you should switch SQLite from push mode to migrations and point
DATABASE_URI at a persistent/hosted libSQL database (e.g. Turso). See the
Payload SQLite docs.