diff --git a/content/pages/.gitkeep b/content/pages/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/package.json b/package.json index d7623a5..4dec62b 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "type": "module", "scripts": { "dev": "tinacms dev -c \"vite\"", - "build": "tinacms build && node scripts/sync-blog.mjs && node scripts/generate-sitemap.mjs && tsc -b && vite build && node scripts/prerender.mjs", + "build": "tinacms build && node scripts/sync-blog.mjs && node scripts/copy-pages.mjs && node scripts/generate-sitemap.mjs && tsc -b && vite build && node scripts/prerender.mjs", "lint": "eslint .", "preview": "vite preview", "sync-blog": "node scripts/sync-blog.mjs", diff --git a/scripts/copy-pages.mjs b/scripts/copy-pages.mjs new file mode 100644 index 0000000..8038384 --- /dev/null +++ b/scripts/copy-pages.mjs @@ -0,0 +1,22 @@ +import { readdirSync, copyFileSync, mkdirSync, existsSync } from 'node:fs'; +import { resolve, dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const root = resolve(__dirname, '..'); +const src = resolve(root, 'content/pages'); +const dest = resolve(root, 'public/pages'); + +if (!existsSync(src)) { + console.log('No content/pages directory, skipping.'); + process.exit(0); +} + +mkdirSync(dest, { recursive: true }); + +const files = readdirSync(src).filter(f => f.endsWith('.json')); +for (const file of files) { + copyFileSync(resolve(src, file), resolve(dest, file)); + console.log(`Copied: ${file}`); +} +console.log(`Pages copy complete: ${files.length} file(s).`); diff --git a/scripts/prerender.mjs b/scripts/prerender.mjs index 945c779..f0b50e3 100644 --- a/scripts/prerender.mjs +++ b/scripts/prerender.mjs @@ -5,7 +5,7 @@ * * Usage: node scripts/prerender.mjs */ -import { readFileSync, writeFileSync, mkdirSync } from 'node:fs'; +import { readFileSync, writeFileSync, mkdirSync, readdirSync } from 'node:fs'; import { resolve, dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; @@ -20,6 +20,19 @@ function getBlogRoutes() { } catch { return []; } } +function getPageRoutes() { + try { + const pagesDir = resolve(root, 'public/pages'); + const files = readdirSync(pagesDir).filter(f => f.endsWith('.json')); + return files + .map(f => { + const data = JSON.parse(readFileSync(resolve(pagesDir, f), 'utf-8')); + return data.published ? `/p/${f.replace('.json', '')}` : null; + }) + .filter(Boolean); + } catch { return []; } +} + const routes = [ '/', '/about', @@ -29,6 +42,7 @@ const routes = [ '/privacy-policy', '/terms-of-use', ...getBlogRoutes(), + ...getPageRoutes(), ]; async function prerender() { diff --git a/src/App.tsx b/src/App.tsx index 01bbf10..bf13b69 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,6 +6,7 @@ import ScrollToTop from './components/ScrollToTop'; import CookieConsent from './components/CookieConsent'; import React from 'react'; const ChatWidget = React.lazy(() => import('./components/ChatWidget')); +const DynamicPage = React.lazy(() => import('./pages/DynamicPage')); import HomePage from './pages/HomePage'; import BlogPage from './pages/BlogPage'; import BlogPostPage from './pages/BlogPostPage'; @@ -30,6 +31,7 @@ function App() { } /> } /> } /> + } />