Initial react editor website template

This commit is contained in:
Rami Bitar
2026-08-29 14:03:50 -04:00
commit 3e072967e6
61 changed files with 7041 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
import type { Metadata } from 'next';
import { site } from '@/config/site';
interface EditorPage {
root?: {
props?: {
title?: string;
description?: string;
ogImage?: string;
};
};
}
export function pageMetadata(
page: EditorPage,
overrides: { title?: string; description?: string; path?: string } = {}
): Metadata {
const props = page.root?.props ?? {};
const title = overrides.title ?? props.title ?? site.name;
const description = overrides.description ?? props.description ?? site.description;
const image = props.ogImage;
return {
title: { absolute: title },
description,
alternates: overrides.path ? { canonical: overrides.path } : undefined,
openGraph: {
type: 'website',
siteName: site.name,
title,
description,
url: overrides.path ?? '/',
images: image ? [{ url: image, alt: title }] : undefined,
},
twitter: {
card: 'summary_large_image',
title,
description,
images: image ? [image] : undefined,
},
};
}
+42
View File
@@ -0,0 +1,42 @@
'use server';
import { writeFile } from 'node:fs/promises';
import path from 'node:path';
const GLOBALS_FILE = path.join(process.cwd(), 'app.globals.json');
export async function publishPage(pagePath: string, page: unknown) {
if (!page || typeof page !== 'object') {
return { error: 'Expected a page object.' };
}
const appDir = path.join(process.cwd(), 'app');
const file = path.resolve(process.cwd(), pagePath);
const relativeToApp = path.relative(appDir, file);
if (
!relativeToApp ||
relativeToApp.startsWith(`..${path.sep}`) ||
path.isAbsolute(relativeToApp) ||
path.basename(file) !== 'page.json'
) {
return { error: 'Invalid page file.' };
}
const { globals, ...pageData } = page as Record<string, unknown>;
try {
await writeFile(file, `${JSON.stringify(pageData, null, 2)}\n`, 'utf8');
if (globals && typeof globals === 'object') {
await writeFile(
GLOBALS_FILE,
`${JSON.stringify(globals, null, 2)}\n`,
'utf8'
);
}
return { file: path.relative(process.cwd(), file) };
} catch (error) {
console.error(`Failed to write ${file}:`, error);
return { error: 'Could not save the page. Run the editor on a writable filesystem.' };
}
}
+6
View File
@@ -0,0 +1,6 @@
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}