Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions web/bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
"@types/mdx": "^2.0.13",
"ethers": "^6.16.0",
"lenis": "^1.3.0",
"lucide-react": "^1.23.0",
"next": "16.1.1",
"next-themes": "^0.4.6",
"posthog-js": "^1.382.0",
"react": "19.2.3",
"react-dom": "19.2.3"
Expand Down
21 changes: 21 additions & 0 deletions web/src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,27 @@
--alert-soft: #fbe4e4;
}

.dark {
--paper: #0f1115;
--paper-deep: #1a1d23;

--ink: #f5f5f5;
--ink-soft: #d0d0d0;
--ink-faint: #8d8d8d;

--rule: #f5f5f5;

--accent: #5b7fff;
--accent-press: #3d63ff;
--accent-soft: #1c2648;

--ok: #37c871;
--ok-soft: #163222;

--alert: #ff6b6b;
--alert-soft: #3a1717;
}

@theme inline {
--color-paper: var(--paper);
--color-paper-deep: var(--paper-deep);
Expand Down
11 changes: 7 additions & 4 deletions web/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import localFont from "next/font/local";
import "./globals.css";
import { SmoothScroll } from "@/components/smooth-scroll";
import { ColdStartWarmup } from "@/components/cold-start-warmup";
import { ThemeProvider } from "@/components/theme-provider";

// Satoshi Variable (Fontshare, ITF) — humanist grotesk for body / UI.
const satoshi = localFont({
Expand Down Expand Up @@ -40,13 +41,15 @@ export default function RootLayout({
children: React.ReactNode;
}>) {
return (
<html lang="en">
<html lang="en" suppressHydrationWarning>
<body
className={`${satoshi.variable} ${clashDisplay.variable} overflow-x-hidden bg-paper text-ink antialiased`}
>
<SmoothScroll />
<ColdStartWarmup />
{children}
<ThemeProvider>
Comment thread
AnkanMisra marked this conversation as resolved.
<SmoothScroll />
<ColdStartWarmup />
{children}
</ThemeProvider>
</body>
</html>
);
Expand Down
7 changes: 5 additions & 2 deletions web/src/components/nav.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Link from "next/link";
import { ThemeToggle } from "./theme-toggle";
import { WalletWidget } from "./wallet-widget";

const CHAIN_NAME_LOWER = (
Expand All @@ -8,21 +9,22 @@ const CHAIN_NAME_LOWER = (
export function Nav() {
return (
<header className="sticky top-0 z-40 border-b border-ink bg-paper/95 backdrop-blur supports-[backdrop-filter]:bg-paper/85">
<div className="mx-auto flex max-w-[1280px] items-center justify-between gap-4 px-6 py-3 lg:px-12">
<div className="mx-auto flex max-w-[1280px] flex-wrap items-center justify-between gap-3 px-4 py-3 sm:flex-nowrap sm:px-6 lg:px-12">
<Link href="/" className="flex items-baseline gap-3">
<span className="font-display text-xl leading-none text-ink">MicroAI Paygate</span>
<span className="hidden font-mono text-[10px] uppercase tracking-[0.16em] text-ink-soft sm:inline">
x402 · {CHAIN_NAME_LOWER}
</span>
</Link>
<div className="flex items-center gap-3">
<div className="flex flex-wrap items-center justify-end gap-2 sm:flex-nowrap sm:gap-3">
<Link
href="/docs"
className="border border-ink bg-accent px-3 py-1.5 font-mono text-[10px] uppercase tracking-[0.12em] text-paper transition-colors duration-150 hover:bg-accent-press"
>
Docs
</Link>
<WalletWidget />

<a
href="https://github.com/AnkanMisra/MicroAI-Paygate"
target="_blank"
Expand All @@ -31,6 +33,7 @@ export function Nav() {
>
View source ↗
</a>
<ThemeToggle />
</div>
</div>
</header>
Expand Down
17 changes: 17 additions & 0 deletions web/src/components/theme-provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"use client";

import { ThemeProvider as NextThemesProvider } from "next-themes";
Comment thread
AnkanMisra marked this conversation as resolved.
import type { ReactNode } from "react";

export function ThemeProvider({ children }: { children: ReactNode }) {
return (
<NextThemesProvider
attribute="class"
defaultTheme="light"
enableSystem={false}
storageKey="microai-theme"
>
{children}
</NextThemesProvider>
);
}
39 changes: 39 additions & 0 deletions web/src/components/theme-toggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"use client";

import { Moon, Sun } from "lucide-react";
import { useTheme } from "next-themes";
import { useEffect, useState } from "react";

export function ThemeToggle() {
const { theme, setTheme } = useTheme();
const [mounted, setMounted] = useState(false);
const isLightTheme = theme === "light";

useEffect(() => {
const frame = requestAnimationFrame(() => setMounted(true));

return () => cancelAnimationFrame(frame);
}, []);

if (!mounted) return null;

return (
<button
onClick={() => setTheme(isLightTheme ? "dark" : "light")}
aria-pressed={!isLightTheme}
aria-label={
isLightTheme ? "Switch to dark mode" : "Switch to light mode"
}
className="inline-flex items-center gap-1 border border-ink bg-paper px-2.5 py-1.5 font-mono text-[10px] uppercase tracking-[0.12em] text-ink transition-all duration-300 hover:bg-ink hover:text-paper sm:px-3"
>
{isLightTheme ? (
<Moon aria-hidden="true" className="size-3.5" strokeWidth={2} />
) : (
<Sun aria-hidden="true" className="size-3.5" strokeWidth={2} />
)}
<span className="sr-only sm:not-sr-only">
{isLightTheme ? "Dark" : "Light"}
</span>
</button>
);
}
Loading