@vendure-platform/create 0.1.0 → 0.2.1-nightly.202605190703

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/README.md +37 -27
  2. package/dist/assets/storefront/.env.example +14 -14
  3. package/dist/assets/storefront/messages/de.json +2 -3
  4. package/dist/assets/storefront/messages/en.json +2 -3
  5. package/dist/assets/storefront/next.config.ts +22 -21
  6. package/dist/assets/storefront/package.json +75 -75
  7. package/dist/assets/storefront/public/scenarios/customer/logo.svg +4 -0
  8. package/dist/assets/storefront/src/app/[locale]/layout.tsx +0 -4
  9. package/dist/assets/storefront/src/app/[locale]/sign-in/login-form.tsx +70 -102
  10. package/dist/assets/storefront/src/app/[locale]/sign-in/page.tsx +2 -3
  11. package/dist/assets/storefront/src/config/scenario-meta.ts +3 -7
  12. package/dist/assets/storefront/src/config/scenario.ts +14 -30
  13. package/dist/assets/storefront/src/graphql-env.d.ts +456 -0
  14. package/dist/assets/storefront/src/scenarios/customer/branding.ts +142 -0
  15. package/dist/assets/storefront/src/scenarios/customer/hero.tsx +76 -0
  16. package/dist/assets/storefront/src/scenarios/{default → customer}/index.ts +3 -3
  17. package/dist/assets/storefront/src/scenarios/{default → customer}/meta.ts +1 -1
  18. package/dist/assets/storefront/src/schema.graphql +5852 -0
  19. package/dist/assets/storefront/tsconfig.json +17 -8
  20. package/dist/assets/templates/README.md.hbs +1 -1
  21. package/dist/assets/templates/docker-compose.yml.hbs +0 -4
  22. package/dist/assets/templates/env.hbs +13 -7
  23. package/dist/assets/templates/environment.d.ts.hbs +1 -5
  24. package/dist/assets/templates/npmrc.hbs +1 -1
  25. package/dist/assets/templates/populate.ts.hbs +17 -0
  26. package/dist/assets/templates/server-package.json.hbs +3 -2
  27. package/dist/bin/run.js +17 -3
  28. package/dist/bin/run.js.map +1 -1
  29. package/dist/cli.d.ts +6 -1
  30. package/dist/cli.js +147 -25
  31. package/dist/cli.js.map +1 -1
  32. package/dist/index.d.ts +5 -3
  33. package/dist/index.js +9 -3
  34. package/dist/index.js.map +1 -1
  35. package/dist/plugin-registry.d.ts +43 -6
  36. package/dist/plugin-registry.js +139 -421
  37. package/dist/plugin-registry.js.map +1 -1
  38. package/dist/registry.d.ts +18 -0
  39. package/dist/registry.js +29 -0
  40. package/dist/registry.js.map +1 -0
  41. package/dist/scaffold-shared.d.ts +19 -0
  42. package/dist/scaffold-shared.js +114 -0
  43. package/dist/scaffold-shared.js.map +1 -0
  44. package/dist/scaffold-storefront-only.d.ts +6 -0
  45. package/dist/scaffold-storefront-only.js +101 -0
  46. package/dist/scaffold-storefront-only.js.map +1 -0
  47. package/dist/scaffolder.js +22 -42
  48. package/dist/scaffolder.js.map +1 -1
  49. package/dist/storefront-copier.d.ts +26 -3
  50. package/dist/storefront-copier.js +63 -12
  51. package/dist/storefront-copier.js.map +1 -1
  52. package/dist/template-renderer.d.ts +24 -7
  53. package/dist/template-renderer.js +32 -64
  54. package/dist/template-renderer.js.map +1 -1
  55. package/dist/types.d.ts +46 -27
  56. package/package.json +3 -1
  57. package/dist/assets/storefront/.env.local +0 -1
  58. package/dist/assets/storefront/public/scenarios/b2b-wholesale/hero/hero-bg.webp +0 -0
  59. package/dist/assets/storefront/public/scenarios/b2b-wholesale/logo.svg +0 -4
  60. package/dist/assets/storefront/public/scenarios/default/logo.svg +0 -4
  61. package/dist/assets/storefront/public/scenarios/kaminpro/hero/hero-bg.webp +0 -0
  62. package/dist/assets/storefront/public/scenarios/kaminpro/logo.svg +0 -7
  63. package/dist/assets/storefront/src/components/shared/scenario-paused.tsx +0 -80
  64. package/dist/assets/storefront/src/scenarios/b2b-wholesale/branding.ts +0 -180
  65. package/dist/assets/storefront/src/scenarios/b2b-wholesale/hero.tsx +0 -122
  66. package/dist/assets/storefront/src/scenarios/b2b-wholesale/index.ts +0 -21
  67. package/dist/assets/storefront/src/scenarios/b2b-wholesale/meta.ts +0 -3
  68. package/dist/assets/storefront/src/scenarios/default/branding.ts +0 -148
  69. package/dist/assets/storefront/src/scenarios/default/hero.tsx +0 -107
  70. package/dist/assets/storefront/src/scenarios/kaminpro/auth-gate.tsx +0 -36
  71. package/dist/assets/storefront/src/scenarios/kaminpro/branding.ts +0 -238
  72. package/dist/assets/storefront/src/scenarios/kaminpro/cart-items.tsx +0 -359
  73. package/dist/assets/storefront/src/scenarios/kaminpro/hero.tsx +0 -123
  74. package/dist/assets/storefront/src/scenarios/kaminpro/index.ts +0 -50
  75. package/dist/assets/storefront/src/scenarios/kaminpro/meta.ts +0 -9
  76. package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/banners.tsx +0 -21
  77. package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/bom-basket.tsx +0 -221
  78. package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/btn.tsx +0 -38
  79. package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/chip.tsx +0 -35
  80. package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/config-header.tsx +0 -72
  81. package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/field-row.tsx +0 -126
  82. package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/info-dot.tsx +0 -38
  83. package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/login-notice.tsx +0 -81
  84. package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/module-panel.tsx +0 -144
  85. package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/quote-dialog.tsx +0 -110
  86. package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/schematic.tsx +0 -674
  87. package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/why-panel.tsx +0 -66
  88. package/dist/assets/storefront/src/scenarios/kaminpro/pdp/configurator-pdp.tsx +0 -43
  89. package/dist/assets/storefront/src/scenarios/kaminpro/pdp/configurator-shell.tsx +0 -320
  90. package/dist/assets/storefront/src/scenarios/kaminpro/pdp/lib/data.ts +0 -150
  91. package/dist/assets/storefront/src/scenarios/kaminpro/pdp/lib/types.ts +0 -30
  92. package/dist/assets/storefront/src/scenarios/kaminpro/pdp/styles.css +0 -104
  93. package/dist/assets/storefront/src/scenarios/kaminpro/shop-by-system.tsx +0 -97
  94. package/dist/assets/storefront/src/scenarios/kaminpro/system-finder/decision-tree.ts +0 -261
  95. package/dist/assets/storefront/src/scenarios/kaminpro/system-finder/page.tsx +0 -21
  96. package/dist/assets/storefront/src/scenarios/kaminpro/system-finder/wizard.tsx +0 -600
  97. package/dist/assets/storefront/src/schema.graphql.placeholder +0 -5
