← Writing

Every Pixel Earned: How I Built This Site

In February 2026, I set out to build a new portfolio site. Not a template. Not a theme. A website that would embody the same design philosophy I apply to every product I build — constraint, modularity, and an obsessive attention to invisible details. This is a technical essay about how that site came together: the grid system, the code-driven visuals, the design token architecture, and the decisions that shaped it all.

The site runs on Astro. Every visual you see on the homepage is built entirely in code. No external images. No illustration libraries. No canvas elements at initial render. Just HTML, CSS, and SVG — server-rendered, performant, and fully responsive.

The Grid System

The single most important architectural decision was the grid. Not the CSS Grid spec itself — that’s a given — but the component abstraction on top of it. Inspired by the approach the Vercel team described in their homepage craft essay, I wanted a grid system that could draw its own guide lines regardless of how many children it contained.

The Problem with Borders

The most common method for drawing grid lines involves bordering every child element on two perpendicular sides — say, border-right and border-bottom. If every cell in the grid is filled, you get a clean result. Add border-top and border-left on the grid container itself, and the illusion is complete.

But the illusion breaks the moment you have empty cells, cells that span multiple columns, or a layout where the number of children doesn’t perfectly fill the grid. Suddenly, you’re drawing borders on elements that don’t exist, or missing borders where they should appear.

I needed a grid that would render guide lines for all cells — filled or empty — and still allow content to be placed arbitrarily at any row and column intersection.

display: contents — The Hidden Gem

The solution came from a CSS property that most developers have never used: display: contents.

.grid-guides {
  display: contents;
}

When applied to a container, display: contents causes the element to vanish from the box model entirely. Its children are rendered as if they were direct children of the element’s parent. This means we can create a guide overlay inside a CSS Grid container without disrupting the grid’s layout whatsoever.

Here’s how the Grid component works at its core:

---
const { rows = 3, columns = 3 } = Astro.props;

const guides = Array.from(
  { length: rows * columns },
  (_, index) => ({
    x: (index % columns) + 1,
    y: Math.floor(index / columns) + 1,
  })
);
---

<div
  class="relative grid border-t border-l border-grid-line"
  style={`
    grid-template-columns: repeat(${columns}, minmax(0, 1fr));
    grid-template-rows: repeat(${rows}, minmax(0, 1fr));
  `}
>
  <!-- Guide overlay: display: contents -->
  <div class="contents pointer-events-none">
    {guides.map(({ x, y }) => (
      <div
        class="absolute inset-0 border-b border-r border-grid-line"
        style={`grid-column-start: ${x}; grid-row-start: ${y};`}
      />
    ))}
  </div>

  <!-- Actual content goes here -->
  <slot />
</div>

The guides array generates rows × columns placeholder elements. Each one is positioned at its grid coordinate and draws a border-bottom and border-right. Because they sit inside a display: contents wrapper, they participate in the parent grid’s layout without creating their own box. The parent grid adds border-top and border-left to complete the visual frame.

Here’s a live demonstration of this exact technique. Notice how the grid draws a complete set of guide lines for all 16 cells, even though only two cells contain actual content:

Cell 1row: 1 / span 2, col: 1 / span 2
Cell 2
4 × 4 grid — only 2 cells filled, all 16 guide lines visible

The result: a grid that always draws a complete set of guide lines, no matter how many or how few children are actually rendered inside it. It’s one of those solutions that, once you see it, feels completely obvious — but took a surprising amount of iteration to arrive at.

GridCell and GridCross

With the grid foundation in place, two companion components complete the system:

GridCell — A content container that can be placed at any row/column intersection with optional colSpan and rowSpan:

---
const {
  row = 'auto', column = 'auto',
  rowSpan = 1, colSpan = 1,
  solid = false
} = Astro.props;

const gridRow = row === 'auto'
  ? 'auto' : `${row} / span ${rowSpan}`;
const gridColumn = column === 'auto'
  ? 'auto' : `${column} / span ${colSpan}`;
---

<div
  class={`relative ${solid
    ? 'z-20 bg-white dark:bg-black border-r border-b'
    : 'z-10'}`}
  style={`grid-row: ${gridRow}; grid-column: ${gridColumn};`}
>
  <slot />
</div>

The solid prop is what creates the opaque white/black cells that sit above the grid lines (z-20 vs z-10), giving the visual effect of content floating over the guide grid. This layered z-index strategy is central to the site’s visual identity.

GridCross — Small crosshair markers inspired by traditional print registration marks. They’re absolutely positioned at grid intersections and serve as a subtle navigational cue:

<div
  class="absolute z-30 w-3 h-3 text-grid-cross pointer-events-none"
  style={`
    grid-row-start: ${row};
    grid-column-start: ${column};
    transform: translate(-50%, -50%);
  `}
