bsmnt 0.2.11 → 0.3.1

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 (188) hide show
  1. package/dist/helpers/create/copy-template.d.ts +1 -1
  2. package/dist/helpers/create/copy-template.d.ts.map +1 -1
  3. package/dist/helpers/create/index.d.ts.map +1 -1
  4. package/dist/helpers/create/index.js +2 -1
  5. package/dist/helpers/create/index.js.map +1 -1
  6. package/dist/helpers/integrate/merge-config.d.ts.map +1 -1
  7. package/dist/helpers/integrate/merge-config.js +0 -2
  8. package/dist/helpers/integrate/merge-config.js.map +1 -1
  9. package/dist/helpers/integrate/sanity/config.d.ts.map +1 -1
  10. package/dist/helpers/integrate/sanity/config.js +2 -4
  11. package/dist/helpers/integrate/sanity/config.js.map +1 -1
  12. package/dist/index.js +84 -35
  13. package/dist/index.js.map +1 -1
  14. package/index.js +2 -2
  15. package/package.json +1 -1
  16. package/src/templates/next-default/.vscode/settings.json +1 -1
  17. package/src/templates/next-default/README.md +6 -7
  18. package/src/templates/next-default/app/layout.tsx +17 -4
  19. package/src/templates/next-default/biome.json +1 -1
  20. package/src/templates/next-default/css.d.ts +1 -0
  21. package/src/templates/next-default/lib/README.md +4 -8
  22. package/src/templates/next-default/lib/hooks/use-media.ts +3 -1
  23. package/src/templates/next-default/lib/styles/global.css +182 -0
  24. package/src/templates/next-default/lib/utils/json-ld.tsx +13 -18
  25. package/src/templates/next-default/lib/utils/portable-text-to-markdown.ts +83 -0
  26. package/src/templates/next-default/package.json +3 -3
  27. package/src/templates/next-experiments/.vscode/settings.json +1 -1
  28. package/src/templates/next-experiments/README.md +6 -7
  29. package/src/templates/next-experiments/app/layout.tsx +17 -4
  30. package/src/templates/next-experiments/biome.json +1 -1
  31. package/src/templates/next-experiments/css.d.ts +1 -0
  32. package/src/templates/next-experiments/lib/README.md +4 -8
  33. package/src/templates/next-experiments/lib/hooks/use-media.ts +3 -1
  34. package/src/templates/next-experiments/lib/styles/global.css +182 -0
  35. package/src/templates/next-experiments/lib/utils/json-ld.tsx +13 -18
  36. package/src/templates/next-experiments/lib/utils/portable-text-to-markdown.ts +83 -0
  37. package/src/templates/next-experiments/package.json +3 -3
  38. package/src/templates/next-pagebuilder/.env.example +11 -0
  39. package/src/templates/next-pagebuilder/README.md +23 -0
  40. package/src/templates/next-pagebuilder/_gitignore +67 -0
  41. package/src/templates/next-pagebuilder/app/(content)/[[...slug]]/page.tsx +68 -0
  42. package/src/templates/next-pagebuilder/app/(content)/layout.tsx +13 -0
  43. package/src/templates/next-pagebuilder/app/api/[[...slug]]/route.ts +100 -0
  44. package/src/templates/next-pagebuilder/app/api/draft-mode/disable/route.ts +7 -0
  45. package/src/templates/next-pagebuilder/app/api/draft-mode/enable/route.ts +20 -0
  46. package/src/templates/next-pagebuilder/app/api/revalidate/route.ts +121 -0
  47. package/src/templates/next-pagebuilder/app/favicon.ico +0 -0
  48. package/src/templates/next-pagebuilder/app/layout.tsx +80 -0
  49. package/src/templates/next-pagebuilder/app/robots.ts +15 -0
  50. package/src/templates/next-pagebuilder/app/sitemap.md/route.ts +124 -0
  51. package/src/templates/next-pagebuilder/app/sitemap.xml/route.ts +80 -0
  52. package/src/templates/next-pagebuilder/app/studio/[[...tool]]/page.tsx +8 -0
  53. package/src/templates/next-pagebuilder/biome.json +239 -0
  54. package/src/templates/next-pagebuilder/components/layout/footer/index.tsx +95 -0
  55. package/src/templates/next-pagebuilder/components/layout/header/components/cta-button.tsx +28 -0
  56. package/src/templates/next-pagebuilder/components/layout/header/components/mega-menu-panel.tsx +90 -0
  57. package/src/templates/next-pagebuilder/components/layout/header/components/nav-item-renderer.tsx +98 -0
  58. package/src/templates/next-pagebuilder/components/layout/header/components/nav-leaf-item.tsx +33 -0
  59. package/src/templates/next-pagebuilder/components/layout/header/components/types.ts +7 -0
  60. package/src/templates/next-pagebuilder/components/layout/header/header-client.tsx +110 -0
  61. package/src/templates/next-pagebuilder/components/layout/header/index.tsx +8 -0
  62. package/src/templates/next-pagebuilder/components/layout/json-ld/index.tsx +45 -0
  63. package/src/templates/next-pagebuilder/components/layout/wrapper/index.tsx +30 -0
  64. package/src/templates/next-pagebuilder/components/page-builder/components/article-content/index.tsx +83 -0
  65. package/src/templates/next-pagebuilder/components/page-builder/components/article-content/related-post-item.tsx +27 -0
  66. package/src/templates/next-pagebuilder/components/page-builder/components/description.tsx +17 -0
  67. package/src/templates/next-pagebuilder/components/page-builder/components/hero.tsx +17 -0
  68. package/src/templates/next-pagebuilder/components/page-builder/components/post-collection/content-card.tsx +66 -0
  69. package/src/templates/next-pagebuilder/components/page-builder/components/post-collection/content-grid.tsx +42 -0
  70. package/src/templates/next-pagebuilder/components/page-builder/components/post-collection/index.tsx +28 -0
  71. package/src/templates/next-pagebuilder/components/page-builder/components/post-collection/types.ts +16 -0
  72. package/src/templates/next-pagebuilder/components/page-builder/renderer.tsx +36 -0
  73. package/src/templates/next-pagebuilder/components/page-builder/types.ts +23 -0
  74. package/src/templates/next-pagebuilder/components/page-document/index.tsx +91 -0
  75. package/src/templates/next-pagebuilder/components/sanity/draft-mode-toggle.tsx +27 -0
  76. package/src/templates/next-pagebuilder/components/sanity/rich-text.tsx +87 -0
  77. package/src/templates/next-pagebuilder/components/sanity/visual-editing.tsx +27 -0
  78. package/src/templates/next-pagebuilder/components/ui/image/index.tsx +216 -0
  79. package/src/templates/next-pagebuilder/components/ui/link/index.tsx +152 -0
  80. package/src/templates/next-pagebuilder/components/ui/sanity-image/index.tsx +41 -0
  81. package/src/templates/next-pagebuilder/lib/integrations/check-integration.ts +5 -0
  82. package/src/templates/next-pagebuilder/lib/integrations/sanity/client.ts +27 -0
  83. package/src/templates/next-pagebuilder/lib/integrations/sanity/components/disable-draft-mode.tsx +23 -0
  84. package/src/templates/next-pagebuilder/lib/integrations/sanity/components/page-builder-input.tsx +36 -0
  85. package/src/templates/next-pagebuilder/lib/integrations/sanity/components/page-category-input.tsx +50 -0
  86. package/src/templates/next-pagebuilder/lib/integrations/sanity/components/rich-text.tsx +84 -0
  87. package/src/templates/next-pagebuilder/lib/integrations/sanity/confirm-publish-action.ts +40 -0
  88. package/src/templates/next-pagebuilder/lib/integrations/sanity/env.ts +34 -0
  89. package/src/templates/next-pagebuilder/lib/integrations/sanity/fetchers/layout.ts +35 -0
  90. package/src/templates/next-pagebuilder/lib/integrations/sanity/icons.ts +58 -0
  91. package/src/templates/next-pagebuilder/lib/integrations/sanity/live/index.tsx +61 -0
  92. package/src/templates/next-pagebuilder/lib/integrations/sanity/markdown-proxy.config.ts +50 -0
  93. package/src/templates/next-pagebuilder/lib/integrations/sanity/page-builder-config.ts +132 -0
  94. package/src/templates/next-pagebuilder/lib/integrations/sanity/page-category.ts +28 -0
  95. package/src/templates/next-pagebuilder/lib/integrations/sanity/queries.ts +281 -0
  96. package/src/templates/next-pagebuilder/lib/integrations/sanity/sanity.cli.ts +29 -0
  97. package/src/templates/next-pagebuilder/lib/integrations/sanity/sanity.config.ts +211 -0
  98. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/components/index.ts +4 -0
  99. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/components/reusable/blog-content.ts +89 -0
  100. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/components/reusable/description.ts +29 -0
  101. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/components/reusable/hero.ts +28 -0
  102. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/components/singleton/content-collection.ts +45 -0
  103. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/content/author.ts +70 -0
  104. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/content/blog-category.ts +55 -0
  105. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/index.ts +96 -0
  106. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/layout/company-data.ts +62 -0
  107. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/layout/footer.ts +79 -0
  108. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/layout/navbar.ts +74 -0
  109. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/shared/link.ts +125 -0
  110. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/shared/logo-field.ts +9 -0
  111. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/shared/metadata.ts +68 -0
  112. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/shared/nav-objects.ts +192 -0
  113. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/shared/page-builder.ts +39 -0
  114. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/shared/page-folder.ts +124 -0
  115. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/shared/page.ts +232 -0
  116. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/shared/richText.ts +63 -0
  117. package/src/templates/next-pagebuilder/lib/integrations/sanity/singletons.ts +44 -0
  118. package/src/templates/next-pagebuilder/lib/integrations/sanity/structure.ts +453 -0
  119. package/src/templates/next-pagebuilder/lib/integrations/sanity/utils/image.ts +8 -0
  120. package/src/templates/next-pagebuilder/lib/integrations/sanity/utils/link.ts +137 -0
  121. package/src/templates/next-pagebuilder/lib/integrations/sanity/utils/page-builder-markdown.ts +81 -0
  122. package/src/templates/next-pagebuilder/lib/scripts/sanity-typegen.ts +45 -0
  123. package/src/templates/next-pagebuilder/lib/styles/cn.ts +5 -0
  124. package/src/templates/next-pagebuilder/lib/styles/global.css +70 -0
  125. package/src/templates/next-pagebuilder/lib/utils/base-url.ts +17 -0
  126. package/src/templates/next-pagebuilder/lib/utils/format-date.ts +8 -0
  127. package/src/templates/next-pagebuilder/lib/utils/json-ld.tsx +213 -0
  128. package/src/templates/next-pagebuilder/lib/utils/metadata.ts +167 -0
  129. package/src/templates/next-pagebuilder/lib/utils/sitemap.ts +37 -0
  130. package/src/templates/next-pagebuilder/lib/utils/slug-tag.ts +6 -0
  131. package/src/templates/next-pagebuilder/next.config.ts +134 -0
  132. package/src/templates/next-pagebuilder/package.json +71 -0
  133. package/src/templates/next-pagebuilder/postcss.config.mjs +39 -0
  134. package/src/templates/next-pagebuilder/proxy.ts +81 -0
  135. package/src/templates/next-pagebuilder/svg.d.ts +5 -0
  136. package/src/templates/next-pagebuilder/tsconfig.json +38 -0
  137. package/src/templates/next-webgl/.vscode/settings.json +1 -1
  138. package/src/templates/next-webgl/README.md +6 -7
  139. package/src/templates/next-webgl/app/layout.tsx +17 -4
  140. package/src/templates/next-webgl/biome.json +1 -1
  141. package/src/templates/next-webgl/css.d.ts +1 -0
  142. package/src/templates/next-webgl/lib/README.md +4 -8
  143. package/src/templates/next-webgl/lib/hooks/use-media.ts +3 -1
  144. package/src/templates/next-webgl/lib/styles/global.css +182 -0
  145. package/src/templates/next-webgl/lib/utils/json-ld.tsx +13 -18
  146. package/src/templates/next-webgl/lib/utils/portable-text-to-markdown.ts +83 -0
  147. package/src/templates/next-webgl/package.json +3 -3
  148. package/src/helpers/integrate/sanity/files/lib/scripts/copy-sanity-mcp.ts +0 -23
  149. package/src/helpers/integrate/sanity/files/lib/scripts/generate-page.ts +0 -297
  150. package/src/templates/next-default/lib/scripts/dev.ts +0 -32
  151. package/src/templates/next-default/lib/styles/README.md +0 -13
  152. package/src/templates/next-default/lib/styles/fonts.ts +0 -20
  153. package/src/templates/next-default/lib/styles/index.css +0 -3
  154. package/src/templates/next-default/lib/styles/tokens.css +0 -179
  155. package/src/templates/next-default/lib/utils/README.md +0 -40
  156. package/src/templates/next-default/lib/utils/easings.ts +0 -240
  157. package/src/templates/next-default/lib/utils/fetch.ts +0 -84
  158. package/src/templates/next-default/lib/utils/global-css.d.ts +0 -1
  159. package/src/templates/next-default/lib/utils/math.ts +0 -236
  160. package/src/templates/next-default/lib/utils/strings.ts +0 -246
  161. package/src/templates/next-default/lib/utils/types.d.ts +0 -15
  162. package/src/templates/next-default/lib/utils/viewport.ts +0 -199
  163. package/src/templates/next-experiments/lib/scripts/dev.ts +0 -32
  164. package/src/templates/next-experiments/lib/styles/README.md +0 -13
  165. package/src/templates/next-experiments/lib/styles/fonts.ts +0 -20
  166. package/src/templates/next-experiments/lib/styles/index.css +0 -3
  167. package/src/templates/next-experiments/lib/styles/tokens.css +0 -179
  168. package/src/templates/next-experiments/lib/utils/README.md +0 -40
  169. package/src/templates/next-experiments/lib/utils/easings.ts +0 -240
  170. package/src/templates/next-experiments/lib/utils/fetch.ts +0 -84
  171. package/src/templates/next-experiments/lib/utils/global-css.d.ts +0 -1
  172. package/src/templates/next-experiments/lib/utils/math.ts +0 -236
  173. package/src/templates/next-experiments/lib/utils/strings.ts +0 -246
  174. package/src/templates/next-experiments/lib/utils/types.d.ts +0 -15
  175. package/src/templates/next-experiments/lib/utils/viewport.ts +0 -199
  176. package/src/templates/next-webgl/lib/scripts/dev.ts +0 -32
  177. package/src/templates/next-webgl/lib/styles/README.md +0 -13
  178. package/src/templates/next-webgl/lib/styles/fonts.ts +0 -20
  179. package/src/templates/next-webgl/lib/styles/index.css +0 -3
  180. package/src/templates/next-webgl/lib/styles/tokens.css +0 -179
  181. package/src/templates/next-webgl/lib/utils/README.md +0 -40
  182. package/src/templates/next-webgl/lib/utils/easings.ts +0 -240
  183. package/src/templates/next-webgl/lib/utils/fetch.ts +0 -84
  184. package/src/templates/next-webgl/lib/utils/global-css.d.ts +0 -1
  185. package/src/templates/next-webgl/lib/utils/math.ts +0 -236
  186. package/src/templates/next-webgl/lib/utils/strings.ts +0 -246
  187. package/src/templates/next-webgl/lib/utils/types.d.ts +0 -15
  188. package/src/templates/next-webgl/lib/utils/viewport.ts +0 -199