package/README.md CHANGED
@@ -8,12 +8,12 @@ Scaffold a Vendure Platform project with selected plugins, Docker infrastructure
8
8
  npx @vendure-platform/create my-project
9
9
  ```
10
10
 
11
- This starts an interactive setup. For non-interactive usage, provide all required flags:
11
+ This starts an interactive setup. For non-interactive usage, provide both `--plugins` and `--company`:
12
12
 
13
13
  ```bash
14
14
  npx @vendure-platform/create my-project \
15
15
  --company "Acme Corp" \
16
- --plugins org-hierarchy,approval-workflows,price-rules \
16
+ --plugins approval-workflows,price-rules \
17
17
  --no-storefront
18
18
  ```
19
19
 
@@ -21,42 +21,52 @@ npx @vendure-platform/create my-project \
21
21
 
22
22
  | Flag | Description | Default |
23
23
  |------|-------------|---------|
24
- | `--plugins <list>` | Comma-separated plugin keys | (interactive prompt) |
24
+ | `--plugins <list>` | Comma-separated optional plugin keys | (interactive prompt) |
25
25
  | `--company <name>` | Company name for branding | (derived from project name) |
26
26
  | `--no-storefront` | Skip the Next.js storefront | included |
27
27
  | `--github` | Create a private GitHub repo via `gh` CLI | no |
28
- | `--github-org <org>` | GitHub organization for the repo | `vendurehq` |
28
+ | `--github-org <org>` | GitHub organization for the repo (only used with `--github`) | `vendurehq` |
29
29
  | `--no-install` | Skip `npm install` after scaffolding | runs install |
30
30
  | `--no-git` | Skip `git init` | inits git |
31
31
  | `--dry-run` | Print what would be created without writing files | off |
32
32
 
33
33
  When `--plugins` and `--company` are both provided, the CLI runs in non-interactive mode.
34
34
 
35
- ## Plugin Keys
36
-
37
- | Key | Plugin | Category |
38
- |-----|--------|----------|
39
- | `advanced-search` | Advanced Search | search |
40
- | `global-search` | Global Search | search |
41
- | `org-hierarchy` | Org Hierarchy | b2b |
42
- | `approval-workflows` | Approval Workflows | b2b |
43
- | `entity-access-control` | Entity Access Control | b2b |
44
- | `quote-management` | Quote Management | b2b |
45
- | `tax-id-management` | Tax ID Management | b2b |
46
- | `price-rules` | Price Rules | commerce |
47
- | `packaging-units` | Packaging Units | commerce |
48
- | `shopping-list` | Shopping List | commerce |
49
- | `store-credit` | Store Credit / Gift Cards | commerce |
50
- | `workflow-engine` | Workflow Engine | platform |
51
- | `audit-trail` | Audit Trail | platform |
52
- | `content-versioning` | Content Versioning | platform |
53
- | `sso` | SSO | platform |
54
-
55
- The B2B suite (`org-hierarchy`, `approval-workflows`, `workflow-engine`, `entity-access-control`, `quote-management`) is pre-selected in interactive mode.
35
+ ## Plugin Tiers
36
+
37
+ Plugins fall into three tiers (mirroring `@vendure-platform/plugin-meta`):
38
+
39
+ - **Core** — always active, can't be disabled. Hidden from the interactive prompt.
40
+ - **Optional** — active by default. Pre-ticked in the prompt; deselect to emit `<key>: false` in the generated `vendure-config.ts`.
41
+ - **Requires config** — inactive by default. Pick from the prompt to enable; the generated config carries the env-var-driven options block.
42
+
43
+ | Key | Plugin | Category | Tier |
44
+ |-----|--------|----------|------|
45
+ | `license-guard` | License Guard | platform | core-requires-config |
46
+ | `org-hierarchy` | Org Hierarchy | b2b | core |
47
+ | `advanced-search` | Advanced Search | search | core |
48
+ | `workflow-engine` | Workflow Engine | platform | core |
49
+ | `approval-workflows` | Approval Workflows | b2b | optional |
50
+ | `global-search` | Global Search | search | optional |
51
+ | `entity-access-control` | Entity Access Control | b2b | optional |
52
+ | `tax-id-management` | Tax ID Management | b2b | optional |
53
+ | `shopping-list` | Shopping List | commerce | optional |
54
+ | `quick-order` | Quick Order | commerce | optional |
55
+ | `reorder-from-history` | Reorder from History | commerce | optional |
56
+ | `store-credit` | Store Credit / Gift Cards | commerce | optional |
57
+ | `quote-management` | Quote Management | b2b | optional |
58
+ | `price-rules` | Price Rules | commerce | optional |
59
+ | `packaging-units` | Packaging Units | commerce | optional |
60
+ | `content-versioning` | Content Versioning | platform | optional |
61
+ | `configurator` | Configurator | commerce | optional |
62
+ | `sso` | SSO | platform | requires-config |
63
+ | `audit-trail` | Audit Trail | platform | requires-config |
64
+
65
+ The canonical list lives in `libs/plugin-meta/src/index.ts`; this table mirrors it.
56
66
 
57
67
  ## Dependencies
58
68
 
59
- Plugin dependencies are resolved automatically. Selecting `approval-workflows` pulls in `org-hierarchy`, `workflow-engine`, and the integration plugin. Selecting `global-search` pulls in `advanced-search`.
69
+ Inter-plugin dependencies are resolved by `VendurePlatform.init()` at runtime — not by the scaffolder. Selecting `approval-workflows` will activate `org-hierarchy` and `workflow-engine` automatically (they're core anyway). Selecting `global-search` will activate `advanced-search` (also core). Integration sub-plugins between active pairs are wired automatically.
60
70
 
61
71
  ## After Scaffolding
62
72
 
@@ -67,4 +77,4 @@ npm run populate
67
77
  npm run dev
68
78
  ```
