A modern, headless portfolio CMS built with Keystone 6, Next.js 16, Prisma 7, GraphQL, and PostgreSQL.
The project provides a flexible content management backend for a personal portfolio, with Keystone handling the CMS and GraphQL API, Prisma providing database access, and PostgreSQL serving as the primary database.
- ๐ Keystone 6 headless CMS
- โก Next.js 16 and React 19
- ๐ข Node.js runtime
- ๐ Built-in GraphQL API
- ๐๏ธ Prisma 7 ORM
- ๐ PostgreSQL database
- ๐ Prisma PostgreSQL adapter (
@prisma/adapter-pg) - ๐ Keystone authentication
- ๐ค User/session management
- ๐ Document field support
- ๐ GraphQL operation logging
- โ๏ธ Suitable for serverless PostgreSQL deployments
- ๐งฉ Schema separated from Keystone configuration
- ๐ Headless architecture for API-first content delivery
| Technology | Version / Role |
|---|---|
| Next.js | 16.x โ Application framework |
| React | 19.x โ UI library |
| Node.js | JavaScript runtime |
| KeystoneJS | 6.x โ Headless CMS |
| GraphQL | API layer provided by Keystone |
| Prisma | 7.x โ ORM and database toolkit |
| PostgreSQL | Primary relational database |
| PrismaPg | PostgreSQL driver adapter |
| TypeScript | Application language |
The project's dependencies include Keystone 6 core/authentication, Prisma 7, Next.js 16, React 19, and the PostgreSQL Prisma adapter.
The application follows a headless CMS architecture:
โโโโโโโโโโโโโโโโโโโโโโโโ
โ Portfolio โ
โ Next.js App โ
โโโโโโโโโโโโฌโโโโโโโโโโโโ
โ
โ GraphQL
โผ
โโโโโโโโโโโโโโโโโโโโโโโโ
โ Keystone 6 โ
โ Headless CMS โ
โ โ
โ Authentication โ
โ Sessions โ
โ GraphQL API โ
โโโโโโโโโโโโฌโโโโโโโโโโโโ
โ
โ PrismaPg
โผ
โโโโโโโโโโโโโโโโโโโโโโโโ
โ Prisma 7 โ
โ ORM โ
โโโโโโโโโโโโฌโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโ
โ PostgreSQL โ
โ Serverless DB โ
โโโโโโโโโโโโโโโโโโโโโโโโ
- Content is managed through the Keystone Admin UI.
- Keystone exposes the content through its GraphQL API.
- GraphQL operations are handled by the Keystone backend.
- Keystone uses Prisma for database access.
- Prisma connects to PostgreSQL through the PrismaPg adapter.
- The Next.js application can consume the GraphQL API to render portfolio content.
The Keystone configuration explicitly uses the PostgreSQL provider and initializes PrismaPg with the POSTGRES_URL environment variable.
The Keystone configuration separates the application into dedicated schema and authentication modules:
portfolio-cms/
โโโ auth.ts # Authentication and session configuration
โโโ keystone.ts # Keystone application configuration
โโโ schema.ts # Keystone lists / content schema
โโโ prisma/
โ โโโ migrations/ # Prisma database migrations
โโโ package.json
โโโ tsconfig.json
โโโ .env # Local environment variables
โโโ README.md
The exact project structure may contain additional Next.js components, pages, utilities, and assets.
Make sure you have:
- Node.js installed
- npm or another Node.js package manager
- A PostgreSQL database
- Git
git clone <your-repository-url>
cd <project-directory>npm installThe project runs Keystone's post-install setup automatically through the configured postinstall script.
Create a .env file in the project root:
POSTGRES_URL="postgresql://USER:PASSWORD@HOST:DATABASE"The Keystone configuration reads the PostgreSQL connection string from:
POSTGRES_URL
For example:
POSTGRES_URL="postgresql://postgres:password@localhost:5432/portfolio"Important: Never commit your
.envfile or database credentials to Git.
This project uses PostgreSQL with Prisma 7.
The Keystone configuration specifies:
provider: postgresql
and uses:
PrismaPg
as the Prisma PostgreSQL adapter.
The project provides a dedicated migration script:
npm run migrateThis executes:
prisma migrate deployIf required during development:
npx prisma generateStart the Keystone development server with:
npm run devThe project defines this as:
keystone devOnce running, Keystone's Admin UI and GraphQL API will be available according to your Keystone configuration.
Build the application:
npm run buildThe project maps this command to:
keystone buildStart the production server:
npm run startwhich executes:
keystone startKeystone provides the project's GraphQL API.
The API acts as the primary interface between the CMS data layer and consuming applications.
A typical query might look like:
query {
projects {
id
title
description
}
}The available queries, mutations, fields, and relationships depend on the lists defined in
schema.ts.
The Keystone configuration includes an Apollo plugin that logs GraphQL operations:
graphql operation <operation-name>
It also logs errors encountered during GraphQL requests.
This can be useful during development and debugging.
Authentication is configured separately from the main Keystone configuration.
The project imports:
import { withAuth, session } from './auth.ts'and wraps the Keystone configuration with:
withAuth(...)while providing the configured session to Keystone. This keeps authentication and session configuration separate from the core CMS configuration.
The current development configuration contains an onConnect hook that checks whether any users exist.
If no users exist, it creates an initial administrator account:
Email: admin@example.com
Name: admin
Password: generated automatically
The password is generated randomly at startup and printed to the console.
The existing implementation explicitly warns that this automatic user creation is intended for development and should not be used in production.
Before deploying to production, remove or replace this initialization logic with a secure administrator provisioning process.
Keystone loads the application's content schema from:
schema.ts
The main Keystone configuration imports:
import { lists } from './schema.ts'and passes those lists into the Keystone configuration. This means your portfolio's content models and relationships can be maintained independently from the main Keystone configuration.
For example, your schema can contain models such as:
Portfolio
โโโ Projects
โโโ Skills
โโโ Technologies
โโโ Experience
โโโ Education
โโโ Categories
โโโ Users
The exact models should be documented from
schema.ts.
| Command | Description |
|---|---|
npm run dev |
Start Keystone development server |
npm run build |
Build Keystone for production |
npm run start |
Start production server |
npm run migrate |
Deploy Prisma migrations |
npm install |
Install dependencies and run Keystone post-install |
These commands are defined directly in the project's package.json.
Before deploying this CMS to production:
- Use a secure PostgreSQL connection string.
- Store secrets in environment variables.
- Never commit
.envfiles. - Remove the automatic development admin creation.
- Use strong administrator credentials.
- Configure appropriate Keystone access controls.
- Restrict administrative access.
- Use HTTPS in production.
- Review GraphQL permissions and mutations.
- Keep dependencies updated.
- Avoid logging sensitive information.
The architecture is suitable for deployment using modern cloud and serverless infrastructure.
Internet
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ Next.js App โ
โโโโโโโโโโฌโโโโโโโโโ
โ
GraphQL
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ Keystone 6 โ
โ CMS + API โ
โโโโโโโโโโฌโโโโโโโโโ
โ
Prisma
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ PostgreSQL โ
โ Serverless โ
โโโโโโโโโโโโโโโโโโโ
For production deployment:
- Configure
POSTGRES_URL. - Install dependencies.
- Deploy database migrations.
- Build Keystone.
- Start the production server.
- Configure authentication and access control.
- Remove development-only admin initialization.
Example:
npm install
npm run migrate
npm run build
npm run start โโโโโโโโโโโโโโโโโโโโโ
โ Keystone Admin โ
โ UI โ
โโโโโโโโโโโฌโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโ
โ GraphQL API โ
โโโโโโโโโโโฌโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโ
โ Prisma 7 โ
โโโโโโโโโโโฌโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโ
โ PostgreSQL โ
โโโโโโโโโโโฌโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโ
โ Next.js App โ
โโโโโโโโโโโโโโโโโโโโโ
The separation between CMS, API, database, and frontend allows portfolio content to be consumed independently from the presentation layer.
Keystone manages content independently from the frontend.
This makes it possible to reuse the same portfolio content across:
- Web applications
- Mobile applications
- Multiple frontend applications
- Static websites
- External services
- Future applications
GraphQL allows clients to request only the fields they need and provides a structured API for interacting with CMS data.
Prisma provides a type-safe database layer between Keystone and PostgreSQL.
PostgreSQL provides a robust relational database for structured portfolio content and relationships.
- Keystone headless CMS
- GraphQL API
- PostgreSQL integration
- Prisma ORM
- Authentication
- Session management
- GraphQL error logging
- Production administrator provisioning
- Image optimization/CDN
- SEO metadata management
- Draft/publishing workflow
- Content versioning
- Automated tests
- CI/CD pipeline
- API documentation
- Monitoring and observability
Contributions, suggestions, and improvements are welcome.
git checkout -b feature/my-featuregit commit -m "Add my feature"git push origin feature/my-featureThis project is licensed under the MIT License, unless another license is specified by the repository.
Portfolio CMS is a modern headless content management system designed to manage portfolio content through Keystone 6 and expose it through a GraphQL API.
The system combines:
Next.js + KeystoneJS + GraphQL + Prisma + PostgreSQL
to provide a flexible, API-first architecture that separates content management from content presentation.
Next.js 16
+
KeystoneJS 6
+
GraphQL
+
Prisma 7
+
PostgreSQL
=
Modern Headless Portfolio CMS