initial commit

This commit is contained in:
Hunter
2026-11-01 13:23:44 -05:00
commit e03ea4f770
53 changed files with 10802 additions and 0 deletions

54
app/layout.tsx Normal file
View File

@@ -0,0 +1,54 @@
import type { Metadata } from "next";
import Link from "next/link";
import { JetBrains_Mono, DM_Sans } from "next/font/google";
import { gitStatus } from "@/lib/git";
import "./manager.css";
export const dynamic = "force-dynamic";
const mono = JetBrains_Mono({ subsets: ["latin"], variable: "--mono", display: "swap" });
const sans = DM_Sans({ subsets: ["latin"], variable: "--sans", display: "swap" });
export const metadata: Metadata = {
title: "Blog Manager",
description: "Local editor for the portfolio blog",
};
async function PublishBadge() {
const status = await gitStatus();
if (!status.available) {
return <span className="badge err" title={status.error}>git unavailable</span>;
}
const pending = status.changes.length;
const ahead = status.ahead ?? 0;
if (!pending && !ahead) return <span className="badge ok">published</span>;
return (
<Link href="/publish" className="badge warn">
{pending ? `${pending} unpublished change${pending === 1 ? "" : "s"}` : `${ahead} commit(s) not pushed`}
</Link>
);
}
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" className={`${mono.variable} ${sans.variable}`}>
<body>
<div className="shell">
<header className="topbar">
<Link href="/" className="brand">blog-manager</Link>
<nav>
<Link href="/">posts</Link>
<Link href="/posts/new">new post</Link>
<Link href="/categories">categories</Link>
<Link href="/tags">tags</Link>
<Link href="/publish">publish</Link>
</nav>
<span className="spacer" />
<PublishBadge />
</header>
{children}
</div>
</body>
</html>
);
}