69
79
 
70
- See the [Quick Start](https://docs.vendure.io/vendure-ee/getting-started/quick-start) guide for the full walkthrough.
80
+ See the [Quick Start](https://docs.vendure.io/vendure-platform/getting-started/quick-start) guide for the full walkthrough.
@@ -1,14 +1,14 @@
1
- # Storefront environment variables are loaded from the monorepo root .env.local
2
- # See ../../.env.example for all available options
3
- #
4
- # The following variables are derived automatically from VENDURE_PORT and STOREFRONT_PORT:
5
- # - VENDURE_SHOP_API_URL (defaults to http://localhost:${VENDURE_PORT}/shop-api)
6
- # - NEXT_PUBLIC_SITE_URL (defaults to http://localhost:${STOREFRONT_PORT})
7
- #
8
- # Note: We use VENDURE_PORT instead of PORT because Next.js overwrites PORT with its own port.
9
- #
10
- # You can override them in the root .env.local if needed.
11
- #
12
- # Scenario branding (controls logo, colors, hero copy, metadata):
13
- # - NEXT_PUBLIC_SCENARIO (defaults to 'default', maps to apps/storefront/src/scenarios/<name>/)
14
- # - Baked at build time — switching requires rebuild
1
+ # Vendure Shop API URL.
2
+ # VENDURE_SHOP_API_URL=https://shop.example.com/shop-api
3
+
4
+ # Public site URL (used for canonical URLs and metadata).
5
+ # NEXT_PUBLIC_SITE_URL=https://www.example.com
6
+
7
+ # Active scenario from src/scenarios/. Defaults to "customer".
8
+ # NEXT_PUBLIC_SCENARIO=customer
9
+
10
+ # Multi-channel: route the storefront to a specific Vendure channel.
11
+ # VENDURE_CHANNEL_TOKEN=your-channel-token
12
+
13
+ # Required: random secret used to authenticate revalidation webhooks.
14
+ # REVALIDATION_SECRET=generate-a-long-random-string
@@ -408,8 +408,7 @@
408
408
  "newPassword": "Neues Passwort",
409
409
  "confirmPassword": "Passwort bestätigen",
410
410
  "resetPassword": "Passwort zurücksetzen",
411
- "resettingPassword": "Wird zurückgesetzt...",
412
- "demoAccounts": "Demo-Konten"
411
+ "resettingPassword": "Wird zurückgesetzt..."
413
412
  },
414
413
  "Search": {
415
414
  "title": "Suche",
@@ -1193,4 +1192,4 @@
1193
1192
  "max": "Max. {value}",
1194
1193
  "range": "{min} – {max}"
1195
1194
  }
1196
- }
1195
+ }
@@ -408,8 +408,7 @@
408
408
  "newPassword": "New Password",
