Skip to content
Authoring Surfaces
AutoXXS (320px)XS (375px)SM (640px)MD (768px)LG (1024px)XL (1280px)XXL (1536px)
SketchMaterialiOSTamagui
DataInjectionKeyPatternsServiceTransactionProcessResearchProductQualityPerformanceSpecDomainFunctionTechnologyArchitectureConfigMiddlewareDataDatabaseDrizzleMigrationModelop-sqliteSchemaSQLState ManagementDraftKeystoneMergePatchPatchesPersistenceReactiveRedoStoreUndoTestingDeviceFactoryIsolationTypeScriptZodTopicsCommunicationBidsNVCDesignDesign ImplicationsEducationPedagogyFoundationsPsychologyAttachmentFloodingRelatingAuthentic RelatingUIEditorReact Native

Authoring Surfaces

Fragment reference Authoring Surfaces
tags
guidesurface

The mental model

A surface is a low-fidelity wireframe β€” a structural sketch of a UI screen or component authored directly in your spec using a restricted Pug DSL. It answers: β€œWhat does this screen contain, how is it laid out, and what can the user interact with?”

Surfaces are intentionally lo-fi. They communicate structure and interaction points, not visual polish. Think of them as a whiteboard sketch β€” precise enough to implement from, abstract enough to leave room for design decisions.

The Pug DSL

Surfaces use a subset of Pug compiled into themed HTML components. The vocabulary covers:

  • Layout: stack, row, grid, card, section, sidebar
  • Forms: input, select, checkbox, radio, textarea, switch
  • Actions: button, link; Navigation: tabs, nav, breadcrumb
  • Display: table, list, badge, avatar, icon; Typography: heading, text

No mixins, includes, or JavaScript logic are allowed. The DSL is deliberately constrained to keep wireframes focused on structure.

Linking surfaces to features

The feature attribute connects a surface to the feature or flow it visualizes:

{% surface id="add-bookmark-form" title="Add Bookmark" feature="feature/add-bookmark" %}

This creates bidirectional cross-references: the feature page links to its surfaces, and the surface page links back to its feature.

Surface types

The type attribute classifies the surface:

  • screen β€” a full page layout
  • widget β€” a self-contained component embedded in larger screens
  • atomic β€” a primitive component (button variant, input state)

Choose the type that matches the scope of what you are designing. Most authored surfaces are screens or widgets.

Grouping with tabs

When a feature has multiple related views (e.g., desktop vs. mobile, empty state vs. populated), use the group attribute to render them together in a tabbed view:

{% surface id="bookmarks-empty" group="bookmarks-list" label="Empty State" ... %}
{% surface id="bookmarks-populated" group="bookmarks-list" label="With Items" ... %}

Designing effective wireframes

Start with content hierarchy. What is the most important thing on this screen? Place it first in the structure.

Use real-ish content. Instead of β€œLorem ipsum”, use plausible values: β€œhttps://example.com/article”, β€œMeeting Notes - Q2 Planning”. This reveals layout issues that placeholder text hides.

Show states. A form has empty, filled, error, and success states. Create surfaces for each meaningful state, grouped together.

Keep it structural. Resist the urge to specify colors, fonts, or pixel dimensions. The Pug DSL intentionally omits these β€” they are design system concerns, not specification concerns.

Common mistakes

MistakeWhy it hurts
High-fidelity designSurfaces are wireframes, not mockups. Specifying exact colors, spacing in pixels, or font weights defeats the purpose.
Orphaned surfacesA surface without a feature attribute is disconnected from the spec graph. Always link to the feature or flow it serves.
JavaScript logic in PugThe DSL is static structure only. Conditionals and loops are not supported β€” show different states as separate grouped surfaces.
Duplicating flow sequenceA surface shows one screen state, not a multi-step flow. Use multiple grouped surfaces for multi-step UIs, one per step.
Ignoring component vocabularyThe DSL has specific component names. Using HTML tags (div, span) will not compile. Learn the vocabulary from the Component Gallery.
Skipping error statesShowing only the happy-path UI leaves developers guessing about error presentation. Add surfaces for validation errors and empty states.

All available DSL components with live interactive examples are in the Component Gallery at /showroom. Consult it for the exact attribute vocabulary of each component.

Evolution

Surfaces evolve alongside features. When requirements change, update surfaces to reflect new interaction points. Because surfaces are low-fidelity, changes are lightweight β€” restructuring a wireframe is minutes of work, not hours.