app/), UI (components/), static content (data/), and utilities (lib/, types/) — plus static assets in public/.
Directory Tree
Top-Level Directories
app/
Contains everything that belongs to the Next.js App Router. Files named layout.tsx and page.tsx are special Next.js conventions; any other file is a co-located module. The api/ subdirectory holds server-side Route Handlers.
components/
All React components live here. Components without a "use client" directive at the top run as React Server Components. Those that need browser APIs (scroll events, useTheme, useChat) are marked "use client". The Shared/ subdirectory holds components that are imported by multiple parents.
data/
Plain TypeScript modules that export typed arrays and functions. No runtime fetching — all content is bundled at build time. The only exception is portfolio-context.ts, whose output is consumed by the API route at request time.
lib/
Two small utility modules:
| File | Export | Purpose |
|---|---|---|
utils.ts | cn() | Merges Tailwind class names with clsx + tailwind-merge |
chat-utils.tsx | formatMessageContent() | Converts raw AI message text to React nodes, rendering URLs as <a> links and **bold** as <strong> |
public/
Static files served directly at the root URL path. All images are in AVIF format for optimal compression. Japanese pattern tiles (patterns/) are referenced by CSS background-image rules in globals.css.
types/
A single file (index.ts) that exports the four shared TypeScript interfaces used across data/ and components/. See the Data Layer page for the full interface definitions.
Next.js App Router Structure
The project uses the App Router introduced in Next.js 13. The key conventions are:app/layout.tsx is the root layout. It:
- Loads
Noto_Sans_JPandNoto_Serif_JPfrom Google Fonts vianext/font - Wraps the entire app in
<ThemeProvider>(next-themes) - Renders
<Navigation />above the page content - Renders
<Contact />and<AIDrawerLazy />below — making them available on every page without needing to include them inpage.tsx - Includes
<Analytics />from@vercel/analytics
app/page.tsx is the home route. It renders four section components in order:
The Chat API Route
app/api/chat/route.ts exposes a single POST handler at /api/chat.
How it works:
- Receives a JSON body with a
messagesarray (AI SDKUIMessage[]format) - Calls
getPortfolioContext(), which caches the output ofgeneratePortfolioContext()for 5 minutes to avoid rebuilding the string on every request - Passes the cached context string as the
systemprompt to Groq’sllama-3.1-8b-instantmodel via the AI SDK’sstreamTextfunction - Returns a streaming text response via
result.toTextStreamResponse()
maxDuration = 30 export sets the Vercel serverless function timeout to 30 seconds, which is required for streaming responses.
Data Flow
Content moves from static TypeScript files through components to the browser in a single direction:types/index.ts, ensuring that the shape of the data matches what each component expects.
Because all data files are static TypeScript modules with no
async exports, Next.js can fully render the Works, Skills, and Experience sections as React Server Components — no client-side fetching or hydration is needed for content.Components
Props, render output, and implementation notes for every component.
Data Layer
TypeScript interfaces and how each data file connects to components.