409
409
  "confirmPassword": "Confirm Password",
410
410
  "resetPassword": "Reset password",
411
- "resettingPassword": "Resetting password...",
412
- "demoAccounts": "Demo Accounts"
411
+ "resettingPassword": "Resetting password..."
413
412
  },
414
413
  "Search": {
415
414
  "title": "Search",
@@ -1193,4 +1192,4 @@
1193
1192
  "max": "Max {value}",
1194
1193
  "range": "{min} – {max}"
1195
1194
  }
1196
- }
1195
+ }
@@ -1,15 +1,20 @@
1
1
  import {NextConfig} from 'next';
2
- import {config} from 'dotenv';
3
- import * as path from 'path';
4
2
  import createNextIntlPlugin from 'next-intl/plugin';
5
3
 
6
- // Load env vars from monorepo root
7
- config({ path: path.resolve(__dirname, '../.env') });
8
-
9
4
  // Derive URLs from port variables if not explicitly set
10
5
  const vendurePort = process.env.VENDURE_PORT ?? '3500';
11
6
  const storefrontPort = process.env.STOREFRONT_PORT ?? '3001';
12
7
 
8
+ const activeScenario = process.env.NEXT_PUBLIC_SCENARIO ?? 'default';
9
+
10
+ // Build-time CSS swap: `@/styles/globals` resolves to the active scenario's
11
+ // globals.css. Today only the `vendure-branded` scenario has its own (which
12
+ // imports `@vendure-io/design-tokens`); every other scenario falls back to
13
+ // the shared storefront globals.css.
14
+ const scenarioGlobalsCss = activeScenario === 'vendure-branded'
15
+ ? path.resolve(__dirname, 'src/scenarios/vendure-branded/globals.css')
16
+ : path.resolve(__dirname, 'src/app/[locale]/globals.css');
17
+
13
18
  const withNextIntl = createNextIntlPlugin('./src/i18n/request.ts');
14
19
 
