minutework 0.1.31 → 0.1.33
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 +33 -33
- package/README.md +34 -34
- package/assets/claude-local/CLAUDE.md.template +12 -12
- package/assets/claude-local/skills/README.md +3 -1
- package/assets/claude-local/skills/app-pack-authoring/SKILL.md +17 -4
- package/assets/claude-local/skills/capability-gap-reporting/SKILL.md +3 -3
- package/assets/claude-local/skills/contract-first-public-intake/SKILL.md +11 -3
- package/assets/claude-local/skills/generated-workspace-architecture/SKILL.md +12 -5
- package/assets/claude-local/skills/layering-and-import-modes/SKILL.md +2 -2
- package/assets/claude-local/skills/openclaw-skill-importer/SKILL.md +2 -2
- package/assets/claude-local/skills/project-overview-and-strategy/SKILL.md +8 -8
- package/assets/claude-local/skills/published-web-and-mw-core-site/SKILL.md +11 -8
- package/assets/claude-local/skills/standalone-mobile-client/SKILL.md +6 -5
- package/assets/claude-local/skills/vuilder-discovery-output-contract/SKILL.md +6 -6
- package/assets/claude-local/skills/workspace-guidance-refresh/SKILL.md +4 -4
- package/assets/templates/fastapi-sidecar/pyproject.toml +1 -1
- package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/main.py +1 -1
- package/assets/templates/mobile-app/.env.example +4 -4
- package/assets/templates/mobile-app/AGENTS.md +3 -3
- package/assets/templates/mobile-app/README.md +10 -10
- package/assets/templates/mobile-app/app/(app)/_layout.tsx +2 -2
- package/assets/templates/mobile-app/app/(app)/index.tsx +2 -2
- package/assets/templates/mobile-app/app/(auth)/login.tsx +3 -3
- package/assets/templates/mobile-app/app/_layout.tsx +1 -1
- package/assets/templates/mobile-app/babel.config.js +1 -1
- package/assets/templates/mobile-app/eas.json +1 -1
- package/assets/templates/mobile-app/expo-env.d.ts +1 -1
- package/assets/templates/mobile-app/metro.config.js +2 -2
- package/assets/templates/mobile-app/package.json +1 -1
- package/assets/templates/mobile-app/src/mw/client.ts +3 -3
- package/assets/templates/mobile-app/src/mw/contracts.ts +2 -2
- package/assets/templates/mobile-app/src/mw/endpoints.ts +2 -2
- package/assets/templates/mobile-app/src/mw/env.ts +4 -4
- package/assets/templates/mobile-app/src/mw/session.ts +1 -1
- package/assets/templates/mobile-app/template.json +1 -1
- package/assets/templates/mobile-app/tools/template/validate-template.mjs +2 -2
- package/assets/templates/mobile-app/tsconfig.json +1 -1
- package/assets/templates/next-tenant-app/.env.example +1 -1
- package/assets/templates/next-tenant-app/README.md +26 -138
- package/assets/templates/next-tenant-app/package.json +1 -0
- package/assets/templates/next-tenant-app/src/app/app/demo/page.tsx +15 -0
- package/assets/templates/next-tenant-app/src/app/app/layout.tsx +1 -4
- package/assets/templates/next-tenant-app/src/app/app/page.tsx +2 -17
- package/assets/templates/next-tenant-app/src/app/blog/[slug]/page.tsx +9 -67
- package/assets/templates/next-tenant-app/src/app/blog/page.tsx +10 -46
- package/assets/templates/next-tenant-app/src/app/docs/[...slug]/page.tsx +9 -65
- package/assets/templates/next-tenant-app/src/app/docs/page.tsx +10 -46
- package/assets/templates/next-tenant-app/src/app/layout.tsx +8 -10
- package/assets/templates/next-tenant-app/src/app/login/page.tsx +3 -23
- package/assets/templates/next-tenant-app/src/app/page.tsx +11 -44
- package/assets/templates/next-tenant-app/src/app/pricing/page.tsx +10 -44
- package/assets/templates/next-tenant-app/src/app/providers.tsx +2 -1
- package/assets/templates/next-tenant-app/src/app/robots.ts +7 -18
- package/assets/templates/next-tenant-app/src/app/sitemap.ts +4 -39
- package/assets/templates/next-tenant-app/src/features/auth/components/login-screen.tsx +97 -98
- package/assets/templates/next-tenant-app/src/features/dashboard/components/tenant-dashboard.tsx +43 -78
- package/assets/templates/next-tenant-app/src/features/demo/components/manifest-demo.tsx +89 -0
- package/assets/templates/next-tenant-app/src/features/public-shell/components/static-public-page.tsx +58 -0
- package/assets/templates/next-tenant-app/src/features/shell/components/private-app-shell.tsx +48 -552
- package/assets/templates/next-tenant-app/src/lib/app-routes.ts +2 -2
- package/assets/templates/next-tenant-app/src/lib/public-site.test.ts +1 -1
- package/assets/templates/next-tenant-app/src/lib/public-site.ts +5 -30
- package/assets/templates/next-tenant-app/src/mw/client.ts +18 -0
- package/assets/templates/next-tenant-app/src/mw/mock.test.ts +21 -0
- package/assets/templates/next-tenant-app/src/mw/mock.ts +35 -0
- package/assets/templates/next-tenant-app/src/mw/provider.tsx +17 -0
- package/assets/templates/next-tenant-app/template.json +3 -3
- package/assets/templates/next-tenant-app/template.schema.json +1 -0
- package/assets/templates/next-tenant-app/tools/template/validate-route-contract.mjs +4 -5
- package/assets/templates/next-tenant-app/tools/template/with-public-site-fixture.mjs +2 -2
- package/bin/minutework.js +1 -1
- package/dist/agent.js +7 -7
- package/dist/agent.js.map +1 -1
- package/dist/auth.js +7 -7
- package/dist/auth.js.map +1 -1
- package/dist/compile.js +5 -5
- package/dist/config.js +6 -6
- package/dist/config.js.map +1 -1
- package/dist/deploy.js +7 -7
- package/dist/deploy.js.map +1 -1
- package/dist/developer-client.js +2 -2
- package/dist/developer-client.js.map +1 -1
- package/dist/index.js +30 -30
- package/dist/index.js.map +1 -1
- package/dist/init.js +10 -10
- package/dist/init.js.map +1 -1
- package/dist/launcher.js +1 -1
- package/dist/launcher.js.map +1 -1
- package/dist/managed-engine.js +6 -6
- package/dist/managed-engine.js.map +1 -1
- package/dist/orchestrator-context.js +1 -1
- package/dist/orchestrator-context.js.map +1 -1
- package/dist/orchestrator.js +15 -15
- package/dist/orchestrator.js.map +1 -1
- package/dist/paths.js +1 -1
- package/dist/paths.js.map +1 -1
- package/dist/publish.js +3 -3
- package/dist/publish.js.map +1 -1
- package/dist/reporting.js +8 -8
- package/dist/reporting.js.map +1 -1
- package/dist/sandbox.js +5 -5
- package/dist/sandbox.js.map +1 -1
- package/dist/state.js +1 -1
- package/dist/state.js.map +1 -1
- package/dist/tokens.js +9 -9
- package/dist/tokens.js.map +1 -1
- package/dist/workspace-assets.js +6 -6
- package/dist/workspace-assets.js.map +1 -1
- package/dist/workspace.js +3 -3
- package/dist/workspace.js.map +1 -1
- package/package.json +3 -3
- package/vendor/workspace-mcp/context.d.ts +6 -6
- package/vendor/workspace-mcp/context.js +56 -56
- package/vendor/workspace-mcp/context.js.map +1 -1
- package/vendor/workspace-mcp/types.d.ts +4 -0
- package/assets/templates/next-tenant-app/src/app/(cms)/[...path]/page.tsx +0 -89
- package/assets/templates/next-tenant-app/src/app/api/auth/context/route.test.ts +0 -90
- package/assets/templates/next-tenant-app/src/app/api/auth/context/route.ts +0 -78
- package/assets/templates/next-tenant-app/src/app/api/auth/login/route.ts +0 -31
- package/assets/templates/next-tenant-app/src/app/api/auth/logout/route.ts +0 -16
- package/assets/templates/next-tenant-app/src/app/api/auth/password-change/route.test.ts +0 -79
- package/assets/templates/next-tenant-app/src/app/api/auth/password-change/route.ts +0 -40
- package/assets/templates/next-tenant-app/src/app/api/auth/password-status/route.test.ts +0 -42
- package/assets/templates/next-tenant-app/src/app/api/auth/password-status/route.ts +0 -29
- package/assets/templates/next-tenant-app/src/app/api/auth/session/route.ts +0 -26
- package/assets/templates/next-tenant-app/src/app/api/gateway/commands/[runId]/route.test.ts +0 -40
- package/assets/templates/next-tenant-app/src/app/api/gateway/commands/[runId]/route.ts +0 -47
- package/assets/templates/next-tenant-app/src/app/api/gateway/commands/route.test.ts +0 -43
- package/assets/templates/next-tenant-app/src/app/api/gateway/commands/route.ts +0 -45
- package/assets/templates/next-tenant-app/src/app/app/examples/runtime-commands/page.test.ts +0 -83
- package/assets/templates/next-tenant-app/src/app/app/examples/runtime-commands/page.tsx +0 -30
- package/assets/templates/next-tenant-app/src/app/app/page.test.ts +0 -62
- package/assets/templates/next-tenant-app/src/app/app/private-content-source.test.ts +0 -88
- package/assets/templates/next-tenant-app/src/app/blog/[slug]/page.test.ts +0 -70
- package/assets/templates/next-tenant-app/src/app/blog/page.test.ts +0 -46
- package/assets/templates/next-tenant-app/src/app/docs/[...slug]/page.test.ts +0 -70
- package/assets/templates/next-tenant-app/src/app/docs/page.test.ts +0 -46
- package/assets/templates/next-tenant-app/src/app/login/page.test.ts +0 -55
- package/assets/templates/next-tenant-app/src/app/page.test.ts +0 -90
- package/assets/templates/next-tenant-app/src/app/pricing/page.test.ts +0 -59
- package/assets/templates/next-tenant-app/src/app/robots.test.ts +0 -40
- package/assets/templates/next-tenant-app/src/app/sitemap.test.ts +0 -63
- package/assets/templates/next-tenant-app/src/features/examples/runtime-command-demo/components/runtime-command-demo.tsx +0 -342
- package/assets/templates/next-tenant-app/src/features/public-shell/components/content-article.tsx +0 -66
- package/assets/templates/next-tenant-app/src/features/public-shell/components/content-collection.tsx +0 -108
- package/assets/templates/next-tenant-app/src/features/public-shell/components/marketing-page-canvas.tsx +0 -111
- package/assets/templates/next-tenant-app/src/features/public-shell/components/public-site-shell.tsx +0 -111
- package/assets/templates/next-tenant-app/src/features/public-shell/components/section-renderer.test.ts +0 -38
- package/assets/templates/next-tenant-app/src/features/public-shell/components/section-renderer.tsx +0 -145
- package/assets/templates/next-tenant-app/src/lib/content/__fixtures__/public-site-snapshot.ts +0 -189
- package/assets/templates/next-tenant-app/src/lib/content/adapter.server.test.ts +0 -444
- package/assets/templates/next-tenant-app/src/lib/content/adapter.server.ts +0 -383
- package/assets/templates/next-tenant-app/src/lib/content/contracts.test.ts +0 -138
- package/assets/templates/next-tenant-app/src/lib/content/contracts.ts +0 -399
- package/assets/templates/next-tenant-app/src/lib/content/custom-adapter.ts +0 -5
- package/assets/templates/next-tenant-app/src/lib/content/empty-state.ts +0 -96
- package/assets/templates/next-tenant-app/src/lib/content/release-manifest.test.ts +0 -93
- package/assets/templates/next-tenant-app/src/lib/content/release-manifest.ts +0 -123
- package/assets/templates/next-tenant-app/src/lib/platform/auth.server.test.ts +0 -75
- package/assets/templates/next-tenant-app/src/lib/platform/auth.server.ts +0 -25
- package/assets/templates/next-tenant-app/src/lib/platform/client.server.test.ts +0 -170
- package/assets/templates/next-tenant-app/src/lib/platform/client.server.ts +0 -661
- package/assets/templates/next-tenant-app/src/lib/platform/contracts.ts +0 -131
- package/assets/templates/next-tenant-app/src/lib/platform/endpoints.server.ts +0 -34
- package/assets/templates/next-tenant-app/src/lib/platform/env.server.test.ts +0 -211
- package/assets/templates/next-tenant-app/src/lib/platform/env.server.ts +0 -151
- package/assets/templates/next-tenant-app/src/lib/platform/route-response.ts +0 -33
- package/assets/templates/next-tenant-app/src/lib/platform/session.server.ts +0 -108
package/assets/templates/next-tenant-app/src/features/dashboard/components/tenant-dashboard.tsx
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import Link from "next/link";
|
|
4
|
-
import {
|
|
4
|
+
import { ArrowRight, Database, ShieldCheck, UserRound } from "lucide-react";
|
|
5
|
+
import type { TenantCustomerSession } from "@minutework/web-auth";
|
|
5
6
|
|
|
6
7
|
import { PanelFrame } from "@/design-system/patterns/panel-frame";
|
|
7
8
|
import { StatusBadge } from "@/design-system/patterns/status-badge";
|
|
8
9
|
import { Button } from "@/design-system/primitives/button";
|
|
9
10
|
import { appRoutes } from "@/lib/app-routes";
|
|
10
|
-
import type { AuthenticatedPlatformSession } from "@/lib/platform/contracts";
|
|
11
11
|
|
|
12
12
|
function DashboardMetric({
|
|
13
13
|
label,
|
|
@@ -28,40 +28,32 @@ function DashboardMetric({
|
|
|
28
28
|
|
|
29
29
|
export function TenantDashboard({
|
|
30
30
|
appName,
|
|
31
|
-
runtimeCommandExampleEnabled,
|
|
32
31
|
session,
|
|
33
32
|
}: {
|
|
34
33
|
appName: string;
|
|
35
|
-
|
|
36
|
-
session: AuthenticatedPlatformSession;
|
|
34
|
+
session: TenantCustomerSession;
|
|
37
35
|
}) {
|
|
38
36
|
return (
|
|
39
37
|
<div className="grid gap-6">
|
|
40
38
|
<PanelFrame tone="floating" radius="xl" padding="lg" className="space-y-6">
|
|
41
39
|
<div className="space-y-2">
|
|
42
|
-
<p className="text-sm font-semibold uppercase tracking-widest text-muted-foreground">
|
|
43
|
-
Authenticated Workspace
|
|
44
|
-
</p>
|
|
45
40
|
<h2 className="text-3xl font-semibold tracking-tight">
|
|
46
|
-
{appName}
|
|
41
|
+
{appName} workspace
|
|
47
42
|
</h2>
|
|
48
43
|
<p className="max-w-3xl text-sm leading-7 text-muted-foreground">
|
|
49
|
-
|
|
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`.
|
|
44
|
+
Customer session state is loaded through the MinuteWork web auth SDK.
|
|
53
45
|
</p>
|
|
54
46
|
</div>
|
|
55
47
|
|
|
56
48
|
<div className="grid gap-3 md:grid-cols-3">
|
|
57
|
-
<DashboardMetric label="Signed-in user" value={session.user.username} />
|
|
58
49
|
<DashboardMetric
|
|
59
|
-
label="
|
|
60
|
-
value={session.
|
|
50
|
+
label="Customer"
|
|
51
|
+
value={session.user?.display_name || session.user?.email || "Customer"}
|
|
61
52
|
/>
|
|
53
|
+
<DashboardMetric label="Tenant" value={session.tenant.name} />
|
|
62
54
|
<DashboardMetric
|
|
63
|
-
label="
|
|
64
|
-
value={
|
|
55
|
+
label="Role"
|
|
56
|
+
value={session.customer_membership?.roles.join(", ") || "customer"}
|
|
65
57
|
/>
|
|
66
58
|
</div>
|
|
67
59
|
</PanelFrame>
|
|
@@ -71,85 +63,58 @@ export function TenantDashboard({
|
|
|
71
63
|
<div className="flex items-center gap-2">
|
|
72
64
|
<ShieldCheck className="size-5 text-primary" />
|
|
73
65
|
<h3 className="text-xl font-semibold tracking-tight">
|
|
74
|
-
|
|
66
|
+
Tenant web auth
|
|
75
67
|
</h3>
|
|
76
68
|
</div>
|
|
77
69
|
<div className="flex flex-wrap gap-3">
|
|
78
|
-
<StatusBadge tone="primary">
|
|
79
|
-
<StatusBadge tone="info">
|
|
80
|
-
<StatusBadge tone="success">CSRF
|
|
70
|
+
<StatusBadge tone="primary">tenant_web_auth_sdk</StatusBadge>
|
|
71
|
+
<StatusBadge tone="info">HttpOnly cookies</StatusBadge>
|
|
72
|
+
<StatusBadge tone="success">CSRF protected</StatusBadge>
|
|
81
73
|
</div>
|
|
82
74
|
<p className="text-sm leading-7 text-muted-foreground">
|
|
83
|
-
|
|
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.
|
|
75
|
+
Customer sessions stay same-origin through /_mw.
|
|
87
76
|
</p>
|
|
88
77
|
</PanelFrame>
|
|
89
78
|
|
|
90
79
|
<PanelFrame tone="raised" radius="xl" padding="lg" className="space-y-4">
|
|
91
80
|
<div className="flex items-center gap-2">
|
|
92
|
-
<
|
|
81
|
+
<Database className="size-5 text-primary" />
|
|
93
82
|
<h3 className="text-xl font-semibold tracking-tight">
|
|
94
|
-
|
|
83
|
+
Manifest API
|
|
95
84
|
</h3>
|
|
96
85
|
</div>
|
|
97
86
|
<p className="text-sm leading-7 text-muted-foreground">
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
Builder flows that writable root lives at
|
|
101
|
-
`BuilderWorkspace.sandbox_root/app/`; in CLI scaffolds the same
|
|
102
|
-
starter lands in `tenant-app/`. This source bundle stays governed
|
|
103
|
-
and read-only in normal authoring flows.
|
|
87
|
+
Query and action calls go through the SDK and are authorized as
|
|
88
|
+
`tenant_customer`.
|
|
104
89
|
</p>
|
|
90
|
+
<Button asChild className="w-fit">
|
|
91
|
+
<Link href={appRoutes.demo}>
|
|
92
|
+
Open demo
|
|
93
|
+
<ArrowRight className="size-4" />
|
|
94
|
+
</Link>
|
|
95
|
+
</Button>
|
|
105
96
|
</PanelFrame>
|
|
106
97
|
</section>
|
|
107
98
|
|
|
108
|
-
<
|
|
109
|
-
<
|
|
110
|
-
<
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
<PanelFrame tone="raised" radius="xl" padding="lg" className="space-y-4">
|
|
125
|
-
<div className="flex items-center gap-2">
|
|
126
|
-
<FolderKanban className="size-5 text-primary" />
|
|
127
|
-
<h3 className="text-xl font-semibold tracking-tight">
|
|
128
|
-
Optional example surface
|
|
129
|
-
</h3>
|
|
130
|
-
</div>
|
|
131
|
-
<p className="text-sm leading-7 text-muted-foreground">
|
|
132
|
-
The runtime-command example is bundled as optional sample code rather
|
|
133
|
-
than the template's default product identity.
|
|
134
|
-
</p>
|
|
135
|
-
{runtimeCommandExampleEnabled ? (
|
|
136
|
-
<Button asChild className="w-fit">
|
|
137
|
-
<Link href={appRoutes.runtimeCommandExample}>
|
|
138
|
-
Open runtime command example
|
|
139
|
-
</Link>
|
|
140
|
-
</Button>
|
|
141
|
-
) : (
|
|
142
|
-
<div className="space-y-2">
|
|
143
|
-
<StatusBadge tone="default">Disabled by default</StatusBadge>
|
|
144
|
-
<p className="text-sm leading-6 text-muted-foreground">
|
|
145
|
-
Set `MW_ENABLE_RUNTIME_COMMAND_EXAMPLE=true` in the materialized
|
|
146
|
-
workspace to enable the example route and its matching gateway
|
|
147
|
-
proxy handlers.
|
|
148
|
-
</p>
|
|
149
|
-
</div>
|
|
99
|
+
<PanelFrame tone="raised" radius="xl" padding="lg" className="space-y-4">
|
|
100
|
+
<div className="flex items-center gap-2">
|
|
101
|
+
<UserRound className="size-5 text-primary" />
|
|
102
|
+
<h3 className="text-xl font-semibold tracking-tight">
|
|
103
|
+
Session payload
|
|
104
|
+
</h3>
|
|
105
|
+
</div>
|
|
106
|
+
<pre className="overflow-auto rounded-md bg-muted p-4 text-xs text-muted-foreground">
|
|
107
|
+
{JSON.stringify(
|
|
108
|
+
{
|
|
109
|
+
principal_kind: session.principal_kind,
|
|
110
|
+
tenant_id: session.tenant.id,
|
|
111
|
+
customer_membership_id: session.customer_membership?.id,
|
|
112
|
+
},
|
|
113
|
+
null,
|
|
114
|
+
2,
|
|
150
115
|
)}
|
|
151
|
-
</
|
|
152
|
-
</
|
|
116
|
+
</pre>
|
|
117
|
+
</PanelFrame>
|
|
153
118
|
</div>
|
|
154
119
|
);
|
|
155
120
|
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { Database, Play, RefreshCcw } from "lucide-react";
|
|
5
|
+
|
|
6
|
+
import { PanelFrame } from "@/design-system/patterns/panel-frame";
|
|
7
|
+
import { Button } from "@/design-system/primitives/button";
|
|
8
|
+
import { Input } from "@/design-system/primitives/input";
|
|
9
|
+
import { createIdempotencyKey, mw } from "@/mw/client";
|
|
10
|
+
|
|
11
|
+
type DemoResult = {
|
|
12
|
+
data?: unknown;
|
|
13
|
+
count?: number;
|
|
14
|
+
created?: boolean;
|
|
15
|
+
idempotency_key?: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export function ManifestDemo() {
|
|
19
|
+
const [title, setTitle] = useState("Demo record");
|
|
20
|
+
const [result, setResult] = useState<DemoResult | null>(null);
|
|
21
|
+
const [error, setError] = useState("");
|
|
22
|
+
const [pending, setPending] = useState(false);
|
|
23
|
+
|
|
24
|
+
async function runQuery() {
|
|
25
|
+
setPending(true);
|
|
26
|
+
setError("");
|
|
27
|
+
try {
|
|
28
|
+
setResult(await mw.query<DemoResult>("demo.list", { limit: 10 }));
|
|
29
|
+
} catch (caught) {
|
|
30
|
+
setError(caught instanceof Error ? caught.message : "Query failed.");
|
|
31
|
+
} finally {
|
|
32
|
+
setPending(false);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function runAction() {
|
|
37
|
+
setPending(true);
|
|
38
|
+
setError("");
|
|
39
|
+
try {
|
|
40
|
+
setResult(
|
|
41
|
+
await mw.action<DemoResult>(
|
|
42
|
+
"demo.create",
|
|
43
|
+
{ title, status: "new" },
|
|
44
|
+
{ idempotencyKey: createIdempotencyKey("demo-create") },
|
|
45
|
+
),
|
|
46
|
+
);
|
|
47
|
+
} catch (caught) {
|
|
48
|
+
setError(caught instanceof Error ? caught.message : "Action failed.");
|
|
49
|
+
} finally {
|
|
50
|
+
setPending(false);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<div className="grid gap-6">
|
|
56
|
+
<PanelFrame tone="floating" radius="xl" padding="lg" className="space-y-5">
|
|
57
|
+
<div className="flex items-center gap-2">
|
|
58
|
+
<Database className="size-5 text-primary" />
|
|
59
|
+
<h2 className="text-2xl font-semibold tracking-tight">
|
|
60
|
+
Manifest query and action
|
|
61
|
+
</h2>
|
|
62
|
+
</div>
|
|
63
|
+
<div className="grid gap-3 md:grid-cols-[1fr,auto,auto]">
|
|
64
|
+
<Input
|
|
65
|
+
value={title}
|
|
66
|
+
onChange={(event) => setTitle(event.target.value)}
|
|
67
|
+
className="h-11"
|
|
68
|
+
aria-label="Demo title"
|
|
69
|
+
/>
|
|
70
|
+
<Button type="button" variant="outline" onClick={runQuery} disabled={pending}>
|
|
71
|
+
<RefreshCcw className="size-4" />
|
|
72
|
+
Query
|
|
73
|
+
</Button>
|
|
74
|
+
<Button type="button" onClick={runAction} disabled={pending}>
|
|
75
|
+
<Play className="size-4" />
|
|
76
|
+
Action
|
|
77
|
+
</Button>
|
|
78
|
+
</div>
|
|
79
|
+
{error ? <p className="text-sm text-destructive">{error}</p> : null}
|
|
80
|
+
</PanelFrame>
|
|
81
|
+
|
|
82
|
+
<PanelFrame tone="raised" radius="xl" padding="lg">
|
|
83
|
+
<pre className="min-h-40 overflow-auto rounded-md bg-muted p-4 text-xs text-muted-foreground">
|
|
84
|
+
{result ? JSON.stringify(result, null, 2) : "No result yet"}
|
|
85
|
+
</pre>
|
|
86
|
+
</PanelFrame>
|
|
87
|
+
</div>
|
|
88
|
+
);
|
|
89
|
+
}
|
package/assets/templates/next-tenant-app/src/features/public-shell/components/static-public-page.tsx
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import Link from "next/link";
|
|
2
|
+
import { ArrowRight } from "lucide-react";
|
|
3
|
+
|
|
4
|
+
import { Button } from "@/design-system/primitives/button";
|
|
5
|
+
import { appRoutes } from "@/lib/app-routes";
|
|
6
|
+
|
|
7
|
+
export function StaticPublicPage({
|
|
8
|
+
eyebrow,
|
|
9
|
+
title,
|
|
10
|
+
body,
|
|
11
|
+
}: {
|
|
12
|
+
eyebrow: string;
|
|
13
|
+
title: string;
|
|
14
|
+
body: string;
|
|
15
|
+
}) {
|
|
16
|
+
return (
|
|
17
|
+
<main className="min-h-screen bg-background text-foreground">
|
|
18
|
+
<div className="mx-auto flex min-h-screen max-w-6xl flex-col px-6 py-6">
|
|
19
|
+
<nav className="flex items-center justify-between">
|
|
20
|
+
<Link className="text-sm font-semibold text-foreground" href={appRoutes.publicHome}>
|
|
21
|
+
Tenant App
|
|
22
|
+
</Link>
|
|
23
|
+
<div className="flex items-center gap-2">
|
|
24
|
+
<Button asChild variant="ghost">
|
|
25
|
+
<Link href={appRoutes.pricing}>Pricing</Link>
|
|
26
|
+
</Button>
|
|
27
|
+
<Button asChild variant="ghost">
|
|
28
|
+
<Link href={appRoutes.docsIndex}>Docs</Link>
|
|
29
|
+
</Button>
|
|
30
|
+
<Button asChild>
|
|
31
|
+
<Link href={appRoutes.login}>Log in</Link>
|
|
32
|
+
</Button>
|
|
33
|
+
</div>
|
|
34
|
+
</nav>
|
|
35
|
+
|
|
36
|
+
<section className="grid flex-1 content-center gap-8 py-16">
|
|
37
|
+
<div className="max-w-3xl space-y-5">
|
|
38
|
+
<p className="text-sm font-semibold uppercase tracking-widest text-muted-foreground">
|
|
39
|
+
{eyebrow}
|
|
40
|
+
</p>
|
|
41
|
+
<h1 className="text-5xl font-semibold tracking-tight text-balance sm:text-6xl">
|
|
42
|
+
{title}
|
|
43
|
+
</h1>
|
|
44
|
+
<p className="max-w-2xl text-lg leading-8 text-muted-foreground">
|
|
45
|
+
{body}
|
|
46
|
+
</p>
|
|
47
|
+
<Button asChild className="w-fit">
|
|
48
|
+
<Link href={appRoutes.login}>
|
|
49
|
+
Continue
|
|
50
|
+
<ArrowRight className="size-4" />
|
|
51
|
+
</Link>
|
|
52
|
+
</Button>
|
|
53
|
+
</div>
|
|
54
|
+
</section>
|
|
55
|
+
</div>
|
|
56
|
+
</main>
|
|
57
|
+
);
|
|
58
|
+
}
|