@@ -0,0 +1,83 @@
1
+ export interface PortableTextMarkDefinition {
2
+ _key?: string;
3
+ _type?: string;
4
+ href?: string;
5
+ }
6
+
7
+ export interface PortableTextSpan {
8
+ _type?: string;
9
+ text?: string;
10
+ marks?: string[];
11
+ }
12
+
13
+ export interface PortableTextBlock {
14
+ _type?: string;
15
+ style?: string;
16
+ listItem?: "bullet" | "number";
17
+ level?: number;
18
+ children?: PortableTextSpan[];
19
+ markDefs?: PortableTextMarkDefinition[];
20
+ }
21
+
22
+ const headingStyles: Record<string, string> = {
23
+ h1: "#",
24
+ h2: "##",
25
+ h3: "###",
26
+ h4: "####",
27
+ h5: "#####",
28
+ h6: "######",
29
+ }
30
+
31
+ function applyMarks(
32
+ text: string,
33
+ marks: string[] | undefined,
34
+ markDefs: PortableTextMarkDefinition[]
35
+ ) {
36
+ return (marks ?? []).reduce((result, mark) => {
37
+ if (mark === "strong") return `**${result}**`
38
+ if (mark === "em") return `*${result}*`
39
+ if (mark === "code") return `\`${result}\``
40
+
41
+ const link = markDefs.find((definition) => definition._key === mark)
42
+ if (link?._type === "link" && link.href) {
43
+ return `[${result}](${link.href})`
44
+ }
45
+
46
+ return result
47
+ }, text)
48
+ }
49
+
50
+ function serializeBlock(block: PortableTextBlock) {
51
+ const text = (block.children ?? [])
52
+ .map((child) =>
53
+ applyMarks(child.text ?? "", child.marks, block.markDefs ?? [])
54
+ )
55
+ .join("")
56
+ .trim()
57
+
58
+ if (!text) return ""
59
+
60
+ if (block.listItem) {
61
+ const level = Math.max((block.level ?? 1) - 1, 0)
62
+ const indent = " ".repeat(level)
63
+ const marker = block.listItem === "number" ? "1." : "-"
64
+ return `${indent}${marker} ${text}`
65
+ }
66
+
67
+ if (block.style === "blockquote") {
68
+ return `> ${text}`
69
+ }
70
+
71
+ const headingPrefix = headingStyles[block.style ?? ""]
72
+ if (headingPrefix) {
73
+ return `${headingPrefix} ${text}`
74
+ }
75
+
76
+ return text
77
+ }
78
+
79
+ export function portableTextToMarkdown(
80
+ value: PortableTextBlock[] | null | undefined
81
+ ) {
82
+ return (value ?? []).map(serializeBlock).filter(Boolean).join("\n\n")
83
+ }
@@ -8,9 +8,9 @@
8
8
  "analyze": "cross-env ANALYZE=true bun run build",