15
20
  const nextConfig: NextConfig = {
@@ -44,28 +49,24 @@ const nextConfig: NextConfig = {
44
49
  VENDURE_SHOP_API_URL: process.env.VENDURE_SHOP_API_URL ?? `http://localhost:${vendurePort}/shop-api`,
45
50
  NEXT_PUBLIC_SITE_URL: process.env.NEXT_PUBLIC_SITE_URL ?? `http://localhost:${storefrontPort}`,
46
51
  ...(process.env.VENDURE_CHANNEL_TOKEN ? { VENDURE_CHANNEL_TOKEN: process.env.VENDURE_CHANNEL_TOKEN } : {}),
47
- REVALIDATION_SECRET: process.env.REVALIDATION_SECRET ?? 'dev-secret-change-in-production',
52
+ REVALIDATION_SECRET: process.env.REVALIDATION_SECRET,
48
53
  NEXT_PUBLIC_SCENARIO: process.env.NEXT_PUBLIC_SCENARIO ?? 'default',
49
54
  },
55
+ webpack: (config) => {
56
+ config.resolve = config.resolve ?? {};
57
+ config.resolve.alias = {
58
+ ...(config.resolve.alias ?? {}),
59
+ '@/styles/globals.css': scenarioGlobalsCss,
60
+ };
61
+ return config;
62
+ },
50
63
  images: {
51
64
  // This is necessary to display images from your local Vendure instance
52
65
  dangerouslyAllowLocalIP: true,
53
66
  remotePatterns: [
54
- {
55
- hostname: 'readonlydemo.vendure.io',
56
- },
57
- {
58
- hostname: '**.platform.vendure.io'
59
- },
60
- {
61
- hostname: 'demo.enterprise.vendure.io'
62
- },
63
- {
64
- hostname: 'localhost'
65
- },
66
- {
67
- hostname: '**.code.run'
68
- }
67
+ { hostname: 'localhost' },
68
+ // Add hostnames here for any remote Vendure server you fetch images from, e.g.:
69
+ // { hostname: 'shop.example.com' },
69
70
  ],
70
71
  },
71
72
  };
