feat: revamp to dynamic database-first architecture and cleanup phase docs
CI / typecheck + build (turbo) (push) Canceled after 0s
CI / typecheck + build (turbo) (push) Canceled after 0s
- Migrate document fetching and CRUD to be PostgreSQL-authoritative - Remove static section enums and add dynamic listSections query - Support custom sections and metadata across API, MCP, and Web UI - Add /api/sections endpoint and update Header, Sidebar, and Forms - Remove obsolete phase planning docs and modernize README/AGENTS
This commit is contained in:
@@ -39,20 +39,27 @@ export const EMBED_BASE_URL = process.env.EMBED_BASE_URL ?? "";
|
||||
export const EMBED_API_KEY = process.env.EMBED_API_KEY ?? "";
|
||||
export const EMBED_MODEL = process.env.EMBED_MODEL ?? "";
|
||||
|
||||
// Phase 3: Redis + BullMQ (shared imrnes Redis, no auth by default).
|
||||
// Redis + BullMQ (shared Redis instance).
|
||||
export const REDIS_URL = process.env.REDIS_URL ?? "redis://100.121.180.82:6379";
|
||||
export const REDIS_PASSWORD = process.env.REDIS_PASSWORD ?? "";
|
||||
export const QUEUE_PREFIX = process.env.QUEUE_PREFIX ?? "mcpedia";
|
||||
|
||||
// Phase 4: git-sync webhook shared secret.
|
||||
// Git-sync webhook and API write shared secret.
|
||||
export const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET ?? "";
|
||||
|
||||
// Phase 11: Admin password for web-based CRUD.
|
||||
// Admin password for web-based CRUD.
|
||||
export const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD ?? "";
|
||||
|
||||
// Phase 14: Section registry — re-exported from a Node-free module so client
|
||||
// components can safely import SECTIONS without pulling in node:fs.
|
||||
export { SECTIONS, SECTIONS_BY_ID, SECTION_IDS, type SectionConfig } from "./sections";
|
||||
// Dynamic Section registry & helpers — re-exported from a Node-free module.
|
||||
export {
|
||||
SECTIONS,
|
||||
SECTIONS_BY_ID,
|
||||
SECTION_IDS,
|
||||
DEFAULT_SECTIONS,
|
||||
SECTION_PRESETS,
|
||||
getSectionMeta,
|
||||
type SectionConfig,
|
||||
} from "./sections";
|
||||
|
||||
// NOTE: we deliberately do NOT throw here if DATABASE_URL is empty.
|
||||
// Throwing at import time breaks `next build` SSG and any runtime-injected env.
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
/**
|
||||
* Section registry — defines all content sections for the UI.
|
||||
* This file is intentionally free of Node.js built-in imports (no fs/path)
|
||||
* so it can be safely imported by client components.
|
||||
*
|
||||
* Adding a new section is as simple as adding an entry here + creating a
|
||||
* `content/<id>/` directory with markdown files. No UI code changes needed.
|
||||
* Dynamic Section Registry & Metadata Generator.
|
||||
* Safe for client and server components.
|
||||
*/
|
||||
export interface SectionConfig {
|
||||
id: string;
|
||||
@@ -13,32 +9,80 @@ export interface SectionConfig {
|
||||
desc: string;
|
||||
}
|
||||
|
||||
export const SECTIONS: SectionConfig[] = [
|
||||
{
|
||||
id: "docs",
|
||||
export const SECTION_PRESETS: Record<string, { label: string; icon: string; desc: string }> = {
|
||||
docs: {
|
||||
label: "Documentation",
|
||||
icon: "📄",
|
||||
desc: "Setup guides, API references, and protocol specs.",
|
||||
},
|
||||
{
|
||||
id: "writeups",
|
||||
writeups: {
|
||||
label: "Writeups",
|
||||
icon: "📝",
|
||||
desc: "Post-mortems, debugging stories, and case studies.",
|
||||
desc: "Post-mortems, CTF writeups, debugging stories, and case studies.",
|
||||
},
|
||||
{
|
||||
id: "research",
|
||||
research: {
|
||||
label: "Research",
|
||||
icon: "🔬",
|
||||
desc: "Deep-dive analysis, architecture notes, and experiments.",
|
||||
},
|
||||
{
|
||||
id: "notes",
|
||||
notes: {
|
||||
label: "Notes",
|
||||
icon: "📌",
|
||||
desc: "Quick references, patterns, and gotchas.",
|
||||
desc: "Quick references, patterns, and cheat-sheets.",
|
||||
},
|
||||
guides: {
|
||||
label: "Guides",
|
||||
icon: "🧭",
|
||||
desc: "Step-by-step guides and implementation walkthroughs.",
|
||||
},
|
||||
tutorials: {
|
||||
label: "Tutorials",
|
||||
icon: "🎓",
|
||||
desc: "Educational lessons and practical tutorials.",
|
||||
},
|
||||
ctf: {
|
||||
label: "CTF",
|
||||
icon: "🚩",
|
||||
desc: "Capture The Flag challenge writeups and exploit solutions.",
|
||||
},
|
||||
api: {
|
||||
label: "API",
|
||||
icon: "⚡",
|
||||
desc: "API documentation and endpoint definitions.",
|
||||
},
|
||||
projects: {
|
||||
label: "Projects",
|
||||
icon: "🚀",
|
||||
desc: "Project overviews and technical architecture roadmaps.",
|
||||
},
|
||||
};
|
||||
|
||||
export function getSectionMeta(id: string, count?: number): SectionConfig {
|
||||
const cleanId = (id || "docs").toLowerCase().trim();
|
||||
if (SECTION_PRESETS[cleanId]) {
|
||||
return { id: cleanId, ...SECTION_PRESETS[cleanId] };
|
||||
}
|
||||
const formattedLabel = cleanId
|
||||
.split(/[-_]/)
|
||||
.map((w) => (w ? w.charAt(0).toUpperCase() + w.slice(1) : ""))
|
||||
.join(" ");
|
||||
return {
|
||||
id: cleanId,
|
||||
label: formattedLabel || "Custom Section",
|
||||
icon: "📁",
|
||||
desc: `Documents in the ${formattedLabel || cleanId} section.`,
|
||||
};
|
||||
}
|
||||
|
||||
export const DEFAULT_SECTIONS: SectionConfig[] = [
|
||||
getSectionMeta("docs"),
|
||||
getSectionMeta("writeups"),
|
||||
getSectionMeta("research"),
|
||||
getSectionMeta("notes"),
|
||||
];
|
||||
|
||||
// Backwards-compatible constants:
|
||||
export const SECTIONS: SectionConfig[] = DEFAULT_SECTIONS;
|
||||
export const SECTIONS_BY_ID = new Map(SECTIONS.map((s) => [s.id, s]));
|
||||
export const SECTION_IDS = SECTIONS.map((s) => s.id);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user