@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.
- package/LICENSE +21 -0
- package/README.md +81 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +91 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/list-sections.d.ts +19 -0
- package/dist/tools/list-sections.d.ts.map +1 -0
- package/dist/tools/list-sections.js +152 -0
- package/dist/tools/list-sections.js.map +1 -0
- package/dist/tools/scaffold-project.d.ts +11 -0
- package/dist/tools/scaffold-project.d.ts.map +1 -0
- package/dist/tools/scaffold-project.js +90 -0
- package/dist/tools/scaffold-project.js.map +1 -0
- package/dist/tools/validate-config.d.ts +9 -0
- package/dist/tools/validate-config.d.ts.map +1 -0
- package/dist/tools/validate-config.js +72 -0
- package/dist/tools/validate-config.js.map +1 -0
- package/dist/utils/helpers.d.ts +2 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/helpers.js +5 -0
- package/dist/utils/helpers.js.map +1 -0
- package/package.json +36 -0
- package/template/.env.example +9 -0
- package/template/LIVE-PREVIEW.md +267 -0
- package/template/README.md +210 -0
- package/template/next.config.ts +14 -0
- package/template/package.json +24 -0
- package/template/postcss.config.mjs +8 -0
- package/template/src/app/[slug]/page.tsx +38 -0
- package/template/src/app/api/revalidate/route.ts +34 -0
- package/template/src/app/blog/[slug]/page.tsx +60 -0
- package/template/src/app/blog/page.tsx +68 -0
- package/template/src/app/collections/[uuid]/page.tsx +28 -0
- package/template/src/app/events/[slug]/page.tsx +62 -0
- package/template/src/app/events/page.tsx +70 -0
- package/template/src/app/layout.tsx +27 -0
- package/template/src/app/news/[slug]/page.tsx +66 -0
- package/template/src/app/news/page.tsx +68 -0
- package/template/src/app/page.tsx +40 -0
- package/template/src/app/search/page.tsx +136 -0
- package/template/src/app/sitemap.ts +48 -0
- package/template/src/components/Footer.tsx +47 -0
- package/template/src/components/Navigation.tsx +65 -0
- package/template/src/components/SectionRenderer.tsx +43 -0
- package/template/src/components/cms-preview-listener.tsx +114 -0
- package/template/src/components/sections/CTASection.tsx +32 -0
- package/template/src/components/sections/ContactSection.tsx +74 -0
- package/template/src/components/sections/FAQSection.tsx +48 -0
- package/template/src/components/sections/FeaturesSection.tsx +42 -0
- package/template/src/components/sections/GallerySection.tsx +44 -0
- package/template/src/components/sections/GenericSection.tsx +63 -0
- package/template/src/components/sections/HeroSection.tsx +27 -0
- package/template/src/components/sections/SliderSection.tsx +66 -0
- package/template/src/components/sections/TestimonialsSection.tsx +52 -0
- package/template/src/components/sections/TextSection.tsx +31 -0
- package/template/src/lib/cms-api.ts +103 -0
- package/template/src/lib/content-helpers.ts +18 -0
- package/template/src/lib/types.ts +109 -0
- package/template/src/styles/globals.css +1 -0
- 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
|
package/dist/index.d.ts
ADDED
|
@@ -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":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AASjC,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,WAAmB;IACtD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,GAAG,GAA2B,EAAE,CAAC;IAEvC,kBAAkB;IAClB,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAChD,IAAI,UAAkB,CAAC;IACvB,IAAI,CAAC;QACH,UAAU,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,CAAC,2BAA2B,OAAO,EAAE,CAAC;YAC9C,QAAQ,EAAE,EAAE;YACZ,GAAG,EAAE,EAAE;SACR,CAAC;IACJ,CAAC;IAED,iBAAiB;IACjB,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAClD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,OAAO,KAAK,CAAC,CAAC;YAAE,SAAS;QAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAChD,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACnB,CAAC;IAED,sBAAsB;IACtB,MAAM,QAAQ,GAAG,CAAC,aAAa,EAAE,eAAe,EAAE,mBAAmB,CAAC,CAAC;IACvE,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACd,MAAM,CAAC,IAAI,CAAC,0CAA0C,GAAG,EAAE,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,sBAAsB,CAAC,EAAE,CAAC;QACjC,QAAQ,CAAC,IAAI,CAAC,6EAA6E,CAAC,CAAC;IAC/F,CAAC;IAED,4BAA4B;IAC5B,IAAI,GAAG,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;QAC/C,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,CAAC;YAC5D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,GAAG,CAAC,aAAa,CAAC,uBAAuB,EAAE;gBACpE,OAAO,EAAE,EAAE,aAAa,EAAE,GAAG,CAAC,eAAe,CAAC,EAAE;gBAChD,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YACH,YAAY,CAAC,OAAO,CAAC,CAAC;YAEtB,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,CAAC,IAAI,CAAC,oBAAoB,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,MAAM,CAAC,IAAI,CAAC,wBAAwB,OAAO,EAAE,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;QAC1B,MAAM;QACN,QAAQ;QACR,GAAG,EAAE;YACH,WAAW,EAAE,GAAG,CAAC,aAAa,CAAC,IAAI,EAAE;YACrC,oBAAoB,EAAE,GAAG,CAAC,sBAAsB,CAAC,IAAI,EAAE;SACxD;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -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 @@
|
|
|
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"}
|