@@ -1,77 +1,77 @@
1
1
  {
2
- "name": "storefront",
3
- "version": "0.0.0",
4
- "private": true,
5
- "scripts": {
6
- "dev": "next dev --port ${STOREFRONT_PORT:-3001}",
7
- "build": "next build",
8
- "start": "next start",
9
- "lint": "eslint .",
10
- "check-types": "tsc --noEmit"
11
- },
12
- "dependencies": {
13
- "@hookform/resolvers": "^5.2.2",
14
- "@radix-ui/react-accordion": "^1.2.12",
15
- "@radix-ui/react-alert-dialog": "^1.1.15",
16
- "@radix-ui/react-aspect-ratio": "^1.1.8",
17
- "@radix-ui/react-avatar": "^1.1.11",
18
- "@radix-ui/react-checkbox": "^1.3.3",
19
- "@radix-ui/react-collapsible": "^1.1.12",
20
- "@radix-ui/react-context-menu": "^2.2.16",
21
- "@radix-ui/react-dialog": "^1.1.15",
22
- "@radix-ui/react-dropdown-menu": "^2.1.16",
23
- "@radix-ui/react-hover-card": "^1.1.15",
24
- "@radix-ui/react-label": "^2.1.8",
25
- "@radix-ui/react-menubar": "^1.1.16",
26
- "@radix-ui/react-navigation-menu": "^1.2.14",
27
- "@radix-ui/react-popover": "^1.1.15",
28
- "@radix-ui/react-progress": "^1.1.8",
29
- "@radix-ui/react-radio-group": "^1.3.8",
30
- "@radix-ui/react-scroll-area": "^1.2.10",
31
- "@radix-ui/react-select": "^2.2.6",
32
- "@radix-ui/react-separator": "^1.1.8",
33
- "@radix-ui/react-slider": "^1.3.6",
34
- "@radix-ui/react-slot": "^1.2.4",
35
- "@radix-ui/react-switch": "^1.2.6",
36
- "@radix-ui/react-tabs": "^1.1.13",
37
- "@radix-ui/react-toggle": "^1.1.10",
38
- "@radix-ui/react-toggle-group": "^1.1.11",
39
- "@radix-ui/react-tooltip": "^1.2.8",
40
- "@vendure-platform/storefront-client": "nightly",
41
- "class-variance-authority": "^0.7.1",
42
- "clsx": "^2.1.1",
43
- "cmdk": "^1.1.1",
44
- "date-fns": "^4.1.0",
45
- "dotenv": "^17.2.3",
46
- "embla-carousel-react": "^8.6.0",
47
- "gql.tada": "^1.9.0",
48
- "input-otp": "^1.4.2",
49
- "lucide-react": "^0.544.0",
50
- "next": "^16.0.10",
51
- "next-intl": "^4.8.3",
52
- "next-themes": "^0.4.6",
53
- "react": " ^19.2.0",
54
- "react-day-picker": "^9.11.3",
55
- "react-dom": "^19.2.0",
56
- "react-hook-form": "^7.68.0",
57
- "react-resizable-panels": "^3.0.6",
58
- "recharts": "^2.15.4",
59
- "sonner": "^2.0.7",
60
- "tailwind-merge": "^3.4.0",
61
- "vaul": "^1.1.2",
62
- "zod": "^4.1.13"
63
- },
64
- "devDependencies": {
65
- "@eslint/eslintrc": "^3.3.3",
66
- "@tailwindcss/postcss": "^4.1.17",
67
- "@types/node": "^20.19.25",
68
- "@types/react": "^19.2.7",
69
- "@types/react-dom": "^19.2.3",
70
- "baseline-browser-mapping": "^2.9.14",
71
- "eslint": "^9.39.1",
72
- "eslint-config-next": "16.0.0",
73
- "tailwindcss": "^4.1.17",
74
- "tw-animate-css": "^1.4.0",
75
- "typescript": "^5.9.3"
76
- }
2
+ "name": "storefront",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "dev": "next dev --webpack --port ${STOREFRONT_PORT:-3001}",
7
+ "build": "next build --webpack",
8
+ "start": "next start",
9
+ "lint": "eslint .",
10
+ "check-types": "tsc --noEmit"
11
+ },
12
+ "dependencies": {
13
+ "@hookform/resolvers": "^5.2.2",
14
+ "@radix-ui/react-accordion": "^1.2.12",
15
+ "@radix-ui/react-alert-dialog": "^1.1.15",
16
+ "@radix-ui/react-aspect-ratio": "^1.1.8",
17
+ "@radix-ui/react-avatar": "^1.1.11",
18
+ "@radix-ui/react-checkbox": "^1.3.3",
19
+ "@radix-ui/react-collapsible": "^1.1.12",
20
+ "@radix-ui/react-context-menu": "^2.2.16",
21
+ "@radix-ui/react-dialog": "^1.1.15",
22
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
23
+ "@radix-ui/react-hover-card": "^1.1.15",
24
+ "@radix-ui/react-label": "^2.1.8",
25
+ "@radix-ui/react-menubar": "^1.1.16",
26
+ "@radix-ui/react-navigation-menu": "^1.2.14",
27
+ "@radix-ui/react-popover": "^1.1.15",
28
+ "@radix-ui/react-progress": "^1.1.8",
29
+ "@radix-ui/react-radio-group": "^1.3.8",
30
+ "@radix-ui/react-scroll-area": "^1.2.10",
31
+ "@radix-ui/react-select": "^2.2.6",
32
+ "@radix-ui/react-separator": "^1.1.8",
33
+ "@radix-ui/react-slider": "^1.3.6",
34
+ "@radix-ui/react-slot": "^1.2.4",
35
+ "@radix-ui/react-switch": "^1.2.6",
36
+ "@radix-ui/react-tabs": "^1.1.13",
37
+ "@radix-ui/react-toggle": "^1.1.10",
38
+ "@radix-ui/react-toggle-group": "^1.1.11",
39
+ "@radix-ui/react-tooltip": "^1.2.8",
40
+ "@vendure-io/design-tokens": "^1.1.2",
41
+ "@vendure-platform/storefront-client": "^0.2.0",
42
+ "class-variance-authority": "^0.7.1",
43
+ "clsx": "^2.1.1",
44
+ "cmdk": "^1.1.1",
45
+ "date-fns": "^4.1.0",
46
+ "embla-carousel-react": "^8.6.0",
47
+ "gql.tada": "^1.9.0",
48
+ "input-otp": "^1.4.2",
49
+ "lucide-react": "^0.544.0",
50
+ "next": "^16.0.10",
51
+ "next-intl": "^4.8.3",
52
+ "next-themes": "^0.4.6",
53
+ "react": " ^19.2.0",
54
+ "react-day-picker": "^9.11.3",
55
+ "react-dom": "^19.2.0",
56
+ "react-hook-form": "^7.68.0",
57
+ "react-resizable-panels": "^3.0.6",
58
+ "recharts": "^2.15.4",
59
+ "sonner": "^2.0.7",
60
+ "tailwind-merge": "^3.4.0",
61
+ "vaul": "^1.1.2",
62
+ "zod": "^4.1.13"
63
+ },
64
+ "devDependencies": {
65
+ "@eslint/eslintrc": "^3.3.3",
66
+ "@tailwindcss/postcss": "^4.1.17",
67
+ "@types/node": "^20.19.25",
68
+ "@types/react": "^19.2.7",
69
+ "@types/react-dom": "^19.2.3",
70
+ "baseline-browser-mapping": "^2.9.14",
71
+ "eslint": "^9.39.1",
72
+ "eslint-config-next": "16.0.0",
73
+ "tailwindcss": "^4.1.17",
74
+ "tw-animate-css": "^1.4.0",
75
+ "typescript": "^5.9.3"
76
+ }
77
77
  }
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 32 32">
2
+ <rect width="32" height="32" rx="7" fill="#0ea5e9"/>
3
+ <path d="M11 10 L17 16 L11 22 M17 10 L21 16 L17 22" stroke="#ffffff" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
4
+ </svg>
@@ -14,7 +14,6 @@ import {CartCountProvider} from "@/lib/cart-count-context";
14
14
  import {CartCountServer} from "@/components/providers/cart-count-server";
