@estation/create-cms-site 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.
Files changed (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +81 -0
  3. package/dist/index.d.ts +3 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +91 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/tools/list-sections.d.ts +19 -0
  8. package/dist/tools/list-sections.d.ts.map +1 -0
  9. package/dist/tools/list-sections.js +152 -0
  10. package/dist/tools/list-sections.js.map +1 -0
  11. package/dist/tools/scaffold-project.d.ts +11 -0
  12. package/dist/tools/scaffold-project.d.ts.map +1 -0
  13. package/dist/tools/scaffold-project.js +90 -0
  14. package/dist/tools/scaffold-project.js.map +1 -0
  15. package/dist/tools/validate-config.d.ts +9 -0
  16. package/dist/tools/validate-config.d.ts.map +1 -0
  17. package/dist/tools/validate-config.js +72 -0
  18. package/dist/tools/validate-config.js.map +1 -0
  19. package/dist/utils/helpers.d.ts +2 -0
  20. package/dist/utils/helpers.d.ts.map +1 -0
  21. package/dist/utils/helpers.js +5 -0
  22. package/dist/utils/helpers.js.map +1 -0
  23. package/package.json +36 -0
  24. package/template/.env.example +9 -0
  25. package/template/LIVE-PREVIEW.md +267 -0
  26. package/template/README.md +210 -0
  27. package/template/next.config.ts +14 -0
  28. package/template/package.json +24 -0
  29. package/template/postcss.config.mjs +8 -0
  30. package/template/src/app/[slug]/page.tsx +38 -0
  31. package/template/src/app/api/revalidate/route.ts +34 -0
  32. package/template/src/app/blog/[slug]/page.tsx +60 -0
  33. package/template/src/app/blog/page.tsx +68 -0
  34. package/template/src/app/collections/[uuid]/page.tsx +28 -0
  35. package/template/src/app/events/[slug]/page.tsx +62 -0
  36. package/template/src/app/events/page.tsx +70 -0
  37. package/template/src/app/layout.tsx +27 -0
  38. package/template/src/app/news/[slug]/page.tsx +66 -0
  39. package/template/src/app/news/page.tsx +68 -0
  40. package/template/src/app/page.tsx +40 -0
  41. package/template/src/app/search/page.tsx +136 -0
  42. package/template/src/app/sitemap.ts +48 -0
  43. package/template/src/components/Footer.tsx +47 -0
  44. package/template/src/components/Navigation.tsx +65 -0
  45. package/template/src/components/SectionRenderer.tsx +43 -0
  46. package/template/src/components/cms-preview-listener.tsx +114 -0
  47. package/template/src/components/sections/CTASection.tsx +32 -0
  48. package/template/src/components/sections/ContactSection.tsx +74 -0
  49. package/template/src/components/sections/FAQSection.tsx +48 -0
  50. package/template/src/components/sections/FeaturesSection.tsx +42 -0
  51. package/template/src/components/sections/GallerySection.tsx +44 -0
  52. package/template/src/components/sections/GenericSection.tsx +63 -0
  53. package/template/src/components/sections/HeroSection.tsx +27 -0
  54. package/template/src/components/sections/SliderSection.tsx +66 -0
  55. package/template/src/components/sections/TestimonialsSection.tsx +52 -0
  56. package/template/src/components/sections/TextSection.tsx +31 -0
  57. package/template/src/lib/cms-api.ts +103 -0
  58. package/template/src/lib/content-helpers.ts +18 -0
  59. package/template/src/lib/types.ts +109 -0
  60. package/template/src/styles/globals.css +1 -0
  61. package/template/tsconfig.json +23 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 eSTATION
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,81 @@
1
+ # @estation/create-cms-site
2
+
3
+ MCP server that scaffolds new Next.js sites powered by [eSTATION CMS](https://estation.io).
4
+
5
+ ## Usage
6
+
7
+ ### Claude Desktop
8
+
9
+ Add to your `claude_desktop_config.json`:
10
+
11
+ ```json
12
+ {
13
+ "mcpServers": {
14
+ "create-cms-site": {
15
+ "command": "npx",
16
+ "args": ["-y", "@estation/create-cms-site"]
17
+ }
18
+ }
19
+ }
20
+ ```
21
+
22
+ ### Claude Code
23
+
24
+ ```bash
25
+ claude mcp add create-cms-site -- npx -y @estation/create-cms-site
26
+ ```
27
+
28
+ ## Tools
29
+
30
+ ### `scaffold_project`
31
+
32
+ Scaffold a new Next.js site from the template.
33
+
34
+ | Parameter | Type | Required | Description |
35
+ |-----------|------|----------|-------------|
36
+ | `project_name` | string | yes | Directory name and package.json name |
37
+ | `destination` | string | yes | Parent directory for the project |
38
+ | `cms_api_url` | string | yes | CMS API base URL |
39
+ | `cms_api_token` | string | yes | Tenant API token |
40
+ | `site_url` | string | no | Public URL for sitemap |
41
+ | `site_name` | string | no | Display name for metadata |
42
+ | `install_deps` | boolean | no | Run `npm install` (default: false) |
43
+
44
+ ### `list_sections`
45
+
46
+ List all available section components with their tags and expected CMS fields.
47
+
48
+ ### `validate_config`
49
+
50
+ Validate an existing project's CMS configuration. Checks `.env.local` for required variables and tests API connectivity.
51
+
52
+ | Parameter | Type | Required | Description |
53
+ |-----------|------|----------|-------------|
54
+ | `project_path` | string | yes | Path to the project directory |
55
+
56
+ ## Available Sections
57
+
58
+ The template includes 10 section components:
59
+
60
+ - **HeroSection** (`hero`) — Hero banner with title, description, and CTA button
61
+ - **TextSection** (`text`) — Rich text content with title and subtitle
62
+ - **FeaturesSection** (`features`) — Grid of feature cards
63
+ - **FAQSection** (`faq`) — Accordion-style Q&A
64
+ - **TestimonialsSection** (`testimonials`) — Testimonial cards with quotes
65
+ - **CTASection** (`cta`) — Call-to-action with dark background
66
+ - **SliderSection** (`slider`) — Carousel with navigation
67
+ - **GallerySection** (`gallery`) — Responsive image grid
68
+ - **ContactSection** (`contact`) — Contact info and form
69
+ - **GenericSection** (`generic`) — Dynamic fallback for any fields
70
+
71
+ ## Development
72
+
73
+ ```bash
74
+ npm install
75
+ npm run build
76
+ npm run inspect # Opens MCP Inspector
77
+ ```
78
+
79
+ ## License
80
+
81
+ MIT
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { z } from "zod";
5
+ import { scaffoldProject } from "./tools/scaffold-project.js";
6
+ import { SECTIONS } from "./tools/list-sections.js";
7
+ import { validateConfig } from "./tools/validate-config.js";
8
+ const server = new McpServer({
9
+ name: "create-cms-site",
10
+ version: "1.0.0",
11
+ });
12
+ // Tool 1: scaffold_project
13
+ server.tool("scaffold_project", "Scaffold a new Next.js site powered by eSTATION CMS. Copies the template, configures environment variables, and optionally installs dependencies.", {
14
+ project_name: z.string().describe("Directory name and package.json name for the new project"),
15
+ destination: z.string().describe("Parent directory where the project will be created"),
16
+ cms_api_url: z.string().describe("CMS API base URL (e.g. https://cms-gateway.estation.io/api/v1)"),
17
+ cms_api_token: z.string().describe("Tenant API token for CMS authentication"),
18
+ site_url: z.string().optional().describe("Public URL for sitemap generation"),
19
+ site_name: z.string().optional().describe("Display name used in page metadata"),
20
+ install_deps: z.boolean().optional().describe("Run npm install after scaffolding (default: false)"),
21
+ }, async (params) => {
22
+ try {
23
+ const result = await scaffoldProject(params);
24
+ return { content: [{ type: "text", text: result }] };
25
+ }
26
+ catch (err) {
27
+ const message = err instanceof Error ? err.message : String(err);
28
+ return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
29
+ }
30
+ });
31
+ // Tool 2: list_sections
32
+ server.tool("list_sections", "List all available section components in the CMS website template with their tags, descriptions, and expected CMS fields.", {}, async () => {
33
+ const output = SECTIONS.map((s) => {
34
+ const lines = [
35
+ `## ${s.component} (tag: "${s.tag}"${s.aliases.length ? `, aliases: ${s.aliases.map((a) => `"${a}"`).join(", ")}` : ""})`,
36
+ s.description,
37
+ "",
38
+ "Fields:",
39
+ ];
40
+ if (s.fields.length === 0) {
41
+ lines.push(" (dynamic — renders any CMS fields based on fieldType)");
42
+ }
43
+ else {
44
+ for (const f of s.fields) {
45
+ lines.push(` - ${f.name} (${f.type}): ${f.description}`);
46
+ if (f.subFields) {
47
+ for (const sf of f.subFields) {
48
+ lines.push(` - ${sf.name} (${sf.type}): ${sf.description}`);
49
+ }
50
+ }
51
+ }
52
+ }
53
+ return lines.join("\n");
54
+ }).join("\n\n");
55
+ return { content: [{ type: "text", text: output }] };
56
+ });
57
+ // Tool 3: validate_config
58
+ server.tool("validate_config", "Validate CMS configuration for an existing project. Checks .env.local for required variables and tests CMS API connectivity.", {
59
+ project_path: z.string().describe("Path to the project directory to validate"),
60
+ }, async ({ project_path }) => {
61
+ const result = await validateConfig(project_path);
62
+ const lines = [];
63
+ lines.push(result.valid ? "Configuration is valid." : "Configuration has errors.");
64
+ lines.push("");
65
+ if (result.errors.length) {
66
+ lines.push("Errors:");
67
+ for (const e of result.errors)
68
+ lines.push(` - ${e}`);
69
+ lines.push("");
70
+ }
71
+ if (result.warnings.length) {
72
+ lines.push("Warnings:");
73
+ for (const w of result.warnings)
74
+ lines.push(` - ${w}`);
75
+ lines.push("");
76
+ }
77
+ if (result.env.CMS_API_URL) {
78
+ lines.push(`CMS API URL: ${result.env.CMS_API_URL}`);
79
+ }
80
+ if (result.env.NEXT_PUBLIC_SITE_URL) {
81
+ lines.push(`Site URL: ${result.env.NEXT_PUBLIC_SITE_URL}`);
82
+ }
83
+ return {
84
+ content: [{ type: "text", text: lines.join("\n") }],
85
+ isError: !result.valid,
86
+ };
87
+ });
88
+ // Start server
89
+ const transport = new StdioServerTransport();
90
+ await server.connect(transport);
91
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface SectionInfo {
2
+ tag: string;
3
+ aliases: string[];
4
+ component: string;
5
+ description: string;
6
+ fields: FieldInfo[];
7
+ }
8
+ export interface FieldInfo {
9
+ name: string;
10
+ type: "string" | "list";
11
+ description: string;
12
+ subFields?: {
13
+ name: string;
14
+ type: string;
15
+ description: string;
16
+ }[];
17
+ }
18
+ export declare const SECTIONS: SectionInfo[];
19
+ //# sourceMappingURL=list-sections.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-sections.d.ts","sourceRoot":"","sources":["../../src/tools/list-sections.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,SAAS,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACnE;AAED,eAAO,MAAM,QAAQ,EAAE,WAAW,EAsJjC,CAAC"}
@@ -0,0 +1,152 @@
1
+ export const SECTIONS = [
2
+ {
3
+ tag: "hero",
4
+ aliases: [],
5
+ component: "HeroSection",
6
+ description: "Hero banner with title, description, and optional CTA button",
7
+ fields: [
8
+ { name: "header", type: "string", description: "Hero title" },
9
+ { name: "description", type: "string", description: "Hero description text" },
10
+ { name: "buttonText", type: "string", description: "Button label" },
11
+ { name: "buttonLink", type: "string", description: "Button URL" },
12
+ ],
13
+ },
14
+ {
15
+ tag: "text",
16
+ aliases: [],
17
+ component: "TextSection",
18
+ description: "Flexible text content section with title, subtitle, and rich text body",
19
+ fields: [
20
+ { name: "title", type: "string", description: "Section title" },
21
+ { name: "subtitle", type: "string", description: "Section subtitle" },
22
+ { name: "body", type: "string", description: "HTML content body" },
23
+ ],
24
+ },
25
+ {
26
+ tag: "features",
27
+ aliases: ["feature"],
28
+ component: "FeaturesSection",
29
+ description: "Grid of feature cards with title and description",
30
+ fields: [
31
+ { name: "title", type: "string", description: "Section title" },
32
+ { name: "description", type: "string", description: "Section description" },
33
+ {
34
+ name: "items",
35
+ type: "list",
36
+ description: "Array of feature items",
37
+ subFields: [
38
+ { name: "title", type: "string", description: "Feature title" },
39
+ { name: "description", type: "string", description: "Feature description" },
40
+ ],
41
+ },
42
+ ],
43
+ },
44
+ {
45
+ tag: "faq",
46
+ aliases: [],
47
+ component: "FAQSection",
48
+ description: "Accordion-style FAQ section with collapsible questions and answers",
49
+ fields: [
50
+ { name: "title", type: "string", description: "Section title" },
51
+ {
52
+ name: "items",
53
+ type: "list",
54
+ description: "Array of FAQ items",
55
+ subFields: [
56
+ { name: "question", type: "string", description: "Question text" },
57
+ { name: "answer", type: "string", description: "Answer text" },
58
+ ],
59
+ },
60
+ ],
61
+ },
62
+ {
63
+ tag: "testimonials",
64
+ aliases: ["testimonial"],
65
+ component: "TestimonialsSection",
66
+ description: "Grid of testimonial cards with quotes and author info",
67
+ fields: [
68
+ { name: "title", type: "string", description: "Section title" },
69
+ {
70
+ name: "items",
71
+ type: "list",
72
+ description: "Array of testimonials",
73
+ subFields: [
74
+ { name: "name", type: "string", description: "Author name" },
75
+ { name: "quote", type: "string", description: "Testimonial quote" },
76
+ { name: "role", type: "string", description: "Author role/title" },
77
+ ],
78
+ },
79
+ ],
80
+ },
81
+ {
82
+ tag: "cta",
83
+ aliases: [],
84
+ component: "CTASection",
85
+ description: "Call-to-action section with dark background, title, description, and button",
86
+ fields: [
87
+ { name: "title", type: "string", description: "CTA title" },
88
+ { name: "description", type: "string", description: "CTA description" },
89
+ { name: "buttonText", type: "string", description: "Button label" },
90
+ { name: "buttonLink", type: "string", description: "Button URL" },
91
+ ],
92
+ },
93
+ {
94
+ tag: "slider",
95
+ aliases: ["sliders"],
96
+ component: "SliderSection",
97
+ description: "Carousel/slider with navigation showing one item at a time",
98
+ fields: [
99
+ {
100
+ name: "items",
101
+ type: "list",
102
+ description: "Array of slide items",
103
+ subFields: [
104
+ { name: "title", type: "string", description: "Slide title" },
105
+ { name: "subtitle", type: "string", description: "Slide subtitle" },
106
+ { name: "image", type: "string", description: "Slide image URL" },
107
+ { name: "linkUrl", type: "string", description: "Slide link URL" },
108
+ { name: "linkText", type: "string", description: "Slide link text" },
109
+ ],
110
+ },
111
+ ],
112
+ },
113
+ {
114
+ tag: "gallery",
115
+ aliases: [],
116
+ component: "GallerySection",
117
+ description: "Responsive image grid with optional captions",
118
+ fields: [
119
+ { name: "title", type: "string", description: "Gallery title" },
120
+ {
121
+ name: "items",
122
+ type: "list",
123
+ description: "Array of gallery items",
124
+ subFields: [
125
+ { name: "image", type: "string", description: "Image URL" },
126
+ { name: "caption", type: "string", description: "Image caption" },
127
+ ],
128
+ },
129
+ ],
130
+ },
131
+ {
132
+ tag: "contact",
133
+ aliases: ["form"],
134
+ component: "ContactSection",
135
+ description: "Contact information display with embedded contact form",
136
+ fields: [
137
+ { name: "title", type: "string", description: "Section title" },
138
+ { name: "description", type: "string", description: "Section description" },
139
+ { name: "email", type: "string", description: "Contact email address" },
140
+ { name: "phone", type: "string", description: "Contact phone number" },
141
+ { name: "address", type: "string", description: "Contact physical address" },
142
+ ],
143
+ },
144
+ {
145
+ tag: "generic",
146
+ aliases: [],
147
+ component: "GenericSection",
148
+ description: "Generic fallback section that renders any CMS fields dynamically based on fieldType",
149
+ fields: [],
150
+ },
151
+ ];
152
+ //# sourceMappingURL=list-sections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-sections.js","sourceRoot":"","sources":["../../src/tools/list-sections.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface ScaffoldOptions {
2
+ project_name: string;
3
+ destination: string;
4
+ cms_api_url: string;
5
+ cms_api_token: string;
6
+ site_url?: string;
7
+ site_name?: string;
8
+ install_deps?: boolean;
9
+ }
10
+ export declare function scaffoldProject(options: ScaffoldOptions): Promise<string>;
11
+ //# sourceMappingURL=scaffold-project.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold-project.d.ts","sourceRoot":"","sources":["../../src/tools/scaffold-project.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAoG/E"}
@@ -0,0 +1,90 @@
1
+ import { cp, readFile, writeFile, stat } from "node:fs/promises";
2
+ import { join, dirname } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { execSync } from "node:child_process";
5
+ import { generateSecret } from "../utils/helpers.js";
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = dirname(__filename);
8
+ const TEMPLATE_DIR = join(__dirname, "..", "..", "template");
9
+ export async function scaffoldProject(options) {
10
+ const { project_name, destination, cms_api_url, cms_api_token, site_url, site_name, install_deps = false, } = options;
11
+ // Validate destination exists
12
+ try {
13
+ const destStat = await stat(destination);
14
+ if (!destStat.isDirectory()) {
15
+ throw new Error(`Destination "${destination}" is not a directory`);
16
+ }
17
+ }
18
+ catch (err) {
19
+ if (err.code === "ENOENT") {
20
+ throw new Error(`Destination directory "${destination}" does not exist`);
21
+ }
22
+ throw err;
23
+ }
24
+ const projectDir = join(destination, project_name);
25
+ // Check project dir doesn't exist
26
+ try {
27
+ await stat(projectDir);
28
+ throw new Error(`Directory "${projectDir}" already exists`);
29
+ }
30
+ catch (err) {
31
+ if (err.code !== "ENOENT")
32
+ throw err;
33
+ }
34
+ // Copy template
35
+ await cp(TEMPLATE_DIR, projectDir, {
36
+ recursive: true,
37
+ filter: (src) => {
38
+ const name = src.split("/").pop() || "";
39
+ return name !== "node_modules" && name !== ".next" && name !== "package-lock.json";
40
+ },
41
+ });
42
+ // Write .env.local
43
+ const revalidateSecret = generateSecret();
44
+ const envContent = [
45
+ "# CMS API",
46
+ `CMS_API_URL=${cms_api_url}`,
47
+ `CMS_API_TOKEN=${cms_api_token}`,
48
+ "",
49
+ "# On-demand ISR revalidation",
50
+ `REVALIDATE_SECRET=${revalidateSecret}`,
51
+ "",
52
+ "# Public site URL (used for sitemap generation)",
53
+ `NEXT_PUBLIC_SITE_URL=${site_url || "http://localhost:3000"}`,
54
+ ].join("\n");
55
+ await writeFile(join(projectDir, ".env.local"), envContent + "\n");
56
+ // Patch package.json name
57
+ const pkgPath = join(projectDir, "package.json");
58
+ const pkg = JSON.parse(await readFile(pkgPath, "utf-8"));
59
+ pkg.name = project_name;
60
+ delete pkg.private;
61
+ await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
62
+ // Patch layout.tsx metadata if site_name provided
63
+ if (site_name) {
64
+ const layoutPath = join(projectDir, "src", "app", "layout.tsx");
65
+ let layout = await readFile(layoutPath, "utf-8");
66
+ layout = layout.replace(/title:\s*["'].*?["']/, `title: "${site_name}"`);
67
+ layout = layout.replace(/description:\s*["'].*?["']/, `description: "${site_name} - Powered by eSTATION CMS"`);
68
+ await writeFile(layoutPath, layout);
69
+ }
70
+ // Optionally install dependencies
71
+ if (install_deps) {
72
+ execSync("npm install", { cwd: projectDir, stdio: "pipe" });
73
+ }
74
+ const steps = [
75
+ `Project created at ${projectDir}`,
76
+ `.env.local configured with CMS API credentials`,
77
+ `package.json name set to "${project_name}"`,
78
+ ];
79
+ if (site_name)
80
+ steps.push(`Layout metadata updated with site name "${site_name}"`);
81
+ if (install_deps)
82
+ steps.push("Dependencies installed");
83
+ steps.push("");
84
+ steps.push("Next steps:");
85
+ if (!install_deps)
86
+ steps.push(" cd " + projectDir + " && npm install");
87
+ steps.push(" npm run dev");
88
+ return steps.join("\n");
89
+ }
90
+ //# sourceMappingURL=scaffold-project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold-project.js","sourceRoot":"","sources":["../../src/tools/scaffold-project.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ interface ValidationResult {
2
+ valid: boolean;
3
+ errors: string[];
4
+ warnings: string[];
5
+ env: Record<string, string>;
6
+ }
7
+ export declare function validateConfig(projectPath: string): Promise<ValidationResult>;
8
+ export {};
9
+ //# sourceMappingURL=validate-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-config.d.ts","sourceRoot":"","sources":["../../src/tools/validate-config.ts"],"names":[],"mappings":"AAGA,UAAU,gBAAgB;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B;AAED,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAuEnF"}
@@ -0,0 +1,72 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ export async function validateConfig(projectPath) {
4
+ const errors = [];
5
+ const warnings = [];
6
+ const env = {};
7
+ // Read .env.local
8
+ const envPath = join(projectPath, ".env.local");
9
+ let envContent;
10
+ try {
11
+ envContent = await readFile(envPath, "utf-8");
12
+ }
13
+ catch {
14
+ return {
15
+ valid: false,
16
+ errors: [`.env.local not found at ${envPath}`],
17
+ warnings: [],
18
+ env: {},
19
+ };
20
+ }
21
+ // Parse env vars
22
+ for (const line of envContent.split("\n")) {
23
+ const trimmed = line.trim();
24
+ if (!trimmed || trimmed.startsWith("#"))
25
+ continue;
26
+ const eqIndex = trimmed.indexOf("=");
27
+ if (eqIndex === -1)
28
+ continue;
29
+ const key = trimmed.slice(0, eqIndex).trim();
30
+ const value = trimmed.slice(eqIndex + 1).trim();
31
+ env[key] = value;
32
+ }
33
+ // Check required vars
34
+ const required = ["CMS_API_URL", "CMS_API_TOKEN", "REVALIDATE_SECRET"];
35
+ for (const key of required) {
36
+ if (!env[key]) {
37
+ errors.push(`Missing required environment variable: ${key}`);
38
+ }
39
+ }
40
+ if (!env["NEXT_PUBLIC_SITE_URL"]) {
41
+ warnings.push("NEXT_PUBLIC_SITE_URL is not set — sitemap generation will use a placeholder");
42
+ }
43
+ // Test CMS API connectivity
44
+ if (env["CMS_API_URL"] && env["CMS_API_TOKEN"]) {
45
+ try {
46
+ const controller = new AbortController();
47
+ const timeout = setTimeout(() => controller.abort(), 10000);
48
+ const res = await fetch(`${env["CMS_API_URL"]}/public/content/pages`, {
49
+ headers: { "X-API-TOKEN": env["CMS_API_TOKEN"] },
50
+ signal: controller.signal,
51
+ });
52
+ clearTimeout(timeout);
53
+ if (!res.ok) {
54
+ errors.push(`CMS API returned ${res.status} ${res.statusText}`);
55
+ }
56
+ }
57
+ catch (err) {
58
+ const message = err instanceof Error ? err.message : String(err);
59
+ errors.push(`CMS API unreachable: ${message}`);
60
+ }
61
+ }
62
+ return {
63
+ valid: errors.length === 0,
64
+ errors,
65
+ warnings,
66
+ env: {
67
+ CMS_API_URL: env["CMS_API_URL"] || "",
68
+ NEXT_PUBLIC_SITE_URL: env["NEXT_PUBLIC_SITE_URL"] || "",
69
+ },
70
+ };
71
+ }
72
+ //# sourceMappingURL=validate-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-config.js","sourceRoot":"","sources":["../../src/tools/validate-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function generateSecret(length?: number): string;
2
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":"AAEA,wBAAgB,cAAc,CAAC,MAAM,SAAK,GAAG,MAAM,CAElD"}
@@ -0,0 +1,5 @@
1
+ import { randomBytes } from "node:crypto";
2
+ export function generateSecret(length = 32) {
3
+ return randomBytes(length).toString("hex");
4
+ }
5
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,UAAU,cAAc,CAAC,MAAM,GAAG,EAAE;IACxC,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC7C,CAAC"}