Configuring Saleor Dashboard
Saleor Dashboard is a separate React application (TypeScript, Apollo Client, Material UI) that deploys independently from the API. It communicates with Saleor Core exclusively via GraphQL. Configuration includes building for a specific environment, configuring CORS/CSP on the API side, and optional UI customization.
Requirements and Repository
Dashboard lives in a separate repository: github.com/saleor/saleor-dashboard. The Dashboard version should match the Core version — major and minor versions must be identical.
git clone https://github.com/saleor/saleor-dashboard.git
cd saleor-dashboard
git checkout 3.20 # version = your Saleor Core version
npm install
Environment Variables
# .env
API_URI=https://api.your-store.com/graphql/
APP_MOUNT_URI=/dashboard/
STATIC_URL=/dashboard/static/
SENTRY_DSN=https://[email protected]/0
SENTR_ENABLED=true
IS_CLOUD_INSTANCE=false
API_URI is the only required variable. The rest are optional, but STATIC_URL is critical if Dashboard is not at the domain root.
Build and Deploy
npm run build
# dist/ contains static files
The artifact is a clean SPA with no SSR. It deploys on any static host: S3 + CloudFront, Nginx, Vercel. When deploying to a subpath, configure React Router's basename — this is done via APP_MOUNT_URI.
Nginx config for subpath:
location /dashboard/ {
alias /var/www/dashboard/dist/;
try_files $uri $uri/ /dashboard/index.html;
location ~* \.(js|css|png|jpg|ico|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
Configuring CORS on the API Side
Dashboard and API can be on different domains. Saleor Core (settings.py):
CORS_ALLOWED_ORIGINS = [
"https://dashboard.your-store.com",
"https://your-store.com",
]
# For staging:
CORS_ALLOW_ALL_ORIGINS = False
CORS_ALLOW_CREDENTIALS = True
Without proper CORS, the browser will block GraphQL requests — this is the first issue on a fresh setup.
Configuring CSP
If Content-Security-Policy is enabled on the server, allow:
Content-Security-Policy:
default-src 'self';
script-src 'self' 'unsafe-inline';
connect-src 'self' https://api.your-store.com wss://api.your-store.com;
img-src 'self' data: https://cdn.your-store.com;
font-src 'self' https://fonts.gstatic.com;
wss:// is needed for GraphQL subscriptions (live updates in Dashboard).
Initial Setup After Deployment
- Open
/dashboard/ - On first run, a superuser creation wizard will appear (if database is empty)
- Configure sales channels: Channels → Create Channel
- Connect payment methods: Plugins → Payment
- Set up warehouses: Warehouses → Create
- Add shipping zones and shipping methods
UI Branding
Dashboard is not designed for deep customization, but basic branding is possible:
// src/config.ts — can override:
export const APP_NAME = "My Store Admin";
export const LOGO_URL = "/static/logo.svg";
Replacing the logo and color scheme (Material UI theme) requires editing source code and rebuilding. This is acceptable if Dashboard is forked.
Saleor Apps Integration
Since version 3.x, Dashboard supports installing Apps via App Store or manifest URL:
Settings → Apps → Install external app:
https://my-app.vercel.app/api/manifest
The app should return a valid JSON manifest with id, name, permissions, and appUrl. Dashboard embeds the App via iframe with token authentication.
Typical Setup Issues
| Symptom | Cause | Solution |
|---|---|---|
| Blank screen after deploy | Incorrect APP_MOUNT_URI |
Check router basename |
| 401 on all GraphQL requests | Superuser not created | python manage.py createsuperuser |
| CORS error in console | CORS_ALLOWED_ORIGINS doesn't include Dashboard domain |
Add origin in settings.py |
| Subscriptions not working | WSS blocked by proxy | Configure Nginx for websocket upgrade |
Updating Dashboard
Dashboard updates independently from Core, but versions must match. Procedure:
git fetch origin
git checkout 3.21
npm install
npm run build
# deploy new dist/
No database migrations, no API restart — just front-end rebuild.







