@forgeailab/create-spark 0.1.1 → 0.1.2
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/package.json +7 -4
- package/packs/README.md +132 -0
- package/packs/ai-anthropic/files/app/api/ai/route.ts +57 -0
- package/packs/ai-anthropic/files/lib/anthropic.ts +15 -0
- package/packs/ai-anthropic/pack.toml +32 -0
- package/packs/ai-anthropic/skills/ai-feature-patterns/SKILL.md +87 -0
- package/packs/ai-anthropic/tasks.yaml +9 -0
- package/packs/ai-openai/files/app/api/ai-openai/route.ts +55 -0
- package/packs/ai-openai/files/lib/openai.ts +21 -0
- package/packs/ai-openai/pack.toml +30 -0
- package/packs/ai-openai/tasks.yaml +9 -0
- package/packs/analytics-posthog/files/components/PostHogProvider.tsx +19 -0
- package/packs/analytics-posthog/files/lib/posthog/client.ts +20 -0
- package/packs/analytics-posthog/files/lib/posthog/server.ts +24 -0
- package/packs/analytics-posthog/pack.toml +35 -0
- package/packs/analytics-posthog/tasks.yaml +15 -0
- package/packs/auth-better-auth/files/app/(auth)/login/page.tsx +58 -0
- package/packs/auth-better-auth/files/app/api/auth/[...all]/route.ts +4 -0
- package/packs/auth-better-auth/files/lib/auth.ts +21 -0
- package/packs/auth-better-auth/pack.toml +32 -0
- package/packs/auth-better-auth/tasks.yaml +10 -0
- package/packs/auth-better-auth-pg/files/app/api/auth/[...all]/route.ts +4 -0
- package/packs/auth-better-auth-pg/files/lib/auth.ts +86 -0
- package/packs/auth-better-auth-pg/pack.toml +32 -0
- package/packs/auth-better-auth-pg/tasks.yaml +17 -0
- package/packs/auth-supabase/files/app/(auth)/login/page.tsx +64 -0
- package/packs/auth-supabase/files/app/auth/callback/route.ts +15 -0
- package/packs/auth-supabase/files/middleware.ts +41 -0
- package/packs/auth-supabase/pack.toml +34 -0
- package/packs/auth-supabase/tasks.yaml +10 -0
- package/packs/db-postgres/files/compose/postgres.yml +28 -0
- package/packs/db-postgres/files/docker-compose.include.yml +1 -0
- package/packs/db-postgres/files/docker-compose.yml +6 -0
- package/packs/db-postgres/files/drizzle.config.ts +10 -0
- package/packs/db-postgres/files/lib/db/index.ts +10 -0
- package/packs/db-postgres/files/lib/db/schema.ts +11 -0
- package/packs/db-postgres/pack.toml +53 -0
- package/packs/db-postgres/tasks.yaml +11 -0
- package/packs/db-sqlite/files/drizzle.config.ts +10 -0
- package/packs/db-sqlite/files/lib/db.ts +8 -0
- package/packs/db-sqlite/files/lib/schema.ts +13 -0
- package/packs/db-sqlite/pack.toml +34 -0
- package/packs/db-sqlite/tasks.yaml +6 -0
- package/packs/db-supabase/files/lib/supabase/client.ts +8 -0
- package/packs/db-supabase/files/lib/supabase/server.ts +27 -0
- package/packs/db-supabase/pack.toml +32 -0
- package/packs/db-supabase/skills/supabase-patterns/SKILL.md +82 -0
- package/packs/db-supabase/tasks.yaml +6 -0
- package/packs/deploy-vercel/files/docs/deploy.md +21 -0
- package/packs/deploy-vercel/files/vercel.json +4 -0
- package/packs/deploy-vercel/pack.toml +30 -0
- package/packs/deploy-vercel/tasks.yaml +14 -0
- package/packs/docker-compose-dev/files/.env.docker.example +2 -0
- package/packs/docker-compose-dev/files/compose/redis.yml +17 -0
- package/packs/docker-compose-dev/files/docker-compose.include.yml +1 -0
- package/packs/docker-compose-dev/files/docker-compose.yml +6 -0
- package/packs/docker-compose-dev/pack.toml +38 -0
- package/packs/docker-compose-dev/tasks.yaml +9 -0
- package/packs/email-resend/files/app/api/email/test/route.ts +38 -0
- package/packs/email-resend/files/emails/welcome.tsx +66 -0
- package/packs/email-resend/files/lib/email.ts +40 -0
- package/packs/email-resend/pack.toml +34 -0
- package/packs/email-resend/tasks.yaml +9 -0
- package/packs/example/pack.toml +69 -0
- package/packs/payments-stripe/files/app/api/billing-portal/route.ts +24 -0
- package/packs/payments-stripe/files/app/api/checkout/route.ts +58 -0
- package/packs/payments-stripe/files/app/api/webhooks/stripe/route.ts +84 -0
- package/packs/payments-stripe/files/lib/stripe.ts +60 -0
- package/packs/payments-stripe/pack.toml +49 -0
- package/packs/payments-stripe/skills/stripe-patterns/SKILL.md +93 -0
- package/packs/payments-stripe/tasks.yaml +16 -0
- package/packs/sync-zero/files/components/ZeroProvider.tsx +3 -0
- package/packs/sync-zero/files/compose/zero-cache.yml +26 -0
- package/packs/sync-zero/files/docker-compose.include.yml +1 -0
- package/packs/sync-zero/files/docker-compose.yml +6 -0
- package/packs/sync-zero/files/lib/zero/client.ts +18 -0
- package/packs/sync-zero/files/lib/zero/schema.ts +17 -0
- package/packs/sync-zero/files/zero.config.ts +26 -0
- package/packs/sync-zero/pack.toml +61 -0
- package/packs/sync-zero/skills/zero-patterns/SKILL.md +69 -0
- package/packs/sync-zero/tasks.yaml +16 -0
- package/packs/testing-playwright/files/e2e/example.spec.ts +7 -0
- package/packs/testing-playwright/files/playwright.config.ts +33 -0
- package/packs/testing-playwright/pack.toml +25 -0
- package/packs/testing-playwright/tasks.yaml +9 -0
- package/packs/ui-shadcn/files/app/globals.css +56 -0
- package/packs/ui-shadcn/files/components/ui/button.tsx +47 -0
- package/packs/ui-shadcn/files/components/ui/card.tsx +33 -0
- package/packs/ui-shadcn/files/lib/utils.ts +6 -0
- package/packs/ui-shadcn/files/postcss.config.mjs +7 -0
- package/packs/ui-shadcn/files/tailwind.config.ts +57 -0
- package/packs/ui-shadcn/pack.toml +44 -0
- package/packs/ui-shadcn/skills/shadcn-dashboard-patterns/SKILL.md +85 -0
- package/packs/ui-shadcn/tasks.yaml +6 -0
- package/presets/docs-site.toml +4 -0
- package/presets/internal-tool.toml +4 -0
- package/presets/lean-saas.toml +4 -0
- package/presets/local-ai-mvp.toml +4 -0
- package/presets/saas-classic.toml +4 -0
- package/src/paths.ts +22 -4
- package/templates/README.md +43 -0
- package/templates/astro/README.md +3 -0
- package/templates/astro/template.toml +4 -0
- package/templates/astro-starlight/README.md +3 -0
- package/templates/astro-starlight/template.toml +4 -0
- package/templates/nextjs/.ai/architecture.md +13 -0
- package/templates/nextjs/.ai/board.md +7 -0
- package/templates/nextjs/.ai/product-spec.md +11 -0
- package/templates/nextjs/.claude/skills/.gitkeep +0 -0
- package/templates/nextjs/.codex/skills/.gitkeep +0 -0
- package/templates/nextjs/AGENTS.md +95 -0
- package/templates/nextjs/CLAUDE.md +3 -0
- package/templates/nextjs/README.md +20 -0
- package/templates/nextjs/anvil.config.json +4 -0
- package/templates/nextjs/app/(app)/home/page.tsx +43 -0
- package/templates/nextjs/app/(app)/home/posts-panel.tsx +83 -0
- package/templates/nextjs/app/(app)/layout.tsx +12 -0
- package/templates/nextjs/app/(auth)/login/page.tsx +97 -0
- package/templates/nextjs/app/globals.css +23 -0
- package/templates/nextjs/app/layout.tsx +20 -0
- package/templates/nextjs/app/page.tsx +39 -0
- package/templates/nextjs/lib/auth-placeholder.ts +21 -0
- package/templates/nextjs/lib/posts-placeholder.ts +30 -0
- package/templates/nextjs/next.config.ts +5 -0
- package/templates/nextjs/package.json +26 -0
- package/templates/nextjs/postcss.config.mjs +7 -0
- package/templates/nextjs/template.toml +4 -0
- package/templates/nextjs/tsconfig.json +27 -0
- package/templates/nextjs/types/post.ts +13 -0
- package/templates/one/README.md +5 -0
- package/templates/one/template.toml +4 -0
- package/templates/vite-react/README.md +3 -0
- package/templates/vite-react/template.toml +4 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState, type FormEvent } from 'react';
|
|
4
|
+
import { usePosts } from '@/lib/posts-placeholder';
|
|
5
|
+
|
|
6
|
+
export function PostsPanel() {
|
|
7
|
+
const { posts, createPost } = usePosts();
|
|
8
|
+
const [title, setTitle] = useState('');
|
|
9
|
+
const [body, setBody] = useState('');
|
|
10
|
+
const [pending, setPending] = useState(false);
|
|
11
|
+
|
|
12
|
+
async function onSubmit(event: FormEvent<HTMLFormElement>) {
|
|
13
|
+
event.preventDefault();
|
|
14
|
+
if (!title.trim()) return;
|
|
15
|
+
setPending(true);
|
|
16
|
+
try {
|
|
17
|
+
await createPost({ title: title.trim(), body: body.trim() });
|
|
18
|
+
setTitle('');
|
|
19
|
+
setBody('');
|
|
20
|
+
} finally {
|
|
21
|
+
setPending(false);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<div className="mt-3 space-y-4">
|
|
27
|
+
<form
|
|
28
|
+
onSubmit={onSubmit}
|
|
29
|
+
className="rounded-xl border border-slate-200 bg-white p-4 shadow-sm"
|
|
30
|
+
>
|
|
31
|
+
<input
|
|
32
|
+
value={title}
|
|
33
|
+
onChange={(e) => setTitle(e.target.value)}
|
|
34
|
+
placeholder="Post title"
|
|
35
|
+
className="block w-full rounded-md border border-slate-300 px-3 py-2 text-sm placeholder:text-slate-400 focus:border-slate-900 focus:outline-none focus:ring-1 focus:ring-slate-900"
|
|
36
|
+
/>
|
|
37
|
+
<textarea
|
|
38
|
+
value={body}
|
|
39
|
+
onChange={(e) => setBody(e.target.value)}
|
|
40
|
+
placeholder="Write something…"
|
|
41
|
+
rows={2}
|
|
42
|
+
className="mt-2 block w-full rounded-md border border-slate-300 px-3 py-2 text-sm placeholder:text-slate-400 focus:border-slate-900 focus:outline-none focus:ring-1 focus:ring-slate-900"
|
|
43
|
+
/>
|
|
44
|
+
<div className="mt-3 flex items-center justify-end">
|
|
45
|
+
<button
|
|
46
|
+
type="submit"
|
|
47
|
+
disabled={pending || !title.trim()}
|
|
48
|
+
className="inline-flex items-center justify-center rounded-md bg-slate-900 px-4 py-1.5 text-sm font-medium text-white shadow-sm transition hover:bg-slate-800 disabled:cursor-not-allowed disabled:opacity-50"
|
|
49
|
+
>
|
|
50
|
+
{pending ? 'Posting…' : 'Post'}
|
|
51
|
+
</button>
|
|
52
|
+
</div>
|
|
53
|
+
</form>
|
|
54
|
+
|
|
55
|
+
{posts.length === 0 ? (
|
|
56
|
+
<div className="rounded-xl border border-dashed border-slate-300 bg-white/60 px-4 py-8 text-center text-sm text-slate-500">
|
|
57
|
+
No posts yet. Install the{' '}
|
|
58
|
+
<code className="rounded bg-slate-100 px-1">sync-zero</code> pack to
|
|
59
|
+
persist and sync posts in real time.
|
|
60
|
+
</div>
|
|
61
|
+
) : (
|
|
62
|
+
<ul className="space-y-2">
|
|
63
|
+
{posts.map((post) => (
|
|
64
|
+
<li
|
|
65
|
+
key={post.id}
|
|
66
|
+
className="rounded-xl border border-slate-200 bg-white p-4 shadow-sm"
|
|
67
|
+
>
|
|
68
|
+
<h3 className="text-sm font-semibold text-slate-900">
|
|
69
|
+
{post.title}
|
|
70
|
+
</h3>
|
|
71
|
+
{post.body && (
|
|
72
|
+
<p className="mt-1 text-sm text-slate-600">{post.body}</p>
|
|
73
|
+
)}
|
|
74
|
+
<p className="mt-2 text-xs text-slate-400">
|
|
75
|
+
{post.createdAt.toLocaleString()}
|
|
76
|
+
</p>
|
|
77
|
+
</li>
|
|
78
|
+
))}
|
|
79
|
+
</ul>
|
|
80
|
+
)}
|
|
81
|
+
</div>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
// Placeholder authed-route layout.
|
|
4
|
+
//
|
|
5
|
+
// The `auth-better-auth` pack will replace this with a server-side guard that
|
|
6
|
+
// calls `getSessionUser()` and `redirect('/login')` when there is no session.
|
|
7
|
+
// Until then this just renders children so the scaffold compiles and runs.
|
|
8
|
+
export default function AppLayout({ children }: { children: ReactNode }) {
|
|
9
|
+
return (
|
|
10
|
+
<div className="min-h-screen bg-slate-50 text-slate-900">{children}</div>
|
|
11
|
+
);
|
|
12
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import Link from 'next/link';
|
|
2
|
+
|
|
3
|
+
// NOTE: no auth wired yet. The `action` and the GitHub button are placeholders.
|
|
4
|
+
// The `auth-better-auth` pack will:
|
|
5
|
+
// - replace `action="/api/auth/sign-in"` with the real route handler path
|
|
6
|
+
// - replace the GitHub button's form with a real OAuth start endpoint
|
|
7
|
+
// - add `app/api/auth/[...all]/route.ts` and `lib/auth.ts`
|
|
8
|
+
export default function LoginPage() {
|
|
9
|
+
return (
|
|
10
|
+
<main className="min-h-screen flex items-center justify-center bg-slate-50 px-6 py-16">
|
|
11
|
+
<div className="w-full max-w-sm">
|
|
12
|
+
<div className="mb-8 text-center">
|
|
13
|
+
<h1 className="text-2xl font-semibold tracking-tight text-slate-900">
|
|
14
|
+
Welcome back
|
|
15
|
+
</h1>
|
|
16
|
+
<p className="mt-1 text-sm text-slate-600">
|
|
17
|
+
Sign in to continue to your workspace.
|
|
18
|
+
</p>
|
|
19
|
+
</div>
|
|
20
|
+
<div className="rounded-xl border border-slate-200 bg-white p-6 shadow-sm">
|
|
21
|
+
<form action="/api/auth/sign-in" method="post" className="space-y-4">
|
|
22
|
+
<div>
|
|
23
|
+
<label
|
|
24
|
+
htmlFor="email"
|
|
25
|
+
className="block text-xs font-medium text-slate-700"
|
|
26
|
+
>
|
|
27
|
+
Email
|
|
28
|
+
</label>
|
|
29
|
+
<input
|
|
30
|
+
id="email"
|
|
31
|
+
name="email"
|
|
32
|
+
type="email"
|
|
33
|
+
autoComplete="email"
|
|
34
|
+
required
|
|
35
|
+
className="mt-1 block w-full rounded-md border border-slate-300 bg-white px-3 py-2 text-sm text-slate-900 shadow-sm placeholder:text-slate-400 focus:border-slate-900 focus:outline-none focus:ring-1 focus:ring-slate-900"
|
|
36
|
+
placeholder="you@example.com"
|
|
37
|
+
/>
|
|
38
|
+
</div>
|
|
39
|
+
<div>
|
|
40
|
+
<label
|
|
41
|
+
htmlFor="password"
|
|
42
|
+
className="block text-xs font-medium text-slate-700"
|
|
43
|
+
>
|
|
44
|
+
Password
|
|
45
|
+
</label>
|
|
46
|
+
<input
|
|
47
|
+
id="password"
|
|
48
|
+
name="password"
|
|
49
|
+
type="password"
|
|
50
|
+
autoComplete="current-password"
|
|
51
|
+
required
|
|
52
|
+
className="mt-1 block w-full rounded-md border border-slate-300 bg-white px-3 py-2 text-sm text-slate-900 shadow-sm placeholder:text-slate-400 focus:border-slate-900 focus:outline-none focus:ring-1 focus:ring-slate-900"
|
|
53
|
+
placeholder="••••••••"
|
|
54
|
+
/>
|
|
55
|
+
</div>
|
|
56
|
+
<button
|
|
57
|
+
type="submit"
|
|
58
|
+
className="w-full rounded-md bg-slate-900 px-4 py-2 text-sm font-medium text-white shadow-sm transition hover:bg-slate-800 focus:outline-none focus:ring-2 focus:ring-slate-900 focus:ring-offset-2"
|
|
59
|
+
>
|
|
60
|
+
Sign in
|
|
61
|
+
</button>
|
|
62
|
+
</form>
|
|
63
|
+
<div className="relative my-5">
|
|
64
|
+
<div className="absolute inset-0 flex items-center">
|
|
65
|
+
<div className="w-full border-t border-slate-200" />
|
|
66
|
+
</div>
|
|
67
|
+
<div className="relative flex justify-center text-xs uppercase">
|
|
68
|
+
<span className="bg-white px-2 text-slate-500">or</span>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
<form action="/api/auth/sign-in/github" method="post">
|
|
72
|
+
<button
|
|
73
|
+
type="submit"
|
|
74
|
+
className="inline-flex w-full items-center justify-center gap-2 rounded-md border border-slate-300 bg-white px-4 py-2 text-sm font-medium text-slate-800 shadow-sm transition hover:bg-slate-50"
|
|
75
|
+
>
|
|
76
|
+
<svg
|
|
77
|
+
aria-hidden="true"
|
|
78
|
+
viewBox="0 0 24 24"
|
|
79
|
+
className="h-4 w-4"
|
|
80
|
+
fill="currentColor"
|
|
81
|
+
>
|
|
82
|
+
<path d="M12 .5C5.65.5.5 5.65.5 12c0 5.08 3.29 9.39 7.86 10.91.58.11.79-.25.79-.56v-2c-3.2.7-3.87-1.37-3.87-1.37-.52-1.33-1.28-1.69-1.28-1.69-1.05-.72.08-.7.08-.7 1.16.08 1.77 1.19 1.77 1.19 1.03 1.77 2.7 1.26 3.36.96.1-.75.4-1.26.73-1.55-2.55-.29-5.24-1.28-5.24-5.7 0-1.26.45-2.29 1.19-3.1-.12-.29-.52-1.46.11-3.04 0 0 .97-.31 3.18 1.18a11 11 0 015.79 0c2.2-1.49 3.17-1.18 3.17-1.18.63 1.58.23 2.75.12 3.04.74.81 1.19 1.84 1.19 3.1 0 4.43-2.69 5.41-5.25 5.69.41.36.78 1.06.78 2.14v3.17c0 .31.21.68.8.56 4.57-1.52 7.86-5.83 7.86-10.91C23.5 5.65 18.35.5 12 .5z" />
|
|
83
|
+
</svg>
|
|
84
|
+
Continue with GitHub
|
|
85
|
+
</button>
|
|
86
|
+
</form>
|
|
87
|
+
</div>
|
|
88
|
+
<p className="mt-6 text-center text-xs text-slate-500">
|
|
89
|
+
Don't have an account?{' '}
|
|
90
|
+
<Link href="/" className="font-medium text-slate-900 hover:underline">
|
|
91
|
+
Back home
|
|
92
|
+
</Link>
|
|
93
|
+
</p>
|
|
94
|
+
</div>
|
|
95
|
+
</main>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
2
|
+
|
|
3
|
+
:root {
|
|
4
|
+
color-scheme: light;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
html,
|
|
8
|
+
body {
|
|
9
|
+
height: 100%;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
body {
|
|
13
|
+
font-family:
|
|
14
|
+
ui-sans-serif,
|
|
15
|
+
system-ui,
|
|
16
|
+
-apple-system,
|
|
17
|
+
'Segoe UI',
|
|
18
|
+
Roboto,
|
|
19
|
+
sans-serif;
|
|
20
|
+
background-color: #f8fafc;
|
|
21
|
+
color: #0f172a;
|
|
22
|
+
line-height: 1.5;
|
|
23
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Metadata } from 'next';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import './globals.css';
|
|
4
|
+
|
|
5
|
+
export const metadata: Metadata = {
|
|
6
|
+
title: 'Spark App',
|
|
7
|
+
description: 'Minimal Next.js scaffold for spark projects.',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default function RootLayout({
|
|
11
|
+
children,
|
|
12
|
+
}: Readonly<{
|
|
13
|
+
children: ReactNode;
|
|
14
|
+
}>) {
|
|
15
|
+
return (
|
|
16
|
+
<html lang="en">
|
|
17
|
+
<body>{children}</body>
|
|
18
|
+
</html>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import Link from 'next/link';
|
|
2
|
+
|
|
3
|
+
export default function PublicLanding() {
|
|
4
|
+
return (
|
|
5
|
+
<main className="min-h-screen flex items-center justify-center bg-gradient-to-b from-slate-50 to-slate-100 px-6 py-16">
|
|
6
|
+
<section className="w-full max-w-xl text-center">
|
|
7
|
+
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-slate-500">
|
|
8
|
+
Spark
|
|
9
|
+
</p>
|
|
10
|
+
<h1 className="mt-3 text-4xl font-semibold tracking-tight text-slate-900 sm:text-5xl">
|
|
11
|
+
{'{{appName}}'}
|
|
12
|
+
</h1>
|
|
13
|
+
<p className="mt-4 text-base leading-relaxed text-slate-600">
|
|
14
|
+
A board-driven Next.js scaffold. Plan the work in{' '}
|
|
15
|
+
<code className="rounded bg-slate-200/70 px-1.5 py-0.5 text-sm text-slate-800">
|
|
16
|
+
.ai/board.md
|
|
17
|
+
</code>{' '}
|
|
18
|
+
and add capabilities with packs.
|
|
19
|
+
</p>
|
|
20
|
+
<div className="mt-8 flex items-center justify-center gap-3">
|
|
21
|
+
<Link
|
|
22
|
+
href="/login"
|
|
23
|
+
className="inline-flex items-center justify-center rounded-md bg-slate-900 px-5 py-2.5 text-sm font-medium text-white shadow-sm transition hover:bg-slate-800 focus:outline-none focus:ring-2 focus:ring-slate-900 focus:ring-offset-2"
|
|
24
|
+
>
|
|
25
|
+
Sign in
|
|
26
|
+
</Link>
|
|
27
|
+
<a
|
|
28
|
+
href="https://nextjs.org/docs/app"
|
|
29
|
+
target="_blank"
|
|
30
|
+
rel="noreferrer"
|
|
31
|
+
className="inline-flex items-center justify-center rounded-md border border-slate-300 bg-white px-5 py-2.5 text-sm font-medium text-slate-700 shadow-sm transition hover:bg-slate-50"
|
|
32
|
+
>
|
|
33
|
+
Docs
|
|
34
|
+
</a>
|
|
35
|
+
</div>
|
|
36
|
+
</section>
|
|
37
|
+
</main>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Placeholder session lookup.
|
|
3
|
+
*
|
|
4
|
+
* Returns `null` until an auth pack (e.g. `auth-better-auth`) replaces this
|
|
5
|
+
* module with a real `getSessionUser` that reads cookies / headers and
|
|
6
|
+
* resolves the active user.
|
|
7
|
+
*
|
|
8
|
+
* The shape returned here is the contract auth packs must honor: they should
|
|
9
|
+
* export the same `getSessionUser` signature so consumers in `app/(app)/**`
|
|
10
|
+
* keep working without further edits.
|
|
11
|
+
*/
|
|
12
|
+
export interface SessionUser {
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
email: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function getSessionUser(): Promise<SessionUser | null> {
|
|
19
|
+
// TODO: replaced by `auth-better-auth` (or another auth pack).
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import type { Post } from '@/types/post';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Placeholder posts hook.
|
|
8
|
+
*
|
|
9
|
+
* Returns an empty list and a no-op `createPost` until a sync pack
|
|
10
|
+
* (e.g. `sync-zero`) replaces this module with a real Zero client query.
|
|
11
|
+
*
|
|
12
|
+
* Sync packs should export the same `usePosts` signature so the UI in
|
|
13
|
+
* `app/(app)/page.tsx` keeps working without further edits.
|
|
14
|
+
*/
|
|
15
|
+
export interface UsePostsResult {
|
|
16
|
+
posts: Post[];
|
|
17
|
+
createPost: (input: { title: string; body: string }) => Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function usePosts(): UsePostsResult {
|
|
21
|
+
return useMemo<UsePostsResult>(
|
|
22
|
+
() => ({
|
|
23
|
+
posts: [],
|
|
24
|
+
createPost: async () => {
|
|
25
|
+
// TODO: replaced by `sync-zero` (or another sync pack).
|
|
26
|
+
},
|
|
27
|
+
}),
|
|
28
|
+
[],
|
|
29
|
+
);
|
|
30
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "spark-nextjs-template",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"packageManager": "bun@1.3.0",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "next dev",
|
|
9
|
+
"build": "next build",
|
|
10
|
+
"start": "next start"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"next": "^15",
|
|
14
|
+
"react": "^19",
|
|
15
|
+
"react-dom": "^19"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@tailwindcss/postcss": "^4",
|
|
19
|
+
"@types/node": "^22",
|
|
20
|
+
"@types/react": "^19",
|
|
21
|
+
"@types/react-dom": "^19",
|
|
22
|
+
"postcss": "^8",
|
|
23
|
+
"tailwindcss": "^4",
|
|
24
|
+
"typescript": "^5"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2017",
|
|
4
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
5
|
+
"allowJs": false,
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"module": "esnext",
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"jsx": "preserve",
|
|
15
|
+
"incremental": true,
|
|
16
|
+
"plugins": [
|
|
17
|
+
{
|
|
18
|
+
"name": "next"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"paths": {
|
|
22
|
+
"@/*": ["./*"]
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
26
|
+
"exclude": ["node_modules"]
|
|
27
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post entity shape.
|
|
3
|
+
*
|
|
4
|
+
* Kept stable so packs that wire real data (e.g. `sync-zero`) can reuse the
|
|
5
|
+
* same type without diverging field names.
|
|
6
|
+
*/
|
|
7
|
+
export interface Post {
|
|
8
|
+
id: string;
|
|
9
|
+
userId: string;
|
|
10
|
+
title: string;
|
|
11
|
+
body: string;
|
|
12
|
+
createdAt: Date;
|
|
13
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# One Template
|
|
2
|
+
|
|
3
|
+
This template is registered for pack compatibility planning, but it is not implemented yet. The planned scope is a full-stack web and native scaffold using the One framework: https://onestack.dev/
|
|
4
|
+
|
|
5
|
+
Implementation should follow the Bun workspace and CLI shape proven in the takeout2 reference project while keeping the generated scaffold minimal and ready for pack-based composition.
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
# Vite React Template
|
|
2
|
+
|
|
3
|
+
This template is registered for pack compatibility planning, but it is not implemented yet. The planned scope is a Vite-powered React scaffold for SPAs and internal tools, with no server runtime by default and the same AI workflow artifacts as the stable Next.js template.
|