minutework 0.1.0
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.
- package/EXTERNAL_ALPHA.md +74 -0
- package/README.md +57 -0
- package/assets/claude-local/CLAUDE.md.template +45 -0
- package/assets/claude-local/bundle.json +22 -0
- package/assets/claude-local/skills/README.md +6 -0
- package/assets/claude-local/skills/app-pack-authoring.md +8 -0
- package/assets/claude-local/skills/event-bus.md +8 -0
- package/assets/claude-local/skills/ontology-mapping.md +8 -0
- package/assets/claude-local/skills/openclaw-skill-importer.md +7 -0
- package/assets/claude-local/skills/schema-engine.md +8 -0
- package/assets/claude-local/skills/secrets-runtime-bridge.md +9 -0
- package/assets/claude-local/skills/sidecar-generation.md +9 -0
- package/assets/templates/fastapi-sidecar/.env.example +8 -0
- package/assets/templates/fastapi-sidecar/README.md +77 -0
- package/assets/templates/fastapi-sidecar/poetry.lock +757 -0
- package/assets/templates/fastapi-sidecar/pyproject.toml +42 -0
- package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/__init__.py +3 -0
- package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/auth.py +70 -0
- package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/bridge/__init__.py +3 -0
- package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/bridge/client.py +71 -0
- package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/logging_utils.py +25 -0
- package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/main.py +85 -0
- package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/receipts.py +24 -0
- package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/settings.py +41 -0
- package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/template_validation.py +26 -0
- package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/worker.py +33 -0
- package/assets/templates/fastapi-sidecar/template.json +43 -0
- package/assets/templates/fastapi-sidecar/template.schema.json +160 -0
- package/assets/templates/fastapi-sidecar/tests/conftest.py +36 -0
- package/assets/templates/fastapi-sidecar/tests/test_app.py +39 -0
- package/assets/templates/fastapi-sidecar/tests/test_auth.py +32 -0
- package/assets/templates/fastapi-sidecar/tests/test_bridge_client.py +31 -0
- package/assets/templates/fastapi-sidecar/tests/test_materialization.py +55 -0
- package/assets/templates/fastapi-sidecar/tests/test_template_contract.py +49 -0
- package/assets/templates/fastapi-sidecar/tests/test_worker.py +7 -0
- package/assets/templates/fastapi-sidecar/tools/template/validate_template.py +20 -0
- package/assets/templates/next-tenant-app/.env.example +8 -0
- package/assets/templates/next-tenant-app/.storybook/main.ts +19 -0
- package/assets/templates/next-tenant-app/.storybook/preview.tsx +38 -0
- package/assets/templates/next-tenant-app/README.md +115 -0
- package/assets/templates/next-tenant-app/components.json +21 -0
- package/assets/templates/next-tenant-app/eslint.config.mjs +41 -0
- package/assets/templates/next-tenant-app/next-env.d.ts +6 -0
- package/assets/templates/next-tenant-app/next.config.ts +8 -0
- package/assets/templates/next-tenant-app/package-lock.json +9682 -0
- package/assets/templates/next-tenant-app/package.json +59 -0
- package/assets/templates/next-tenant-app/pnpm-lock.yaml +6062 -0
- package/assets/templates/next-tenant-app/postcss.config.mjs +8 -0
- package/assets/templates/next-tenant-app/src/app/api/auth/context/route.test.ts +90 -0
- package/assets/templates/next-tenant-app/src/app/api/auth/context/route.ts +78 -0
- package/assets/templates/next-tenant-app/src/app/api/auth/login/route.ts +31 -0
- package/assets/templates/next-tenant-app/src/app/api/auth/logout/route.ts +16 -0
- package/assets/templates/next-tenant-app/src/app/api/auth/password-change/route.test.ts +79 -0
- package/assets/templates/next-tenant-app/src/app/api/auth/password-change/route.ts +40 -0
- package/assets/templates/next-tenant-app/src/app/api/auth/password-status/route.test.ts +42 -0
- package/assets/templates/next-tenant-app/src/app/api/auth/password-status/route.ts +29 -0
- package/assets/templates/next-tenant-app/src/app/api/auth/session/route.ts +26 -0
- package/assets/templates/next-tenant-app/src/app/api/gateway/commands/[runId]/route.test.ts +40 -0
- package/assets/templates/next-tenant-app/src/app/api/gateway/commands/[runId]/route.ts +47 -0
- package/assets/templates/next-tenant-app/src/app/api/gateway/commands/route.test.ts +43 -0
- package/assets/templates/next-tenant-app/src/app/api/gateway/commands/route.ts +45 -0
- package/assets/templates/next-tenant-app/src/app/app/examples/runtime-commands/page.test.ts +83 -0
- package/assets/templates/next-tenant-app/src/app/app/examples/runtime-commands/page.tsx +30 -0
- package/assets/templates/next-tenant-app/src/app/app/layout.tsx +20 -0
- package/assets/templates/next-tenant-app/src/app/app/page.test.ts +62 -0
- package/assets/templates/next-tenant-app/src/app/app/page.tsx +24 -0
- package/assets/templates/next-tenant-app/src/app/blog/[slug]/page.test.ts +70 -0
- package/assets/templates/next-tenant-app/src/app/blog/[slug]/page.tsx +57 -0
- package/assets/templates/next-tenant-app/src/app/blog/page.test.ts +42 -0
- package/assets/templates/next-tenant-app/src/app/blog/page.tsx +37 -0
- package/assets/templates/next-tenant-app/src/app/docs/[...slug]/page.test.ts +70 -0
- package/assets/templates/next-tenant-app/src/app/docs/[...slug]/page.tsx +55 -0
- package/assets/templates/next-tenant-app/src/app/docs/page.test.ts +42 -0
- package/assets/templates/next-tenant-app/src/app/docs/page.tsx +37 -0
- package/assets/templates/next-tenant-app/src/app/globals.css +70 -0
- package/assets/templates/next-tenant-app/src/app/layout.tsx +69 -0
- package/assets/templates/next-tenant-app/src/app/login/page.test.ts +55 -0
- package/assets/templates/next-tenant-app/src/app/login/page.tsx +33 -0
- package/assets/templates/next-tenant-app/src/app/page.test.ts +56 -0
- package/assets/templates/next-tenant-app/src/app/page.tsx +35 -0
- package/assets/templates/next-tenant-app/src/app/pricing/page.test.ts +55 -0
- package/assets/templates/next-tenant-app/src/app/pricing/page.tsx +35 -0
- package/assets/templates/next-tenant-app/src/app/providers.tsx +25 -0
- package/assets/templates/next-tenant-app/src/app/robots.test.ts +20 -0
- package/assets/templates/next-tenant-app/src/app/robots.ts +18 -0
- package/assets/templates/next-tenant-app/src/app/sitemap.test.ts +49 -0
- package/assets/templates/next-tenant-app/src/app/sitemap.ts +54 -0
- package/assets/templates/next-tenant-app/src/components/ui/button.tsx +59 -0
- package/assets/templates/next-tenant-app/src/components/ui/input.tsx +21 -0
- package/assets/templates/next-tenant-app/src/design-system/docs/governance.mdx +26 -0
- package/assets/templates/next-tenant-app/src/design-system/patterns/panel-frame.stories.tsx +48 -0
- package/assets/templates/next-tenant-app/src/design-system/patterns/panel-frame.tsx +26 -0
- package/assets/templates/next-tenant-app/src/design-system/patterns/status-badge.stories.tsx +26 -0
- package/assets/templates/next-tenant-app/src/design-system/patterns/status-badge.tsx +35 -0
- package/assets/templates/next-tenant-app/src/design-system/patterns/theme-mode-toggle.stories.tsx +21 -0
- package/assets/templates/next-tenant-app/src/design-system/patterns/theme-mode-toggle.tsx +75 -0
- package/assets/templates/next-tenant-app/src/design-system/primitives/button.stories.tsx +37 -0
- package/assets/templates/next-tenant-app/src/design-system/primitives/button.ts +1 -0
- package/assets/templates/next-tenant-app/src/design-system/primitives/input.stories.tsx +26 -0
- package/assets/templates/next-tenant-app/src/design-system/primitives/input.ts +1 -0
- package/assets/templates/next-tenant-app/src/design-system/recipes/chrome.ts +28 -0
- package/assets/templates/next-tenant-app/src/design-system/tokens/foundation.css +31 -0
- package/assets/templates/next-tenant-app/src/design-system/tokens/index.css +3 -0
- package/assets/templates/next-tenant-app/src/design-system/tokens/manifest.json +85 -0
- package/assets/templates/next-tenant-app/src/design-system/tokens/manifest.ts +87 -0
- package/assets/templates/next-tenant-app/src/design-system/tokens/semantic.css +105 -0
- package/assets/templates/next-tenant-app/src/design-system/tokens/theme.css +59 -0
- package/assets/templates/next-tenant-app/src/design-system/tokens/tokens.stories.tsx +71 -0
- package/assets/templates/next-tenant-app/src/features/auth/components/login-screen.tsx +198 -0
- package/assets/templates/next-tenant-app/src/features/dashboard/components/tenant-dashboard.tsx +153 -0
- package/assets/templates/next-tenant-app/src/features/examples/runtime-command-demo/components/runtime-command-demo.tsx +342 -0
- package/assets/templates/next-tenant-app/src/features/public-shell/components/content-article.tsx +66 -0
- package/assets/templates/next-tenant-app/src/features/public-shell/components/content-collection.tsx +108 -0
- package/assets/templates/next-tenant-app/src/features/public-shell/components/marketing-page-canvas.tsx +111 -0
- package/assets/templates/next-tenant-app/src/features/public-shell/components/public-site-shell.tsx +111 -0
- package/assets/templates/next-tenant-app/src/features/shell/components/private-app-shell.tsx +624 -0
- package/assets/templates/next-tenant-app/src/lib/app-routes.test.ts +20 -0
- package/assets/templates/next-tenant-app/src/lib/app-routes.ts +59 -0
- package/assets/templates/next-tenant-app/src/lib/content/__fixtures__/public-site-snapshot.ts +189 -0
- package/assets/templates/next-tenant-app/src/lib/content/adapter.server.test.ts +318 -0
- package/assets/templates/next-tenant-app/src/lib/content/adapter.server.ts +232 -0
- package/assets/templates/next-tenant-app/src/lib/content/contracts.ts +339 -0
- package/assets/templates/next-tenant-app/src/lib/content/custom-adapter.ts +5 -0
- package/assets/templates/next-tenant-app/src/lib/content/empty-state.ts +96 -0
- package/assets/templates/next-tenant-app/src/lib/platform/auth.server.test.ts +75 -0
- package/assets/templates/next-tenant-app/src/lib/platform/auth.server.ts +25 -0
- package/assets/templates/next-tenant-app/src/lib/platform/client.server.test.ts +170 -0
- package/assets/templates/next-tenant-app/src/lib/platform/client.server.ts +661 -0
- package/assets/templates/next-tenant-app/src/lib/platform/contracts.ts +131 -0
- package/assets/templates/next-tenant-app/src/lib/platform/endpoints.server.ts +34 -0
- package/assets/templates/next-tenant-app/src/lib/platform/env.server.test.ts +102 -0
- package/assets/templates/next-tenant-app/src/lib/platform/env.server.ts +87 -0
- package/assets/templates/next-tenant-app/src/lib/platform/route-response.ts +33 -0
- package/assets/templates/next-tenant-app/src/lib/platform/session.server.ts +108 -0
- package/assets/templates/next-tenant-app/src/lib/public-site.test.ts +20 -0
- package/assets/templates/next-tenant-app/src/lib/public-site.ts +49 -0
- package/assets/templates/next-tenant-app/src/lib/theme-config.ts +10 -0
- package/assets/templates/next-tenant-app/src/lib/theme.tsx +159 -0
- package/assets/templates/next-tenant-app/src/lib/utils.ts +6 -0
- package/assets/templates/next-tenant-app/template.json +27 -0
- package/assets/templates/next-tenant-app/template.schema.json +160 -0
- package/assets/templates/next-tenant-app/test/server-only-stub.ts +1 -0
- package/assets/templates/next-tenant-app/tools/design-system/build-token-manifest.mjs +3 -0
- package/assets/templates/next-tenant-app/tools/design-system/check-imports.mjs +9 -0
- package/assets/templates/next-tenant-app/tools/design-system/check-stories.mjs +9 -0
- package/assets/templates/next-tenant-app/tools/design-system/check-values.mjs +9 -0
- package/assets/templates/next-tenant-app/tools/design-system/checks.mjs +238 -0
- package/assets/templates/next-tenant-app/tools/design-system/eslint-plugin-design-system.mjs +184 -0
- package/assets/templates/next-tenant-app/tools/design-system/playwright.config.mjs +34 -0
- package/assets/templates/next-tenant-app/tools/design-system/run-checks.mjs +22 -0
- package/assets/templates/next-tenant-app/tools/design-system/shared.mjs +166 -0
- package/assets/templates/next-tenant-app/tools/design-system/visual.spec.ts +41 -0
- package/assets/templates/next-tenant-app/tools/template/validate-route-contract.mjs +39 -0
- package/assets/templates/next-tenant-app/tools/template/validate-template.mjs +45 -0
- package/assets/templates/next-tenant-app/tsconfig.json +42 -0
- package/assets/templates/next-tenant-app/vitest.config.ts +25 -0
- package/bin/minutework.js +40 -0
- package/dist/auth.d.ts +59 -0
- package/dist/auth.js +338 -0
- package/dist/auth.js.map +1 -0
- package/dist/browser.d.ts +1 -0
- package/dist/browser.js +26 -0
- package/dist/browser.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +5 -0
- package/dist/cli.js.map +1 -0
- package/dist/compile.d.ts +20 -0
- package/dist/compile.js +121 -0
- package/dist/compile.js.map +1 -0
- package/dist/config.d.ts +25 -0
- package/dist/config.js +102 -0
- package/dist/config.js.map +1 -0
- package/dist/deploy-state.d.ts +35 -0
- package/dist/deploy-state.js +30 -0
- package/dist/deploy-state.js.map +1 -0
- package/dist/deploy.d.ts +22 -0
- package/dist/deploy.js +308 -0
- package/dist/deploy.js.map +1 -0
- package/dist/developer-client.d.ts +88 -0
- package/dist/developer-client.js +78 -0
- package/dist/developer-client.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +290 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +22 -0
- package/dist/init.js +421 -0
- package/dist/init.js.map +1 -0
- package/dist/launcher.d.ts +1 -0
- package/dist/launcher.js +50 -0
- package/dist/launcher.js.map +1 -0
- package/dist/paths.d.ts +12 -0
- package/dist/paths.js +33 -0
- package/dist/paths.js.map +1 -0
- package/dist/sandbox.d.ts +30 -0
- package/dist/sandbox.js +852 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/state.d.ts +46 -0
- package/dist/state.js +82 -0
- package/dist/state.js.map +1 -0
- package/dist/tokens.d.ts +14 -0
- package/dist/tokens.js +293 -0
- package/dist/tokens.js.map +1 -0
- package/package.json +43 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--background: #f6fafc;
|
|
3
|
+
--foreground: var(--ds-foundation-neutral-950);
|
|
4
|
+
--card: #fcfdff;
|
|
5
|
+
--card-foreground: var(--ds-foundation-neutral-950);
|
|
6
|
+
--popover: #fcfdff;
|
|
7
|
+
--popover-foreground: var(--ds-foundation-neutral-950);
|
|
8
|
+
--primary: var(--ds-foundation-cyan-600);
|
|
9
|
+
--primary-foreground: var(--ds-foundation-white);
|
|
10
|
+
--secondary: #edf3f7;
|
|
11
|
+
--secondary-foreground: var(--ds-foundation-neutral-950);
|
|
12
|
+
--muted: #eef5f8;
|
|
13
|
+
--muted-foreground: #617487;
|
|
14
|
+
--accent: var(--ds-foundation-cyan-100);
|
|
15
|
+
--accent-foreground: var(--ds-foundation-neutral-950);
|
|
16
|
+
--destructive: var(--ds-foundation-red-500);
|
|
17
|
+
--destructive-foreground: var(--ds-foundation-white);
|
|
18
|
+
--border: #d7e5ed;
|
|
19
|
+
--input: #d7e5ed;
|
|
20
|
+
--ring: var(--ds-foundation-cyan-500);
|
|
21
|
+
--chart-1: var(--ds-foundation-cyan-500);
|
|
22
|
+
--chart-2: var(--ds-foundation-green-500);
|
|
23
|
+
--chart-3: var(--ds-foundation-blue-500);
|
|
24
|
+
--chart-4: var(--ds-foundation-yellow-500);
|
|
25
|
+
--chart-5: var(--ds-foundation-red-500);
|
|
26
|
+
--radius: 0.5rem;
|
|
27
|
+
--sidebar: #f8fbfd;
|
|
28
|
+
--sidebar-foreground: var(--ds-foundation-neutral-950);
|
|
29
|
+
--sidebar-primary: var(--ds-foundation-cyan-600);
|
|
30
|
+
--sidebar-primary-foreground: var(--ds-foundation-white);
|
|
31
|
+
--sidebar-accent: #edf5f8;
|
|
32
|
+
--sidebar-accent-foreground: var(--ds-foundation-neutral-950);
|
|
33
|
+
--sidebar-border: #d7e5ed;
|
|
34
|
+
--sidebar-ring: var(--ds-foundation-cyan-500);
|
|
35
|
+
|
|
36
|
+
--surface: #ffffff;
|
|
37
|
+
--surface-raised: #f3f8fb;
|
|
38
|
+
--text-link: var(--ds-foundation-cyan-700);
|
|
39
|
+
--success: var(--ds-foundation-green-500);
|
|
40
|
+
--warning: var(--ds-foundation-yellow-500);
|
|
41
|
+
--danger: var(--ds-foundation-red-500);
|
|
42
|
+
--info: var(--ds-foundation-blue-500);
|
|
43
|
+
--ai-bubble: #eef5f8;
|
|
44
|
+
--user-bubble: var(--ds-foundation-cyan-600);
|
|
45
|
+
--tenant-rail: var(--ds-foundation-cyan-50);
|
|
46
|
+
--tenant-rail-foreground: var(--ds-foundation-ink-500);
|
|
47
|
+
--tenant-rail-muted: #627789;
|
|
48
|
+
--tenant-rail-border: rgb(148 163 184 / 0.24);
|
|
49
|
+
--tenant-rail-surface: rgb(255 255 255 / 0.72);
|
|
50
|
+
--overlay: var(--ds-foundation-overlay-50);
|
|
51
|
+
--overlay-strong: var(--ds-foundation-overlay-60);
|
|
52
|
+
--strong-foreground: var(--ds-foundation-white);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.dark {
|
|
56
|
+
--background: var(--ds-foundation-neutral-950);
|
|
57
|
+
--foreground: var(--ds-foundation-neutral-100);
|
|
58
|
+
--card: var(--ds-foundation-neutral-850);
|
|
59
|
+
--card-foreground: var(--ds-foundation-neutral-100);
|
|
60
|
+
--popover: var(--ds-foundation-neutral-850);
|
|
61
|
+
--popover-foreground: var(--ds-foundation-neutral-100);
|
|
62
|
+
--primary: var(--ds-foundation-cyan-500);
|
|
63
|
+
--primary-foreground: var(--ds-foundation-white);
|
|
64
|
+
--secondary: var(--ds-foundation-neutral-800);
|
|
65
|
+
--secondary-foreground: var(--ds-foundation-neutral-100);
|
|
66
|
+
--muted: var(--ds-foundation-neutral-850);
|
|
67
|
+
--muted-foreground: var(--ds-foundation-neutral-500);
|
|
68
|
+
--accent: var(--ds-foundation-ink-700);
|
|
69
|
+
--accent-foreground: var(--ds-foundation-neutral-100);
|
|
70
|
+
--destructive: var(--ds-foundation-red-500);
|
|
71
|
+
--destructive-foreground: var(--ds-foundation-white);
|
|
72
|
+
--border: var(--ds-foundation-neutral-700);
|
|
73
|
+
--input: var(--ds-foundation-neutral-800);
|
|
74
|
+
--ring: var(--ds-foundation-cyan-500);
|
|
75
|
+
--chart-1: var(--ds-foundation-cyan-500);
|
|
76
|
+
--chart-2: var(--ds-foundation-green-500);
|
|
77
|
+
--chart-3: var(--ds-foundation-blue-500);
|
|
78
|
+
--chart-4: var(--ds-foundation-yellow-500);
|
|
79
|
+
--chart-5: var(--ds-foundation-red-500);
|
|
80
|
+
--sidebar: var(--ds-foundation-neutral-900);
|
|
81
|
+
--sidebar-foreground: var(--ds-foundation-neutral-100);
|
|
82
|
+
--sidebar-primary: var(--ds-foundation-cyan-500);
|
|
83
|
+
--sidebar-primary-foreground: var(--ds-foundation-white);
|
|
84
|
+
--sidebar-accent: var(--ds-foundation-neutral-800);
|
|
85
|
+
--sidebar-accent-foreground: var(--ds-foundation-neutral-100);
|
|
86
|
+
--sidebar-border: var(--ds-foundation-neutral-700);
|
|
87
|
+
--sidebar-ring: var(--ds-foundation-cyan-500);
|
|
88
|
+
--surface: var(--ds-foundation-neutral-850);
|
|
89
|
+
--surface-raised: var(--ds-foundation-neutral-800);
|
|
90
|
+
--text-link: var(--ds-foundation-cyan-300);
|
|
91
|
+
--success: var(--ds-foundation-green-500);
|
|
92
|
+
--warning: var(--ds-foundation-yellow-500);
|
|
93
|
+
--danger: var(--ds-foundation-red-500);
|
|
94
|
+
--info: var(--ds-foundation-blue-500);
|
|
95
|
+
--ai-bubble: var(--ds-foundation-neutral-850);
|
|
96
|
+
--user-bubble: var(--ds-foundation-cyan-600);
|
|
97
|
+
--tenant-rail: var(--ds-foundation-neutral-950);
|
|
98
|
+
--tenant-rail-foreground: var(--ds-foundation-white);
|
|
99
|
+
--tenant-rail-muted: rgb(255 255 255 / 0.72);
|
|
100
|
+
--tenant-rail-border: rgb(255 255 255 / 0.08);
|
|
101
|
+
--tenant-rail-surface: rgb(255 255 255 / 0.06);
|
|
102
|
+
--overlay: var(--ds-foundation-overlay-50);
|
|
103
|
+
--overlay-strong: var(--ds-foundation-overlay-60);
|
|
104
|
+
--strong-foreground: var(--ds-foundation-white);
|
|
105
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
@custom-variant dark (&:is(.dark *));
|
|
2
|
+
|
|
3
|
+
@theme inline {
|
|
4
|
+
--font-sans: "Geist", "Geist Fallback";
|
|
5
|
+
--font-mono: "Geist Mono", "Geist Mono Fallback";
|
|
6
|
+
--color-background: var(--background);
|
|
7
|
+
--color-foreground: var(--foreground);
|
|
8
|
+
--color-card: var(--card);
|
|
9
|
+
--color-card-foreground: var(--card-foreground);
|
|
10
|
+
--color-popover: var(--popover);
|
|
11
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
12
|
+
--color-primary: var(--primary);
|
|
13
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
14
|
+
--color-secondary: var(--secondary);
|
|
15
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
16
|
+
--color-muted: var(--muted);
|
|
17
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
18
|
+
--color-accent: var(--accent);
|
|
19
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
20
|
+
--color-destructive: var(--destructive);
|
|
21
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
|
22
|
+
--color-border: var(--border);
|
|
23
|
+
--color-input: var(--input);
|
|
24
|
+
--color-ring: var(--ring);
|
|
25
|
+
--color-chart-1: var(--chart-1);
|
|
26
|
+
--color-chart-2: var(--chart-2);
|
|
27
|
+
--color-chart-3: var(--chart-3);
|
|
28
|
+
--color-chart-4: var(--chart-4);
|
|
29
|
+
--color-chart-5: var(--chart-5);
|
|
30
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
31
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
32
|
+
--radius-lg: var(--radius);
|
|
33
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
34
|
+
--color-sidebar: var(--sidebar);
|
|
35
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
36
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
37
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
38
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
39
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
40
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
41
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
42
|
+
--color-surface: var(--surface);
|
|
43
|
+
--color-surface-raised: var(--surface-raised);
|
|
44
|
+
--color-text-link: var(--text-link);
|
|
45
|
+
--color-success: var(--success);
|
|
46
|
+
--color-warning: var(--warning);
|
|
47
|
+
--color-danger: var(--danger);
|
|
48
|
+
--color-info: var(--info);
|
|
49
|
+
--color-ai-bubble: var(--ai-bubble);
|
|
50
|
+
--color-user-bubble: var(--user-bubble);
|
|
51
|
+
--color-tenant-rail: var(--tenant-rail);
|
|
52
|
+
--color-tenant-rail-foreground: var(--tenant-rail-foreground);
|
|
53
|
+
--color-tenant-rail-muted: var(--tenant-rail-muted);
|
|
54
|
+
--color-tenant-rail-border: var(--tenant-rail-border);
|
|
55
|
+
--color-tenant-rail-surface: var(--tenant-rail-surface);
|
|
56
|
+
--color-overlay: var(--overlay);
|
|
57
|
+
--color-overlay-strong: var(--overlay-strong);
|
|
58
|
+
--color-strong-foreground: var(--strong-foreground);
|
|
59
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/nextjs-vite";
|
|
2
|
+
|
|
3
|
+
import tokenManifest from "@/design-system/tokens/manifest";
|
|
4
|
+
|
|
5
|
+
function TokenGrid({
|
|
6
|
+
entries,
|
|
7
|
+
}: {
|
|
8
|
+
entries: Array<[string, string]>;
|
|
9
|
+
}) {
|
|
10
|
+
return (
|
|
11
|
+
<div className="grid gap-3 sm:grid-cols-2">
|
|
12
|
+
{entries.map(([name, value]) => (
|
|
13
|
+
<div
|
|
14
|
+
key={name}
|
|
15
|
+
className="flex items-center gap-3 rounded-lg border border-border bg-surface p-3"
|
|
16
|
+
>
|
|
17
|
+
<div
|
|
18
|
+
className="h-10 w-10 rounded-md border border-border"
|
|
19
|
+
style={{ backgroundColor: `var(--${name})` }}
|
|
20
|
+
/>
|
|
21
|
+
<div className="min-w-0">
|
|
22
|
+
<p className="truncate text-sm font-medium text-foreground">{name}</p>
|
|
23
|
+
<p className="truncate text-xs text-muted-foreground">{value}</p>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
))}
|
|
27
|
+
</div>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function TokenShowcase() {
|
|
32
|
+
return (
|
|
33
|
+
<div className="w-[720px] space-y-8">
|
|
34
|
+
<section className="space-y-3">
|
|
35
|
+
<div>
|
|
36
|
+
<p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
|
|
37
|
+
Semantic
|
|
38
|
+
</p>
|
|
39
|
+
<h2 className="text-xl font-semibold text-foreground">Shared UI roles</h2>
|
|
40
|
+
</div>
|
|
41
|
+
<TokenGrid entries={Object.entries(tokenManifest.semantic)} />
|
|
42
|
+
</section>
|
|
43
|
+
<section className="space-y-3">
|
|
44
|
+
<div>
|
|
45
|
+
<p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
|
|
46
|
+
Foundation
|
|
47
|
+
</p>
|
|
48
|
+
<h2 className="text-xl font-semibold text-foreground">Literal sources</h2>
|
|
49
|
+
</div>
|
|
50
|
+
<TokenGrid entries={Object.entries(tokenManifest.foundation)} />
|
|
51
|
+
</section>
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const meta = {
|
|
57
|
+
title: "Design System/Tokens",
|
|
58
|
+
component: TokenShowcase,
|
|
59
|
+
tags: ["autodocs"],
|
|
60
|
+
parameters: {
|
|
61
|
+
layout: "fullscreen",
|
|
62
|
+
},
|
|
63
|
+
} satisfies Meta<typeof TokenShowcase>;
|
|
64
|
+
|
|
65
|
+
export default meta;
|
|
66
|
+
|
|
67
|
+
type Story = StoryObj<typeof meta>;
|
|
68
|
+
|
|
69
|
+
export const Overview: Story = {
|
|
70
|
+
render: () => <TokenShowcase />,
|
|
71
|
+
};
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { startTransition, useEffect, useState } from "react";
|
|
4
|
+
import type { FormEvent } from "react";
|
|
5
|
+
|
|
6
|
+
import { ArrowRight, ShieldCheck, TerminalSquare } from "lucide-react";
|
|
7
|
+
import { useRouter } from "next/navigation";
|
|
8
|
+
|
|
9
|
+
import { Button } from "@/design-system/primitives/button";
|
|
10
|
+
import { Input } from "@/design-system/primitives/input";
|
|
11
|
+
import { PanelFrame } from "@/design-system/patterns/panel-frame";
|
|
12
|
+
import { ThemeModeToggle } from "@/design-system/patterns/theme-mode-toggle";
|
|
13
|
+
import { appRoutes } from "@/lib/app-routes";
|
|
14
|
+
|
|
15
|
+
export function LoginScreen({
|
|
16
|
+
appName,
|
|
17
|
+
operatorConsoleHref,
|
|
18
|
+
}: {
|
|
19
|
+
appName: string;
|
|
20
|
+
operatorConsoleHref: string;
|
|
21
|
+
}) {
|
|
22
|
+
const router = useRouter();
|
|
23
|
+
const [username, setUsername] = useState("demo-user");
|
|
24
|
+
const [password, setPassword] = useState("demo-password");
|
|
25
|
+
const [error, setError] = useState("");
|
|
26
|
+
const [submitting, setSubmitting] = useState(false);
|
|
27
|
+
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
void fetch("/api/auth/session", {
|
|
30
|
+
method: "GET",
|
|
31
|
+
cache: "no-store",
|
|
32
|
+
}).catch(() => null);
|
|
33
|
+
}, []);
|
|
34
|
+
|
|
35
|
+
async function handleSubmit(event: FormEvent<HTMLFormElement>) {
|
|
36
|
+
event.preventDefault();
|
|
37
|
+
setSubmitting(true);
|
|
38
|
+
setError("");
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
const response = await fetch("/api/auth/login", {
|
|
42
|
+
method: "POST",
|
|
43
|
+
headers: { "Content-Type": "application/json" },
|
|
44
|
+
body: JSON.stringify({ username, password }),
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
if (!response.ok) {
|
|
48
|
+
const payload = (await response.json().catch(() => ({}))) as {
|
|
49
|
+
detail?: string;
|
|
50
|
+
};
|
|
51
|
+
setError(payload.detail || "Login failed.");
|
|
52
|
+
setSubmitting(false);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
startTransition(() => {
|
|
57
|
+
router.replace(appRoutes.appHome);
|
|
58
|
+
router.refresh();
|
|
59
|
+
});
|
|
60
|
+
} catch {
|
|
61
|
+
setError("Unable to reach the platform right now.");
|
|
62
|
+
setSubmitting(false);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<main className="min-h-screen bg-background text-foreground">
|
|
68
|
+
<div className="mx-auto flex min-h-screen max-w-6xl flex-col gap-10 px-6 py-8 lg:flex-row lg:items-center lg:justify-between">
|
|
69
|
+
<div className="flex justify-end lg:hidden">
|
|
70
|
+
<ThemeModeToggle className="max-w-xs" />
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
<section className="max-w-2xl space-y-6">
|
|
74
|
+
<div className="space-y-3">
|
|
75
|
+
<p className="text-sm font-semibold uppercase tracking-widest text-muted-foreground">
|
|
76
|
+
Combined Web Starter
|
|
77
|
+
</p>
|
|
78
|
+
<h1 className="max-w-xl text-4xl font-semibold tracking-tight text-balance sm:text-5xl">
|
|
79
|
+
Cross the public-to-private boundary without splitting the app.
|
|
80
|
+
</h1>
|
|
81
|
+
<p className="max-w-xl text-base leading-7 text-muted-foreground sm:text-lg">
|
|
82
|
+
{appName} keeps marketing, docs, and blog routes public at the
|
|
83
|
+
root while preserving a server-owned platform session BFF under
|
|
84
|
+
`/app`.
|
|
85
|
+
</p>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<div className="grid gap-3 sm:grid-cols-2">
|
|
89
|
+
<PanelFrame tone="raised" radius="xl" padding="lg" className="space-y-2">
|
|
90
|
+
<TerminalSquare className="size-5 text-primary" />
|
|
91
|
+
<p className="text-sm font-medium">Generic tenant shell</p>
|
|
92
|
+
<p className="text-sm leading-6 text-muted-foreground">
|
|
93
|
+
Start with public storytelling at the root and authenticated
|
|
94
|
+
workspace routing under `/app` instead of a private-only home page.
|
|
95
|
+
</p>
|
|
96
|
+
</PanelFrame>
|
|
97
|
+
<PanelFrame tone="raised" radius="xl" padding="lg" className="space-y-2">
|
|
98
|
+
<ShieldCheck className="size-5 text-primary" />
|
|
99
|
+
<p className="text-sm font-medium">Server-owned session</p>
|
|
100
|
+
<p className="text-sm leading-6 text-muted-foreground">
|
|
101
|
+
Session cookies stay on the server boundary while public pages
|
|
102
|
+
remain free of tenant-context reads and private BFF assumptions.
|
|
103
|
+
</p>
|
|
104
|
+
</PanelFrame>
|
|
105
|
+
</div>
|
|
106
|
+
</section>
|
|
107
|
+
|
|
108
|
+
<div className="flex w-full max-w-md flex-col gap-4 self-center lg:self-auto">
|
|
109
|
+
<div className="hidden justify-end lg:flex">
|
|
110
|
+
<ThemeModeToggle className="max-w-xs" />
|
|
111
|
+
</div>
|
|
112
|
+
|
|
113
|
+
<PanelFrame tone="floating" radius="xl" padding="lg" className="space-y-6 shadow-2xl">
|
|
114
|
+
<div className="space-y-2">
|
|
115
|
+
<p className="text-sm font-semibold uppercase tracking-widest text-muted-foreground">
|
|
116
|
+
Template sign-in
|
|
117
|
+
</p>
|
|
118
|
+
<h2 className="text-2xl font-semibold tracking-tight">
|
|
119
|
+
Log into {appName}
|
|
120
|
+
</h2>
|
|
121
|
+
<p className="text-sm leading-6 text-muted-foreground">
|
|
122
|
+
Use platform tenant credentials to establish a server-owned
|
|
123
|
+
session before entering the authenticated shell under `/app`.
|
|
124
|
+
</p>
|
|
125
|
+
</div>
|
|
126
|
+
|
|
127
|
+
<form className="space-y-5" onSubmit={handleSubmit}>
|
|
128
|
+
<div className="space-y-2">
|
|
129
|
+
<label
|
|
130
|
+
className="text-xs font-semibold uppercase tracking-widest text-muted-foreground"
|
|
131
|
+
htmlFor="username"
|
|
132
|
+
>
|
|
133
|
+
Username
|
|
134
|
+
</label>
|
|
135
|
+
<Input
|
|
136
|
+
id="username"
|
|
137
|
+
name="username"
|
|
138
|
+
autoComplete="username"
|
|
139
|
+
className="h-12 text-base"
|
|
140
|
+
value={username}
|
|
141
|
+
onChange={(event) => {
|
|
142
|
+
setUsername(event.target.value);
|
|
143
|
+
setError("");
|
|
144
|
+
}}
|
|
145
|
+
/>
|
|
146
|
+
</div>
|
|
147
|
+
|
|
148
|
+
<div className="space-y-2">
|
|
149
|
+
<label
|
|
150
|
+
className="text-xs font-semibold uppercase tracking-widest text-muted-foreground"
|
|
151
|
+
htmlFor="password"
|
|
152
|
+
>
|
|
153
|
+
Password
|
|
154
|
+
</label>
|
|
155
|
+
<Input
|
|
156
|
+
id="password"
|
|
157
|
+
name="password"
|
|
158
|
+
type="password"
|
|
159
|
+
autoComplete="current-password"
|
|
160
|
+
className="h-12 text-base"
|
|
161
|
+
value={password}
|
|
162
|
+
onChange={(event) => {
|
|
163
|
+
setPassword(event.target.value);
|
|
164
|
+
setError("");
|
|
165
|
+
}}
|
|
166
|
+
/>
|
|
167
|
+
</div>
|
|
168
|
+
|
|
169
|
+
{error ? (
|
|
170
|
+
<p className="text-sm leading-6 text-destructive">{error}</p>
|
|
171
|
+
) : null}
|
|
172
|
+
|
|
173
|
+
<Button
|
|
174
|
+
type="submit"
|
|
175
|
+
className="h-12 w-full text-sm font-semibold"
|
|
176
|
+
disabled={submitting}
|
|
177
|
+
>
|
|
178
|
+
{submitting ? "Signing in" : "Sign In"}
|
|
179
|
+
<ArrowRight className="size-4" />
|
|
180
|
+
</Button>
|
|
181
|
+
</form>
|
|
182
|
+
|
|
183
|
+
<div className="flex flex-wrap items-center justify-between gap-3 border-t border-border pt-4">
|
|
184
|
+
<p className="text-sm text-muted-foreground">
|
|
185
|
+
Need the operator console instead?
|
|
186
|
+
</p>
|
|
187
|
+
<Button asChild type="button" variant="outline">
|
|
188
|
+
<a href={operatorConsoleHref} target="_blank" rel="noreferrer">
|
|
189
|
+
Open /ops
|
|
190
|
+
</a>
|
|
191
|
+
</Button>
|
|
192
|
+
</div>
|
|
193
|
+
</PanelFrame>
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
</main>
|
|
197
|
+
);
|
|
198
|
+
}
|
package/assets/templates/next-tenant-app/src/features/dashboard/components/tenant-dashboard.tsx
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import Link from "next/link";
|
|
4
|
+
import { Blocks, Building2, FolderKanban, ShieldCheck } from "lucide-react";
|
|
5
|
+
|
|
6
|
+
import { PanelFrame } from "@/design-system/patterns/panel-frame";
|
|
7
|
+
import { StatusBadge } from "@/design-system/patterns/status-badge";
|
|
8
|
+
import { Button } from "@/design-system/primitives/button";
|
|
9
|
+
import { appRoutes } from "@/lib/app-routes";
|
|
10
|
+
import type { AuthenticatedPlatformSession } from "@/lib/platform/contracts";
|
|
11
|
+
|
|
12
|
+
function DashboardMetric({
|
|
13
|
+
label,
|
|
14
|
+
value,
|
|
15
|
+
}: {
|
|
16
|
+
label: string;
|
|
17
|
+
value: string;
|
|
18
|
+
}) {
|
|
19
|
+
return (
|
|
20
|
+
<PanelFrame tone="raised" radius="xl" padding="md" className="space-y-2">
|
|
21
|
+
<p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
|
|
22
|
+
{label}
|
|
23
|
+
</p>
|
|
24
|
+
<p className="text-sm font-semibold text-foreground">{value}</p>
|
|
25
|
+
</PanelFrame>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function TenantDashboard({
|
|
30
|
+
appName,
|
|
31
|
+
runtimeCommandExampleEnabled,
|
|
32
|
+
session,
|
|
33
|
+
}: {
|
|
34
|
+
appName: string;
|
|
35
|
+
runtimeCommandExampleEnabled: boolean;
|
|
36
|
+
session: AuthenticatedPlatformSession;
|
|
37
|
+
}) {
|
|
38
|
+
return (
|
|
39
|
+
<div className="grid gap-6">
|
|
40
|
+
<PanelFrame tone="floating" radius="xl" padding="lg" className="space-y-6">
|
|
41
|
+
<div className="space-y-2">
|
|
42
|
+
<p className="text-sm font-semibold uppercase tracking-widest text-muted-foreground">
|
|
43
|
+
Authenticated Workspace
|
|
44
|
+
</p>
|
|
45
|
+
<h2 className="text-3xl font-semibold tracking-tight">
|
|
46
|
+
{appName} ships with a reusable authenticated shell behind `/app`.
|
|
47
|
+
</h2>
|
|
48
|
+
<p className="max-w-3xl text-sm leading-7 text-muted-foreground">
|
|
49
|
+
This template is designed for Builder materialization into a writable
|
|
50
|
+
sandbox. Public storytelling lives at the root, while the
|
|
51
|
+
authenticated shell, tenant context controls, password settings,
|
|
52
|
+
route gating, and BFF auth boundary remain real under `/app`.
|
|
53
|
+
</p>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<div className="grid gap-3 md:grid-cols-3">
|
|
57
|
+
<DashboardMetric label="Signed-in user" value={session.user.username} />
|
|
58
|
+
<DashboardMetric
|
|
59
|
+
label="Active tenant"
|
|
60
|
+
value={session.active_tenant.tenant_name}
|
|
61
|
+
/>
|
|
62
|
+
<DashboardMetric
|
|
63
|
+
label="Membership count"
|
|
64
|
+
value={`${session.memberships.length}`}
|
|
65
|
+
/>
|
|
66
|
+
</div>
|
|
67
|
+
</PanelFrame>
|
|
68
|
+
|
|
69
|
+
<section className="grid gap-6 xl:grid-cols-[1fr,1fr]">
|
|
70
|
+
<PanelFrame tone="raised" radius="xl" padding="lg" className="space-y-4">
|
|
71
|
+
<div className="flex items-center gap-2">
|
|
72
|
+
<ShieldCheck className="size-5 text-primary" />
|
|
73
|
+
<h3 className="text-xl font-semibold tracking-tight">
|
|
74
|
+
Auth profile
|
|
75
|
+
</h3>
|
|
76
|
+
</div>
|
|
77
|
+
<div className="flex flex-wrap gap-3">
|
|
78
|
+
<StatusBadge tone="primary">platform_session_bff</StatusBadge>
|
|
79
|
+
<StatusBadge tone="info">Server-owned cookies</StatusBadge>
|
|
80
|
+
<StatusBadge tone="success">CSRF forwarding</StatusBadge>
|
|
81
|
+
</div>
|
|
82
|
+
<p className="text-sm leading-7 text-muted-foreground">
|
|
83
|
+
The browser talks only to this Next.js app. Upstream platform session
|
|
84
|
+
cookies and CSRF tokens remain server-owned inside route handlers.
|
|
85
|
+
Request-scoped tenant overrides stay scoped to feature actions unless
|
|
86
|
+
the explicit session-context APIs are used.
|
|
87
|
+
</p>
|
|
88
|
+
</PanelFrame>
|
|
89
|
+
|
|
90
|
+
<PanelFrame tone="raised" radius="xl" padding="lg" className="space-y-4">
|
|
91
|
+
<div className="flex items-center gap-2">
|
|
92
|
+
<Building2 className="size-5 text-primary" />
|
|
93
|
+
<h3 className="text-xl font-semibold tracking-tight">
|
|
94
|
+
Builder materialization
|
|
95
|
+
</h3>
|
|
96
|
+
</div>
|
|
97
|
+
<p className="text-sm leading-7 text-muted-foreground">
|
|
98
|
+
The canonical template bundle is meant to be copied into
|
|
99
|
+
`BuilderWorkspace.sandbox_root/app/` before an agent edits it. The
|
|
100
|
+
copied workspace becomes the writable app root; this source bundle stays
|
|
101
|
+
governed and read-only in normal authoring flows.
|
|
102
|
+
</p>
|
|
103
|
+
</PanelFrame>
|
|
104
|
+
</section>
|
|
105
|
+
|
|
106
|
+
<section className="grid gap-6 xl:grid-cols-[1fr,1fr]">
|
|
107
|
+
<PanelFrame tone="raised" radius="xl" padding="lg" className="space-y-4">
|
|
108
|
+
<div className="flex items-center gap-2">
|
|
109
|
+
<Blocks className="size-5 text-primary" />
|
|
110
|
+
<h3 className="text-xl font-semibold tracking-tight">
|
|
111
|
+
Scaffold contents
|
|
112
|
+
</h3>
|
|
113
|
+
</div>
|
|
114
|
+
<ul className="space-y-3 text-sm leading-6 text-muted-foreground">
|
|
115
|
+
<li>Design-system primitives, patterns, docs, and governance checks.</li>
|
|
116
|
+
<li>Public marketing, docs, and blog routes with a swappable content adapter.</li>
|
|
117
|
+
<li>Typed platform session BFF routes for login, context, and password flows.</li>
|
|
118
|
+
<li>Tenant-aware shell components ready for Builder-specific feature work.</li>
|
|
119
|
+
</ul>
|
|
120
|
+
</PanelFrame>
|
|
121
|
+
|
|
122
|
+
<PanelFrame tone="raised" radius="xl" padding="lg" className="space-y-4">
|
|
123
|
+
<div className="flex items-center gap-2">
|
|
124
|
+
<FolderKanban className="size-5 text-primary" />
|
|
125
|
+
<h3 className="text-xl font-semibold tracking-tight">
|
|
126
|
+
Optional example surface
|
|
127
|
+
</h3>
|
|
128
|
+
</div>
|
|
129
|
+
<p className="text-sm leading-7 text-muted-foreground">
|
|
130
|
+
The runtime-command example is bundled as optional sample code rather
|
|
131
|
+
than the template's default product identity.
|
|
132
|
+
</p>
|
|
133
|
+
{runtimeCommandExampleEnabled ? (
|
|
134
|
+
<Button asChild className="w-fit">
|
|
135
|
+
<Link href={appRoutes.runtimeCommandExample}>
|
|
136
|
+
Open runtime command example
|
|
137
|
+
</Link>
|
|
138
|
+
</Button>
|
|
139
|
+
) : (
|
|
140
|
+
<div className="space-y-2">
|
|
141
|
+
<StatusBadge tone="default">Disabled by default</StatusBadge>
|
|
142
|
+
<p className="text-sm leading-6 text-muted-foreground">
|
|
143
|
+
Set `MW_ENABLE_RUNTIME_COMMAND_EXAMPLE=true` in the materialized
|
|
144
|
+
workspace to enable the example route and its matching gateway
|
|
145
|
+
proxy handlers.
|
|
146
|
+
</p>
|
|
147
|
+
</div>
|
|
148
|
+
)}
|
|
149
|
+
</PanelFrame>
|
|
150
|
+
</section>
|
|
151
|
+
</div>
|
|
152
|
+
);
|
|
153
|
+
}
|