# 8 Hours, Gemini, and a Dream: Building Kelexine.is-a.dev

**Author:** kelexine  
**Date:** 2025-12-05  
**Category:** Engineering  
**Tags:** React 19, Vercel, Gemini, Vite, Debugging, Story  
**URL:** https://kelexine.is-a.dev/blog/building-kelexine-dev

---

# The Genesis

About 6 weeks ago, this domain was empty. I had a terminal, an idea, and a goal: to build a developer blog that didn't just look "clean"—it needed to look **Legendary**.

I didn't want a generic WordPress template or a cookie-cutter static site. I wanted a platform that felt alive. A site that pulsed with neon energy, used the latest tech stack (React 19, Vite 7), and ran on the bleeding edge of serverless infrastructure. (Originally Cloudflare Workers, now migrated to **Vercel Serverless Functions**.)

But I wasn't coding alone. I had a partner—**Gemini**, Google's advanced AI model, running directly in my CLI. This isn't just a story about code; it's a story about human-AI synergy, navigating the messy reality of software engineering, and the stubborn persistence required to bring a vision to life.

## The Vision: "Legendary" or Nothing

We started with a keyword: **Legendary**.

Most developer blogs are minimalist to a fault. White backgrounds, black text, maybe a blue link color. I wanted the opposite.
- **Theme**: Cyberpunk-meets-Glassmorphism.
- **Palette**: Deep charcoal backgrounds with a signature "Lemon Green" (`#A8E063`) accent.
- **Feel**: Fluid. Animated. When you hover over a card, it shouldn't just change color; it should glow.

Gemini understood the assignment immediately. It didn't just generate boilerplate; it architected a "Layout" component that looked like a HUD from a sci-fi movie, using Tailwind CSS for structure and Framer Motion for that "living" feel.

## Phase 1: The Foundation & The Polyfill Trap

The first technical hurdle appeared almost immediately. I wanted to write my posts in **MDX** (Markdown + JSX) so I could embed interactive components directly into my writing. We chose `gray-matter` to parse the frontmatter.

But `gray-matter` was built for Node.js. It expects `Buffer` and `process` to exist. In a modern browser environment like Vite, those things are gone.

> **The Error**: `Uncaught ReferenceError: Buffer is not defined`

Gemini didn't just suggest a different library; it hacked the environment. It wrote a custom polyfill injection in `vite.config.js` and patched `main.jsx` to make the browser behave like Node. It was a reminder that "Universal JavaScript" is still a messy dream that requires a bit of duct tape—and a smart AI—to hold together.

## Phase 2: The Infrastructure (Cloudflare Era)

I initially chose **Cloudflare Workers** for deployment. Why? Because I wanted dynamic API capabilities (for the newsletter) without managing a server, and because I'm a broke developer who doesn't even have enough money to pay his bills.

But here’s where things got tricky. We weren't just deploying a static site; we were deploying a **Single Page Application (SPA)** *inside* a Worker environment.

Gemini configured `wrangler.json` to handle the impossible trinity:
1.  **Static Assets**: Serving the built React app.
2.  **SPA Routing**: Ensuring that if a user visits `/blog/my-post`, they get `index.html` instead of a 404.
3.  **API Routing**: Intercepting requests to `/api/*` for our backend logic.

## Phase 3: The Newsletter Boss Fight

This was the defining battle of the project. I wanted a newsletter subscription form that talked to the **Buttondown API**. Securely. No exposed API keys in the frontend.

We built a backend API route in `workers/app.ts`. We built the frontend form. We hit "Subscribe".

**Result**: `Failed to execute 'json' on 'Response': Unexpected end of JSON input`.

### The "Unexpected End of JSON" Mystery

This error is the developer equivalent of a "Check Engine" light. It tells you nothing useful.
I went into detective mode. I added robust logging and discovered the server was returning **HTML**—specifically, the `index.html` of the React app.

