How I Built This Site: A Dark WordPress from Scratch

Build Log

TL;DR

  • Built on Hostinger AI theme + WooCommerce, fully customised with a design system injected via the header template part
  • The biggest technical challenge: WordPress block gap injects inline margin-top:40px that beats external CSS — must be countered inline
  • Full-width dark sections use box-shadow + clip-path trick; no page builder, all REST API

The approach

Every page on this site was built via the WordPress REST API — no Elementor, no Beaver Builder, no page builder of any kind. Every dark card, every full-width hero, every section was handcrafted as HTML in wp:html blocks and injected via wp.apiFetch() from the browser console on a wp-admin tab.

The constraint was intentional. Page builders produce dependency-heavy, hard-to-migrate HTML. Plain wp:html blocks produce portable HTML that will work regardless of which plugin is installed or removed.

The design system

All CSS lives in the header template part (hostinger-ai-theme//header) as a style block. CSS variables define the full colour palette and typography:

:root {
  --tp-bg: #05070D;       /* page background */
  --tp-bg2: #0B1020;      /* card / panel background */
  --tp-cyan: #22d3ee;
  --tp-blue: #0693e3;
  --tp-violet: #9b51e0;
  --tp-grad: linear-gradient(135deg, var(--tp-cyan), var(--tp-blue), var(--tp-violet));
  --tp-display: 'Space Grotesk', sans-serif;
}

Full-width sections use the box-shadow + clip-path trick — making a constrained block appear to bleed to viewport edges without changing the template structure:

.tp-section-dark {
  background: var(--tp-bg2);
  box-shadow: 0 0 0 9999px var(--tp-bg2);
  clip-path: inset(0 -9999px);
  padding: 80px 24px;
}

The hardest bug: WordPress block gap

WordPress’s block layout system injects margin-top: 40px as an inline style on every block element. Inline styles have higher specificity than any external stylesheet rule — so the gap between sections persisted even with margin-top: 0 !important in the header CSS.

The fix: add margin-top:0 directly to the element’s own inline style attribute. Same specificity level, placed after WordPress’s injection, wins.

WooCommerce dark skin

WooCommerce loads its own stylesheets after the theme, making dark-skinning the My Account and shop pages particularly stubborn. The solution: inject a style block directly in the page content with body.page-id-58 specificity — page-level inline styles win the cascade over external theme and plugin stylesheets.

The build workflow

  1. Navigate to any wp-admin page in the browser
  2. Read current page content via wp.apiFetch({ path: '/wp/v2/pages/ID?context=edit' })
  3. Modify content string in JavaScript
  4. Save via POST to the same endpoint
  5. Purge LiteSpeed cache
  6. Verify visually in a separate tab

Every page, every CSS rule, every section on this site was built and iterated this way. The entire site was designed, built, debugged, and refined without once opening a page builder or the Gutenberg visual editor.

💡 The REST API is underused for WordPress site building. It’s faster than the GUI for making structural changes and modifications, produces cleaner HTML, and leaves no page builder fingerprints in the markup.