summaryrefslogtreecommitdiff
path: root/app/root.tsx
diff options
context:
space:
mode:
authoryyamashita <yyamashita@hetzner.yyamashita.com>2026-06-19 15:18:55 +0900
committeryyamashita <yyamashita@hetzner.yyamashita.com>2026-06-19 15:18:55 +0900
commit30f24e137ee2d1acec11a0da61e134f512ee02dd (patch)
tree28bd91bde3ad883f9f8fa543fca4b25ed50d05e9 /app/root.tsx
parentda4934ae84f8a81fe3f4f8b392a4a3dc3d566f30 (diff)
Initial implementation of microblog
Markdown-based personal microblog with REST API. XSS protection via sanitize-html on server-side markdown rendering. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'app/root.tsx')
-rw-r--r--app/root.tsx46
1 files changed, 46 insertions, 0 deletions
diff --git a/app/root.tsx b/app/root.tsx
new file mode 100644
index 0000000..80570db
--- /dev/null
+++ b/app/root.tsx
@@ -0,0 +1,46 @@
+import { isRouteErrorResponse, Links, Meta, Outlet, Scripts, ScrollRestoration } from "react-router";
+import type { Route } from "./+types/root";
+import "./app.css";
+
+export function Layout({ children }: { children: React.ReactNode }) {
+ return (
+ <html lang="ja">
+ <head>
+ <meta charSet="utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <title>log</title>
+ <Meta />
+ <Links />
+ </head>
+ <body>
+ {children}
+ <ScrollRestoration />
+ <Scripts />
+ </body>
+ </html>
+ );
+}
+
+export default function App() {
+ return <Outlet />;
+}
+
+export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
+ let message = "Error";
+ let details = "An unexpected error occurred.";
+
+ if (isRouteErrorResponse(error)) {
+ message = String(error.status);
+ details = error.statusText || details;
+ } else if (import.meta.env.DEV && error instanceof Error) {
+ details = error.message;
+ }
+
+ return (
+ <div className="wrap">
+ <p style={{ color: "#e06c75", fontFamily: "monospace" }}>
+ {message}: {details}
+ </p>
+ </div>
+ );
+}