15
15
  import {CompanyContextGuard} from "@/components/providers/company-context-guard";
16
16
  import {CompanyPermissionsServer} from "@/components/providers/company-permissions-server";
17
- import {BackendHealthGate} from "@/components/shared/scenario-paused";
18
17
  import {getBranding, getBrandingStyleTag} from "@/config/branding";
19
18
  // next/root-params provides cache-safe locale resolution. The SWC transform
20
19
  // only runs in route files (layout/page), so this import cannot be moved to
@@ -191,9 +190,6 @@ export default async function LocaleLayout({children, params}: {children: React.
191
190
  </CompanyPermissionsServer>
192
191
  </Suspense>
193
192
  </CartCountProvider>
194
- <Suspense fallback={null}>
195
- <BackendHealthGate locale={locale} />
196
- </Suspense>
197
193
  </ThemeProvider>
198
194
  </NextIntlClientProvider>
199
195
  </body>
@@ -29,19 +29,11 @@ function useLoginSchema() {
29
29
 
30
30
  type LoginFormData = z.infer<ReturnType<typeof useLoginSchema>>;
31
31
 
32
- const DEFAULT_DEMO_ACCOUNTS = [
33
- {email: 'buyer@acme-demo.com', label: 'Buyer', description: 'Acme · Places orders (needs approval)'},
34
- {email: 'approver@acme-demo.com', label: 'Approver', description: 'Acme · Approves/rejects orders'},
35
- {email: 'admin@acme-demo.com', label: 'Admin', description: 'Acme · Full company management'},
36
- {email: 'admin@globex-demo.com', label: 'Admin', description: 'Globex · Different company'},
37
- ];
38
-
39
32
  interface LoginFormProps {
40
33
  redirectTo?: string;
41
- demoAccounts?: Array<{ email: string; label: string; description: string }>;
42
34
  }
43
35
 
44
- export function LoginForm({redirectTo, demoAccounts}: LoginFormProps) {
36
+ export function LoginForm({redirectTo}: LoginFormProps) {
45
37
  const t = useTranslations('Auth');
46
38
  const [isPending, startTransition] = useTransition();
47
39
  const [serverError, setServerError] = useState<string | null>(null);
@@ -77,101 +69,77 @@ export function LoginForm({redirectTo, demoAccounts}: LoginFormProps) {
77
69
  ? `/register?redirectTo=${encodeURIComponent(redirectTo)}`
78
70
  : '/register';
79
71
 
80
- const fillDemoAccount = (email: string) => {
81
- form.setValue('username', email);
82
- form.setValue('password', 'test');
83
- };
84
-
85
72
  return (
86
- <div className="space-y-4">
87
- <Card>
88
- <Form {...form}>
89
- <form onSubmit={form.handleSubmit(onSubmit)}>
90
- <CardContent className="space-y-4">
91
- <FormField
92
- control={form.control}
93
- name="username"
94
- render={({field}) => (
95
- <FormItem>
96
- <FormLabel>{t('email')}</FormLabel>
97
- <FormControl>
98
- <Input
99
- type="email"
100
- placeholder="you@example.com"
101
- disabled={isPending}
102
- {...field}
103
- />
104
- </FormControl>
105
- <FormMessage/>
106
- </FormItem>
107
- )}
108
- />
109
-
110
- <FormField
111
- control={form.control}
112
- name="password"
113
- render={({field}) => (
114
- <FormItem>
115
- <div className="flex items-center justify-between">
116
- <FormLabel>{t('password')}</FormLabel>
117
- <Link
118
- href="/forgot-password"
119
- className="text-muted-foreground hover:text-primary text-sm"
120
- >
121
- {t('forgotPassword')}
122
- </Link>
123
- </div>
124
-
125
- <FormControl>
126
- <Input
127
- type="password"
128
- placeholder="••••••••"
129
- disabled={isPending}
130
- {...field}
131
- />
132
- </FormControl>
133
- <FormMessage/>
134
- </FormItem>
135
- )}
136
- />
137
-
138
- {serverError && (
139
- <div className="text-sm text-destructive">
140
- {serverError}
141
- </div>
73
+ <Card>
74
+ <Form {...form}>
75
+ <form onSubmit={form.handleSubmit(onSubmit)}>
76
+ <CardContent className="space-y-4">
77
+ <FormField
78
+ control={form.control}
79
+ name="username"
80
+ render={({field}) => (
81
+ <FormItem>
82
+ <FormLabel>{t('email')}</FormLabel>
83
+ <FormControl>
84
+ <Input
85
+ type="email"
86
+ placeholder="you@example.com"
87
+ disabled={isPending}
88
+ {...field}
89
+ />
90
+ </FormControl>
91
+ <FormMessage/>
92
+ </FormItem>
142
93
  )}
143
- <Button type="submit" className="w-full" disabled={isPending}>
144
- {isPending ? t('signingIn') : t('signIn')}
145
- </Button>
146
- </CardContent>
147
- <CardFooter className="flex flex-col space-y-4 mt-2">
148
- <div className="text-muted-foreground text-sm text-center">
149
- {t('noAccount')}{' '}
150
- <Link href={registerHref} className="hover:text-primary underline">
151
- {t('register')}
152
- </Link>
153
- </div>
154
- </CardFooter>
155
- </form>
156
- </Form>
157
- </Card>
94
+ />
95
+
96
+ <FormField
97
+ control={form.control}
98
+ name="password"
99
+ render={({field}) => (
100
+ <FormItem>
101
+ <div className="flex items-center justify-between">
102
+ <FormLabel>{t('password')}</FormLabel>
103
+ <Link
104
+ href="/forgot-password"
105
+ className="text-muted-foreground hover:text-primary text-sm"
106
+ >
107
+ {t('forgotPassword')}
108
+ </Link>
109
+ </div>
110
+
111
+ <FormControl>
112
+ <Input
113
+ type="password"
114
+ placeholder="••••••••"
115
+ disabled={isPending}
116
+ {...field}
117
+ />
118
+ </FormControl>
119
+ <FormMessage/>
120
+ </FormItem>
121
+ )}
122
+ />
158
123
 
159
- <div className="space-y-2">
160
- <p className="text-xs text-muted-foreground text-center">{t('demoAccounts')}</p>
161
- <div className="grid grid-cols-2 gap-2">
162
- {(demoAccounts ?? DEFAULT_DEMO_ACCOUNTS).map((account) => (
163
- <button
164
- key={account.email}
165
- type="button"
166
- className="text-left rounded-lg border p-3 hover:bg-muted/50 transition-colors"
167
- onClick={() => fillDemoAccount(account.email)}
168
- >
169
- <div className="text-sm font-medium">{account.label}</div>
170
- <div className="text-xs text-muted-foreground">{account.description}</div>
171
- </button>
172
- ))}
173
- </div>
174
- </div>
175
- </div>
124
+ {serverError && (
125
+ <div className="text-sm text-destructive">
126
+ {serverError}
127
+ </div>
128
+ )}
129
+ <Button type="submit" className="w-full" disabled={isPending}>
130
+ {isPending ? t('signingIn') : t('signIn')}
131
+ </Button>
132
+ </CardContent>
133
+ <CardFooter className="flex flex-col space-y-4 mt-2">
134
+ <div className="text-muted-foreground text-sm text-center">
135
+ {t('noAccount')}{' '}
136
+ <Link href={registerHref} className="hover:text-primary underline">
137
+ {t('register')}
138
+ </Link>
139
+ </div>
140
+ </CardFooter>
141
+ </form>
142
+ </Form>
143
+ </Card>
176
144
  );
177
145
  }
@@ -6,7 +6,6 @@ import {LoginForm} from "./login-form";
6
6
  import {Card, CardContent, CardFooter} from "@/components/ui/card";
7
7
  import {Skeleton} from "@/components/ui/skeleton";
8
8
  import {getActiveCustomer} from "@/lib/vendure/actions";
9
- import {getBranding} from "@/config/branding";
10
9
  import {locale as rootLocale} from 'next/root-params';
11
10
  import {type Locale} from '@/i18n/routing';
12
11
  import {AuthPageShell} from '@/components/layout/auth-page-shell';
@@ -56,7 +55,7 @@ async function SignInContent({searchParams, locale}: { searchParams: Promise<Rec
56
55
  redirect(`/${locale}${safeRedirect}`);
57
56
  }
58
57
 
59
- return <LoginForm redirectTo={redirectTo} demoAccounts={getBranding().demoAccounts} />;
58
+ return <LoginForm redirectTo={redirectTo} />;
60
59
  }
61
60
 
62
61
  export default async function SignInPage({searchParams}: {searchParams: Promise<Record<string, string | string[] | undefined>>}) {
@@ -78,4 +77,4 @@ export default async function SignInPage({searchParams}: {searchParams: Promise<
78
77
  </Suspense>
79
78
  </AuthPageShell>
80
79
  );
81
- }
80
+ }