>
  <svg viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
    <path d="M12 4.5v15m7.5-7.5h-15" />
  </svg>
</div>

At z-30, crosses sit above everything — even solid cells. They’re small (12px), use pointer-events: none, and draw their color from the --grid-cross CSS variable. The print-mark metaphor bridges the digital interface with the physical world of design craft — a reference to Müller-Brockmann and the Swiss graphic design tradition that has influenced this project deeply.

The Z-Index Layering Model

The entire visual system relies on a precise layering strategy. Here is the stack, from bottom to top:

z-30
GridCross
z-20
Solid Cell Content
GridCell (solid)
z-15
Beam (light pass)
z-10
Grid Guides

The beam exists at z-index: 15 — it moves visibly between the grid lines (z-10) and behind the solid cell content (z-20). This creates a subtle, atmospheric depth. The crosses sit at z-30, above everything. The effect is entirely CSS — no JavaScript, no canvas, no WebGL.

Hero Composition

The hero section uses the grid at a much larger scale — 12 columns × 8 rows on desktop, 4 × 6 on mobile. A single GridCell with solid enabled spans from row 2 to row 7, columns 2 through 11, creating a centered stage for the heading and call-to-action buttons.

The beam — a drifting radial-gradient — is what gives the hero section its ethereal quality:

.beam {
  position: absolute;
  z-index: 15;
  pointer-events: none;
  width: 60%;
  height: 60%;
  background: radial-gradient(
    ellipse at center,
    rgba(161, 161, 170, 0.25) 0%,
    rgba(161, 161, 170, 0.08) 40%,
    transparent 70%
  );
  animation: beam-drift 14s ease-in-out infinite;
  will-change: transform;
}

It respects prefers-reduced-motion by simply hiding itself when the user has motion sensitivity enabled.

Code-Driven Visuals

Every visual component on the homepage is built as an Astro component using only HTML, CSS, and inline SVG. No external images. No icon fonts. No runtime JavaScript for rendering. This was a deliberate decision with several motivations:

  1. Pristine quality at any scale — Vector-based visuals never pixelate, whether on a 4K display or a mobile screen.
  2. Design token integration — Every visual uses the same CSS variables (--grid-line, --text-muted, --boyut-primary) as the rest of the site, meaning they automatically adapt to light/dark mode.
  3. True responsiveness — Unlike images, code-driven visuals can restructure themselves based on container size.
  4. Zero additional network requests — Everything is inline and server-rendered.

BoyutVisual: The Design System Preview

The Boyut visual simulates a code editor window showing design tokens alongside component previews. Here is an inline reproduction of the exact component:

The visual is structured as a miniature split-pane editor. The left pane displays design token key-value pairs (color.primary, radius.full, spacing.md, font.sans). The right pane renders actual UI components — buttons and an input — all using the real design token values from the CSS variable system.

.boyut-btn-primary {
  background: var(--boyut-primary);
  color: var(--boyut-primary-fg);
  font-size: 8px;
  padding: 4px 10px;
  border-radius: 9999px;
}

The miniature button in the visual uses var(--boyut-primary) — the same variable that powers the real buttons across the site. When the user toggles dark mode, the visual’s buttons flip colors in lockstep with everything else. There is no separate “dark mode visual” — the same component simply responds to the cascade.

PromptVisual: The AI Canvas Preview

The Promptheon visual represents a prompt management canvas with a variables pane and an output stream. Here is the component, rendered inline:

The output pane features thin, rounded rectangles at varying widths that pulse with a staggered CSS animation to simulate streaming AI output. A blinking cursor at the bottom uses step-end timing for a sharp on/off blink, mimicking a real terminal cursor. Both animations respect prefers-reduced-motion.

EmiVisual: The SVG Drawing Animation

The Emi visual is perhaps the most cinematic component. It renders an SVG portrait using stroke-dasharray and stroke-dashoffset to create a drawing animation:

.emi-stroke {
  stroke: #8b6c4f;
  fill: none;
  stroke-dasharray: 400;
  stroke-dashoffset: 400;
  animation: draw 2.5s ease forwards;
}

@keyframes draw {
  to { stroke-dashoffset: 0; }
}

Each SVG path element gets a staggered animation-delay — the face outline draws first (0s), then the eyes (0.4s, 0.7s), the nose (1.0s), the mouth (1.2s), the eyebrows (1.4s), and finally the hair (1.6s). A signature fades in at 2.2s. The entire sequence tells a story of creation in 2.5 seconds, using nothing but CSS and inline SVG.

