inkfangs

how i built this

Behind the scenes of inkfangs.com

"I didn't use a template. I didn't hire someone. I built this from scratch because I wanted to prove—to myself and to you—that I can."

— Noufah, explaining why this took longer than expected

The Tech Stack

Frontend Framework

Next.js 16

App Router, Turbopack, Server Components

Why? I wanted to learn the latest Next.js patterns and App Router. Plus, built-in routing and API routes made development faster.

Language

TypeScript

Type-safe development

Why? Catch errors before runtime. Better autocomplete. More confidence when refactoring.

Backend Touchpoints

Turso/libSQL + Resend

Contact persistence, rate limiting, and email notifications

Why? The site only needs a small backend, so I kept it boring: store contact messages, send the important emails, and rate-limit public forms.

Styling

Tailwind CSS

Utility-first CSS

Why? Faster prototyping. Consistent design system. Easy responsive design.

Creative Inspiration: Doves '25 on Blank Canvas

Where the Aesthetic Came From

While most developer portfolios pull inspiration from Dribbble or Awwwards, mine came from music: Hindia's album Doves '25 on Blank Canvas.

The album's visual identity—newspaper-style typography, contemplative minimalism, editorial layouts—resonated with how I wanted to tell my story. Not flashy. Not competing for attention. Just thoughtful, intentional, and real.

What drew me: Indonesian artist bringing authenticity to global aesthetics. Contemplative, not performative. Minimalist but emotionally rich.

The Symbolism: Doves as Freedom

In the album, doves write on a blank canvas—they represent freedom, new beginnings, and creating something from nothing. Birds that fly where they choose, unbound by expectations.

In the tech world, this resonates deeply. We're often caged by:

  • • Templates and frameworks that all look the same
  • • Comparison culture and imposter syndrome
  • • "Right way" to build, "best practices" that stifle creativity
  • • Expectations of what a CS student portfolio "should" be

Doves don't ask permission to fly. They just fly.

This portfolio is my blank canvas. My code. My story. My freedom to create something authentically mine, even if it doesn't look like everyone else's.

Visual Translation

  • Serif fonts for headlines → Newspaper masthead energy
  • Thoughts and builds pages → Editorial design homage
  • Muted palette → #F5F5F5 (blank canvas), #000000 (ink), #666666 (newsprint)
  • Generous whitespace → Room to breathe and think

Content Philosophy

  • Storytelling over specs → Narrative-first approach
  • Questions over answers → "Building questions, not just systems"
  • Vulnerability as strength → Honest editorial voice
  • Indonesian values → Thoughtful, communal, reflective

"Doves writing on a blank canvas—new beginnings, fresh starts, creating something from nothing."

Listen: Doves '25 on Blank Canvas by Hindia →

Development Timeline

December 23, 2025

v1.0 — Initial Setup

Scaffolded the project with Create Next App. Built the landing page, navigation, and the Hindia-inspired editorial aesthetic.

ee05589
December 28, 2025

v2.0 — Complete Pages & Community

Added the core public pages: Builds, Thoughts, Worklog, Contact, and Community. Earlier experiments were cut when they stopped serving the current story.

929270f
January 29, 2026

v3.0 — Gallery Exhibition & New Content

Major update to builds page with gallery exhibition layout. Added new project content, screenshots, and refined the editorial design across all pages.

e2acc2b
February 2026

v4.0 — The Revamp (Current)

Organization-based worklog with expandable cards. Contact page rework. Content deduplication across all pages. Turso-backed contact form with Resend notifications. Translated all content to English.

Still iterating

Technical Challenges & Solutions

Challenge #1: Theme Without Flash

Problem: Dark mode looked right after hydration, but the first paint could briefly show the wrong theme.

Solution: Read the saved theme before React hydrates and apply the class immediately:

const themeScript = 
  "(function(){var t=localStorage.getItem('theme');" +
  "if(t==='dark')document.documentElement.classList.add('dark');})();";

Lesson learned: Tiny timing details can make a polished interface feel careless if ignored.

Challenge #2: Touch vs Hover Navigation

Problem: Mobile breakpoints alone were not enough. A small touch laptop and a large phone should not be treated the same way.

Solution: Use interaction capability for navigation behavior and `usePathname()` only for route active states.

<nav className="[@media(hover:none)]:hidden">...</nav>
<button className="[@media(hover:hover)]:hidden">...</button>

const isActive = (href: string) => pathname === href;

Lesson learned: Responsive design is not only screen size. Input method matters.

Challenge #3: Small Backend, Real Boundaries

Problem: The contact form needed to be simple for visitors, but still safe enough for production traffic.

Solution: Use a tiny Next.js API surface with Turso persistence, Resend notifications, honeypot fields, safe JSON parsing, and persistent rate limits.

const body = await readJsonBody(request);
if (!body) {
  return NextResponse.json({ error: "Invalid JSON body." }, { status: 400 });
}

await isRateLimited({ request, action: "contact", limit: 3, windowMs });

Lesson learned: A small backend still needs clear failure modes and abuse protection.

Tools & Environment

Code Editor

Extensions: ESLint, Prettier, Tailwind IntelliSense

Design

Mostly coded directly in browser

Version Control

GitHub repo with CI checks on push

Deployment

Vercel deployment from the production branch

Package Manager

Lean dependency set: Next, React, Motion, Turso, Resend

AI Assistant

For brainstorming, debugging, learning

By The Numbers

3

API routes

2

Database tables

8+

Public pages

7

Editorial articles

100+

Hours invested

0

Templates used

CI

Lint, test, build

100%

Built by me

What I Learned

  • •Next.js App Router is powerful but has a learning curve. Server Components vs Client Components took time to understand.
  • •Small backends still deserve care. Validation, rate limits, and clear config errors are not optional just because the site is personal.
  • •Accessibility matters from day one. Adding it later is harder than building it in from the start.
  • •Design systems save time. Defining colors, typography, and spacing early made development faster.
  • •Storytelling > Feature lists. People connect with narrative, not just technical specs.
  • •Iteration is essential. Old ideas can be removed when they no longer support the story.

Want to See the Code?

This portfolio is open source. See every line, every component, every decision.

"Building this portfolio taught me more than any tutorial ever could. Every bug was a lesson. Every iteration was growth."

— Noufah, 2026