@zorgo/next 1.0.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/README.md +19 -0
- package/dist/cli.d.mts +5 -0
- package/dist/cli.d.ts +5 -0
- package/dist/cli.js +2 -0
- package/dist/cli.mjs +2 -0
- package/dist/components.d.mts +337 -0
- package/dist/components.d.ts +337 -0
- package/dist/components.js +1996 -0
- package/dist/components.js.map +1 -0
- package/dist/components.mjs +1962 -0
- package/dist/components.mjs.map +1 -0
- package/dist/index.d.mts +305 -0
- package/dist/index.d.ts +305 -0
- package/dist/index.js +2 -0
- package/dist/index.mjs +2 -0
- package/dist/seo.d.mts +30 -0
- package/dist/seo.d.ts +30 -0
- package/dist/seo.js +82 -0
- package/dist/seo.js.map +1 -0
- package/dist/seo.mjs +56 -0
- package/dist/seo.mjs.map +1 -0
- package/dist/slugs.d.mts +1 -0
- package/dist/slugs.d.ts +1 -0
- package/dist/slugs.js +47 -0
- package/dist/slugs.js.map +1 -0
- package/dist/slugs.mjs +19 -0
- package/dist/slugs.mjs.map +1 -0
- package/dist/tree/.env.gen.ts +27 -0
- package/dist/tree/README.md +0 -0
- package/dist/tree/app/api/zorgo-token/route.ts +11 -0
- package/dist/tree/app/apple-icon.tsx.gen.ts +54 -0
- package/dist/tree/app/checkout/page.tsx +10 -0
- package/dist/tree/app/components/Footer.tsx +50 -0
- package/dist/tree/app/components/Header.tsx +128 -0
- package/dist/tree/app/components/ModalHost.tsx +56 -0
- package/dist/tree/app/components/ModalRegistry.tsx +113 -0
- package/dist/tree/app/components/TestCard.tsx +35 -0
- package/dist/tree/app/components/index.ts +3 -0
- package/dist/tree/app/error.tsx +10 -0
- package/dist/tree/app/global-error.tsx +12 -0
- package/dist/tree/app/globals.css.gen.ts +123 -0
- package/dist/tree/app/icon.tsx.gen.ts +87 -0
- package/dist/tree/app/layout.tsx.gen.ts +55 -0
- package/dist/tree/app/locations/page.tsx +30 -0
- package/dist/tree/app/manifest.ts.gen.ts +39 -0
- package/dist/tree/app/menu/[slug]/ItemCustomizationClient.tsx +18 -0
- package/dist/tree/app/menu/[slug]/page.tsx +78 -0
- package/dist/tree/app/menu/page.tsx +36 -0
- package/dist/tree/app/not-found.tsx +8 -0
- package/dist/tree/app/opengraph-image.tsx.gen.ts +82 -0
- package/dist/tree/app/page.tsx +19 -0
- package/dist/tree/app/privacy/page.tsx.gen.ts +15 -0
- package/dist/tree/app/robots.ts +9 -0
- package/dist/tree/app/sitemap.ts +26 -0
- package/dist/tree/app/terms/page.tsx.gen.ts +16 -0
- package/dist/tree/gitignore +44 -0
- package/dist/tree/lib/zorgoSiteToken.ts +20 -0
- package/dist/tree/next.config.ts +14 -0
- package/dist/tree/open-next.config.ts +4 -0
- package/dist/tree/package.json.gen.ts +24 -0
- package/dist/tree/postcss.config.mjs +7 -0
- package/dist/tree/scripts/prebuild.ts +448 -0
- package/dist/tree/tsconfig.json +35 -0
- package/package.json +72 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useMenu, useHydrateMenu } from "@zorgo/next";
|
|
3
|
+
import {
|
|
4
|
+
GridMenu,
|
|
5
|
+
AccordionMenu,
|
|
6
|
+
type GridMenuItemClasses,
|
|
7
|
+
} from "@zorgo/next/components";
|
|
8
|
+
import { menu } from "../../lib/generated/menu";
|
|
9
|
+
|
|
10
|
+
export default function MenuPage() {
|
|
11
|
+
useHydrateMenu(menu); // client first paint; boot refreshes it
|
|
12
|
+
const store = useMenu();
|
|
13
|
+
// zustand v4 serves getInitialState() (empty) on the server, so the store is
|
|
14
|
+
// never populated during SSR. Fall back to the prebuilt import so crawlers get
|
|
15
|
+
// real HTML; the client swaps to the filtered store data once boot runs.
|
|
16
|
+
const items = store.items.length ? store.items : menu.items;
|
|
17
|
+
const categories = store.categories.length
|
|
18
|
+
? store.categories
|
|
19
|
+
: menu.categories;
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<div className="p-8 md:p-16">
|
|
23
|
+
<div className="max-w-4xl mx-auto">
|
|
24
|
+
<h1 className="text-4xl font-extrabold text-primary text-center mb-8">
|
|
25
|
+
Our Menu
|
|
26
|
+
</h1>
|
|
27
|
+
<AccordionMenu items={items} categories={categories} />
|
|
28
|
+
</div>
|
|
29
|
+
{/*
|
|
30
|
+
<GridMenu
|
|
31
|
+
items={items}
|
|
32
|
+
categories={categories}
|
|
33
|
+
/>*/}
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { ScaffoldOptions } from "../../../types";
|
|
2
|
+
|
|
3
|
+
export default function generateOpengraphImage(opts: ScaffoldOptions): string {
|
|
4
|
+
const projectName = opts.projectName;
|
|
5
|
+
const letter = projectName.charAt(0).toUpperCase();
|
|
6
|
+
|
|
7
|
+
return `import { ImageResponse } from "next/og";
|
|
8
|
+
import { readFileSync } from "fs";
|
|
9
|
+
import { join } from "path";
|
|
10
|
+
|
|
11
|
+
export const alt = ${JSON.stringify(projectName)};
|
|
12
|
+
export const size = { width: 1200, height: 630 };
|
|
13
|
+
export const contentType = "image/png";
|
|
14
|
+
|
|
15
|
+
// Brand palette prebuild drops at public/styles/styles.json. Neutral fallback if
|
|
16
|
+
// it's missing so the card still renders.
|
|
17
|
+
function loadTheme() {
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(
|
|
20
|
+
readFileSync(join(process.cwd(), "public/styles/styles.json"), "utf8"),
|
|
21
|
+
);
|
|
22
|
+
} catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default function OpengraphImage() {
|
|
28
|
+
const theme = loadTheme();
|
|
29
|
+
const background = theme?.backgroundBase ?? "#171717";
|
|
30
|
+
const foreground = theme?.foreground ?? "#ffffff";
|
|
31
|
+
const badge = theme?.primary ?? "#ffffff";
|
|
32
|
+
const badgeForeground = theme?.primaryForeground ?? "#171717";
|
|
33
|
+
return new ImageResponse(
|
|
34
|
+
(
|
|
35
|
+
<div
|
|
36
|
+
style={{
|
|
37
|
+
width: "100%",
|
|
38
|
+
height: "100%",
|
|
39
|
+
display: "flex",
|
|
40
|
+
flexDirection: "column",
|
|
41
|
+
alignItems: "center",
|
|
42
|
+
justifyContent: "center",
|
|
43
|
+
background,
|
|
44
|
+
color: foreground,
|
|
45
|
+
}}
|
|
46
|
+
>
|
|
47
|
+
<div
|
|
48
|
+
style={{
|
|
49
|
+
display: "flex",
|
|
50
|
+
alignItems: "center",
|
|
51
|
+
justifyContent: "center",
|
|
52
|
+
width: 140,
|
|
53
|
+
height: 140,
|
|
54
|
+
borderRadius: 32,
|
|
55
|
+
background: badge,
|
|
56
|
+
color: badgeForeground,
|
|
57
|
+
fontSize: 84,
|
|
58
|
+
fontWeight: 700,
|
|
59
|
+
marginBottom: 48,
|
|
60
|
+
}}
|
|
61
|
+
>
|
|
62
|
+
${letter}
|
|
63
|
+
</div>
|
|
64
|
+
<div
|
|
65
|
+
style={{
|
|
66
|
+
display: "flex",
|
|
67
|
+
fontSize: 72,
|
|
68
|
+
fontWeight: 700,
|
|
69
|
+
letterSpacing: "-0.02em",
|
|
70
|
+
textAlign: "center",
|
|
71
|
+
padding: "0 80px",
|
|
72
|
+
}}
|
|
73
|
+
>
|
|
74
|
+
${projectName}
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
),
|
|
78
|
+
size,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
`;
|
|
82
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useModal } from "@zorgo/next";
|
|
3
|
+
import TestCard from "./components/TestCard";
|
|
4
|
+
|
|
5
|
+
export default function Home() {
|
|
6
|
+
const { open } = useModal();
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<div className="flex flex-col items-center gap-8 py-16">
|
|
10
|
+
<TestCard />
|
|
11
|
+
<button
|
|
12
|
+
onClick={() => open("EXAMPLE_MODAL", { title: "Hello from a modal" })}
|
|
13
|
+
className="rounded-lg bg-primary px-8 p-3 text-xl font-bold text-primary-foreground shadow-md transition-opacity duration-300 hover:opacity-50"
|
|
14
|
+
>
|
|
15
|
+
Open a modal
|
|
16
|
+
</button>
|
|
17
|
+
</div>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ScaffoldOptions } from "../../../../types";
|
|
2
|
+
|
|
3
|
+
export default function generatePrivacyPage(opts: ScaffoldOptions) {
|
|
4
|
+
|
|
5
|
+
if (opts.includePrivacyPage) {
|
|
6
|
+
return `export default function PrivacyPage() {
|
|
7
|
+
return (
|
|
8
|
+
<div>
|
|
9
|
+
<h1>Privacy Policy</h1>
|
|
10
|
+
</div>
|
|
11
|
+
)
|
|
12
|
+
}`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { MetadataRoute } from "next";
|
|
2
|
+
|
|
3
|
+
export default function robots(): MetadataRoute.Robots {
|
|
4
|
+
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL ?? "http://localhost:3000";
|
|
5
|
+
return {
|
|
6
|
+
rules: { userAgent: "*", allow: "/", disallow: "/api" },
|
|
7
|
+
sitemap: `${baseUrl}/sitemap.xml`,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { MetadataRoute } from "next";
|
|
2
|
+
import { menuItemSlug } from "@zorgo/next/slugs";
|
|
3
|
+
import { menu } from "../lib/generated/menu";
|
|
4
|
+
|
|
5
|
+
const BASE_URL = process.env.NEXT_PUBLIC_SITE_URL ?? "http://localhost:3000";
|
|
6
|
+
|
|
7
|
+
// Indexable static pages. Add a route here when you add a page you want crawled.
|
|
8
|
+
// Deliberately excludes /checkout (transactional, not indexable).
|
|
9
|
+
const STATIC_ROUTES = ["/", "/menu", "/locations", "/privacy", "/terms"];
|
|
10
|
+
|
|
11
|
+
// [slug] item pages come from the prebuilt menu — the same data + slug fn that
|
|
12
|
+
// generateStaticParams uses in app/menu/[slug]/page.tsx, so this stays 1:1 with
|
|
13
|
+
// the pages Next actually generates.
|
|
14
|
+
function menuItemRoutes(): string[] {
|
|
15
|
+
return menu.items.map(
|
|
16
|
+
(item) => `/menu/${menuItemSlug(item.name, item.base_item_id)}`,
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default function sitemap(): MetadataRoute.Sitemap {
|
|
21
|
+
const routes = [...STATIC_ROUTES, ...menuItemRoutes()];
|
|
22
|
+
return routes.map((route) => ({
|
|
23
|
+
url: `${BASE_URL}${route}`,
|
|
24
|
+
lastModified: new Date(),
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ScaffoldOptions } from "../../../../types";
|
|
2
|
+
|
|
3
|
+
// add bullshit tos here
|
|
4
|
+
export default function generateTermsPage(opts: ScaffoldOptions) {
|
|
5
|
+
|
|
6
|
+
if (opts.includeTermsPage) {
|
|
7
|
+
return `export default function TermsPage() {
|
|
8
|
+
return (
|
|
9
|
+
<div>
|
|
10
|
+
<h1>Terms of Service</h1>
|
|
11
|
+
</div>
|
|
12
|
+
)
|
|
13
|
+
}`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
|
2
|
+
|
|
3
|
+
# dependencies
|
|
4
|
+
/node_modules
|
|
5
|
+
/.pnp
|
|
6
|
+
.pnp.*
|
|
7
|
+
|
|
8
|
+
# testing
|
|
9
|
+
/coverage
|
|
10
|
+
|
|
11
|
+
# next.js
|
|
12
|
+
/.next/
|
|
13
|
+
/out/
|
|
14
|
+
|
|
15
|
+
# production
|
|
16
|
+
/build
|
|
17
|
+
|
|
18
|
+
# misc
|
|
19
|
+
.DS_Store
|
|
20
|
+
*.pem
|
|
21
|
+
|
|
22
|
+
# debug
|
|
23
|
+
npm-debug.log*
|
|
24
|
+
yarn-debug.log*
|
|
25
|
+
yarn-error.log*
|
|
26
|
+
.pnpm-debug.log*
|
|
27
|
+
|
|
28
|
+
# env files (can opt-in for committing if needed)
|
|
29
|
+
.env*
|
|
30
|
+
!.env.example
|
|
31
|
+
|
|
32
|
+
# vercel
|
|
33
|
+
.vercel
|
|
34
|
+
|
|
35
|
+
# typescript
|
|
36
|
+
*.tsbuildinfo
|
|
37
|
+
next-env.d.ts
|
|
38
|
+
.open-next/
|
|
39
|
+
|
|
40
|
+
/.wrangler/
|
|
41
|
+
|
|
42
|
+
# generated from .env by scripts/prebuild.ts
|
|
43
|
+
/wrangler.toml
|
|
44
|
+
/lib/generated/
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// set at scaffold time in .env (NEXT_PUBLIC_API_BASE_URL); localhost fallback
|
|
2
|
+
// keeps a stray dev run from silently hitting production.
|
|
3
|
+
const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:3000";
|
|
4
|
+
|
|
5
|
+
export async function fetchSiteToken(): Promise<string | undefined> {
|
|
6
|
+
const secret = process.env.ZORGO_SITE_SECRET;
|
|
7
|
+
if (!secret) return undefined;
|
|
8
|
+
try {
|
|
9
|
+
const res = await fetch(`${API_BASE_URL}/auth/site-token`, {
|
|
10
|
+
method: "POST",
|
|
11
|
+
headers: { "x-zorgo-site-secret": secret },
|
|
12
|
+
next: { revalidate: 3600 },
|
|
13
|
+
});
|
|
14
|
+
if (!res.ok) return undefined;
|
|
15
|
+
const { token } = await res.json();
|
|
16
|
+
return token as string;
|
|
17
|
+
} catch {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { NextConfig } from "next";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
const monorepoRoot = path.resolve(__dirname, "../../..");
|
|
5
|
+
|
|
6
|
+
const nextConfig: NextConfig = {
|
|
7
|
+
outputFileTracingRoot: monorepoRoot,
|
|
8
|
+
turbopack: {
|
|
9
|
+
root: monorepoRoot,
|
|
10
|
+
},
|
|
11
|
+
transpilePackages: ["@zorgo", "@zorgo-website-core"],
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default nextConfig;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { PINNED_VERSIONS, DEV_DEPENDENCIES } from "../../../config-registry";
|
|
2
|
+
import type { ScaffoldOptions } from "../../types";
|
|
3
|
+
|
|
4
|
+
export default function generatePackageJson(opts: ScaffoldOptions): string {
|
|
5
|
+
return JSON.stringify(
|
|
6
|
+
{
|
|
7
|
+
name: opts.projectName,
|
|
8
|
+
version: "1.0.0",
|
|
9
|
+
private: true,
|
|
10
|
+
scripts: {
|
|
11
|
+
"dev": "tsx scripts/prebuild.ts && next dev",
|
|
12
|
+
"dev:no-prebuild": "next dev",
|
|
13
|
+
"prebuild": "tsx scripts/prebuild.ts",
|
|
14
|
+
"build": "tsx scripts/prebuild.ts && next build",
|
|
15
|
+
"cloudflare:deploy": "tsx scripts/prebuild.ts && opennextjs-cloudflare build && wrangler deploy",
|
|
16
|
+
"preview": "tsx scripts/prebuild.ts && opennextjs-cloudflare build && wrangler dev",
|
|
17
|
+
},
|
|
18
|
+
dependencies: PINNED_VERSIONS,
|
|
19
|
+
devDependencies: DEV_DEPENDENCIES,
|
|
20
|
+
},
|
|
21
|
+
null,
|
|
22
|
+
2,
|
|
23
|
+
);
|
|
24
|
+
}
|