Run Ticketory locally
Get your package running on your computer, with Docker.
For the Full Stack package
Before you start: install and open Docker Desktop, or Docker Engine with Compose.
View requirementsDownload your template
Open My templates and download the ZIP for your package.
Expected result: A file named like
ticketory-full-stack-….zipis in your downloads.Unzip and open the folder
Open a terminal where the ZIP is, extract it and move into the
ticketory-full-stackfolder. On Windows, you can extract it in File Explorer instead, then open a terminal in the folder.Terminalunzip -q ticketory-full-stack-*.zip cd ticketory-full-stack lsExpected result: The folder lists
Having trouble?admin-dashboard,back-end,storefrontanddocker-compose.yml, besideREADME.md,QUICKSTART.mdandLICENSE.md.Start the apps
Build and start the API, the public website and the organiser dashboard. Nothing has to be configured first. The first start builds three images and fills the database with the sample organisers and their events, which takes a few minutes; later starts take seconds.
Terminalinticketory-full-stackdocker compose up --buildA port is already in use?
If the start stops with
A port is already in useports are not available,address already in useorport is already allocated, another program uses 3030, 3031 or 8000. Either stop it, or create a file named.envin theticketory-full-stackfolder, besidedocker-compose.yml, with the port you need, such asADMIN_PORT=3041(SITE_PORTfor the website,API_PORTfor the API). Rundocker compose up --buildagain and open the app on its new port.Expected result: The three services keep running and the log stops scrolling. Leave this terminal open.
Having trouble?Open the public website
Open localhost:3030Local. English is at
/enand Arabic at/ar. Anyone can buy without an account; to see an attendee's tickets, orders and saved events, sign in withattendee@example.testand the passwordDemoOnly!2026.Expected result: The website opens on its home page with the sample events and their pictures.
Having trouble?Sign in to the organiser dashboard
Open localhost:3031Local. Sign in with
owner@example.testand the passwordDemoOnly!2026. Every seeded account uses that password; change them before the stack is reachable from the internet.Expected result: The dashboard opens on its overview, with the ticket sales, the live door and the next events.
Having trouble?
Take a tour
What the sample organisers look like once everything runs.
| Account | Where | |
|---|---|---|
| Owner: everything, including refunds, the team, roles and settings | owner@example.test | Dashboard |
| Manager: events, venues, check-in, reports, inquiries, the studio and the assistant; orders read only | manager@example.test | Dashboard |
| Finance: the overview, orders, refunds, ticket reissue and void, and reports | finance@example.test | Dashboard |
| Check-in: the door only, for the sessions assigned to it | checkin@example.test | Dashboard |
| Attendee Taylor Morgan: eight orders and four saved events | attendee@example.test | Website |
Every account signs in with the password DemoOnly!2026. These are local demo accounts only.
The seed adds four organisers, each a workspace of its own that the Owner switches between from the dashboard's top bar: Northline Events, Kiln & Co., Mill Street Talks and Meadow Days. Between them they have 9 venues, 36 events (22 on the website, 3 of them on now, 9 already over, 1 called off and 4 drafts), 1,145 orders and 14 staff accounts, so every screen opens full.
Stop and start again
Press Ctrl+C in the terminal to stop the apps, or run this from the ticketory-full-stack folder. Your data, the database, the uploads and the CSV exports, is kept in the ticketory-data volume.
ticketory-full-stackdocker compose downStart again with the same command as step 3. Without --build it reuses the images you already built.
ticketory-full-stackdocker compose upKeep your data
docker compose down -v also deletes the data volume. The next start seeds a fresh copy of the sample organisers, and everything you created is gone.
Run the public website
This package is the public website on its own. It reads everything from the Ticketory API, so start the API first. Unless you build it with another address, the website expects the API at http://localhost:8000. The API is a separate package and is not in this download.
Unzip and open the folder
Terminalunzip -q ticketory-website-*.zip cd ticketory-website lsExpected result: The folder has a
Having trouble?Dockerfileand apackage.json.Build the image
The
NEXT_PUBLIC_*values are compiled into the JavaScript the browser loads, so they are build arguments. Without any, the website uses the API athttp://localhost:8000/api, calls itselfhttp://localhost:3030and sends organisers to the dashboard athttp://localhost:3031. For an API somewhere else, pass its address.Terminalinticketory-websitedocker build -t ticketory-website .With your own API and domains:
Terminalinticketory-websitedocker build -t ticketory-website --build-arg NEXT_PUBLIC_API_BASE_URL=https://api.your-domain.com/api --build-arg NEXT_PUBLIC_SITE_URL=https://www.your-domain.com --build-arg NEXT_PUBLIC_DASHBOARD_URL=https://dashboard.your-domain.com .Having trouble?Start it
Inside the container
localhostis the container itself, soAPI_INTERNAL_URLtells the website's own server where to reach the API on your computer, for event page titles, the first render of the home, event, venue and organiser pages, and the sitemap.--add-hostmakeshost.docker.internalwork on Linux; Docker Desktop already has it. If port3030is taken, change the number on the left of-p, for example-p 3040:3030, open that port instead, addhttp://localhost:3040to the API'sCORS_ORIGINand set it as the API'sSTOREFRONT_URL.Terminalinticketory-websitedocker run -p 3030:3030 -e API_INTERNAL_URL=http://host.docker.internal:8000/api --add-host=host.docker.internal:host-gateway ticketory-websiteExpected result: localhost:3030Local opens the website with the events from your API. English is at
Having trouble?/en, Arabic at/ar.
To let the API refresh the event, venue and organiser pages the moment they change, add -e REVALIDATE_SECRET= followed by the same value as REVALIDATE_SECRET in the API's .env. Without it those pages refresh on their own within an hour.
Run the organiser dashboard
This package is the organiser dashboard on its own. Every screen reads the Ticketory API, so start the API first. Unless you build it with another address, the dashboard expects the API at http://localhost:8000. The API is a separate package and is not in this download.
Unzip and open the folder
Terminalunzip -q ticketory-dashboard-*.zip cd ticketory-dashboard lsExpected result: The folder has a
Having trouble?Dockerfileand apackage.json.Build the image
Without build arguments the dashboard uses the API at
http://localhost:8000/api. For an API somewhere else, pass its address, its address without/apifor the live notifications, the host serving its pictures, and the website's address for the "View website" link.Terminalinticketory-dashboarddocker build -t ticketory-dashboard .With your own API:
Terminalinticketory-dashboarddocker build -t ticketory-dashboard --build-arg NEXT_PUBLIC_API_BASE_URL=https://api.your-domain.com/api --build-arg NEXT_PUBLIC_WEBSOCKET_BASE_URL=https://api.your-domain.com --build-arg NEXT_PUBLIC_MEDIA_HOSTNAME=api.your-domain.com --build-arg NEXT_PUBLIC_SITE_URL=https://your-domain.com .Having trouble?Start it and sign in
If port
3031is taken, change the number on the left of-p, for example-p 3041:3031, open that port instead, addhttp://localhost:3041to the API'sCORS_ORIGINand set itsFRONTEND_URLto it (the address the live notifications connect from), then restart the API.Terminalinticketory-dashboarddocker run -p 3031:3031 ticketory-dashboardExpected result: localhost:3031Local opens the sign-in form. Sign in with
Having trouble?owner@example.testand the passwordDemoOnly!2026, which a seeded API accepts.
Run the API
This package is the NestJS API on its own, on a SQLite file kept in a Docker volume with the uploads and the CSV exports. The public website and the organiser dashboard are separate packages and are not in this download.
Unzip and open the folder
Terminalunzip -q ticketory-backend-*.zip cd ticketory-backend lsExpected result: The folder has a
Having trouble?Dockerfile, adocker-entrypoint.shand apackage.json.Start it with the sample data
A new volume gets empty tables and no accounts unless you ask for the sample organisers, so keep
-e SEED_DEMO_DATA=truefor a first start. Theticketory-api-datavolume keeps the database, the uploads and the CSV exports between runs. If port8000is taken, change the number on the left of-p, for example-p 8010:8000, and add-e PUBLIC_MEDIA_URL=http://localhost:8010/mediaand-e PUBLIC_API_URL=http://localhost:8010so the picture addresses and the ticket download links use it too. Your frontends must then point athttp://localhost:8010/api.Terminalinticketory-backenddocker run -p 8000:8000 -v ticketory-api-data:/data -e SEED_DEMO_DATA=true ticketory-apiExpected result: localhost:8000/
Having trouble?api/ healthLocal answers with "status":"ok"and"database":"up".
The container accepts the website on http://localhost:3030 and the dashboard on http://localhost:3031. On other addresses, set CORS_ORIGIN (both, comma separated), FRONTEND_URL (the dashboard) and STOREFRONT_URL (the website) with -e.
To give the container your own keys (payments, mail, AI, R2, MCP), create .env from .env.example with cp .env.example .env, fill it in, and add --env-file .env -e NODE_ENV=production to docker run:
ticketory-backenddocker run -p 8000:8000 -v ticketory-api-data:/data -e SEED_DEMO_DATA=true --env-file .env -e NODE_ENV=production ticketory-apiA value given with -e wins over the same name in the file, so the container runs in production whatever .env says, and it moves the file's relative paths (SQLITE_DATABASE, MEDIA_UPLOAD_DIR, EXPORT_DIR) into the volume. Without a JWT_SECRET of your own, or with the example one, the container generates a secret and keeps it in the volume, so sign-ins survive a restart.