Getting started with Dealership

Clone the source, configure PostgreSQL, sessions, and storage, apply migrations, create the first user, run onboarding, and deploy.

Hosted app

The hosted app is at dealership.openship.org.

Requirements

  • Node.js 20 or later (engines in package.json).
  • npm.
  • A PostgreSQL database you are allowed to migrate.
  • An S3-compatible bucket for production. Development falls back to placeholder storage settings.
  • Optional: SMTP for password reset and email verification, Stripe for card checkout, and an OpenRouter key for the dashboard assistant.

Clone and install

git clone https://github.com/openshiporg/openfront-dealership.git
cd openfront-dealership
npm install

Configure .env

Copy the template and replace every placeholder:

cp .env.example .env
VariableRequiredRead by
DATABASE_URLAlwaysKeystone and Prisma. The app will not start without it.
SESSION_SECRETAlwaysSession sealing and email verification tokens. Must be at least 32 characters.
S3_BUCKET_NAMEProductionImage storage. Required when NODE_ENV=production.
S3_REGIONProductionImage storage.
S3_ACCESS_KEY_IDProductionImage storage.
S3_SECRET_ACCESS_KEYProductionImage storage.
S3_ENDPOINTProductionS3-compatible endpoint. Also used by next.config.ts to allow image hosts.
SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASSWORD, SMTP_FROMOptionalPassword reset and customer email verification. Password reset email is offered only when SMTP_HOST is set.
SMTP_STORE_LINKOptionalBase URL used in email links.
STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRETOptionalStripe adapter (checkout, refunds, webhook verification).
OPENROUTER_API_KEY, OPENROUTER_MODEL, OPENROUTER_MAX_TOKENSOptionalDashboard AI assistant at /api/completion.
PUBLIC_SIGNUPS_ALLOWEDOptionalSet to true to open the dashboard sign-up page. Off by default.
TRUSTED_PROXY_IPSOptionalProxy IPs allowed to supply X-Forwarded-For for API key IP limits.
NEXT_PUBLIC_BACKEND_URLOptionalGraphQL origin for the storefront if it differs from the current site.
HIDE_OPENFRONT_BRANDINGOptionalSet to true to hide Openfront branding in the storefront.

A minimal local file:

DATABASE_URL=postgresql://user:password@localhost:5432/openfront_dealership
SESSION_SECRET=replace-with-output-of-openssl-rand-hex-32

Generate the secret with openssl rand -hex 32. .env files are ignored by git. Never commit real keys.

.env.example also lists NEXT_PUBLIC_STRIPE_KEY. Current source does not read it.

Apply migrations

The repository has 47 checked-in Prisma migrations. Apply them with:

npm run migrate

npm run dev runs keystone build, then npm run migrate, then next dev. It migrates the database in DATABASE_URL. npm run migrate:gen creates new migrations and is for development databases.

One migration inserts a default dealer group (sams-motor-company) and rooftop (SAM-MAIN, slug main) with no members. Onboarding adopts this rooftop instead of creating a second one.

Run locally

npm run dev
PathWhat it is
/Storefront
/dashboardOperator dashboard
/dashboard/platform/overviewDealership overview desk
/api/graphqlGraphQL API

Create the first user

On an empty database, open /dashboard/init. It creates the first user with an Admin role that has every permission, including onboarding. Later staff are added from /dashboard/platform/users. Roles and memberships are managed on /dashboard/platform/organization.

Storefront shoppers register at /account. They get a user with no role and cannot reach the dashboard.

Run onboarding

Users with canManageOnboarding see a setup card in the dashboard. It opens a dialog with three templates:

TemplateWhat it adds
Complete SetupDealership profile, 8 makes, 13 models, 13 vehicles, 8 service packages, 8 parts, 5 F&I products, 5 lead routing rules, 11 accounting mappings, 2 payment providers, 8 staff roles
Basic SetupProfile, 3 makes, 4 models and their vehicles, 3 service packages, 3 parts, 2 F&I products, 2 routing rules, all accounting mappings, the Manual payment provider, 3 roles
Custom SetupYour own JSON in the same shape

Each record is saved through ensureDealershipOnboardingRecord. The Dealership step adopts the unclaimed default rooftop, fills the profile, and gives you a dealer-group membership with access to all rooftops. Vehicles go through the normal intake command, so they come out listed. Parts get an opening-stock receipt.

If a run fails part-way, your status stays in_progress and a retry reuses saved records. A store that is already set up refuses a new run.

Onboarding creates no leads, customers, deals, applications, appointments, repair orders, or payments. Replace the seeded names, addresses, and prices with your own.

On this page