Pixel-Perfect Gutenberg Blocks from Figma and Static WordPress Deploys

Two things I did on the Coradine/LogTenPro project that are worth writing down: building Gutenberg blocks that precisely match Figma designs, and deploying the production site as a static HTML export via Simply Static. Both are underused approaches with significant practical benefits.

Figma design mapped to a Gutenberg block
Custom Gutenberg blocks mapped pixel-for-pixel to the Figma source.

The Design-to-Block Translation Problem

The gap between a Figma design and a Gutenberg block is a translation problem. The designer works in precise visual terms: this text is 18px, colour #1A1A2E, 24px below the icon. The block author works in PHP and React: register_block_type(), block.json, save() functions, edit() functions.

The translation fails in predictable ways:

  • Typography tokens in the design do not map to --wp--preset--* variables without deliberate work
  • Spacing values are hardcoded rather than pulled from the design system
  • The editor preview (edit mode) does not match the frontend output (save mode) because they use different CSS

My approach on Coradine:

1. Build the SCSS design system first, before any blocks. The design palette — colours, typography scales, spacing increments, border radii — lives in SCSS variables. Block styles import from the palette. When the designer changes a colour, one variable changes.

2. Use CSS custom properties as the bridge. The SCSS variables compile to CSS custom properties on :root. The block editor.css imports the same properties as the frontend style.css. Editor and frontend use the same token values.

3. Match the Figma component boundaries. If the design has a “Feature Card” component, there is a Feature Card block — not a Group block with a Columns block with an Image block with a Paragraph block. One-to-one mapping between design components and blocks makes the translation auditable.

SCSS Architecture for a Block Library

The structure I use:

scss/
  tokens/
    _colours.scss
    _typography.scss
    _spacing.scss
  components/
    _feature-card.scss
    _hero.scss
  blocks/
    feature-card/
      style.scss
      editor.scss
  main.scss

tokens/ contains nothing but variable definitions. components/ contains style rules for visual components, importing from tokens. blocks/*/style.scss composes components and handles block-specific layout. blocks/*/editor.scss adapts the component for the Gutenberg editor context.

On Coradine, I resolved SASS compilation bottlenecks that had been slowing the team down. The root cause was @import chaining that caused SASS to compile the same partial multiple times. The fix was converting shared partials to @use with @forward, which compiles each partial once regardless of how many files import it. Build times dropped significantly.

Simply Static: WordPress as a Build Environment

Simply Static generates a complete static HTML export of a WordPress site. You author content in the WordPress admin, then run the static export. The export — HTML, CSS, JS, images — deploys to any static host.

For Coradine, this meant:

  • Production has no PHP runtime. No WordPress, no database, no attack surface for the category of exploits that target WP installs.
  • Performance by default. A static file served from a CDN edge node is the fastest possible delivery. No TTFB from PHP execution.
  • Deployment is a file copy. The CI pipeline runs Simply Static on the WP build environment, then rsyncs the output to the production host. Rollback is another file copy.

The tradeoff: no dynamic functionality on the frontend. Forms need a third-party service or a custom endpoint. Search needs a client-side index or an external service.

For a marketing site like LogTenPro, this is an acceptable trade. For a site with user accounts, personalisation, or a checkout flow, it is not.

CI Integration

The GitHub Actions workflow:

  • Push to main
  • SSH into the WordPress build server
  • Run wp simply-static run via WP-CLI
  • Rsync the static output to the production host
  • Purge CDN cache

The whole pipeline runs in under three minutes. The team deploys by pushing to main. There are no manual steps.

When to Use This Approach

Use this stack — custom Gutenberg blocks + SCSS design system + Simply Static CI — when:

  • You have a Figma design that needs to be matched precisely
  • The site is a marketing or content site (no user accounts, no checkout)
  • The client values security and performance over editorial dynamism
  • You want a deployment model that is simple, auditable, and reversible

It is not the right choice for every project. But for the right project, it is very good.