9
9
  "analyze:experimental": "next experimental-analyze",
10
10
  "build": "next build",
11
- "dev": "bun ./lib/scripts/dev.ts",
12
- "dev:https": "bun ./lib/scripts/dev.ts --https",
13
- "dev:inspect": "bun ./lib/scripts/dev.ts --inspect",
11
+ "dev": "next dev",
12
+ "dev:https": "next dev --experimental-https",
13
+ "dev:inspect": "next dev --inspect",
14
14
  "format": "biome format --write .",
15
15
  "lighthouse": "bunx @unlighthouse/cli --site http://localhost:3000",
16
16
  "lint": "biome lint --max-diagnostics=200",
@@ -1,23 +0,0 @@
1
- /**
2
- * Cross-platform Sanity MCP setup helper
3
- * Copies the Cursor deeplink to clipboard on macOS/Linux/Windows
4
- */
5
-
6
- import { copyToClipboard } from "./utils";
7
-
8
- const link =
9
- "cursor://anysphere.cursor-deeplink/mcp/install?name=Sanity&config=eyJ1cmwiOiJodHRwczovL21jcC5zYW5pdHkuaW8iLCJ0eXBlIjoiaHR0cCJ9Cg==";
10
-
11
- const copied = await copyToClipboard(link);
12
-
13
- console.log("\n🔗 Sanity MCP Setup for Cursor\n");
14
-
15
- if (copied) {
16
- console.log("✅ Link copied to clipboard!");
17
- console.log(" Paste it in your browser or Cursor address bar.\n");
18
- } else {
19
- console.log("📋 Copy this link manually:\n");
20
- console.log(` ${link}\n`);
21
- }
22
-
23
- console.log("This will install the Sanity MCP server in Cursor.");
@@ -1,297 +0,0 @@
1
- #!/usr/bin/env bun
2
- /**
3
- * Generate Page Module
4
- *
5
- * Generates new pages with pre-configured templates through interactive prompts.
6
- * Used by the unified generator: `bun run generate`
7
- *
8
- * Cross-platform compatible (Windows, macOS, Linux)
9
- */
10
-
11
- import * as p from "@clack/prompts";
12
- import { createDir } from "./utils";
13
-
14
- interface PageOptions {
15
- webgl?: boolean;
16
- sanity?: boolean;
17
- theme?: string;
18
- css?: boolean;
19
- }
20
-
21
- export interface PageConfig {
22
- name: string;
23
- options: PageOptions;
24
- }
25
-
26
- /**
27
- * Interactive prompts for page configuration
28
- */
29
- export const promptPageConfig = async (): Promise<PageConfig> => {
30
- const name = await p.text({
31
- message: "What should the page be called?",
32
- placeholder: "about, contact, products",
33
- validate: (value) => {
34
- if (!value) return "Page name is required";
35
- if (!/^[a-zA-Z][a-zA-Z0-9-_]*$/.test(value)) {
36
- return "Page name must start with a letter and contain only letters, numbers, hyphens, and underscores";
37
- }
38
- return undefined;
39
- },
40
- });
41
-
42
- if (p.isCancel(name)) {
43
- p.cancel("Page generation cancelled");
44
- process.exit(0);
45
- }
46
-
47
- const theme = await p.select({
48
- message: "Choose a theme for the page",
49
- options: [
50
- { value: "dark", label: "Dark (default)", hint: "Standard dark theme" },
51
- { value: "light", label: "Light", hint: "Light theme" },
52
- { value: "red", label: "Red", hint: "Red accent theme" },
53
- ],
54
- initialValue: "dark",
55
- });
56
-
57
- if (p.isCancel(theme)) {
58
- p.cancel("Page generation cancelled");
59
- process.exit(0);
60
- }
61
-
62
- const integrations = await p.multiselect({
63
- message: "Which integrations should this page use?",
64
- options: [
65
- { value: "webgl", label: "WebGL Canvas", hint: "Enable 3D graphics" },
66
- { value: "sanity", label: "Sanity CMS", hint: "Content management" },
67
- ],
68
- required: false,
69
- });
70
-
71
- if (p.isCancel(integrations)) {
72
- p.cancel("Page generation cancelled");
73
- process.exit(0);
74
- }
75
-
76
- const includeCss = await p.confirm({
77
- message: "Include a CSS module file?",
78
- initialValue: false,
79
- });
80
-
81
- if (p.isCancel(includeCss)) {
82
- p.cancel("Page generation cancelled");
83
- process.exit(0);
84
- }
85
-
86
- return {
87
- name,
88
- options: {
89
- theme,
90
- webgl: integrations.includes("webgl"),
91
- sanity: integrations.includes("sanity"),
92
- css: includeCss,
93
- },
94
- };
95
- };
96
-
97
- /**
98
- * Generate page.tsx content
99
- */
100
- const generatePageContent = (
101
- pageName: string,
102
- options: PageOptions,
103
- ): string => {
104
- const { webgl, sanity, theme = "dark" } = options;
105
-
106
- // Capitalize first letter for title
107
- const title = pageName.charAt(0).toUpperCase() + pageName.slice(1);
108
-
109
- // Build imports
110
- const imports: string[] = [];
111
- imports.push(`import type { Metadata } from 'next'`);
112
- imports.push(`import { Wrapper } from '@/components/layout/wrapper'`);
113
-
114
- // Integration-specific imports
115
- if (sanity) {
116
- imports.push(
117
- `import { NotConfigured } from '@/components/ui/not-configured'`,
118
- );
119
- }
120
-
121
- if (sanity) {
122
- imports.push(
123
- `import { isSanityConfigured } from '@/lib/integrations/check-integration'`,
124
- );
125
- // sanityFetch and generateSanityMetadata are available for use:
126
- // import { sanityFetch } from 'next-sanity/live'
127
- // import { generateSanityMetadata } from '@/lib/utils/metadata'
128
- }
129
-
130
- // Build wrapper props
131
- const wrapperProps: string[] = [`theme="${theme}"`];
132
- if (webgl) {
133
- wrapperProps.push("webgl");
134
- }
135
-
136
- // Build component body based on integrations
137
- let componentBody: string;
138
-
139
- if (sanity) {
140
- // Sanity only
141
- componentBody = ` // Show setup instructions if Sanity is not configured
142
- if (!isSanityConfigured()) {
143
- return (
144
- <Wrapper theme="${theme}">
145
- <NotConfigured integration="Sanity" />
146
- </Wrapper>
147
- )
148
- }
149
-
150
- // TODO: Create a GROQ query for this page's content type
151
- // const { data } = await sanityFetch({
152
- // query: yourQuery,
153
- // params: { slug: '${pageName}' },
154
- // })
155
-
156
- return (
157
- <Wrapper ${wrapperProps.join(" ")}>
158
- <section className="dr-py-100">
159
- <div className="container">
160
- <h1>${title}</h1>
161
- {/* Your content here */}
162
- {/* Fetch data from Sanity using a custom query */}
163
- </div>
164
- </section>
165
- </Wrapper>
166
- )`;
167
- } else {
168
- // No integrations
169
- componentBody = ` return (
170
- <Wrapper ${wrapperProps.join(" ")}>
171
- <section className="dr-py-100">
172
- <div className="container">
173
- <h1>${title}</h1>
174
- {/* Your content here */}
175
- </div>
176
- </section>
177
- </Wrapper>
178
- )`;
179
- }
180
-
181
- // Build metadata export
182
- let metadataExport: string;
183
- if (sanity) {
184
- metadataExport = `
185
- export async function generateMetadata(): Promise<Metadata> {
186
- if (!isSanityConfigured()) {
187
- return {
188
- title: '${title}',
189
- description: '${title} page description',
190
- }
191
- }
192
-
193
- // TODO: Fetch metadata from Sanity using a custom query
194
- // const { data } = await sanityFetch({
195
- // query: yourQuery,
196
- // params: { slug: '${pageName}' },
197
- // })
198
-
199
- return {
200
- title: '${title}',
201
- description: '${title} page description',
202
- }
203
- }`;
204
- } else {
205
- metadataExport = `
206
- export const metadata: Metadata = {
207
- title: '${title}',
208
- description: '${title} page description',
209
- }`;
210
- }
211
-
212
- // Determine if component should be async
213
- const isAsync = sanity;
214
-
215
- return `${imports.join("\n")}
216
- ${metadataExport}
217
-
218
- export default ${isAsync ? "async " : ""}function ${title}Page() {
219
- ${componentBody}
220
- }
221
- `;
222
- };
223
-
224
- /**
225
- * Create page files and directories
226
- */
227
- export const createPage = async (
228
- pageName: string,
229
- options: PageOptions,
230
- ): Promise<void> => {
231
- const s = p.spinner();
232
-
233
- try {
234
- // Create directory structure
235
- const pageDir = `app/${pageName}`;
236
- const componentsDir = `${pageDir}/_components`;
237
-
238
- s.start(`Creating page structure for "${pageName}"`);
239
-
240
- // Create main page directory (cross-platform)
241
- await createDir(pageDir);
242
-
243
- // Create _components subdirectory (cross-platform)
244
- await createDir(componentsDir);
245
-
246
- // Create .gitkeep in _components
247
- await Bun.write(`${componentsDir}/.gitkeep`, "");
248
-
249
- // Generate and write page.tsx
250
- const pageContent = generatePageContent(pageName, options);
251
- await Bun.write(`${pageDir}/page.tsx`, pageContent);
252
-
253
- // Create CSS module if requested
254
- if (options.css) {
255
- const cssContent = `/* ${pageName}.module.css */
256
-
257
- .container {
258
- /* Add your styles here */
259
- }
260
- `;
261
- await Bun.write(`${pageDir}/${pageName}.module.css`, cssContent);
262
- }
263
-
264
- s.stop(`Page "${pageName}" generated successfully!`);
265
-
266
- // Show what was created
267
- p.log.success(`Generated files:`);
268
- p.log.message(` 📄 ${pageDir}/page.tsx`);
269
- p.log.message(` 📁 ${componentsDir}/`);
270
- if (options.css) {
271
- p.log.message(` 🎨 ${pageDir}/${pageName}.module.css`);
272
- }
273
-
274
- // Build next steps message
275
- const nextSteps = [`1. Customize ${pageDir}/page.tsx`];
276
-
277
- if (options.sanity) {
278
- nextSteps.push(
279
- `2. Create a "${pageName}" page in Sanity Studio at /studio`,
280
- );
281
- }
282
-
283
- nextSteps.push(
284
- `${nextSteps.length + 1}. Add components to ${componentsDir}/`,
285
- );
286
- nextSteps.push(
287
- `${nextSteps.length + 1}. Visit /${pageName} to see your page`,
288
- );
289
-
290
- p.note(`Next steps:\n ${nextSteps.join("\n ")}`);
291
- } catch (error) {
292
- s.stop(`Failed to generate page "${pageName}"`);
293
- throw error;
294
- }
295
- };
296
-
297
- // Export functions for use by unified generate script
@@ -1,32 +0,0 @@
1
- /**
2
- * Cross-platform Next.js dev launcher.
3
- */
4
-
5
- import { bunExecutable, colorEnv } from "./utils"
6
-
7
- const isHttps = process.argv.includes("--https")
8
- const isInspect = process.argv.includes("--inspect")
9
-
10
- // Build next dev command args
11
- const nextDevArgs = [bunExecutable, "next", "dev"]
12
- if (isHttps) nextDevArgs.push("--experimental-https")
13
- if (isInspect) nextDevArgs.push("--inspect")
14
-
15
- const devEnv = colorEnv()
16
-
17
- const nextDevProcess = Bun.spawn(nextDevArgs, {
18
- stdout: "inherit",
19
- stderr: "inherit",
20
- env: devEnv,
21
- })
22
-
23
- const cleanup = () => {
24
- nextDevProcess.kill()
25
- process.exit(0)
26
- }
27
-
28
- process.on("SIGINT", cleanup)
29
- process.on("SIGTERM", cleanup)
30
-
31
- await nextDevProcess.exited
32
- cleanup()
@@ -1,13 +0,0 @@
1
- # Styles
2
-
3
- Minimal Tailwind setup for the starter.
4
-
5
- ## Files
6
-
7
- | File | Purpose |
8
- |------|---------|
9
- | `index.css` | Single stylesheet entrypoint imported by `app/layout.tsx` |
10
- | `tokens.css` | Theme variables, breakpoints, and custom Tailwind utilities |
11
- | `global.css` | Reset and global app styles |
12
- | `fonts.ts` | Font variable setup |
13
- | `cn.ts` | Tailwind class merging helper |
@@ -1,20 +0,0 @@
1
- import { Geist_Mono } from "next/font/google";
2
-
3
- const mono = Geist_Mono({
4
- subsets: ["latin"],
5
- display: "swap",
6
- variable: "--geist-mono",
7
- fallback: [
8
- "ui-monospace",
9
- "SFMono-Regular",
10
- "Consolas",
11
- "Liberation Mono",
12
- "Menlo",
13
- "monospace",
14
- ],
15
- });
16
-
17
- const fonts = [mono];
18
- const fontsVariable = fonts.map((font) => font.variable).join(" ");
19
-
20
- export { fontsVariable };
@@ -1,3 +0,0 @@
1
- @import "tailwindcss/utilities.css";
2
- @import "./tokens.css";
3
- @import "./global.css";
@@ -1,179 +0,0 @@
1
- @custom-media --hover (hover: hover);
2
- @custom-media --reduced-motion (prefers-reduced-motion: reduce);
3
- @custom-media --mobile-only (width < 768px);
4
- @custom-media --tablet (width >= 768px);
5
- @custom-media --tablet-lg (width >= 1024px);
6
- @custom-media --desktop (width >= 1440px);
7
- @custom-media --desktop-large (width >= 1920px);
8
-
9
- :root {
10
- --device-width: 640;
11
- --device-height: 650;
12
- --columns: 4;
13
- --gap: 16px;
14
- --safe: 16px;
15
- --header-height: 58px;
16
- --layout-width: calc(100vw - (2 * var(--safe)));
17
- --column-width: calc(
18
- (var(--layout-width) - (var(--columns) - 1) * var(--gap)) / var(--columns)
19
- );
20
- --ease-in-quad: cubic-bezier(0.55, 0.085, 0.68, 0.53);
21
- --ease-in-cubic: cubic-bezier(0.55, 0.055, 0.675, 0.19);
22
- --ease-in-quart: cubic-bezier(0.895, 0.03, 0.685, 0.22);
23
- --ease-in-quint: cubic-bezier(0.755, 0.05, 0.855, 0.06);
24
- --ease-in-expo: cubic-bezier(0.95, 0.05, 0.795, 0.035);
25
- --ease-in-circ: cubic-bezier(0.6, 0.04, 0.98, 0.335);
26
- --ease-out-quad: cubic-bezier(0.25, 0.46, 0.45, 0.94);
27
- --ease-out-cubic: cubic-bezier(0.215, 0.61, 0.355, 1);
28
- --ease-out-quart: cubic-bezier(0.165, 0.84, 0.44, 1);
29
- --ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1);
30
- --ease-out-expo: cubic-bezier(0.19, 1, 0.22, 1);
31
- --ease-out-circ: cubic-bezier(0.075, 0.82, 0.165, 1);
32
- --ease-in-out-quad: cubic-bezier(0.455, 0.03, 0.515, 0.955);
33
- --ease-in-out-cubic: cubic-bezier(0.645, 0.045, 0.355, 1);
34
- --ease-in-out-quart: cubic-bezier(0.77, 0, 0.175, 1);
35
- --ease-in-out-quint: cubic-bezier(0.86, 0, 0.07, 1);
36
- --ease-in-out-expo: cubic-bezier(1, 0, 0, 1);
37
- --ease-in-out-circ: cubic-bezier(0.785, 0.135, 0.15, 0.86);
38
- --ease-gleasing: cubic-bezier(0.4, 0, 0, 1);
39
- --color-black: #000000;
40
- --color-white: #ffffff;
41
- --color-orange: #ff4d00;
42
- --color-blue: #487cff;
43
- --color-green: #00ff9b;
44
- --color-violet: #f101a5;
45
- --color-pink: #ff73a6;
46
- --color-gray: #666666;
47
-
48
- @variant desktop {
49
- --device-width: 1440;
50
- --device-height: 816;
51
- --columns: 12;
52
- --header-height: 98px;
53
- }
54
- }
55
-
56
- @theme {
57
- --breakpoint-*: initial;
58
- --breakpoint-desktop-large: 1920px;
59
- --breakpoint-desktop: 1440px;
60
- --breakpoint-tablet-lg: 1024px;
61
- --breakpoint-tablet: 768px;
62
- --breakpoint-mobile: 640px;
63
-
64
- --color-*: initial;
65
- --color-primary: #ffffff;
66
- --color-secondary: #000000;
67
- --color-contrast: #ff4d00;
68
- --color-black: #000000;
69
- --color-white: #ffffff;
70
- --color-orange: #ff4d00;
71
- --color-blue: #487cff;
72
- --color-green: #00ff9b;
73
- --color-violet: #f101a5;
74
- --color-pink: #ff73a6;
75
- --color-gray: #666666;
76
- --color-gray-50: #f5f5f5;
77
- --color-gray-100: #e0e0e0;
78
- --color-gray-200: #c2c2c2;
79
- --color-gray-300: #a3a3a3;
80
- --color-gray-400: #858585;
81
- --color-gray-500: #666666;
82
- --color-gray-600: #4d4d4d;
83
- --color-gray-700: #333333;
84
- --color-gray-800: #1a1a1a;
85
-
86
- --spacing: 0.25rem;
87
- --spacing-0: 0;
88
- --spacing-safe: var(--safe);
89
- --spacing-gap: var(--gap);
90
- --spacing-header-height: var(--header-height);
91
-
92
- --font-*: initial;
93
- --font-mono: var(--geist-mono);
94
-
95
- --ease-*: initial;
96
- --ease-in-quad: var(--ease-in-quad);
97
- --ease-in-cubic: var(--ease-in-cubic);
98
- --ease-in-quart: var(--ease-in-quart);
99
- --ease-in-quint: var(--ease-in-quint);
100
- --ease-in-expo: var(--ease-in-expo);
101
- --ease-in-circ: var(--ease-in-circ);
102
- --ease-out-quad: var(--ease-out-quad);
103
- --ease-out-cubic: var(--ease-out-cubic);
104
- --ease-out-quart: var(--ease-out-quart);
105
- --ease-out-quint: var(--ease-out-quint);
106
- --ease-out-expo: var(--ease-out-expo);
107
- --ease-out-circ: var(--ease-out-circ);
108
- --ease-in-out-quad: var(--ease-in-out-quad);
109
- --ease-in-out-cubic: var(--ease-in-out-cubic);
110
- --ease-in-out-quart: var(--ease-in-out-quart);
111
- --ease-in-out-quint: var(--ease-in-out-quint);
112
- --ease-in-out-expo: var(--ease-in-out-expo);
113
- --ease-in-out-circ: var(--ease-in-out-circ);
114
- --ease-gleasing: var(--ease-gleasing);
115
- }
116
-
117
- [data-theme="light"] {
118
- --color-primary: #ffffff;
119
- --color-secondary: #000000;
120
- --color-contrast: #ff4d00;
121
- }
122
-
123
- [data-theme="dark"] {
124
- --color-primary: #000000;
125
- --color-secondary: #ffffff;
126
- --color-contrast: #ff4d00;
127
- }
128
-
129
- @utility test-mono {
130
- font-family: var(--geist-mono);
131
- font-size: 20px;
132
- font-style: normal;
133
- font-weight: 400;
134
- letter-spacing: 0;
135
- line-height: 90%;
136
-
137
- @variant desktop {
138
- font-size: 24px;
139
- }
140
- }
141
-
142
- @utility desktop-only {
143
- @media (--mobile-only) {
144
- display: none !important;
145
- }
146
- }
147
-
148
- @utility mobile-only {
149
- @media (--tablet) {
150
- display: none !important;
151
- }
152
- }
153
-
154
- @utility b-grid {
155
- column-gap: var(--gap);
156
- display: grid;
157
- grid-template-columns: repeat(var(--columns), minmax(0, 1fr));
158
- }
159
-
160
- @utility b-layout-block {
161
- margin-inline: auto;
162
- width: calc(100% - 2 * var(--safe));
163
- }
164
-
165
- @utility b-layout-block-inner {
166
- padding-inline: var(--safe);
167
- width: 100%;
168
- }
169
-
170
- @utility b-layout-grid {
171
- @apply b-layout-block b-grid;
172
- }
173
-
174
- @utility b-layout-grid-inner {
175
- @apply b-layout-block-inner b-grid;
176
- }
177
-
178
- @custom-variant light (&:where([data-theme="light"], [data-theme="light"] *));
179
- @custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));