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:
2026-08-16 11:14:01 +02:00
co-authored by Claude Sonnet 5
parent 30350d80f4
commit 3f379ca2ac
123 changed files with 65 additions and 104 deletions
+102
View File
@@ -0,0 +1,102 @@
"use client";
import { forwardRef, useEffect, useImperativeHandle, useRef } from "react";
import { Terminal } from "@xterm/xterm";
import { FitAddon } from "@xterm/addon-fit";
import "@xterm/xterm/css/xterm.css";
export interface XtermViewHandle {
write: (data: string) => void;
}
const theme = {
background: "#09090b",
foreground: "#f4f4f5",
cursor: "#f4f4f5",
selectionBackground: "#3f3f46",
black: "#18181b",
red: "#f87171",
green: "#4ade80",
yellow: "#facc15",
blue: "#60a5fa",
magenta: "#c084fc",
cyan: "#22d3ee",
white: "#e4e4e7",
brightBlack: "#3f3f46",
brightRed: "#fca5a5",
brightGreen: "#86efac",
brightYellow: "#fde047",
brightBlue: "#93c5fd",
brightMagenta: "#d8b4fe",
brightCyan: "#67e8f9",
brightWhite: "#f4f4f5",
};
interface XtermViewProps {
/** Written into the terminal as soon as it's created. Only read once, on mount. */
initialData?: string;
}
/** A read-only xterm.js instance: interprets ANSI colors/control codes from streamed script
* output, unlike a plain <pre> which would just show raw escape characters.
*
* `initialData` is written inside the same effect that creates the Terminal - not via a
* ref call from the parent after the fact - specifically because React's Strict Mode (dev
* only) mounts, cleans up, and re-mounts every effect once: a fresh Terminal is created on
* each real mount, so a "write once" flag in the parent would write to the first (disposed)
* instance and silently skip the surviving one, leaving the terminal blank until the next
* live write arrives.
*/
export const XtermView = forwardRef<XtermViewHandle, XtermViewProps>(
function XtermView({ initialData }, ref) {
const containerRef = useRef<HTMLDivElement>(null);
const termRef = useRef<Terminal | null>(null);
useEffect(() => {
if (!containerRef.current) return;
const term = new Terminal({
convertEol: true,
disableStdin: true,
cursorBlink: false,
fontSize: 12,
lineHeight: 1.2,
fontFamily: "ui-monospace, Menlo, monospace",
theme,
});
const fitAddon = new FitAddon();
term.loadAddon(fitAddon);
term.open(containerRef.current);
fitAddon.fit();
if (initialData) term.write(initialData);
termRef.current = term;
const resizeObserver = new ResizeObserver(() => {
try {
fitAddon.fit();
} catch {
// container has zero size (e.g. mid-layout-shift) - next resize will retry
}
});
resizeObserver.observe(containerRef.current);
return () => {
resizeObserver.disconnect();
term.dispose();
termRef.current = null;
};
// eslint-disable-next-line react-hooks/exhaustive-deps -- initialData is intentionally only used on mount
}, []);
useImperativeHandle(ref, () => ({
write: (data: string) => termRef.current?.write(data),
}));
return (
<div
ref={containerRef}
className="h-[60vh] overflow-hidden rounded-lg bg-zinc-950 p-2"
/>
);
},
);