**The Diagnosis**: The Worker configuration was prioritizing static assets. When we POSTed to `/api/newsletter/subscribe`, the Worker looked for a file named `subscribe` in the assets folder, didn't find it, and fell back to the SPA's `index.html`. Since the frontend expected JSON, it choked.

**The Fix**: I explicitly configured `run_worker_first: true` in `wrangler.json` and tightened the routing logic.

### The "Invalid URL" Catastrophe

Just when we thought we were safe, a deployment broke the entire site.
**Error**: `{"error": "Invalid URL: [object Request]"}`.

This was the low point. We were 6 hours in. The site was dead. The error message made no sense.

We initialised detective 🕵️ mode again and analyzed the build process and realized the subtle incompatibility. We were using `esbuild` to bundle the worker with `--platform=node`.
**The Epiphany**: Cloudflare Workers are **not** Node.js. They run on V8 isolates. By telling `esbuild` we were targeting `node`, it injected Node-specific polyfills that were incompatible with the Workers runtime.

I switched the flag to `--platform=neutral`. We rebuilt. We deployed. It worked.

## Phase 4: The Final Polish

With the backend secure and the newsletter working (I actually received the confirmation email—a moment of pure victory), I said to Gemini *Time to Cook* and it understood what I meant and turned its attention to the aesthetics.

- **DevTicker**: A scrolling ticker tape at the bottom of the NavBar, Displaying Random Developer Jokes (Which I think my life is one of them).
- **Featured Images**: Support for custom cover images in MDX frontmatter.
- **SVG Support**: I realized transparent SVGs looked invisible against the dark cards, so asked Gemini `What do we do` and it added a subtle `bg-accent/5` backing plate to make them pop.
- **Robust Fallbacks**: What if an image fails to load?, a question i asked myself, but before I could do anything Gemini wrote a custom hook that auto-swaps broken images for a sleek, generated SVG placeholder.

## The Gemini Experience

I have to give credit where it's due. This wasn't just me typing code. This was an 8-hour dialogue with a highly advanced intelligence.

There were moments of frustration.
*"Why is it still returning HTML?!"*
*"Why did the router crash the site?"*
*"Why am I doing this and not sleeping "*
*"Why am I so Broke"*
*"Why is my life such a joke"*

But every time we hit a wall, Gemini was ready with a new hypothesis. It didn't just spit out code snippets; it analyzed the architecture. It understood the nuance between a Worker environment and a Node environment. I suggested "Legendary" design tweaks and it executed it with precision.

We wrote the code that powers this very page.

## Phase 5: The Vercel Migration

After About a month or 2 of running on Cloudflare Workers, I decided to migrate to **Vercel**. Why?

1.  **Simpler DX**: Vercel's automatic deployments and preview builds are unmatched.
2.  **Built-in Analytics**: Vercel Analytics and Speed Insights are first-class citizens.
3.  **Serverless Functions**: The API routes (newsletter, posts, TIL) ported seamlessly to Vercel's `/api` directory structure.
4.  **The Truth**: I forgot my cloudflare Credentials, the worst part is i never even created a 2FA backup (WHICH I THOUGHT I DID)

The migration was surprisingly smooth. I replaced `wrangler.json` with `vercel.json`, converted the Workers code to standard Node.js handlers, and deployed. The site felt faster, and I no longer had to wrestle with V8 isolate quirks.

> **Tech Stack Summary (Current):**
> - **Frontend**: React 19, Vite 7, Tailwind CSS, Framer Motion
> - **Backend**: Vercel Serverless Functions
> - **Architect**: Google Gemini 3 Pro paired with Antigravity
> - **Database/API**: Buttondown (Newsletter)
> - **CMS**: MDX (Local files)
> - **Analytics**: Vercel Analytics, Speed Insights

---

*This content is available at [kelexine.is-a.dev/blog/building-kelexine-dev](https://kelexine.is-a.dev/blog/building-kelexine-dev)*
