@shipsite.dev/cli 0.1.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.
@@ -0,0 +1,2 @@
1
+ export declare function add(args: string[]): Promise<void>;
2
+ //# sourceMappingURL=add.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAGA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,iBAevC"}
@@ -0,0 +1,99 @@
1
+ import { join } from 'path';
2
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
3
+ export async function add(args) {
4
+ const type = args[0];
5
+ switch (type) {
6
+ case 'page':
7
+ await addPage(args[1]);
8
+ break;
9
+ case 'blog':
10
+ await addBlog(args.slice(1).join(' '));
11
+ break;
12
+ default:
13
+ console.log('Usage: shipsite add page <name> | shipsite add blog <title>');
14
+ }
15
+ }
16
+ async function addPage(name) {
17
+ if (!name) {
18
+ console.error('Error: Page name required. Usage: shipsite add page <name>');
19
+ process.exit(1);
20
+ }
21
+ const rootDir = process.cwd();
22
+ const configPath = join(rootDir, 'shipsite.json');
23
+ const config = JSON.parse(readFileSync(configPath, 'utf-8'));
24
+ const contentDir = join(rootDir, 'content', name);
25
+ mkdirSync(contentDir, { recursive: true });
26
+ const defaultLocale = config.i18n?.defaultLocale || 'en';
27
+ const mdxPath = join(contentDir, `${defaultLocale}.mdx`);
28
+ if (!existsSync(mdxPath)) {
29
+ const title = name.charAt(0).toUpperCase() + name.slice(1);
30
+ writeFileSync(mdxPath, `---
31
+ title: "${title}"
32
+ description: ""
33
+ ---
34
+
35
+ <PageHero title="${title}" />
36
+ `);
37
+ console.log(` Created content/${name}/${defaultLocale}.mdx`);
38
+ }
39
+ config.pages.push({
40
+ slug: name,
41
+ type: 'page',
42
+ content: name,
43
+ locales: [defaultLocale],
44
+ });
45
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
46
+ console.log(` Added "${name}" to shipsite.json pages`);
47
+ }
48
+ async function addBlog(title) {
49
+ if (!title) {
50
+ console.error('Error: Blog title required. Usage: shipsite add blog "My Post Title"');
51
+ process.exit(1);
52
+ }
53
+ const rootDir = process.cwd();
54
+ const configPath = join(rootDir, 'shipsite.json');
55
+ const config = JSON.parse(readFileSync(configPath, 'utf-8'));
56
+ const slug = title
57
+ .toLowerCase()
58
+ .replace(/[^a-z0-9]+/g, '-')
59
+ .replace(/^-|-$/g, '');
60
+ const contentDir = join(rootDir, 'content', 'blog', slug);
61
+ mkdirSync(contentDir, { recursive: true });
62
+ const defaultLocale = config.i18n?.defaultLocale || 'en';
63
+ const mdxPath = join(contentDir, `${defaultLocale}.mdx`);
64
+ if (!existsSync(mdxPath)) {
65
+ const today = new Date().toISOString().split('T')[0];
66
+ writeFileSync(mdxPath, `---
67
+ title: "${title}"
68
+ description: ""
69
+ date: "${today}"
70
+ image: "/images/placeholder.webp"
71
+ readingTime: 5
72
+ featured: false
73
+ author: ""
74
+ ---
75
+
76
+ <BlogArticle>
77
+
78
+ <BlogIntro>
79
+ Write your introduction here.
80
+ </BlogIntro>
81
+
82
+ ## Getting Started
83
+
84
+ Your content here...
85
+
86
+ </BlogArticle>
87
+ `);
88
+ console.log(` Created content/blog/${slug}/${defaultLocale}.mdx`);
89
+ }
90
+ config.pages.push({
91
+ slug: `blog/${slug}`,
92
+ type: 'blog-article',
93
+ content: `blog/${slug}`,
94
+ locales: [defaultLocale],
95
+ });
96
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
97
+ console.log(` Added "blog/${slug}" to shipsite.json pages`);
98
+ }
99
+ //# sourceMappingURL=add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function build(): Promise<void>;
2
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAIA,wBAAsB,KAAK,kBAgE1B"}
@@ -0,0 +1,55 @@
1
+ import { join } from 'path';
2
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
3
+ import { spawn } from 'child_process';
4
+ export async function build() {
5
+ const rootDir = process.cwd();
6
+ const configPath = join(rootDir, 'shipsite.json');
7
+ if (!existsSync(configPath)) {
8
+ console.error('Error: shipsite.json not found in current directory');
9
+ process.exit(1);
10
+ }
11
+ console.log('\n Building ShipSite...\n');
12
+ // 1. Validate config
13
+ const config = JSON.parse(readFileSync(configPath, 'utf-8'));
14
+ console.log(` Config valid: ${config.name}`);
15
+ // 2. Validate content files
16
+ let missingFiles = 0;
17
+ for (const page of config.pages || []) {
18
+ const locales = page.locales || [config.i18n?.defaultLocale || 'en'];
19
+ for (const locale of locales) {
20
+ const mdxPath = join(rootDir, 'content', page.content, `${locale}.mdx`);
21
+ if (!existsSync(mdxPath)) {
22
+ console.error(` Missing: content/${page.content}/${locale}.mdx`);
23
+ missingFiles++;
24
+ }
25
+ }
26
+ }
27
+ if (missingFiles > 0) {
28
+ console.error(`\n ${missingFiles} content file(s) missing. Aborting build.`);
29
+ process.exit(1);
30
+ }
31
+ console.log(` All content files present`);
32
+ // 3. Generate slug map
33
+ const { generateSlugMap } = await import('@shipsite.dev/core/generate-slug-map');
34
+ const shipSiteDir = join(rootDir, '.shipsite');
35
+ const slugMap = generateSlugMap(rootDir);
36
+ writeFileSync(join(shipSiteDir, 'slug-map.json'), JSON.stringify(slugMap, null, 2));
37
+ console.log(` Generated slug-map.json`);
38
+ // 4. Build
39
+ console.log('\n Running next build...\n');
40
+ const nextBuild = spawn('npx', ['next', 'build'], {
41
+ cwd: shipSiteDir,
42
+ stdio: 'inherit',
43
+ env: { ...process.env, SHIPSITE_ROOT: rootDir },
44
+ });
45
+ nextBuild.on('close', (code) => {
46
+ if (code === 0) {
47
+ console.log('\n Build complete!');
48
+ }
49
+ else {
50
+ console.error('\n Build failed');
51
+ }
52
+ process.exit(code || 0);
53
+ });
54
+ }
55
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function dev(): Promise<void>;
2
+ //# sourceMappingURL=dev.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAWA,wBAAsB,GAAG,kBA2CxB"}
@@ -0,0 +1,634 @@
1
+ import { join, relative, dirname } from 'path';
2
+ import { existsSync, mkdirSync, writeFileSync, symlinkSync, readFileSync, realpathSync, } from 'fs';
3
+ import { spawn } from 'child_process';
4
+ export async function dev() {
5
+ const rootDir = process.cwd();
6
+ const configPath = join(rootDir, 'shipsite.json');
7
+ if (!existsSync(configPath)) {
8
+ console.error('Error: shipsite.json not found in current directory');
9
+ process.exit(1);
10
+ }
11
+ console.log('\n Starting ShipSite dev server...\n');
12
+ // 1. Generate .shipsite workspace
13
+ generateWorkspace(rootDir);
14
+ // 2. Generate slug map
15
+ const { generateSlugMap } = await import('@shipsite.dev/core/generate-slug-map');
16
+ const shipSiteDir = join(rootDir, '.shipsite');
17
+ const slugMap = generateSlugMap(rootDir);
18
+ writeFileSync(join(shipSiteDir, 'slug-map.json'), JSON.stringify(slugMap, null, 2));
19
+ console.log(` Generated slug-map.json (${Object.keys(slugMap).length} entries)`);
20
+ // 3. Start next dev
21
+ console.log('\n Starting Next.js dev server...\n');
22
+ const nextDev = spawn('npx', ['next', 'dev'], {
23
+ cwd: shipSiteDir,
24
+ stdio: 'inherit',
25
+ env: { ...process.env, SHIPSITE_ROOT: rootDir },
26
+ });
27
+ nextDev.on('close', (code) => {
28
+ process.exit(code || 0);
29
+ });
30
+ process.on('SIGINT', () => {
31
+ nextDev.kill('SIGINT');
32
+ });
33
+ }
34
+ function hexToHsl(hex) {
35
+ const r = parseInt(hex.slice(1, 3), 16) / 255;
36
+ const g = parseInt(hex.slice(3, 5), 16) / 255;
37
+ const b = parseInt(hex.slice(5, 7), 16) / 255;
38
+ const max = Math.max(r, g, b);
39
+ const min = Math.min(r, g, b);
40
+ const l = (max + min) / 2;
41
+ if (max === min)
42
+ return [0, 0, l * 100];
43
+ const d = max - min;
44
+ const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
45
+ let h = 0;
46
+ if (max === r)
47
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
48
+ else if (max === g)
49
+ h = ((b - r) / d + 2) / 6;
50
+ else
51
+ h = ((r - g) / d + 4) / 6;
52
+ return [Math.round(h * 360), Math.round(s * 100), Math.round(l * 100)];
53
+ }
54
+ function generateShadcnTokens(colors) {
55
+ const primary = colors.primary || '#5d5bd4';
56
+ const accent = colors.accent || '#067647';
57
+ const [pH, pS, pL] = hexToHsl(primary);
58
+ // Light mode
59
+ const brandFgLight = `${pH} ${Math.min(pS + 10, 100)}% ${Math.min(pL + 10, 85)}%`;
60
+ // Dark mode tokens (primary design - Launch UI inspired)
61
+ const darkBgH = pH;
62
+ const darkBgS = Math.min(Math.round(pS * 0.6), 50);
63
+ const darkBg = `${darkBgH} ${darkBgS}% 4%`;
64
+ const darkFg = `0 0% 98%`;
65
+ const darkCard = `${darkBgH} ${darkBgS}% 6%`;
66
+ const darkMuted = `${darkBgH} ${Math.round(darkBgS * 0.8)}% 15%`;
67
+ const darkMutedFg = `${darkBgH} ${Math.round(darkBgS * 0.4)}% 65%`;
68
+ const darkBorder = `${darkBgH} ${Math.round(darkBgS * 0.7)}% 14%`;
69
+ const darkInput = `${darkBgH} ${Math.round(darkBgS * 0.7)}% 18%`;
70
+ const darkRing = `${pH} ${Math.round(pS * 0.5)}% 60%`;
71
+ const darkBrandFg = `${pH} ${Math.min(pS + 10, 100)}% ${Math.min(pL + 15, 80)}%`;
72
+ return `:root {
73
+ --brand: hsl(${pH} ${pS}% ${pL}%);
74
+ --brand-foreground: hsl(${brandFgLight});
75
+ --primary: hsl(${pH} ${pS}% ${pL}%);
76
+ --primary-foreground: hsl(0 0% 98%);
77
+ --background: hsl(0 0% 100%);
78
+ --foreground: hsl(222 47% 11%);
79
+ --card: hsl(0 0% 100%);
80
+ --card-foreground: hsl(222 47% 11%);
81
+ --popover: hsl(0 0% 100%);
82
+ --popover-foreground: hsl(222 47% 11%);
83
+ --secondary: hsl(210 10% 93%);
84
+ --secondary-foreground: hsl(222 47% 20%);
85
+ --muted: hsl(210 10% 93%);
86
+ --muted-foreground: hsl(215 15% 45%);
87
+ --accent: hsl(210 10% 90%);
88
+ --accent-foreground: hsl(222 47% 20%);
89
+ --destructive: hsl(0 72% 51%);
90
+ --destructive-foreground: hsl(0 72% 51%);
91
+ --border: hsl(220 9% 91%);
92
+ --input: hsl(220 9% 91%);
93
+ --ring: hsl(215 15% 70%);
94
+ --radius: 0.625rem;
95
+ --line-width: 1px;
96
+ --shadow: #00000008;
97
+ --shadow-strong: #00000010;
98
+ --ss-primary: ${primary};
99
+ --ss-accent: ${accent};
100
+ }
101
+
102
+ .dark {
103
+ --brand: hsl(${pH} ${pS}% ${pL}%);
104
+ --brand-foreground: hsl(${darkBrandFg});
105
+ --primary: hsl(${pH} ${pS}% ${pL}%);
106
+ --primary-foreground: hsl(0 0% 98%);
107
+ --background: hsl(${darkBg});
108
+ --foreground: hsl(${darkFg});
109
+ --card: hsl(${darkCard});
110
+ --card-foreground: hsl(${darkFg});
111
+ --popover: hsl(${darkCard});
112
+ --popover-foreground: hsl(${darkFg});
113
+ --secondary: hsl(${darkMuted});
114
+ --secondary-foreground: hsl(${darkFg});
115
+ --muted: hsl(${darkMuted});
116
+ --muted-foreground: hsl(${darkMutedFg});
117
+ --accent: hsl(${darkMuted});
118
+ --accent-foreground: hsl(${darkFg});
119
+ --destructive: hsl(0 62% 30%);
120
+ --destructive-foreground: hsl(${darkFg});
121
+ --border: hsl(${darkBorder});
122
+ --input: hsl(${darkInput});
123
+ --ring: hsl(${darkRing});
124
+ --radius: 0.625rem;
125
+ --line-width: 1px;
126
+ --shadow: #00000040;
127
+ --shadow-strong: #00000060;
128
+ --ss-primary: ${primary};
129
+ --ss-accent: ${accent};
130
+ }
131
+ `;
132
+ }
133
+ function generateWorkspace(rootDir) {
134
+ const config = JSON.parse(readFileSync(join(rootDir, 'shipsite.json'), 'utf-8'));
135
+ const shipSiteDir = join(rootDir, '.shipsite');
136
+ if (!existsSync(shipSiteDir)) {
137
+ mkdirSync(shipSiteDir, { recursive: true });
138
+ }
139
+ const locales = config.i18n?.locales || ['en'];
140
+ const defaultLocale = config.i18n?.defaultLocale || 'en';
141
+ const localePrefix = config.i18n?.localePrefix || 'as-needed';
142
+ // Symlink content directory
143
+ const contentLink = join(shipSiteDir, 'content');
144
+ if (!existsSync(contentLink)) {
145
+ symlinkSync(join(rootDir, 'content'), contentLink);
146
+ }
147
+ // Symlink public directory
148
+ const publicLink = join(shipSiteDir, 'public');
149
+ if (!existsSync(publicLink) && existsSync(join(rootDir, 'public'))) {
150
+ symlinkSync(join(rootDir, 'public'), publicLink);
151
+ }
152
+ // Symlink custom components directory
153
+ const hasCustomComponents = existsSync(join(rootDir, 'components'));
154
+ const componentsLink = join(shipSiteDir, 'components');
155
+ if (!existsSync(componentsLink) && hasCustomComponents) {
156
+ symlinkSync(join(rootDir, 'components'), componentsLink);
157
+ }
158
+ // Generate next.config.ts
159
+ // Detect user's custom next.config file (always expected, but graceful fallback)
160
+ const userNextConfigExtensions = ['ts', 'mjs', 'js'];
161
+ const userNextConfig = userNextConfigExtensions.find((ext) => existsSync(join(rootDir, `next.config.${ext}`)));
162
+ const userConfigImport = userNextConfig
163
+ ? `import userConfig from '../next.config.${userNextConfig}';\n`
164
+ : '';
165
+ const userConfigSpread = userNextConfig ? ' ...userConfig,\n' : '';
166
+ writeFileSync(join(shipSiteDir, 'next.config.ts'), `import createNextIntlPlugin from 'next-intl/plugin';
167
+ import { withContentCollections } from '@content-collections/next';
168
+ import type { NextConfig } from 'next';
169
+ ${userConfigImport}
170
+ const withNextIntl = createNextIntlPlugin('./src/i18n/request.ts');
171
+
172
+ const nextConfig: NextConfig = {
173
+ ${userConfigSpread} reactStrictMode: true,
174
+ poweredByHeader: false,
175
+ };
176
+
177
+ export default withContentCollections(withNextIntl(nextConfig));
178
+ `);
179
+ // Generate content-collections.ts
180
+ writeFileSync(join(shipSiteDir, 'content-collections.ts'), `import { defineCollection, defineConfig } from '@content-collections/core';
181
+ import { z } from 'zod';
182
+
183
+ const sitePages = defineCollection({
184
+ name: 'sitePages',
185
+ directory: 'content',
186
+ include: '**/*.mdx',
187
+ schema: z.object({
188
+ content: z.string(),
189
+ title: z.string(),
190
+ description: z.string(),
191
+ category: z.string().optional(),
192
+ date: z.string().optional(),
193
+ image: z.string().optional(),
194
+ readingTime: z.number().optional(),
195
+ featured: z.boolean().optional(),
196
+ author: z.string().optional(),
197
+ slug: z.string().optional(),
198
+ }),
199
+ transform: (doc) => {
200
+ const locale = doc._meta.fileName.replace(/\\.mdx$/, '');
201
+ const contentFolder = doc._meta.directory;
202
+ const contentId = doc._meta.path.replace(/\\.mdx$/, '');
203
+ const path = doc._meta.directory;
204
+ let kind: string;
205
+ if (path.startsWith('blog/')) {
206
+ kind = path.split('/').length > 1 ? 'blog-article' : 'blog-index';
207
+ } else {
208
+ kind = 'page';
209
+ }
210
+ const raw = doc.content;
211
+ const match = raw.match(/<BlogIntro>\\s*([\\s\\S]*?)\\s*<\\/BlogIntro>/);
212
+ const excerpt = match
213
+ ? match[1].replace(/\\*\\*(.*?)\\*\\*/g, '$1').replace(/\\[(.*?)\\]\\(.*?\\)/g, '$1').replace(/[*_~\\\`]/g, '').replace(/\\n+/g, ' ').trim()
214
+ : '';
215
+ return { ...doc, locale, contentFolder, contentId, kind, excerpt, body: { raw: doc.content } };
216
+ },
217
+ });
218
+
219
+ export default defineConfig({ content: [sitePages] });
220
+ `);
221
+ // Generate src directory structure
222
+ const srcDir = join(shipSiteDir, 'src');
223
+ mkdirSync(join(srcDir, 'i18n'), { recursive: true });
224
+ mkdirSync(join(srcDir, 'app', '[locale]', '[[...slug]]'), {
225
+ recursive: true,
226
+ });
227
+ mkdirSync(join(srcDir, 'styles'), { recursive: true });
228
+ // i18n/routing.ts
229
+ writeFileSync(join(srcDir, 'i18n', 'routing.ts'), `import { defineRouting } from 'next-intl/routing';
230
+ import { createNavigation } from 'next-intl/navigation';
231
+
232
+ export const routing = defineRouting({
233
+ locales: ${JSON.stringify(locales)},
234
+ defaultLocale: '${defaultLocale}',
235
+ localePrefix: '${localePrefix}',
236
+ });
237
+
238
+ export const { Link, redirect, usePathname, useRouter, getPathname } = createNavigation(routing);
239
+ `);
240
+ // i18n/request.ts
241
+ writeFileSync(join(srcDir, 'i18n', 'request.ts'), `import { getRequestConfig } from 'next-intl/server';
242
+ import { routing } from './routing';
243
+
244
+ export default getRequestConfig(async ({ requestLocale }) => {
245
+ let locale = await requestLocale;
246
+ if (!locale || !(routing.locales as readonly string[]).includes(locale)) {
247
+ locale = routing.defaultLocale;
248
+ }
249
+ return { locale, messages: {} };
250
+ });
251
+ `);
252
+ // middleware.ts
253
+ writeFileSync(join(srcDir, 'middleware.ts'), `import { createShipSiteMiddleware } from '@shipsite.dev/core/middleware';
254
+ import slugMap from '../slug-map.json';
255
+
256
+ const middleware = createShipSiteMiddleware({
257
+ locales: ${JSON.stringify(locales)},
258
+ defaultLocale: '${defaultLocale}',
259
+ localePrefix: '${localePrefix}',
260
+ slugMap: slugMap as Record<string, Record<string, string>>,
261
+ });
262
+
263
+ export default middleware;
264
+
265
+ // Next.js requires config to be a static object literal (not imported)
266
+ export const config = {
267
+ matcher: ['/((?!api|_next|_vercel|.*\\\\..*).*)'],
268
+ };
269
+ `);
270
+ // Resolve @shipsite.dev/components source path for Tailwind @source directive
271
+ const cssDir = join(srcDir, 'styles');
272
+ let componentsSourceDirective = '';
273
+ let utilsCssImport = '';
274
+ // Walk up from rootDir to find node_modules/@shipsite.dev/components/src
275
+ let searchDir = rootDir;
276
+ for (let i = 0; i < 10; i++) {
277
+ const candidate = join(searchDir, 'node_modules', '@shipsite.dev', 'components', 'src');
278
+ if (existsSync(candidate)) {
279
+ const realPath = realpathSync(candidate);
280
+ const rel = relative(cssDir, realPath).split('\\').join('/');
281
+ componentsSourceDirective = `\n@source "${rel}";`;
282
+ // Also resolve the utils.css path from components
283
+ const utilsCssPath = join(realPath, 'styles', 'utils.css');
284
+ if (existsSync(utilsCssPath)) {
285
+ const utilsRel = relative(cssDir, utilsCssPath).split('\\').join('/');
286
+ utilsCssImport = `\n@import "${utilsRel}";`;
287
+ }
288
+ break;
289
+ }
290
+ const parent = dirname(searchDir);
291
+ if (parent === searchDir)
292
+ break;
293
+ searchDir = parent;
294
+ }
295
+ // Generate shadcn/ui tokens from config colors
296
+ const shadcnTokens = generateShadcnTokens(config.colors || {});
297
+ // globals.css — full Launch UI compatible stylesheet
298
+ writeFileSync(join(cssDir, 'globals.css'), `@import 'tailwindcss';${componentsSourceDirective}${utilsCssImport}
299
+
300
+ @import 'tw-animate-css';
301
+
302
+ @custom-variant dark (&:where(.dark, .dark *));
303
+
304
+ @theme inline {
305
+ --color-brand: var(--brand);
306
+ --color-brand-foreground: var(--brand-foreground);
307
+ --color-background: var(--background);
308
+ --color-foreground: var(--foreground);
309
+ --color-card: var(--card);
310
+ --color-card-foreground: var(--card-foreground);
311
+ --color-popover: var(--popover);
312
+ --color-popover-foreground: var(--popover-foreground);
313
+ --color-primary: var(--primary);
314
+ --color-primary-foreground: var(--primary-foreground);
315
+ --color-secondary: var(--secondary);
316
+ --color-secondary-foreground: var(--secondary-foreground);
317
+ --color-muted: var(--muted);
318
+ --color-muted-foreground: var(--muted-foreground);
319
+ --color-accent: var(--accent);
320
+ --color-accent-foreground: var(--accent-foreground);
321
+ --color-destructive: var(--destructive);
322
+ --color-destructive-foreground: var(--destructive-foreground);
323
+ --color-border: var(--border);
324
+ --color-input: var(--input);
325
+ --color-ring: var(--ring);
326
+
327
+ --radius-sm: calc(var(--radius) - 4px);
328
+ --radius-md: calc(var(--radius) - 2px);
329
+ --radius-lg: var(--radius);
330
+ --radius-xl: calc(var(--radius) + 4px);
331
+ --radius-2xl: calc(var(--radius) + 8px);
332
+
333
+ --spacing-container: 1280px;
334
+ --spacing-container-lg: 1536px;
335
+
336
+ --shadow-md: 0 4px 6px -1px var(--shadow), 0 2px 4px -2px var(--shadow);
337
+ --shadow-xl: 0 20px 25px -5px var(--shadow), 0 8px 10px -6px var(--shadow);
338
+ --shadow-2xl: 0 25px 50px -12px var(--shadow);
339
+ --shadow-mockup: -12px 16px 48px var(--shadow-strong);
340
+
341
+ --line-width: 1px;
342
+
343
+ --animate-accordion-down: accordion-down 0.2s ease-out;
344
+ --animate-accordion-up: accordion-up 0.2s ease-out;
345
+ --animate-appear: appear 0.6s forwards ease-out;
346
+ --animate-appear-zoom: appear-zoom 0.6s forwards ease-out;
347
+
348
+ @keyframes accordion-down {
349
+ from { height: 0; }
350
+ to { height: var(--radix-accordion-content-height); }
351
+ }
352
+ @keyframes accordion-up {
353
+ from { height: var(--radix-accordion-content-height); }
354
+ to { height: 0; }
355
+ }
356
+ @keyframes appear {
357
+ 0% { opacity: 0; transform: translateY(1rem); filter: blur(0.5rem); }
358
+ 50% { filter: blur(0); }
359
+ 100% { opacity: 1; transform: translateY(0); filter: blur(0); }
360
+ }
361
+ @keyframes appear-zoom {
362
+ 0% { opacity: 0; transform: scale(0.5); }
363
+ 100% { opacity: 1; transform: scale(1); }
364
+ }
365
+ }
366
+
367
+ ${shadcnTokens}
368
+ @layer base {
369
+ * {
370
+ @apply border-border;
371
+ }
372
+ body {
373
+ @apply bg-background text-foreground;
374
+ font-family: system-ui, -apple-system, sans-serif;
375
+ -webkit-font-smoothing: antialiased;
376
+ }
377
+ html { scroll-behavior: smooth; }
378
+ }
379
+
380
+ .container-main {
381
+ width: 100%;
382
+ max-width: 76rem;
383
+ margin-inline: auto;
384
+ padding-inline: clamp(1rem, 3vw, 3rem);
385
+ }
386
+
387
+ @layer utilities {
388
+ @keyframes marquee {
389
+ from { transform: translateX(0); }
390
+ to { transform: translateX(calc(-100% - var(--marquee-gap))); }
391
+ }
392
+ .animate-marquee {
393
+ flex-shrink: 0;
394
+ animation: marquee var(--marquee-duration, 30s) linear infinite;
395
+ }
396
+ }
397
+
398
+ .page-prose > h2, .page-prose > h3, .page-prose > h4,
399
+ .page-prose > p, .page-prose > ul, .page-prose > ol,
400
+ .page-prose > blockquote {
401
+ width: 100%;
402
+ max-width: 76rem;
403
+ margin-inline: auto;
404
+ padding-inline: clamp(1rem, 3vw, 3rem);
405
+ }
406
+ .page-prose > h2 { margin-top: 2.5rem; margin-bottom: 1rem; font-size: clamp(1.375rem, 1.1rem + 1.2vw, 2.25rem); font-weight: 600; }
407
+ .page-prose > h3 { margin-top: 1.5rem; margin-bottom: 0.75rem; font-size: clamp(1.125rem, 1rem + 0.6vw, 1.5rem); font-weight: 600; }
408
+ .page-prose > p { font-size: 1rem; line-height: 1.6; margin-top: 0.5rem; margin-bottom: 0.5rem; }
409
+ .page-prose > ul { list-style: disc; padding-left: 1.75rem; margin-block: 0.75rem; }
410
+ .page-prose > ol { list-style: decimal; padding-left: 1.75rem; margin-block: 0.75rem; }
411
+ .page-prose > p a { color: var(--primary); text-decoration: underline; font-weight: 500; }
412
+ .page-prose > p a:hover { text-decoration: none; }
413
+ `);
414
+ // layout.tsx
415
+ writeFileSync(join(srcDir, 'app', '[locale]', 'layout.tsx'), `import { notFound } from 'next/navigation';
416
+ import { routing } from '../../i18n/routing';
417
+ import { ShipSiteProvider } from '@shipsite.dev/components/context';
418
+ import { ThemeProvider } from '@shipsite.dev/components/theme';
419
+ import { Header, Footer } from '@shipsite.dev/components';
420
+ import { generateNavLinks, generateAlternatePathMap, getConfig, getSiteUrl } from '@shipsite.dev/core';
421
+ import '../../styles/globals.css';
422
+ import type { Metadata, Viewport } from 'next';
423
+
424
+ const config = getConfig();
425
+
426
+ export function generateStaticParams() {
427
+ return routing.locales.map((locale) => ({ locale }));
428
+ }
429
+
430
+ export const metadata: Metadata = {
431
+ metadataBase: new URL(getSiteUrl()),
432
+ title: { default: config.name, template: '%s | ' + config.name },
433
+ };
434
+
435
+ export const viewport: Viewport = {
436
+ width: 'device-width',
437
+ initialScale: 1,
438
+ };
439
+
440
+ interface LayoutProps {
441
+ children: React.ReactNode;
442
+ params: Promise<{ locale: string }>;
443
+ }
444
+
445
+ export default async function LocaleLayout({ children, params }: LayoutProps) {
446
+ const { locale } = await params;
447
+ if (!(routing.locales as readonly string[]).includes(locale)) notFound();
448
+
449
+ const navLinks = generateNavLinks(locale);
450
+ const alternatePathMap = generateAlternatePathMap();
451
+
452
+ return (
453
+ <html lang={locale} suppressHydrationWarning>
454
+ <body>
455
+ <ThemeProvider>
456
+ <ShipSiteProvider value={{
457
+ siteName: config.name,
458
+ siteUrl: config.url,
459
+ logo: config.logo,
460
+ ogImage: config.ogImage,
461
+ colors: {
462
+ primary: config.colors?.primary || '#5d5bd4',
463
+ accent: config.colors?.accent || '#067647',
464
+ background: config.colors?.background || '#ffffff',
465
+ text: config.colors?.text || '#1f2a37',
466
+ },
467
+ navigation: config.navigation || { items: [] },
468
+ footer: config.footer || {},
469
+ navLinks,
470
+ alternatePathMap,
471
+ locale,
472
+ locales: config.i18n?.locales || ['en'],
473
+ defaultLocale: config.i18n?.defaultLocale || 'en',
474
+ }}>
475
+ <Header />
476
+ <main id="main-content">{children}</main>
477
+ <Footer />
478
+ </ShipSiteProvider>
479
+ </ThemeProvider>
480
+ </body>
481
+ </html>
482
+ );
483
+ }
484
+ `);
485
+ // page.tsx
486
+ const customComponentsImport = hasCustomComponents
487
+ ? `import * as CustomComponents from '../../../components';\n`
488
+ : '';
489
+ const allComponentsMerge = hasCustomComponents
490
+ ? 'const AllComponents = { ...Components, ...CustomComponents };\n'
491
+ : 'const AllComponents = Components;\n';
492
+ writeFileSync(join(srcDir, 'app', '[locale]', '[[...slug]]', 'page.tsx'), `import { setRequestLocale } from 'next-intl/server';
493
+ import { notFound } from 'next/navigation';
494
+ import { getPageContent } from '@shipsite.dev/core/mdx';
495
+ import { getPageBySlug, generateAllStaticParams, buildCanonicalUrl, getAlternateUrls, isNoIndexPage } from '@shipsite.dev/core/pages';
496
+ import { resolveAuthor } from '@shipsite.dev/core/blog';
497
+ import { getConfig, getSiteUrl } from '@shipsite.dev/core/config';
498
+ import * as Components from '@shipsite.dev/components';
499
+ ${customComponentsImport}import type { Metadata } from 'next';
500
+
501
+ ${allComponentsMerge}
502
+ interface PageProps {
503
+ params: Promise<{ locale: string; slug?: string[] }>;
504
+ }
505
+
506
+ export async function generateStaticParams() {
507
+ return generateAllStaticParams();
508
+ }
509
+
510
+ export const dynamicParams = false;
511
+
512
+ export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
513
+ const { locale, slug } = await params;
514
+ const slugPath = slug?.join('/') || '';
515
+ const pageConfig = getPageBySlug(slugPath, locale);
516
+ if (!pageConfig) return {};
517
+
518
+ try {
519
+ const { frontmatter } = await getPageContent(pageConfig.content, locale, AllComponents);
520
+ const canonicalUrl = buildCanonicalUrl(locale, slugPath);
521
+ const config = getConfig();
522
+ const languages = getAlternateUrls(pageConfig);
523
+
524
+ return {
525
+ title: slugPath === '' ? { absolute: frontmatter.title } : frontmatter.title,
526
+ description: frontmatter.description,
527
+ ...(isNoIndexPage(pageConfig) && { robots: { index: false, follow: true } }),
528
+ alternates: { canonical: canonicalUrl, languages },
529
+ openGraph: {
530
+ title: frontmatter.title,
531
+ description: frontmatter.description,
532
+ url: canonicalUrl,
533
+ siteName: config.name,
534
+ locale,
535
+ type: pageConfig.type === 'blog-article' ? 'article' : 'website',
536
+ },
537
+ };
538
+ } catch {
539
+ return {};
540
+ }
541
+ }
542
+
543
+ export default async function DynamicPage({ params }: PageProps) {
544
+ const { locale, slug } = await params;
545
+ const slugPath = slug?.join('/') || '';
546
+ setRequestLocale(locale);
547
+
548
+ const pageConfig = getPageBySlug(slugPath, locale);
549
+ if (!pageConfig) notFound();
550
+
551
+ let content;
552
+ try {
553
+ const result = await getPageContent(pageConfig.content, locale, AllComponents);
554
+ content = result.content;
555
+ } catch (error) {
556
+ console.error('MDX content error:', error);
557
+ notFound();
558
+ }
559
+
560
+ return <div className="page-prose">{content}</div>;
561
+ }
562
+ `);
563
+ // sitemap.ts
564
+ writeFileSync(join(srcDir, 'app', 'sitemap.ts'), `import sitemap from '@shipsite.dev/core/sitemap';
565
+ export default sitemap;
566
+ `);
567
+ // robots.ts
568
+ writeFileSync(join(srcDir, 'app', 'robots.ts'), `import type { MetadataRoute } from 'next';
569
+ import { getSiteUrl } from '@shipsite.dev/core/config';
570
+
571
+ export default function robots(): MetadataRoute.Robots {
572
+ return {
573
+ rules: [
574
+ { userAgent: '*', allow: '/' },
575
+ { userAgent: 'GPTBot', allow: '/' },
576
+ { userAgent: 'ChatGPT-User', allow: '/' },
577
+ { userAgent: 'ClaudeBot', allow: '/' },
578
+ { userAgent: 'Claude-Web', allow: '/' },
579
+ { userAgent: 'PerplexityBot', allow: '/' },
580
+ { userAgent: 'Applebot-Extended', allow: '/' },
581
+ { userAgent: 'GoogleOther', allow: '/' },
582
+ { userAgent: 'cohere-ai', allow: '/' },
583
+ ],
584
+ sitemap: getSiteUrl() + '/sitemap.xml',
585
+ };
586
+ }
587
+ `);
588
+ // tsconfig.json
589
+ writeFileSync(join(shipSiteDir, 'tsconfig.json'), JSON.stringify({
590
+ compilerOptions: {
591
+ target: 'ES2022',
592
+ lib: ['dom', 'dom.iterable', 'esnext'],
593
+ allowJs: true,
594
+ skipLibCheck: true,
595
+ strict: true,
596
+ noEmit: true,
597
+ esModuleInterop: true,
598
+ module: 'esnext',
599
+ moduleResolution: 'bundler',
600
+ resolveJsonModule: true,
601
+ isolatedModules: true,
602
+ jsx: 'preserve',
603
+ incremental: true,
604
+ plugins: [{ name: 'next' }],
605
+ paths: {
606
+ '@/*': ['./src/*'],
607
+ 'content-collections': ['./.content-collections/generated'],
608
+ },
609
+ },
610
+ include: [
611
+ 'next-env.d.ts',
612
+ '**/*.ts',
613
+ '**/*.tsx',
614
+ '.next/types/**/*.ts',
615
+ ],
616
+ exclude: ['node_modules'],
617
+ }, null, 2));
618
+ // package.json for workspace
619
+ // Dependencies resolve from the parent project's node_modules via Node resolution
620
+ writeFileSync(join(shipSiteDir, 'package.json'), JSON.stringify({
621
+ name: 'shipsite-workspace',
622
+ private: true,
623
+ type: 'module',
624
+ }, null, 2));
625
+ // postcss.config.mjs
626
+ writeFileSync(join(shipSiteDir, 'postcss.config.mjs'), `export default {
627
+ plugins: {
628
+ '@tailwindcss/postcss': {},
629
+ },
630
+ };
631
+ `);
632
+ console.log(' Generated .shipsite workspace');
633
+ }
634
+ //# sourceMappingURL=dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function validate(): Promise<void>;
2
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AA8IA,wBAAsB,QAAQ,kBAsS7B"}
@@ -0,0 +1,317 @@
1
+ import { join, relative } from 'path';
2
+ import { existsSync, readFileSync, readdirSync, statSync } from 'fs';
3
+ const errors = [];
4
+ const warnings = [];
5
+ function fail(message) {
6
+ errors.push(message);
7
+ }
8
+ function warn(message) {
9
+ warnings.push(message);
10
+ }
11
+ function parseFrontmatter(source) {
12
+ const match = source.match(/^---\s*\n([\s\S]*?)\n---\s*\n?/);
13
+ if (!match)
14
+ return null;
15
+ const raw = match[1];
16
+ const data = {};
17
+ for (const line of raw.split('\n')) {
18
+ const trimmed = line.trim();
19
+ if (!trimmed || trimmed.startsWith('#'))
20
+ continue;
21
+ const idx = trimmed.indexOf(':');
22
+ if (idx === -1)
23
+ continue;
24
+ const key = trimmed.slice(0, idx).trim();
25
+ let value = trimmed.slice(idx + 1).trim();
26
+ if ((value.startsWith('"') && value.endsWith('"')) ||
27
+ (value.startsWith("'") && value.endsWith("'"))) {
28
+ value = value.slice(1, -1);
29
+ }
30
+ if (key) {
31
+ data[key] = value;
32
+ }
33
+ }
34
+ return data;
35
+ }
36
+ function extractComponentProps(source, componentName) {
37
+ const match = source.match(new RegExp(`<${componentName}\\b([\\s\\S]*?)>`));
38
+ if (!match)
39
+ return null;
40
+ const raw = match[1] || '';
41
+ const props = new Set();
42
+ const propRegex = /([A-Za-z][A-Za-z0-9_]*)\s*=/g;
43
+ let propMatch;
44
+ while ((propMatch = propRegex.exec(raw))) {
45
+ props.add(propMatch[1]);
46
+ }
47
+ return props;
48
+ }
49
+ function requireComponent(source, componentName, filePath) {
50
+ const props = extractComponentProps(source, componentName);
51
+ if (!props) {
52
+ fail(`Missing <${componentName}> in: ${filePath}`);
53
+ return null;
54
+ }
55
+ return props;
56
+ }
57
+ function requireProps(props, required, componentName, filePath) {
58
+ for (const prop of required) {
59
+ if (!props.has(prop)) {
60
+ fail(`Missing prop "${prop}" in <${componentName}>: ${filePath}`);
61
+ }
62
+ }
63
+ }
64
+ function warnOnSeo(frontmatter, filePath) {
65
+ const title = frontmatter.title || '';
66
+ const description = frontmatter.description || '';
67
+ const titleLength = title.trim().length;
68
+ const descriptionLength = description.trim().length;
69
+ if (titleLength < 30 || titleLength > 70) {
70
+ warn(`SEO title length (${titleLength}) out of range 30-70: ${filePath}`);
71
+ }
72
+ if (descriptionLength < 70 || descriptionLength > 160) {
73
+ warn(`SEO description length (${descriptionLength}) out of range 70-160: ${filePath}`);
74
+ }
75
+ if (description.endsWith('...')) {
76
+ warn(`SEO description ends with ellipsis: ${filePath}`);
77
+ }
78
+ if (title.toLowerCase() === description.toLowerCase()) {
79
+ warn(`SEO title equals description: ${filePath}`);
80
+ }
81
+ const descriptionLower = description.toLowerCase().trim();
82
+ const titleLower = title.toLowerCase().trim();
83
+ if (descriptionLower.startsWith(titleLower) && titleLower.length > 0) {
84
+ warn(`SEO description starts with title: ${filePath}`);
85
+ }
86
+ const punctuation = /[.!?]$/;
87
+ if (descriptionLength > 0 && !punctuation.test(description.trim())) {
88
+ warn(`SEO description should end with punctuation: ${filePath}`);
89
+ }
90
+ const stopwords = new Set([
91
+ 'the', 'and', 'or', 'for', 'with', 'from', 'that', 'this',
92
+ 'your', 'you', 'are', 'our', 'to', 'of', 'in', 'a', 'an',
93
+ ]);
94
+ const tokens = descriptionLower.split(/[^a-z0-9]+/).filter(Boolean);
95
+ const counts = new Map();
96
+ for (const token of tokens) {
97
+ if (token.length < 3 || stopwords.has(token))
98
+ continue;
99
+ counts.set(token, (counts.get(token) || 0) + 1);
100
+ }
101
+ for (const [token, count] of counts.entries()) {
102
+ if (count >= 4) {
103
+ warn(`SEO description repeats "${token}" ${count}x: ${filePath}`);
104
+ break;
105
+ }
106
+ }
107
+ }
108
+ export async function validate() {
109
+ const rootDir = process.cwd();
110
+ const configPath = join(rootDir, 'shipsite.json');
111
+ const contentDir = join(rootDir, 'content');
112
+ console.log('\n Validating content...\n');
113
+ if (!existsSync(configPath)) {
114
+ console.error(' Error: shipsite.json not found in current directory');
115
+ process.exit(1);
116
+ }
117
+ if (!existsSync(contentDir)) {
118
+ console.error(' Error: content/ directory not found');
119
+ process.exit(1);
120
+ }
121
+ const config = JSON.parse(readFileSync(configPath, 'utf-8'));
122
+ const pages = config.pages || [];
123
+ const blogAuthors = Object.keys(config.blog?.authors || {});
124
+ const contentSet = new Set(pages.map((page) => page.content));
125
+ // Track titles/descriptions per locale for duplicate detection
126
+ const titlesByLocale = new Map();
127
+ const descriptionsByLocale = new Map();
128
+ for (const page of pages) {
129
+ if (!page.content) {
130
+ fail(`Page is missing "content" path for slug "${page.slug}"`);
131
+ continue;
132
+ }
133
+ const pageDir = join(contentDir, page.content);
134
+ if (!existsSync(pageDir)) {
135
+ fail(`Missing content folder: content/${page.content}`);
136
+ continue;
137
+ }
138
+ const pageLocales = page.locales || [config.i18n?.defaultLocale || 'en'];
139
+ for (const locale of pageLocales) {
140
+ const mdxPath = join(pageDir, `${locale}.mdx`);
141
+ if (!existsSync(mdxPath)) {
142
+ fail(`Missing MDX file: content/${page.content}/${locale}.mdx`);
143
+ continue;
144
+ }
145
+ const source = readFileSync(mdxPath, 'utf-8');
146
+ const rel = relative(contentDir, mdxPath);
147
+ const frontmatter = parseFrontmatter(source);
148
+ if (!frontmatter) {
149
+ fail(`Missing frontmatter in: content/${rel}`);
150
+ continue;
151
+ }
152
+ if (!frontmatter.title) {
153
+ fail(`Missing "title" in frontmatter: content/${rel}`);
154
+ }
155
+ if (!frontmatter.description) {
156
+ fail(`Missing "description" in frontmatter: content/${rel}`);
157
+ }
158
+ warnOnSeo(frontmatter, `content/${rel}`);
159
+ // Collect titles/descriptions for duplicate detection
160
+ if (frontmatter.title) {
161
+ if (!titlesByLocale.has(locale))
162
+ titlesByLocale.set(locale, new Map());
163
+ const titles = titlesByLocale.get(locale);
164
+ const key = frontmatter.title.trim();
165
+ if (!titles.has(key))
166
+ titles.set(key, []);
167
+ titles.get(key).push(`content/${rel}`);
168
+ }
169
+ if (frontmatter.description) {
170
+ if (!descriptionsByLocale.has(locale))
171
+ descriptionsByLocale.set(locale, new Map());
172
+ const descriptions = descriptionsByLocale.get(locale);
173
+ const key = frontmatter.description.trim();
174
+ if (!descriptions.has(key))
175
+ descriptions.set(key, []);
176
+ descriptions.get(key).push(`content/${rel}`);
177
+ }
178
+ // Blog slugs must not contain "blog/" prefix
179
+ const parts = page.content.split('/');
180
+ if (parts[0] === 'blog' &&
181
+ frontmatter.slug &&
182
+ frontmatter.slug.startsWith('blog/')) {
183
+ fail(`Blog slug "${frontmatter.slug}" must not start with "blog/": content/${rel}`);
184
+ }
185
+ // Raw <img> tags
186
+ if (/<img\b(?![^>]*\bsrc\s*=\s*["']https?:\/\/)/i.test(source)) {
187
+ fail(`Raw <img> tag found — use MDX components: content/${rel}`);
188
+ }
189
+ // --- Component checks per page type ---
190
+ if (page.type === 'landing') {
191
+ const props = requireComponent(source, 'Hero', `content/${rel}`);
192
+ if (props) {
193
+ requireProps(props, ['title', 'description'], 'Hero', `content/${rel}`);
194
+ }
195
+ }
196
+ if (page.type === 'blog-index') {
197
+ const props = requireComponent(source, 'BlogIndex', `content/${rel}`);
198
+ if (props) {
199
+ requireProps(props, ['title', 'description'], 'BlogIndex', `content/${rel}`);
200
+ }
201
+ }
202
+ if (page.type === 'blog-article') {
203
+ requireComponent(source, 'BlogArticle', `content/${rel}`);
204
+ // Required frontmatter fields
205
+ const requiredBlogFields = ['date', 'author', 'readingTime'];
206
+ for (const field of requiredBlogFields) {
207
+ if (!frontmatter[field]) {
208
+ fail(`Missing frontmatter "${field}" for blog article: content/${rel}`);
209
+ }
210
+ }
211
+ if (!frontmatter.image) {
212
+ warn(`Missing frontmatter "image" for blog article (fallback will be used): content/${rel}`);
213
+ }
214
+ // Validate author exists in shipsite.json
215
+ if (frontmatter.author && !blogAuthors.includes(frontmatter.author)) {
216
+ fail(`Unknown author "${frontmatter.author}" (not in shipsite.json blog.authors): content/${rel}`);
217
+ }
218
+ // Validate date format YYYY-MM-DD
219
+ if (frontmatter.date &&
220
+ !/^\d{4}-\d{2}-\d{2}$/.test(frontmatter.date)) {
221
+ fail(`Invalid date format "${frontmatter.date}" (expected YYYY-MM-DD): content/${rel}`);
222
+ }
223
+ // Validate readingTime is a number
224
+ if (frontmatter.readingTime && isNaN(Number(frontmatter.readingTime))) {
225
+ fail(`readingTime must be a number: content/${rel}`);
226
+ }
227
+ // Validate image file exists
228
+ if (frontmatter.image) {
229
+ const imagePath = join(rootDir, 'public', frontmatter.image);
230
+ if (!existsSync(imagePath)) {
231
+ warn(`Blog image not found: public${frontmatter.image} (referenced in content/${rel})`);
232
+ }
233
+ }
234
+ // Minimum word count (300 words)
235
+ const bodyContent = source
236
+ .replace(/^---\s*\n[\s\S]*?\n---\s*\n?/, '')
237
+ .replace(/<[^>]+>/g, '')
238
+ .replace(/import\s+.*?from\s+['"][^'"]+['"]\s*;?/g, '')
239
+ .trim();
240
+ const wordCount = bodyContent.split(/\s+/).filter(Boolean).length;
241
+ if (wordCount < 300) {
242
+ warn(`Blog article has only ${wordCount} words (minimum 300): content/${rel}`);
243
+ }
244
+ // Heading structure validation
245
+ const headingLines = source
246
+ .split('\n')
247
+ .filter((l) => /^#{2,6}\s/.test(l));
248
+ const hasH2 = headingLines.some((l) => /^##\s/.test(l));
249
+ if (!hasH2) {
250
+ warn(`Blog article has no ## headings: content/${rel}`);
251
+ }
252
+ const firstH2Index = headingLines.findIndex((l) => /^##\s/.test(l));
253
+ const firstH3Index = headingLines.findIndex((l) => /^###\s/.test(l));
254
+ if (firstH3Index !== -1 &&
255
+ (firstH2Index === -1 || firstH3Index < firstH2Index)) {
256
+ warn(`Blog article has ### before first ##: content/${rel}`);
257
+ }
258
+ }
259
+ // Component-level checks by presence (any page type)
260
+ const bannerProps = extractComponentProps(source, 'BannerCTA');
261
+ if (bannerProps) {
262
+ requireProps(bannerProps, ['title', 'buttonText'], 'BannerCTA', `content/${rel}`);
263
+ }
264
+ }
265
+ }
266
+ // Cross-page duplicate title/description detection
267
+ for (const [locale, titles] of titlesByLocale.entries()) {
268
+ for (const [title, files] of titles.entries()) {
269
+ if (files.length > 1) {
270
+ warn(`Duplicate title "${title}" in locale "${locale}": ${files.join(', ')}`);
271
+ }
272
+ }
273
+ }
274
+ for (const [locale, descriptions] of descriptionsByLocale.entries()) {
275
+ for (const [, files] of descriptions.entries()) {
276
+ if (files.length > 1) {
277
+ warn(`Duplicate description in locale "${locale}": ${files.join(', ')}`);
278
+ }
279
+ }
280
+ }
281
+ // Warn about orphan content not in shipsite.json
282
+ function walkContentDirs(dir, prefix) {
283
+ for (const entry of readdirSync(dir)) {
284
+ if (entry.startsWith('_') || entry.startsWith('.'))
285
+ continue;
286
+ const entryPath = join(dir, entry);
287
+ if (!statSync(entryPath).isDirectory())
288
+ continue;
289
+ const contentPath = prefix ? `${prefix}/${entry}` : entry;
290
+ const hasMdx = readdirSync(entryPath).some((f) => f.endsWith('.mdx'));
291
+ if (hasMdx && !contentSet.has(contentPath)) {
292
+ warn(`Content folder not referenced in shipsite.json pages: content/${contentPath}`);
293
+ }
294
+ walkContentDirs(entryPath, contentPath);
295
+ }
296
+ }
297
+ walkContentDirs(contentDir, '');
298
+ // Output results
299
+ if (warnings.length) {
300
+ console.warn(' Warnings:');
301
+ for (const message of warnings) {
302
+ console.warn(` - ${message}`);
303
+ }
304
+ console.log();
305
+ }
306
+ if (errors.length) {
307
+ console.error(' Errors:');
308
+ for (const message of errors) {
309
+ console.error(` - ${message}`);
310
+ }
311
+ console.log();
312
+ console.error(` Validation failed: ${errors.length} error(s), ${warnings.length} warning(s)`);
313
+ process.exit(1);
314
+ }
315
+ console.log(` Validation passed. (${warnings.length} warning${warnings.length !== 1 ? 's' : ''})`);
316
+ }
317
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ declare const args: string[];
3
+ declare const command: string;
4
+ declare function main(): Promise<void>;
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,QAAA,MAAM,IAAI,UAAwB,CAAC;AACnC,QAAA,MAAM,OAAO,QAAU,CAAC;AAExB,iBAAe,IAAI,kBAsClB"}
package/dist/index.js ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ const args = process.argv.slice(2);
4
+ const command = args[0];
5
+ async function main() {
6
+ switch (command) {
7
+ case 'dev': {
8
+ const { dev } = await import('./commands/dev.js');
9
+ await dev();
10
+ break;
11
+ }
12
+ case 'build': {
13
+ const { build } = await import('./commands/build.js');
14
+ await build();
15
+ break;
16
+ }
17
+ case 'add': {
18
+ const { add } = await import('./commands/add.js');
19
+ await add(args.slice(1));
20
+ break;
21
+ }
22
+ case 'validate': {
23
+ const { validate } = await import('./commands/validate.js');
24
+ await validate();
25
+ break;
26
+ }
27
+ default:
28
+ console.log(`
29
+ ShipSite CLI
30
+
31
+ Usage:
32
+ shipsite dev Start development server
33
+ shipsite build Build for production
34
+ shipsite add page <name> Add a new page
35
+ shipsite add blog <title> Add a new blog post
36
+ shipsite validate Validate content and SEO
37
+
38
+ Options:
39
+ --help Show this help message
40
+ --version Show version
41
+ `);
42
+ }
43
+ }
44
+ main().catch((err) => {
45
+ console.error(err);
46
+ process.exit(1);
47
+ });
48
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAEA,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AAExB,KAAK,UAAU,IAAI;IACjB,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;YAClD,MAAM,GAAG,EAAE,CAAC;YACZ,MAAM;QACR,CAAC;QACD,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;YACtD,MAAM,KAAK,EAAE,CAAC;YACd,MAAM;QACR,CAAC;QACD,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;YAClD,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACzB,MAAM;QACR,CAAC;QACD,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;YAC5D,MAAM,QAAQ,EAAE,CAAC;YACjB,MAAM;QACR,CAAC;QACD;YACE,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;OAaX,CAAC,CAAC;IACP,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@shipsite.dev/cli",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "bin": {
6
+ "shipsite": "./dist/index.js"
7
+ },
8
+ "files": [
9
+ "dist/"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "dev": "tsc --watch",
14
+ "clean": "rm -rf dist"
15
+ },
16
+ "dependencies": {
17
+ "@shipsite.dev/core": "^0.1.0",
18
+ "chokidar": "^4.0.3"
19
+ },
20
+ "devDependencies": {
21
+ "typescript": "^5.8.3",
22
+ "@types/node": "^20"
23
+ }
24
+ }