@revealui/cli 0.0.0-canary-20260402004330

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 (65) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +99 -0
  3. package/bin/create-revealui.js +6 -0
  4. package/bin/revealui.js +6 -0
  5. package/dist/cli.d.ts +16 -0
  6. package/dist/cli.js +2769 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.js +2767 -0
  10. package/dist/index.js.map +1 -0
  11. package/package.json +72 -0
  12. package/templates/basic-blog/.env.example +36 -0
  13. package/templates/basic-blog/_gitignore +26 -0
  14. package/templates/basic-blog/next.config.mjs +8 -0
  15. package/templates/basic-blog/package.json +36 -0
  16. package/templates/basic-blog/postcss.config.mjs +5 -0
  17. package/templates/basic-blog/revealui.config.ts +19 -0
  18. package/templates/basic-blog/src/app/globals.css +6 -0
  19. package/templates/basic-blog/src/app/layout.tsx +15 -0
  20. package/templates/basic-blog/src/app/page.tsx +57 -0
  21. package/templates/basic-blog/src/app/posts/[slug]/page.tsx +66 -0
  22. package/templates/basic-blog/src/app/posts/page.tsx +61 -0
  23. package/templates/basic-blog/src/collections/Posts.ts +42 -0
  24. package/templates/basic-blog/src/seed.ts +73 -0
  25. package/templates/basic-blog/tsconfig.json +34 -0
  26. package/templates/e-commerce/.env.example +36 -0
  27. package/templates/e-commerce/_gitignore +26 -0
  28. package/templates/e-commerce/next.config.mjs +8 -0
  29. package/templates/e-commerce/package.json +36 -0
  30. package/templates/e-commerce/postcss.config.mjs +5 -0
  31. package/templates/e-commerce/revealui.config.ts +20 -0
  32. package/templates/e-commerce/src/app/globals.css +6 -0
  33. package/templates/e-commerce/src/app/layout.tsx +15 -0
  34. package/templates/e-commerce/src/app/page.tsx +82 -0
  35. package/templates/e-commerce/src/app/products/[slug]/page.tsx +80 -0
  36. package/templates/e-commerce/src/app/products/page.tsx +72 -0
  37. package/templates/e-commerce/src/collections/Orders.ts +63 -0
  38. package/templates/e-commerce/src/collections/Products.ts +50 -0
  39. package/templates/e-commerce/src/seed.ts +72 -0
  40. package/templates/e-commerce/tsconfig.json +34 -0
  41. package/templates/portfolio/.env.example +36 -0
  42. package/templates/portfolio/_gitignore +26 -0
  43. package/templates/portfolio/next.config.mjs +8 -0
  44. package/templates/portfolio/package.json +36 -0
  45. package/templates/portfolio/postcss.config.mjs +5 -0
  46. package/templates/portfolio/revealui.config.ts +19 -0
  47. package/templates/portfolio/src/app/globals.css +6 -0
  48. package/templates/portfolio/src/app/layout.tsx +15 -0
  49. package/templates/portfolio/src/app/page.tsx +60 -0
  50. package/templates/portfolio/src/app/projects/[slug]/page.tsx +95 -0
  51. package/templates/portfolio/src/app/projects/page.tsx +85 -0
  52. package/templates/portfolio/src/collections/Projects.ts +49 -0
  53. package/templates/portfolio/src/seed.ts +73 -0
  54. package/templates/portfolio/tsconfig.json +34 -0
  55. package/templates/starter/.env.example +36 -0
  56. package/templates/starter/_gitignore +26 -0
  57. package/templates/starter/next.config.mjs +8 -0
  58. package/templates/starter/package.json +36 -0
  59. package/templates/starter/postcss.config.mjs +5 -0
  60. package/templates/starter/revealui.config.ts +18 -0
  61. package/templates/starter/src/app/globals.css +6 -0
  62. package/templates/starter/src/app/layout.tsx +15 -0
  63. package/templates/starter/src/app/page.tsx +18 -0
  64. package/templates/starter/src/seed.ts +40 -0
  65. package/templates/starter/tsconfig.json +34 -0
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "{{PROJECT_NAME}}",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "next dev --port 4000",
8
+ "build": "next build",
9
+ "start": "next start --port 4000",
10
+ "lint": "biome check .",
11
+ "typecheck": "tsc --noEmit",
12
+ "test": "vitest run",
13
+ "db:init": "revealui cms",
14
+ "db:migrate": "drizzle-kit migrate",
15
+ "db:seed": "tsx src/seed.ts"
16
+ },
17
+ "dependencies": {
18
+ "@revealui/core": "latest",
19
+ "@revealui/config": "latest",
20
+ "@revealui/db": "latest",
21
+ "@revealui/auth": "latest",
22
+ "@revealui/contracts": "latest",
23
+ "next": "^16.0.0",
24
+ "react": "^19.0.0",
25
+ "react-dom": "^19.0.0",
26
+ "sharp": "^0.34.0",
27
+ "zod": "^4.0.0"
28
+ },
29
+ "devDependencies": {
30
+ "@biomejs/biome": "^2.0.0",
31
+ "@tailwindcss/postcss": "^4.1.0",
32
+ "tailwindcss": "^4.1.0",
33
+ "typescript": "^6.0.0",
34
+ "vitest": "^4.0.0"
35
+ }
36
+ }
@@ -0,0 +1,5 @@
1
+ export default {
2
+ plugins: {
3
+ '@tailwindcss/postcss': {},
4
+ },
5
+ }
@@ -0,0 +1,19 @@
1
+ import config from '@revealui/config';
2
+ import { buildConfig, universalPostgresAdapter } from '@revealui/core';
3
+ import sharp from 'sharp';
4
+ import { Posts } from './src/collections/Posts';
5
+
6
+ export default buildConfig({
7
+ serverURL: config.reveal.publicServerURL || 'http://localhost:4000',
8
+ secret: config.reveal.secret,
9
+ db: config.database.url
10
+ ? universalPostgresAdapter({ connectionString: config.database.url })
11
+ : universalPostgresAdapter({ provider: 'electric' }),
12
+ admin: {
13
+ user: 'users',
14
+ },
15
+ collections: [Posts],
16
+ globals: [],
17
+ plugins: [],
18
+ sharp,
19
+ });
@@ -0,0 +1,6 @@
1
+ @import "tailwindcss";
2
+
3
+ @theme {
4
+ --color-accent: #2563eb;
5
+ --color-accent-hover: #1d4ed8;
6
+ }
@@ -0,0 +1,15 @@
1
+ import type { Metadata } from 'next';
2
+ import './globals.css';
3
+
4
+ export const metadata: Metadata = {
5
+ title: 'RevealUI App',
6
+ description: 'Built with RevealUI',
7
+ };
8
+
9
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
10
+ return (
11
+ <html lang="en">
12
+ <body>{children}</body>
13
+ </html>
14
+ );
15
+ }
@@ -0,0 +1,57 @@
1
+ import Link from 'next/link';
2
+
3
+ export default function HomePage() {
4
+ return (
5
+ <main className="mx-auto max-w-2xl px-4 py-16">
6
+ <h1 className="text-4xl font-bold tracking-tight text-gray-900">Welcome to your blog</h1>
7
+ <p className="mt-4 text-lg text-gray-600">
8
+ Built with{' '}
9
+ <a
10
+ href="https://revealui.com"
11
+ className="font-medium text-accent hover:text-accent-hover"
12
+ target="_blank"
13
+ rel="noopener noreferrer"
14
+ >
15
+ RevealUI
16
+ </a>
17
+ . Start writing posts from the admin panel, or seed sample data to get started.
18
+ </p>
19
+
20
+ <div className="mt-8 flex flex-wrap gap-3">
21
+ <Link
22
+ href="/posts"
23
+ className="rounded-lg bg-accent px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-accent-hover"
24
+ >
25
+ Read the blog
26
+ </Link>
27
+ <a
28
+ href="/admin"
29
+ className="rounded-lg border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50"
30
+ >
31
+ Open admin panel
32
+ </a>
33
+ </div>
34
+
35
+ <div className="mt-12 rounded-lg border border-gray-200 bg-gray-50 p-6">
36
+ <h2 className="text-sm font-semibold uppercase tracking-wide text-gray-500">Quick start</h2>
37
+ <ol className="mt-3 space-y-2 text-sm text-gray-700">
38
+ <li>
39
+ <code className="rounded bg-gray-200 px-1.5 py-0.5 text-xs">pnpm db:seed</code> — add
40
+ sample blog posts
41
+ </li>
42
+ <li>
43
+ Visit{' '}
44
+ <a href="/admin" className="text-accent hover:text-accent-hover">
45
+ /admin
46
+ </a>{' '}
47
+ — manage your content
48
+ </li>
49
+ <li>
50
+ Edit <code className="rounded bg-gray-200 px-1.5 py-0.5 text-xs">src/app/page.tsx</code>{' '}
51
+ — customize this page
52
+ </li>
53
+ </ol>
54
+ </div>
55
+ </main>
56
+ );
57
+ }
@@ -0,0 +1,66 @@
1
+ const API_URL = process.env.NEXT_PUBLIC_SERVER_URL || 'http://localhost:4000';
2
+
3
+ interface Post {
4
+ id: string;
5
+ title: string;
6
+ slug: string;
7
+ content: unknown;
8
+ status: string;
9
+ publishedAt: string | null;
10
+ }
11
+
12
+ async function getPost(slug: string): Promise<Post | null> {
13
+ try {
14
+ const res = await fetch(`${API_URL}/api/posts?where[slug][equals]=${slug}&limit=1`, {
15
+ cache: 'no-store',
16
+ });
17
+ if (!res.ok) return null;
18
+ const data = await res.json();
19
+ return data.docs?.[0] ?? null;
20
+ } catch {
21
+ return null;
22
+ }
23
+ }
24
+
25
+ export default async function PostPage({ params }: { params: Promise<{ slug: string }> }) {
26
+ const { slug } = await params;
27
+ const post = await getPost(slug);
28
+
29
+ if (!post) {
30
+ return (
31
+ <main className="mx-auto max-w-2xl px-4 py-16">
32
+ <h1 className="text-2xl font-bold">Post not found</h1>
33
+ <p className="mt-4">
34
+ <a href="/posts" className="text-accent underline">
35
+ Back to blog
36
+ </a>
37
+ </p>
38
+ </main>
39
+ );
40
+ }
41
+
42
+ return (
43
+ <main className="mx-auto max-w-2xl px-4 py-16">
44
+ <nav className="mb-8">
45
+ <a href="/posts" className="text-sm text-accent underline">
46
+ &larr; Back to blog
47
+ </a>
48
+ </nav>
49
+ <article>
50
+ <h1 className="mb-2 text-3xl font-bold">{post.title}</h1>
51
+ {post.publishedAt && (
52
+ <time className="mb-8 block text-sm text-gray-500">
53
+ {new Date(post.publishedAt).toLocaleDateString()}
54
+ </time>
55
+ )}
56
+ <div className="prose">
57
+ {typeof post.content === 'string' ? (
58
+ <p>{post.content}</p>
59
+ ) : (
60
+ <p className="text-gray-500">Rich text content will render here.</p>
61
+ )}
62
+ </div>
63
+ </article>
64
+ </main>
65
+ );
66
+ }
@@ -0,0 +1,61 @@
1
+ const API_URL = process.env.NEXT_PUBLIC_SERVER_URL || 'http://localhost:4000';
2
+
3
+ interface Post {
4
+ id: string;
5
+ title: string;
6
+ slug: string;
7
+ status: string;
8
+ publishedAt: string | null;
9
+ }
10
+
11
+ async function getPosts(): Promise<Post[]> {
12
+ try {
13
+ const res = await fetch(
14
+ `${API_URL}/api/posts?where[status][equals]=published&sort=-publishedAt`,
15
+ {
16
+ cache: 'no-store',
17
+ },
18
+ );
19
+ if (!res.ok) return [];
20
+ const data = await res.json();
21
+ return data.docs ?? [];
22
+ } catch {
23
+ return [];
24
+ }
25
+ }
26
+
27
+ export default async function PostsPage() {
28
+ const posts = await getPosts();
29
+
30
+ return (
31
+ <main className="mx-auto max-w-2xl px-4 py-16">
32
+ <h1 className="mb-8 text-3xl font-bold">Blog</h1>
33
+
34
+ {posts.length === 0 ? (
35
+ <p className="text-gray-500">
36
+ No posts yet. Create your first post in the{' '}
37
+ <a href="/admin/collections/posts" className="text-accent underline">
38
+ admin panel
39
+ </a>
40
+ , or run <code className="rounded bg-gray-100 px-1">pnpm db:seed</code> to add sample
41
+ data.
42
+ </p>
43
+ ) : (
44
+ <ul className="space-y-6">
45
+ {posts.map((post) => (
46
+ <li key={post.id}>
47
+ <a href={`/posts/${post.slug}`} className="group block">
48
+ <h2 className="text-xl font-semibold group-hover:text-accent">{post.title}</h2>
49
+ {post.publishedAt && (
50
+ <time className="text-sm text-gray-500">
51
+ {new Date(post.publishedAt).toLocaleDateString()}
52
+ </time>
53
+ )}
54
+ </a>
55
+ </li>
56
+ ))}
57
+ </ul>
58
+ )}
59
+ </main>
60
+ );
61
+ }
@@ -0,0 +1,42 @@
1
+ import type { CollectionConfig } from '@revealui/contracts';
2
+
3
+ export const Posts: CollectionConfig = {
4
+ slug: 'posts',
5
+ labels: { singular: 'Post', plural: 'Posts' },
6
+ fields: [
7
+ {
8
+ name: 'title',
9
+ type: 'text',
10
+ required: true,
11
+ },
12
+ {
13
+ name: 'slug',
14
+ type: 'text',
15
+ required: true,
16
+ unique: true,
17
+ admin: {
18
+ description: 'URL-friendly identifier (e.g. "my-first-post")',
19
+ },
20
+ },
21
+ {
22
+ name: 'content',
23
+ type: 'richText',
24
+ },
25
+ {
26
+ name: 'status',
27
+ type: 'select',
28
+ defaultValue: 'draft',
29
+ options: [
30
+ { label: 'Draft', value: 'draft' },
31
+ { label: 'Published', value: 'published' },
32
+ ],
33
+ },
34
+ {
35
+ name: 'publishedAt',
36
+ type: 'date',
37
+ admin: {
38
+ description: 'When this post was published',
39
+ },
40
+ },
41
+ ],
42
+ };
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Seed script for the basic-blog template.
3
+ * Creates 3 sample blog posts via the RevealUI REST API.
4
+ *
5
+ * Usage: pnpm db:seed (requires the dev server to be running)
6
+ */
7
+
8
+ const API_URL = process.env.NEXT_PUBLIC_SERVER_URL || 'http://localhost:4000';
9
+
10
+ interface SeedPost {
11
+ title: string;
12
+ slug: string;
13
+ content: string;
14
+ status: string;
15
+ publishedAt: string;
16
+ }
17
+
18
+ const posts: SeedPost[] = [
19
+ {
20
+ title: 'Getting Started with RevealUI',
21
+ slug: 'getting-started-with-revealui',
22
+ content:
23
+ 'Welcome to your new RevealUI blog! This post was created by the seed script. Edit or delete it from the admin panel at /admin.',
24
+ status: 'published',
25
+ publishedAt: new Date().toISOString(),
26
+ },
27
+ {
28
+ title: 'Customizing Your Blog',
29
+ slug: 'customizing-your-blog',
30
+ content:
31
+ 'You can customize your blog by editing the Posts collection in src/collections/Posts.ts. Add new fields, change validation rules, or add hooks to run custom logic.',
32
+ status: 'published',
33
+ publishedAt: new Date(Date.now() - 86_400_000).toISOString(),
34
+ },
35
+ {
36
+ title: 'Draft Post Example',
37
+ slug: 'draft-post-example',
38
+ content:
39
+ 'This is a draft post. It will not appear on the public blog until you change its status to "published" in the admin panel.',
40
+ status: 'draft',
41
+ publishedAt: '',
42
+ },
43
+ ];
44
+
45
+ const log = (...args: unknown[]) => process.stdout.write(`${args.join(' ')}\n`);
46
+ const logErr = (...args: unknown[]) => process.stderr.write(`${args.join(' ')}\n`);
47
+
48
+ async function seed(): Promise<void> {
49
+ log(`Seeding blog posts to ${API_URL}...`);
50
+
51
+ for (const post of posts) {
52
+ try {
53
+ const res = await fetch(`${API_URL}/api/posts`, {
54
+ method: 'POST',
55
+ headers: { 'Content-Type': 'application/json' },
56
+ body: JSON.stringify(post),
57
+ });
58
+
59
+ if (res.ok) {
60
+ log(` Created: ${post.title}`);
61
+ } else {
62
+ const error = await res.text();
63
+ logErr(` Failed to create "${post.title}": ${error}`);
64
+ }
65
+ } catch (err) {
66
+ logErr(` Error creating "${post.title}":`, err);
67
+ }
68
+ }
69
+
70
+ log('Seeding complete.');
71
+ }
72
+
73
+ seed();
@@ -0,0 +1,34 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "compilerOptions": {
4
+ "strict": true,
5
+ "strictNullChecks": true,
6
+ "strictFunctionTypes": true,
7
+ "noImplicitReturns": true,
8
+ "noFallthroughCasesInSwitch": true,
9
+ "noUncheckedIndexedAccess": true,
10
+ "noUnusedLocals": true,
11
+ "noUnusedParameters": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "isolatedModules": true,
14
+ "verbatimModuleSyntax": true,
15
+ "skipLibCheck": true,
16
+ "allowJs": true,
17
+ "jsx": "preserve",
18
+ "lib": ["DOM", "DOM.Iterable", "ESNext"],
19
+ "module": "ESNext",
20
+ "moduleResolution": "bundler",
21
+ "resolveJsonModule": true,
22
+ "resolvePackageJsonExports": true,
23
+ "target": "ES2022",
24
+ "noEmit": true,
25
+ "incremental": true,
26
+ "plugins": [{ "name": "next" }],
27
+ "baseUrl": ".",
28
+ "paths": {
29
+ "@/*": ["./src/*"]
30
+ }
31
+ },
32
+ "include": ["src", "next-env.d.ts", "next.config.mjs", "revealui.config.ts"],
33
+ "exclude": ["node_modules"]
34
+ }
@@ -0,0 +1,36 @@
1
+ # RevealUI Environment Variables
2
+ # Copy this file to .env.local and fill in your values before running `pnpm dev`
3
+
4
+ # ─── Core ────────────────────────────────────────────────────────────────────
5
+ # 32+ character secret used for signing sessions and tokens
6
+ REVEALUI_SECRET=change-me-to-a-long-random-secret-at-least-32-chars
7
+
8
+ # Public URL of your CMS server (must match NEXT_PUBLIC_SERVER_URL)
9
+ REVEALUI_PUBLIC_SERVER_URL=http://localhost:4000
10
+ NEXT_PUBLIC_SERVER_URL=http://localhost:4000
11
+
12
+ # ─── Database ────────────────────────────────────────────────────────────────
13
+ # PostgreSQL connection string (NeonDB, Supabase, or local Postgres)
14
+ POSTGRES_URL=postgresql://postgres:postgres@localhost:5432/revealui
15
+
16
+ # ─── Storage ─────────────────────────────────────────────────────────────────
17
+ # Vercel Blob token for file uploads (optional — leave placeholder for local dev)
18
+ BLOB_READ_WRITE_TOKEN=vercel_blob_rw_placeholder
19
+
20
+ # ─── Stripe (optional) ───────────────────────────────────────────────────────
21
+ # Use test keys during development: https://dashboard.stripe.com/test/apikeys
22
+ STRIPE_SECRET_KEY=sk_test_placeholder
23
+ STRIPE_WEBHOOK_SECRET=whsec_placeholder
24
+ NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_placeholder
25
+
26
+ # ─── Admin Bootstrap ─────────────────────────────────────────────────────────
27
+ # Used on first run only to create the initial admin account
28
+ REVEALUI_ADMIN_EMAIL=admin@example.com
29
+ REVEALUI_ADMIN_PASSWORD=changeme-min-12-chars
30
+
31
+ # ─── Branding (Enterprise white-label) ───────────────────────────────────────
32
+ # Customize the admin UI for your brand. Enterprise license required for full white-label.
33
+ # REVEALUI_BRAND_NAME=My CMS
34
+ # REVEALUI_BRAND_LOGO_URL=https://example.com/logo.png
35
+ # REVEALUI_BRAND_PRIMARY_COLOR=#ea580c
36
+ # REVEALUI_SHOW_POWERED_BY=false
@@ -0,0 +1,26 @@
1
+ # Dependencies
2
+ node_modules/
3
+ .pnp
4
+ .pnp.js
5
+
6
+ # Next.js
7
+ .next/
8
+ out/
9
+ build/
10
+
11
+ # Environment variables
12
+ .env
13
+ .env.local
14
+ .env.development.local
15
+ .env.test.local
16
+ .env.production.local
17
+
18
+ # Turbo
19
+ .turbo/
20
+
21
+ # Misc
22
+ .DS_Store
23
+ *.pem
24
+ npm-debug.log*
25
+ yarn-debug.log*
26
+ yarn-error.log*
@@ -0,0 +1,8 @@
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {
3
+ reactCompiler: true,
4
+ // Required for RevealUI CMS admin panel
5
+ transpilePackages: ['@revealui/core', '@revealui/presentation'],
6
+ }
7
+
8
+ export default nextConfig
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "{{PROJECT_NAME}}",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "next dev --port 4000",
8
+ "build": "next build",
9
+ "start": "next start --port 4000",
10
+ "lint": "biome check .",
11
+ "typecheck": "tsc --noEmit",
12
+ "test": "vitest run",
13
+ "db:init": "revealui cms",
14
+ "db:migrate": "drizzle-kit migrate",
15
+ "db:seed": "tsx src/seed.ts"
16
+ },
17
+ "dependencies": {
18
+ "@revealui/core": "latest",
19
+ "@revealui/config": "latest",
20
+ "@revealui/db": "latest",
21
+ "@revealui/auth": "latest",
22
+ "@revealui/contracts": "latest",
23
+ "next": "^16.0.0",
24
+ "react": "^19.0.0",
25
+ "react-dom": "^19.0.0",
26
+ "sharp": "^0.34.0",
27
+ "zod": "^4.0.0"
28
+ },
29
+ "devDependencies": {
30
+ "@biomejs/biome": "^2.0.0",
31
+ "@tailwindcss/postcss": "^4.1.0",
32
+ "tailwindcss": "^4.1.0",
33
+ "typescript": "^6.0.0",
34
+ "vitest": "^4.0.0"
35
+ }
36
+ }
@@ -0,0 +1,5 @@
1
+ export default {
2
+ plugins: {
3
+ '@tailwindcss/postcss': {},
4
+ },
5
+ }
@@ -0,0 +1,20 @@
1
+ import config from '@revealui/config';
2
+ import { buildConfig, universalPostgresAdapter } from '@revealui/core';
3
+ import sharp from 'sharp';
4
+ import { Orders } from './src/collections/Orders';
5
+ import { Products } from './src/collections/Products';
6
+
7
+ export default buildConfig({
8
+ serverURL: config.reveal.publicServerURL || 'http://localhost:4000',
9
+ secret: config.reveal.secret,
10
+ db: config.database.url
11
+ ? universalPostgresAdapter({ connectionString: config.database.url })
12
+ : universalPostgresAdapter({ provider: 'electric' }),
13
+ admin: {
14
+ user: 'users',
15
+ },
16
+ collections: [Products, Orders],
17
+ globals: [],
18
+ plugins: [],
19
+ sharp,
20
+ });
@@ -0,0 +1,6 @@
1
+ @import "tailwindcss";
2
+
3
+ @theme {
4
+ --color-accent: #2563eb;
5
+ --color-accent-hover: #1d4ed8;
6
+ }
@@ -0,0 +1,15 @@
1
+ import type { Metadata } from 'next';
2
+ import './globals.css';
3
+
4
+ export const metadata: Metadata = {
5
+ title: 'RevealUI App',
6
+ description: 'Built with RevealUI',
7
+ };
8
+
9
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
10
+ return (
11
+ <html lang="en">
12
+ <body>{children}</body>
13
+ </html>
14
+ );
15
+ }
@@ -0,0 +1,82 @@
1
+ import Link from 'next/link';
2
+
3
+ export default function HomePage() {
4
+ return (
5
+ <main className="mx-auto max-w-4xl px-4 py-16">
6
+ <div className="text-center">
7
+ <h1 className="text-4xl font-bold tracking-tight text-gray-900 sm:text-5xl">
8
+ Your store is live
9
+ </h1>
10
+ <p className="mx-auto mt-4 max-w-xl text-lg text-gray-600">
11
+ Built with{' '}
12
+ <a
13
+ href="https://revealui.com"
14
+ className="font-medium text-accent hover:text-accent-hover"
15
+ target="_blank"
16
+ rel="noopener noreferrer"
17
+ >
18
+ RevealUI
19
+ </a>
20
+ . Add products from the admin panel, configure Stripe for payments, and start selling.
21
+ </p>
22
+
23
+ <div className="mt-8 flex justify-center gap-3">
24
+ <Link
25
+ href="/products"
26
+ className="rounded-lg bg-accent px-5 py-2.5 text-sm font-medium text-white transition-colors hover:bg-accent-hover"
27
+ >
28
+ Browse products
29
+ </Link>
30
+ <a
31
+ href="/admin"
32
+ className="rounded-lg border border-gray-300 px-5 py-2.5 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50"
33
+ >
34
+ Admin panel
35
+ </a>
36
+ </div>
37
+ </div>
38
+
39
+ <div className="mt-16 grid gap-6 sm:grid-cols-3">
40
+ <div className="rounded-lg border border-gray-200 p-5">
41
+ <h3 className="font-semibold text-gray-900">Products</h3>
42
+ <p className="mt-1 text-sm text-gray-600">
43
+ Manage your catalog with custom fields, images, and pricing.
44
+ </p>
45
+ </div>
46
+ <div className="rounded-lg border border-gray-200 p-5">
47
+ <h3 className="font-semibold text-gray-900">Payments</h3>
48
+ <p className="mt-1 text-sm text-gray-600">
49
+ Stripe integration for checkout, subscriptions, and webhooks.
50
+ </p>
51
+ </div>
52
+ <div className="rounded-lg border border-gray-200 p-5">
53
+ <h3 className="font-semibold text-gray-900">Orders</h3>
54
+ <p className="mt-1 text-sm text-gray-600">
55
+ Track and manage orders with status updates and fulfillment.
56
+ </p>
57
+ </div>
58
+ </div>
59
+
60
+ <div className="mt-12 rounded-lg border border-gray-200 bg-gray-50 p-6">
61
+ <h2 className="text-sm font-semibold uppercase tracking-wide text-gray-500">Quick start</h2>
62
+ <ol className="mt-3 space-y-2 text-sm text-gray-700">
63
+ <li>
64
+ <code className="rounded bg-gray-200 px-1.5 py-0.5 text-xs">pnpm db:seed</code> — add
65
+ sample products
66
+ </li>
67
+ <li>
68
+ Add your Stripe keys to{' '}
69
+ <code className="rounded bg-gray-200 px-1.5 py-0.5 text-xs">.env.local</code>
70
+ </li>
71
+ <li>
72
+ Visit{' '}
73
+ <a href="/admin" className="text-accent hover:text-accent-hover">
74
+ /admin
75
+ </a>{' '}
76
+ — manage products and orders
77
+ </li>
78
+ </ol>
79
+ </div>
80
+ </main>
81
+ );
82
+ }