A production-ready Agency CMS built with Payload CMS (3.x), Next.js (16.x App Router), TypeScript, and SQLite/Drizzle.
It provides complete internal agency operational management and a secure client portal interface.
- Framework: Next.js (App Router)
- CMS Platform: Payload CMS 3.x
- Language: TypeScript
- Database: MongoDB
- Package Manager / Runtime: pnpm
Follow these steps to clone and run this project locally.
Clone the project from GitHub:
git clone https://github.com/wevlra/wevlra-cms.git
cd wevlra-cmsCopy the example environment configuration:
cp .env.example .envEnsure the variables are set correctly in .env:
DATABASE_URL=file:./wevlra-cms.db
PAYLOAD_SECRET=your_super_secret_payload_keyInstall all dependencies using pnpm:
pnpm installGenerate Payload types and apply the database migrations to structure the local SQLite file:
# Compile Payload typescript types
pnpm generate:types
# Generate the import map for views/components
pnpm generate:importmap
# Run fresh migrations (creates tables in SQLite)
pnpm payload migrate:freshSeed the database with pre-populated agency operational data (Clients, Projects, Websites, Landing Pages, Blog Posts, Invoices, Tickets, Activity Logs, and Users with various roles):
pnpm run seedRun the local Next.js server:
pnpm run devOpen http://localhost:3000/admin in your browser to access the Payload Admin Panel.
You can log in to the Admin Panel using any of the following seeded user credentials:
| Role | Password | |
|---|---|---|
| Super Admin / Admin | admin@wevlra.dev |
password123 |
| Project Manager | pm@wevlra.dev |
password123 |
| Developer | dev@wevlra.dev |
password123 |
| Client Owner | client@acme.com |
password123 |
- Website Ownership Root: Content structures (Landing Pages, Blog Posts, Media, Tickets) resolve their client ownership through their associated Website relation rather than storing direct client mappings.
- Role-Based Access Control (RBAC): Type-safe access controls restrict staff/clients based on their roles. Client users are fully isolated and can only view their own website content, invoices, and tickets.
- Calculated Invoices: Invoice line items calculate automatically on write. Discounts, subtotals, taxes, and final totals are computed in-database.
- Threaded Tickets: Ticket messages are stored in a normalized
TicketMessagescollection rather than an array, optimized for future features like read states and edits. - Activity Log Hooks: Collection mutations automatically log to an audit trail with before/after state capture, guarded against loop recurrence.
Run integration tests using Vitest (with separate clean database configuration):
DATABASE_URL=file:./test.db pnpm test:intRun end-to-end browser tests using Playwright:
pnpm test:e2e