Flatten the repo: move everything out of app/ to the root
Now that the CLI and the Next.js app are one package, nesting it inside app/ served no purpose - the repo root itself becomes the published npm package. Merges app/.gitignore and app/README.md into the root versions, drops the now-duplicate app/LICENSE, and updates path references (README, docs/ARCHITECTURE.md, docs/CONFIG_REFERENCE.md, package.json's repository.directory) that assumed the app/ nesting. Also fixes a real bug this surfaced: the in-app docs viewer resolved docs/ relative to process.cwd(), which only worked by accident when the CLI happened to be invoked from app/'s parent directory. A first attempt at fixing it with import.meta.dirname broke instead, for the same cross-module-graph reason config-path resolution already documented - Next compiles Route Handlers through a separate module graph that doesn't preserve source-relative import.meta paths. Fixed by exposing the app root via TRIGGERSHELL_APP_ROOT (set once in server.ts, where import.meta *does* resolve correctly), the same pattern already used for TRIGGERSHELL_CONFIG_PATH. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { usePathname, useRouter } from "next/navigation";
|
||||
import { Terminal, History, LogOut } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { ThemeToggle } from "./theme-toggle";
|
||||
|
||||
const links = [
|
||||
{ href: "/", label: "Scripts", icon: Terminal },
|
||||
{ href: "/runs", label: "History", icon: History },
|
||||
];
|
||||
|
||||
export function Nav({
|
||||
authEnabled,
|
||||
username,
|
||||
}: {
|
||||
authEnabled: boolean;
|
||||
username: string | null;
|
||||
}) {
|
||||
const pathname = usePathname();
|
||||
const router = useRouter();
|
||||
|
||||
async function handleLogout() {
|
||||
await fetch("/api/auth/logout", { method: "POST" });
|
||||
router.push("/login");
|
||||
router.refresh();
|
||||
}
|
||||
|
||||
return (
|
||||
<header className="border-b bg-background/95 sticky top-0 z-10 backdrop-blur">
|
||||
<div className="mx-auto flex h-14 max-w-5xl items-center justify-between gap-2 px-4">
|
||||
<div className="flex min-w-0 items-center gap-3 sm:gap-6">
|
||||
<Link
|
||||
href="/"
|
||||
className="flex shrink-0 items-center gap-2 font-semibold tracking-tight"
|
||||
>
|
||||
<Terminal className="size-5" />
|
||||
TriggerShell
|
||||
</Link>
|
||||
<nav className="flex items-center gap-1">
|
||||
{links.map(({ href, label, icon: Icon }) => (
|
||||
<Link
|
||||
key={href}
|
||||
href={href}
|
||||
className={cn(
|
||||
"text-muted-foreground hover:text-foreground flex items-center gap-1.5 rounded-md px-2 py-1.5 text-sm font-medium transition-colors sm:px-3",
|
||||
pathname === href && "bg-muted text-foreground",
|
||||
)}
|
||||
>
|
||||
<Icon className="size-4" />
|
||||
<span className="sr-only sm:not-sr-only">{label}</span>
|
||||
</Link>
|
||||
))}
|
||||
</nav>
|
||||
</div>
|
||||
<div className="flex shrink-0 items-center gap-1 sm:gap-2">
|
||||
<ThemeToggle />
|
||||
{authEnabled && (
|
||||
<>
|
||||
<span className="text-muted-foreground hidden max-w-32 truncate text-sm sm:inline-block">
|
||||
{username}
|
||||
</span>
|
||||
<Button variant="ghost" size="sm" onClick={handleLogout}>
|
||||
<LogOut className="size-4" />
|
||||
<span className="sr-only sm:not-sr-only">Log out</span>
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user