Getting started
Run KDIGI CMS on your machine in a few minutes, log in, and create your first site.
Requirements
Section titled “Requirements”| Path | You need |
|---|---|
| Docker Compose (easiest) | Docker with the Compose plugin |
pnpm dev (for development) | Node.js ≥ 20.9 (22 recommended), pnpm 10 (corepack enable), Docker for PostgreSQL (or your own PostgreSQL; the compose files use 16) |
Option A — Docker Compose (one command)
Section titled “Option A — Docker Compose (one command)”git clone https://github.com/kdigivn/kdigi-cms-open.gitcd kdigi-cms-openSEED_DEMO=true docker compose up --buildOpen http://localhost:3000/admin. On a fresh database the admin shows a "Create first user" form; the first user you create becomes the super-admin. Drop SEED_DEMO=true if you want an empty install.
What the stack does (docker-compose.yml):
- starts PostgreSQL 16 (
dbservice) and builds/starts the app (appservice); - on every app start the entrypoint (
docker/entrypoint.sh) generates aPAYLOAD_SECRETon first start if you did not set one (kept in theapp_datavolume), applies database migrations (payload migrate), optionally loads the demo content (SEED_DEMO=true), then runsnext start; - keeps data in named volumes:
postgres_data(database),media_data(uploads, served by the app),app_data(generated secret).docker compose downkeeps them;docker compose down -vdeletes everything.
Useful switches (set in your shell or in a .env file next to the compose file):
| Variable | Default | Effect |
|---|---|---|
APP_PORT | 3000 | host port of the CMS |
DB_PORT | 5432 | host port of PostgreSQL (bound to 127.0.0.1 only) |
POSTGRES_PASSWORD | kdigi | database password — local use only; change it if you expose the port |
PAYLOAD_PUBLIC_SERVER_URL | http://localhost:3000 | public URL of the CMS; set it if you change APP_PORT or put the stack behind a domain |
SEED_DEMO | empty | true loads the demo site and sample content (idempotent) |
All other settings are described in configuration.
Option B — pnpm dev (hot reload)
Section titled “Option B — pnpm dev (hot reload)”git clone https://github.com/kdigivn/kdigi-cms-open.gitcd kdigi-cms-openpnpm install --frozen-lockfilecp .env.example .env # the defaults match `docker compose up db`; set PAYLOAD_SECRETdocker compose up -d db # only PostgreSQL, on localhost:5432pnpm migrate # create the database schema (explicit; push is disabled)pnpm seed:demo # optional: demo site + sample contentpnpm dev # http://localhost:3000/adminNotes:
- Replace
PAYLOAD_SECRETin.envwith a random string of at least 32 characters (openssl rand -hex 32). - The schema is never auto-synchronised: after pulling new code run
pnpm migrateagain (upgrading). - If port 3000 is busy Next.js picks 3001; development accepts the
localhostorigins 3000, 3001 and 3101, so login keeps working. - Without a running database the app cannot start; use your own PostgreSQL by editing
DATABASE_URIin.env.
First steps in the admin
Section titled “First steps in the admin”- Log in with the first user you created. Forgot the password in a local install? Reset or create a super-admin from the command line:
(with Docker:
Terminal window node --env-file=.env --import tsx src/scripts/create-admin-user.ts you@example.com 'a-long-password'docker compose exec app node --import tsx src/scripts/create-admin-user.ts you@example.com 'a-long-password'). - Create a site (Sites → Create new). A site is one website: set a unique
siteKey(your frontend uses it to ask for its content), the baredomain(for exampleexample.com) and the default language. The demo seed already creates a site withsiteKeydemo. See multi-site. - Pick the site in the admin site selector, then write content: posts, pages, categories/tags, menus, FAQs. The editor is Markdown-first (content-markdown).
- Upload media. Files go to local disk by default (media-storage); no cloud account is needed.
- Invite people (Users) and assign them a role and one or more sites (roles and permissions). Only
super-admincan create users. - Connect a frontend. Your website fetches published content over REST or GraphQL, for example:
Anonymous requests only see published content, and
Terminal window curl 'http://localhost:3000/api/posts?where[tenant][equals]=1&sort=-publishedAt&limit=5'tenantis the numeric id of your site (look it up bysiteKeyvia/api/sites?where[siteKey][equals]=demo). See REST and GraphQL API for the exact contract (site selection, locale, SEO fields, revalidation).
Coming from WordPress?
Section titled “Coming from WordPress?”Use the importer: WordPress migration.
- Configuration — every environment variable
- Deploy — put it on a server
- Architecture — how the code is organised
- Having trouble? Check the troubleshooting table or open an issue.