Midday / apps /website /src /lib /docs.ts
Jules
Final deployment with all fixes and verified content
c09f67c
import fs from "node:fs";
import path from "node:path";
type DocMetadata = {
title: string;
description: string;
section?: string;
order?: number;
};
type DocSection = {
title: string;
slug: string;
docs: Array<{
slug: string;
title: string;
description: string;
order: number;
}>;
};
function parseFrontmatter(fileContent: string) {
const frontmatterRegex = /---\s*([\s\S]*?)\s*---/;
const match = frontmatterRegex.exec(fileContent);
const frontMatterBlock = match?.[1];
const content = fileContent.replace(frontmatterRegex, "").trim();
const frontMatterLines = frontMatterBlock?.trim().split("\n") || [];
const metadata: Partial<DocMetadata> = {};
for (const line of frontMatterLines) {
const [key, ...valueArr] = line.split(": ");
if (key) {
let value = valueArr.join(": ").trim();
value = value.replace(/^['"](.*)['"]$/, "$1");
const trimmedKey = key.trim();
if (trimmedKey === "order") {
metadata.order = Number.parseInt(value, 10);
} else if (
trimmedKey === "title" ||
trimmedKey === "description" ||
trimmedKey === "section"
) {
metadata[trimmedKey] = value;
}
}
}
return { metadata: metadata as DocMetadata, content };
}
function getMDXFiles(dir: string): string[] {
if (!fs.existsSync(dir)) {
return [];
}
return fs.readdirSync(dir).filter((file) => path.extname(file) === ".mdx");
}
function readMDXFile(filePath: string) {
const rawContent = fs.readFileSync(filePath, "utf-8");
return parseFrontmatter(rawContent);
}
export function getDocsData() {
const docsDir = path.join(process.cwd(), "src", "app", "docs", "content");
if (!fs.existsSync(docsDir)) {
return [];
}
const mdxFiles = getMDXFiles(docsDir);
return mdxFiles.map((file) => {
const { metadata, content } = readMDXFile(path.join(docsDir, file));
const slug = path.basename(file, path.extname(file));
return {
metadata,
slug,
content,
};
});
}
export function getDocBySlug(slug: string) {
const docsDir = path.join(process.cwd(), "src", "app", "docs", "content");
const filePath = path.join(docsDir, `${slug}.mdx`);
if (!fs.existsSync(filePath)) {
return null;
}
const { metadata, content } = readMDXFile(filePath);
return {
metadata,
slug,
content,
};
}
export function getAllDocSlugs(): string[] {
const docsDir = path.join(process.cwd(), "src", "app", "docs", "content");
if (!fs.existsSync(docsDir)) {
return [];
}
const mdxFiles = getMDXFiles(docsDir);
return mdxFiles.map((file) => path.basename(file, path.extname(file)));
}
// Navigation structure for the sidebar
export const docsNavigation: DocSection[] = [
{
title: "Getting Started",
slug: "getting-started",
docs: [
{
slug: "introduction",
title: "Introduction",
description: "What is Midday?",
order: 1,
},
{
slug: "quick-start",
title: "Quick Start",
description: "Get running in 5 minutes",
order: 2,
},
{
slug: "desktop-app",
title: "Desktop App",
description: "Native macOS & Windows app",
order: 3,
},
{
slug: "troubleshooting",
title: "Troubleshooting",
description: "Common issues & FAQ",
order: 4,
},
],
},
{
title: "Banking",
slug: "banking",
docs: [
{
slug: "connect-bank-account",
title: "Connect Bank",
description: "Link your bank accounts",
order: 1,
},
{
slug: "import-transactions-csv",
title: "Import CSV",
description: "Import from any source",
order: 2,
},
{
slug: "auto-categorization",
title: "Categorization",
description: "Automatic categories",
order: 3,
},
{
slug: "categories-reference",
title: "Categories Reference",
description: "All categories explained",
order: 4,
},
{
slug: "use-tags",
title: "Tags",
description: "Organize transactions",
order: 5,
},
{
slug: "account-settings",
title: "Account Settings",
description: "Manage bank accounts",
order: 6,
},
{
slug: "multi-currency",
title: "Multi-Currency",
description: "Multiple currencies & exchange",
order: 7,
},
],
},
{
title: "Receipts & Inbox",
slug: "inbox",
docs: [
{
slug: "receipt-matching",
title: "Receipt Matching",
description: "AI-powered matching",
order: 1,
},
{
slug: "forward-receipts-email",
title: "Email Forwarding",
description: "Forward receipts",
order: 2,
},
{
slug: "connect-gmail",
title: "Gmail",
description: "Auto-capture from Gmail",
order: 3,
},
{
slug: "connect-outlook",
title: "Outlook",
description: "Auto-capture from Outlook",
order: 4,
},
{
slug: "connect-slack",
title: "Slack",
description: "Share from Slack",
order: 5,
},
],
},
{
title: "Vault",
slug: "vault",
docs: [
{
slug: "vault-file-storage",
title: "File Storage",
description: "Store documents",
order: 1,
},
],
},
{
title: "Invoicing",
slug: "invoicing",
docs: [
{
slug: "create-invoice",
title: "Create Invoice",
description: "Send professional invoices",
order: 1,
},
{
slug: "customize-invoice-template",
title: "Templates",
description: "Brand your invoices",
order: 2,
},
{
slug: "set-up-recurring-invoice",
title: "Recurring",
description: "Automate billing",
order: 3,
},
{
slug: "accept-online-payments",
title: "Online Payments",
description: "Accept card payments",
order: 4,
},
{
slug: "track-invoice-status",
title: "Track Status",
description: "Payment tracking",
order: 5,
},
{
slug: "invoice-settings",
title: "Invoice Settings",
description: "Configure invoices",
order: 6,
},
],
},
{
title: "Time Tracking",
slug: "time-tracking",
docs: [
{
slug: "create-project",
title: "Projects",
description: "Set up projects",
order: 1,
},
{
slug: "track-time-timer",
title: "Track Time",
description: "Timer and entries",
order: 2,
},
{
slug: "invoice-tracked-time",
title: "Bill Time",
description: "Turn time into invoices",
order: 3,
},
],
},
{
title: "Customers",
slug: "customers",
docs: [
{
slug: "add-customer",
title: "Add Customer",
description: "Create customer profiles",
order: 1,
},
{
slug: "customer-portal",
title: "Customer Portal",
description: "Self-serve access",
order: 2,
},
],
},
{
title: "Reports",
slug: "reports",
docs: [
{
slug: "understanding-metrics",
title: "Understanding Metrics",
description: "How metrics work",
order: 1,
},
{
slug: "view-revenue-profit",
title: "Revenue & Profit",
description: "Track your income",
order: 2,
},
{
slug: "check-runway",
title: "Runway",
description: "Cash runway analysis",
order: 3,
},
{
slug: "view-burn-rate",
title: "Burn Rate",
description: "Monthly spending",
order: 4,
},
{
slug: "share-report",
title: "Share Reports",
description: "Share with others",
order: 5,
},
],
},
{
title: "Export & Integrations",
slug: "export",
docs: [
{
slug: "apps-overview",
title: "Apps Overview",
description: "All integrations",
order: 1,
},
{
slug: "export-transactions-csv",
title: "Export CSV",
description: "Download transactions",
order: 2,
},
{
slug: "connect-xero",
title: "Xero",
description: "Export to Xero",
order: 3,
},
{
slug: "connect-quickbooks",
title: "QuickBooks",
description: "Export to QuickBooks",
order: 4,
},
{
slug: "connect-fortnox",
title: "Fortnox",
description: "Export to Fortnox",
order: 5,
},
],
},
{
title: "Assistant",
slug: "assistant",
docs: [
{
slug: "using-assistant",
title: "Using Assistant",
description: "Ask Midday anything",
order: 1,
},
{
slug: "assistant-mcp",
title: "AI Tools (MCP)",
description: "Cursor, Claude, ChatGPT",
order: 2,
},
],
},
{
title: "Team & Settings",
slug: "team",
docs: [
{
slug: "invite-team-member",
title: "Team Members",
description: "Add your team",
order: 1,
},
{
slug: "notification-settings",
title: "Notifications",
description: "Configure alerts",
order: 2,
},
{
slug: "manage-subscription",
title: "Billing",
description: "Manage subscription",
order: 3,
},
],
},
{
title: "Developer",
slug: "developer",
docs: [
{
slug: "api-reference",
title: "API Reference",
description: "REST API docs",
order: 1,
},
],
},
];
export function getDocNavigation() {
return docsNavigation;
}