Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,14 @@ jobs:
- 5432
options: --health-cmd=pg_isready --health-interval=10s --health-timeout=5s --health-retries=3
elastic:
image: docker.elastic.co/elasticsearch/elasticsearch:7.1.1
image: docker.elastic.co/elasticsearch/elasticsearch:9.1.0
env:
node.name: es
cluster.name: es-docker-cluster
xpack.security.enabled: false
xpack.security.http.ssl.enabled: false
xpack.security.transport.ssl.enabled: false
xpack.license.self_generated.type: basic
discovery.type: single-node
bootstrap.memory_lock: true
ES_JAVA_OPTS: -Xms512m -Xmx512m
Expand Down
12 changes: 9 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,19 @@ services:
volumes:
- keycloak_data:/opt/keycloak/data
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.10.2
image: docker.elastic.co/elasticsearch/elasticsearch:9.1.0
container_name: elasticsearch
environment:
- node.name=es
- cluster.name=es-docker-cluster
- xpack.security.enabled=false
- xpack.security.http.ssl.enabled=false
- xpack.security.transport.ssl.enabled=false
- xpack.license.self_generated.type=basic
- discovery.type=single-node
- bootstrap.memory_lock=true
- 'ES_JAVA_OPTS=-Xms512m -Xmx512m'
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
mem_limit: 536870912
ulimits:
memlock:
soft: -1
Expand All @@ -100,7 +107,6 @@ services:
- ALLOW_EMPTY_PASSWORD=yes
ports:
- '6379:6379'

jaeger:
image: jaegertracing/all-in-one:latest
container_name: jaeger
Expand Down
196 changes: 196 additions & 0 deletions docs/docs/guides/extending-the-dashboard/deployment/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
---
title: 'Deployment'
---

The Vendure Dashboard offers flexible deployment options. You can either serve it directly through your Vendure Server using the `DashboardPlugin`, or host it independently as a static site.

## Deployment Options

### Option 1: Serve with DashboardPlugin

The `DashboardPlugin` integrates seamlessly with your Vendure Server by:

- Serving the React dashboard as static files
- Handling routing for the dashboard UI
- Providing a unified deployment experience

### Option 2: Standalone Hosting

The Vendure Dashboard can be hosted independently as a static site, since the build produces standard web assets (index.html, CSS, and JS files). This approach offers maximum flexibility for deployment on any static hosting service.

## Serving with DashboardPlugin

To configure the DashboardPlugin, follow these steps:

### 1. Configure Vite Base Path

Update your `vite.config.mts` to set the base path where the dashboard will be served:

```typescript title="vite.config.mts"
import { vendureDashboardPlugin } from '@vendure/dashboard/vite';
import path from 'path';
import { pathToFileURL } from 'url';
import { defineConfig } from 'vite';

export default defineConfig({
// highlight-start
base: '/dashboard/',
// highlight-end
plugins: [
vendureDashboardPlugin({
vendureConfigPath: pathToFileURL('./src/vendure-config.ts'),
api: {
host: 'http://localhost',
port: 3000,
},
gqlOutputPath: path.resolve(__dirname, './src/gql/'),
}),
],
});
```

### 2. Add DashboardPlugin to Vendure Config

Add the DashboardPlugin to your `vendure-config.ts`:

```typescript title="src/vendure-config.ts"
import { DashboardPlugin } from '@vendure/dashboard/plugin';
import path from 'path';

export const config: VendureConfig = {
// ... other config
plugins: [
// ... other plugins
DashboardPlugin.init({
// highlight-start
// Important: This must match the base path from vite.config.mts (without slashes)
route: 'dashboard',
// highlight-end
// Path to the Vite build output directory
appDir: path.join(__dirname, './dist'),
}),
],
};
```

## Building for Production

Before deploying your Vendure application, build the dashboard:

```bash
npx vite build
```

This command creates optimized production files in the `dist` directory that the DashboardPlugin will serve.

## Accessing the Dashboard

Once configured and built, your dashboard will be accessible at:

```
http://your-server-url/dashboard/
```

## Configuration Options

### DashboardPlugin Options

