# DB Ministerial A [Payload CMS 3](https://payloadcms.com) 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 ```bash 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 and create your first admin user. ### Optional: seed sample content ```bash 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): ```bash 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: ```ts 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.mjs` enables `@tailwindcss/postcss` - `src/app/(frontend)/styles.css` imports Tailwind and registers daisyUI themes (`corporate` light / `business` dark) 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 ```bash 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](https://payloadcms.com/docs/database/sqlite).