# Koko Blog A fast, beautiful personal blog built with React, TypeScript, and a synthwave purple theme. **Load time target:** < 100ms | **Bundle target:** < 50KB initial JS (gzipped) | **Rendering approach:** static-first + minimal runtime JS --- ## Stack - **Framework:** React 19 + TypeScript - **Build tool:** Vite (fast dev server + optimized production bundles) - **Routing:** React Router with route-level code splitting - **Content:** Markdown posts validated by Zod at build time - **Syntax highlighting:** Shiki at build time (no heavy client runtime highlighter) - **Image optimization:** `node scripts/optimize-images.mjs` (WebP + size variants via sharp) - **Package manager:** pnpm > **For AI agents:** This project is React-first. Use `.tsx` components and standard React patterns. > Do not create non-React template formats. Keep dependencies lean and avoid heavy UI frameworks. --- ## Quick Start ```bash pnpm install pnpm dev # dev server at http://localhost:5173 pnpm build # production build -> dist/ pnpm preview # preview production build pnpm typecheck # TypeScript check (tsc --noEmit) ``` --- ## Project Structure ```text koko-blog/ ├── public/ │ ├── images/ │ │ ├── posts/ # Original post images │ │ └── previews/ # Optimized WebP variants │ └── favicon.svg ├── src/ │ ├── app/ │ │ ├── App.tsx │ │ └── routes.tsx # Route config + lazy loading │ ├── components/ │ │ ├── layout/ │ │ │ ├── Layout.tsx │ │ │ ├── Header.tsx │ │ │ ├── Sidebar.tsx │ │ │ └── Footer.tsx │ │ ├── Hero.tsx │ │ ├── PostCard.tsx │ │ └── PostGrid.tsx │ ├── pages/ │ │ ├── HomePage.tsx │ │ ├── PostPage.tsx │ │ └── NotFoundPage.tsx │ ├── content/ │ │ ├── config.ts # Zod schema for post frontmatter │ │ └── blog/ # Markdown posts (.md files) │ ├── styles/ │ │ ├── synthwave.css # Theme tokens + gradients │ │ └── global.css # Reset + base styles │ ├── lib/ │ │ ├── content.ts # Build-time content loading helpers │ │ └── date.ts # Date formatting utilities │ └── main.tsx ├── scripts/ │ └── optimize-images.mjs ├── vite.config.ts ├── tsconfig.json ├── README.md └── TODO.md ``` --- ## Scripts | Command | Description | |---------|-------------| | `pnpm dev` | Start Vite dev server | | `pnpm build` | Build production assets | | `pnpm preview` | Preview production build | | `pnpm typecheck` | Run TypeScript checks | | `pnpm lint` | Lint codebase | | `node scripts/optimize-images.mjs` | Convert and resize images before build | --- ## Design System ### Colors | Token | Hex | Usage | |-------|-----|-------| | Primary | `#6a1b9a` | Buttons, accents, links | | Primary Dark | `#510ca9` | Hover states | | Secondary | `#000080` | Electronic sheen elements | | Background | `#000000` | Page background | | Paper | `#121212` | Card backgrounds | | Text Primary | `#ffffff` | Headings | | Text Secondary | `#eeeeee` | Body text | | Text Muted | `#888888` | Metadata | ### Typography - **Headlines:** 2.5rem-4rem, weight 800 - **Titles:** 1.8rem, weight 700 - **Body:** 1rem, line-height 1.8 - **Code:** Monospace, dark theme blocks (Shiki) ### Breakpoints - **Mobile:** < 768px - **Tablet:** 768px-1024px - **Desktop:** > 1024px --- ## Writing Content Posts live in `src/content/blog/` as `.md` files with YAML frontmatter: ```markdown --- title: "My Awesome Post" slug: "my-awesome-post" excerpt: "A brief description..." publishedAt: "2026-02-28" category: "Game Development" tags: ["unity", "csharp"] image: "/images/posts/hero.jpg" draft: false --- Your content here with **markdown** support. ``` --- ## TypeScript Path Aliases ```typescript import Layout from '@components/layout/Layout'; import '@styles/global.css'; ``` Available aliases (defined in `tsconfig.json`): - `@/*` -> `./src/*` - `@components/*` -> `./src/components/*` - `@pages/*` -> `./src/pages/*` - `@styles/*` -> `./src/styles/*` - `@lib/*` -> `./src/lib/*` --- ## Performance Targets | Metric | Target | |--------|--------| | Initial JS bundle | < 50KB (gzipped) | | FCP | < 100ms (local baseline) | | LCP | < 1.0s | | CLS | < 0.1 | | Lighthouse performance | > 90 | --- **Built with:** React • TypeScript • Vite • pnpm