| Option | Type | Description |
| -------- | -------- | ----------------------------------------------------------------------------- |
| `route` | `string` | The URL path where the dashboard will be served (must match Vite's base path) |
| `appDir` | `string` | Path to the directory containing the built dashboard files |

## Best Practices

1. **Consistent Paths**: Always ensure the `route` in DashboardPlugin matches the `base` in your Vite config
2. **Build Before Deploy**: Add the Vite build step to your deployment pipeline
3. **Production Builds**: Use `npx vite build` for optimized production builds

## Example Deployment Script

```json title="package.json"
{
"scripts": {
"build": "npm run build:server && npm run build:dashboard",
"build:server": "tsc",
"build:dashboard": "vite build",
"start:prod": "node ./dist/index.js"
}
}
```

## Standalone Hosting

The dashboard can be hosted independently from your Vendure Server on any static hosting service (Netlify, Vercel, AWS S3, etc.).

### Configuration

When hosting standalone, you must configure the dashboard to connect to your Admin API endpoint:

```typescript title="vite.config.mts"
import { vendureDashboardPlugin } from '@vendure/dashboard/vite';
import { defineConfig } from 'vite';

export default defineConfig({
plugins: [
vendureDashboardPlugin({
vendureConfigPath: pathToFileURL('./src/vendure-config.ts'),
// highlight-start
api: {
host: process.env.VENDURE_API_HOST || 'https://api.mystore.com',
port: parseInt(process.env.VENDURE_API_PORT || '443'),
},
// highlight-end
gqlOutputPath: path.resolve(__dirname, './src/gql/'),
}),
],
});
```

:::warning Build-Time Variables
Environment variables are resolved at **build time** and embedded as static strings in the final bundles. Ensure these variables are available during the build process, not just at runtime.
:::

### Build and Deploy

1. **Build the dashboard:**
```bash
npx vite build
```

2. **Deploy the contents of the `dist` directory to your hosting service**

### CORS Configuration

When hosting the dashboard separately, configure CORS on your Vendure Server:

```typescript title="src/vendure-config.ts"
export const config: VendureConfig = {
apiOptions: {
cors: {
origin: ['https://dashboard.mystore.com'],
credentials: true,
},
},
// ... other config
};
```

## Troubleshooting

### Dashboard Not Loading (DashboardPlugin)

- Verify the `route` matches the `base` path in Vite config
- Check that the build output exists in the specified `appDir`
- Ensure the DashboardPlugin is properly initialized in your plugins array

### 404 Errors on Dashboard Routes

- Confirm the base path includes trailing slashes where needed
- Verify the server is running and the plugin is loaded

### Connection Issues (Standalone)

- Verify the API host and port are correct
- Check CORS configuration on your Vendure Server
- Ensure environment variables were available during build
2 changes: 2 additions & 0 deletions docs/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ const sidebars = {
items: [
'guides/extending-the-dashboard/getting-started/index',
'guides/extending-the-dashboard/extending-overview/index',

'guides/extending-the-dashboard/navigation/index',
'guides/extending-the-dashboard/page-blocks/index',
'guides/extending-the-dashboard/action-bar-items/index',
Expand All @@ -156,6 +157,7 @@ const sidebars = {
'guides/extending-the-dashboard/custom-form-components/relation-selectors',
],
},
'guides/extending-the-dashboard/deployment/index',
'guides/extending-the-dashboard/tech-stack/index',
],
},
Expand Down
8 changes: 8 additions & 0 deletions license/signatures/version1/cla.json
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,14 @@
"created_at": "2025-08-03T12:30:08Z",
"repoId": 136938012,
"pullRequestNo": 3729
},
{
"name": "asonnleitner",
"id": 56999154,
"comment_id": 3151022314,
"created_at": "2025-08-04T14:36:00Z",
"repoId": 136938012,
"pullRequestNo": 3703
}
]
}
22 changes: 17 additions & 5 deletions packages/create/templates/docker-compose.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,27 @@ services:
# Checkout our Elasticsearch plugin: https://docs.vendure.io/reference/core-plugins/elasticsearch-plugin/
# To run the elasticsearch container run "docker compose up -d elasticsearch"
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.1.1
image: docker.elastic.co/elasticsearch/elasticsearch:9.1.0
container_name: elasticsearch
environment:
discovery.type: single-node
bootstrap.memory_lock: true
ES_JAVA_OPTS: -Xms512m -Xmx512m
- node.name=es
- cluster.name=es-docker-cluster
- xpack.security.enabled=false
- xpack.security.http.ssl.enabled=false
- xpack.security.transport.ssl.enabled=false
- xpack.license.self_generated.type=basic
- discovery.type=single-node
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
mem_limit: 536870912
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- elasticsearch_data:/usr/share/elasticsearch/data
ports:
- "9300:9200"
- 9200:9200
labels:
- "io.vendure.create.name={{{ escapeSingle name }}}"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ function MoneyInputInternal({ value, currency, onChange }: DataInputComponentPro
return (
<AffixedInput
type="text"
className="bg-background"
value={displayValue}
onChange={e => {
const inputValue = e.target.value;
Expand Down
Loading
Loading