feat(cms): migrate from Directus to Payload v3 and remove contentlayer
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 3m43s
Build & Deploy / 🏗️ Build (push) Failing after 37s
Build & Deploy / 🧪 QA (push) Failing after 3m40s
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🩺 Health Check (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 2s

This commit is contained in:
2026-02-22 20:50:51 +01:00
parent b2f5e2dd4d
commit 072b6b13f1
30 changed files with 4299 additions and 2062 deletions

View File

@@ -0,0 +1,72 @@
import { getPayload } from "payload";
import configPromise from "../payload.config";
import fs from "fs";
import path from "path";
function parseMatter(content: string) {
const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
if (!match) return { data: {}, content };
const data: Record<string, any> = {};
match[1].split("\n").forEach((line) => {
const [key, ...rest] = line.split(":");
if (key && rest.length) {
const field = key.trim();
let val = rest.join(":").trim();
if (val.startsWith("[")) {
// basic array parsing
data[field] = val
.slice(1, -1)
.split(",")
.map((s) => s.trim().replace(/^["']|["']$/g, ""));
} else {
data[field] = val.replace(/^["']|["']$/g, "");
}
}
});
return { data, content: match[2].trim() };
}
async function run() {
const payload = await getPayload({ config: configPromise });
const contentDir = path.join(process.cwd(), "content", "blog");
const files = fs.readdirSync(contentDir).filter((f) => f.endsWith(".mdx"));
for (const file of files) {
const filePath = path.join(contentDir, file);
const content = fs.readFileSync(filePath, "utf-8");
const { data, content: body } = parseMatter(content);
const slug = file.replace(/\.mdx$/, "");
console.log(`Migrating ${slug}...`);
const existing = await payload.find({
collection: "posts",
where: { slug: { equals: slug } },
});
if (existing.docs.length === 0) {
await payload.create({
collection: "posts",
data: {
title: data.title || slug,
slug,
description: data.description || "",
date: data.date
? new Date(data.date).toISOString()
: new Date().toISOString(),
tags: (data.tags || []).map((t: string) => ({ tag: t })),
thumbnail: data.thumbnail || "",
content: body,
},
});
console.log(`✔ Inserted ${slug}`);
} else {
console.log(`⚠ Skipped ${slug} (already exists)`);
}
}
console.log("Migration complete.");
process.exit(0);
}
run().catch(console.error);

View File

@@ -1,72 +0,0 @@
import {
createMintelDirectusClient,
ensureDirectusAuthenticated,
} from "@mintel/next-utils";
import { updateSettings } from "@directus/sdk";
const client = createMintelDirectusClient();
async function setupBranding() {
const prjName = process.env.PROJECT_NAME || "Mintel.me";
const prjColor = process.env.PROJECT_COLOR || "#ff00ff";
console.log(`🎨 Refining Directus Branding for ${prjName}...`);
await ensureDirectusAuthenticated(client);
const cssInjection = `
<style>
@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700&display=swap');
body, .v-app { font-family: 'Outfit', sans-serif !important; }
.public-view .v-card {
backdrop-filter: blur(20px);
background: rgba(255, 255, 255, 0.9) !important;
border-radius: 32px !important;
box-shadow: 0 50px 100px -20px rgba(0, 0, 0, 0.4) !important;
border: 1px solid rgba(255, 255, 255, 0.3) !important;
}
.v-navigation-drawer { background: #000c24 !important; }
.v-list-item--active {
color: ${prjColor} !important;
background: rgba(255, 0, 255, 0.1) !important;
}
</style>
<div style="font-family: 'Outfit', sans-serif; text-align: center; margin-top: 24px;">
<p style="color: rgba(255,255,255,0.6); font-size: 11px; letter-spacing: 2px; margin-bottom: 4px; font-weight: 600; text-transform: uppercase;">Mintel Infrastructure Engine</p>
<h1 style="color: #ffffff; font-size: 20px; font-weight: 700; margin: 0; letter-spacing: -0.5px;">${prjName.toUpperCase()} <span style="color: ${prjColor};">SYNC.</span></h1>
</div>
`;
try {
await client.request(
updateSettings({
project_name: prjName,
project_color: prjColor,
public_note: cssInjection,
module_bar_background: "#00081a",
theme_light_overrides: {
primary: prjColor,
borderRadius: "12px",
navigationBackground: "#000c24",
navigationForeground: "#ffffff",
moduleBarBackground: "#00081a",
},
} as any),
);
console.log("✨ Branding applied!");
} catch (error) {
console.error("❌ Error during bootstrap:", error);
}
}
setupBranding()
.then(() => {
process.exit(0);
})
.catch((err) => {
console.error("🚨 Fatal bootstrap error:", err);
process.exit(1);
});