The warm, parchment-like background color (#fdf6ee in light mode, #1c1710 in dark mode) adds a tactile quality distinct from the rest of the site, signaling that this cell represents a different creative discipline.

GalerionVisual: The Mobile Mockup

Galerion renders as a miniature phone mockup — complete with a notch, an app header, an artwork card with a SVG abstraction of Van Gogh’s Starry Night, and a bottom navigation bar. The phone frame itself is built with CSS borders and border-radius — no image of a phone, no device frame library. Everything is structural HTML styled to look like hardware.

UtilityVisual: The Settings Widget

The utility cell is the only visual that functions as an actual interactive element. It contains a working theme toggle and a working language switcher — both wired to the site’s real state. The theme toggle uses conditional CSS to show/hide sun and moon icons. The small “Designed by The Emi.” attribution at the bottom uses a serif italic font — a deliberate typographic contrast with the monospace labels above it, signaling a shift from the mechanical to the personal.

The Bento Layout

The homepage brings all five visuals together in a bento grid — a 4-row × 3-column layout on desktop, collapsing to a single-column 8-row layout on mobile. Here is a structural wireframe of the desktop bento:

BOYUT · 2col
Writing
Stack
PROMPTHEON · 2col
THE EMI · 2col
TheEmi Text
Contact
GALERION
Utility
← Solid cells (filled) sit at z-20 above grid linescolSpan alternation creates rhythm →

The staggered colSpan values create visual rhythm: Boyut spans 2 columns, then the writing cell takes 1. The stack cell takes 1, then Promptheon spans 2. This alternation prevents the layout from feeling uniform while maintaining strict alignment.

The hideTopBorder prop removes the grid’s top border, creating a seamless visual connection with the hero section above. Crosses are placed at every interior intersection on desktop — that’s 12 crosshairs marking the structural joints of the layout. They’re removed on mobile to avoid visual clutter.

Design Token Architecture

The entire color system flows through CSS custom properties defined in :root and html.dark:

:root {
  --grid-line: #e5e7eb;
  --grid-cross: #9ca3af;
  --text-muted: #555862;
  --boyut-primary: #000000;
  --boyut-primary-fg: #ffffff;
  --brand-accent: #a90432;
}

html.dark {
  --grid-line: #27272a;
  --grid-cross: #71717a;
  --text-muted: #a1a1aa;
  --boyut-primary: #ffffff;
  --boyut-primary-fg: #000000;
  --brand-accent: #d1064a;
}

Every component in the system — from the grid lines to the button backgrounds to the visual components — draws its colors from these seven variables. There are no hardcoded color values anywhere in the component tree. A theme switch means flipping the class on <html>, and every element on the page responds in unison.

The --brand-accent deserves special mention. It’s a deep burgundy (#a90432) in light mode and a more vivid crimson (#d1064a) in dark mode. It appears in exactly two places: the period after “Güney.” in the hero heading, and the text selection highlight. Using it at only 10% frequency preserves its significance — the 60-30-10 principle applied with absolute discipline.

Reduced Motion and Accessibility

Every animation on the site includes a prefers-reduced-motion media query:

@media (prefers-reduced-motion: reduce) {
  .beam { animation: none; opacity: 0; }
  .emi-stroke { animation: none; stroke-dashoffset: 0; }
  .canvas-cursor { animation: none; opacity: 0.6; }
}

The approach differs by animation type. The beam, being purely decorative, is hidden entirely. The SVG drawing animation snaps to its completed state so the illustration is still visible. The cursor holds at partial opacity. Each rule reflects a conscious decision about what serves the content and what merely entertains.

All visual components include proper role="img" and aria-label attributes. Interactive elements like the theme toggle carry descriptive aria-label text. The language switcher communicates its active state through opacity and border changes.

The Stack

  • Framework: Astro 5, chosen for its zero-JS-by-default philosophy
  • Styling: Tailwind CSS 4 with @variant dark and design token overrides
  • Typography: Geist Sans and Geist Mono, loaded via Astro’s <Font> component
  • i18n: Custom utility functions with a flat translation map — no heavy i18n library
  • Content: MDX-based blog with glob loader and Zod-validated frontmatter schema
  • Deployment: Static build

Closing Thoughts

Building this website was an exercise in constraint. Every decision — from the z-index layering strategy to the seven-variable color system to the display: contents trick — was made in service of a single conviction: that the most powerful interfaces are the ones that feel inevitable.

There is no animation on this site that exists purely for spectacle. There is no gradient that doesn’t serve a compositional purpose. There is no element that wasn’t debated, stripped down, and rebuilt at least twice.

The grid is not decoration. It is the architecture. The visuals are not illustrations. They are components. The dark mode is not a feature. It is a fundamental design constraint that was present from line one.