Design overview
The design philosophy, the five-step landing workflow, and the fourteen hard rules that keep a page from looking AI-generated.
On this page
DeepSpace scaffolds working apps fast — and the scaffold's UI is deliberately a placeholder, not a house style. This section is the design system for replacing it: an opinionated workflow that produces pages a person would recognize as designed for this product, plus a mechanical gate that catches the most common tells of template output.
Two surfaces, two guides#
Every app has two front-of-house surfaces, and they need different treatment:
| Surface | What it is | Guide |
|---|---|---|
| Landing page | The marketing front door — a static page for visitors and crawlers | This page + Design direction, Style tile, Patterns |
| Product home | The authenticated app surface — the board, list, feed, or document the user actually works in | Product polish |
Use the landing workflow below for a marketing, splash, or landing page (or when giving design feedback on one). Use Product polish for the dynamic home, theme, primitives, and interaction feedback. The two share a palette and body font but are designed by different procedures.
The landing workflow — five steps, in order#
The workflow is Direction → Style Tile → one inspiration archetype → composition → grep gate. Skipping ahead — reaching for patterns before committing to a direction — is how generic pages happen.
Decide where the landing page lives
Two paths:
- Static (default): rewrite
src/pages/index.tsxat/. Top-level pages mount no providers or app chrome, which suits marketing and crawlers. - Dynamic feature:
npx deepspace add landinginstalls(app)/landing.tsx, primitives, and optional sections. Providers and global navigation mount. Treat every installed section as a skeleton; choose one real front door and remove or repoint the other.
Either path, the rest of the workflow is the same. If the landing lives under (app)/, apply the nav-hiding patch below first.
Fill the Design Direction block before any JSX
At the top of the landing page file, write a prose block with two halves: a 6-prompt brief (product, emotion, visual metaphor, three references, signature element, hero visual) and a 6-token Style Tile (color, type pair, theme, art direction, motion personality, voice). The brief is prose; the Style Tile is six one-line commitments.
If you can't fill a prompt, you don't understand the product well enough to design for it yet — go read the rest of the app first. See Design direction for how to write a good brief and Style tile for the commitment menus. Apply the sentence test (below) at the end.
Read one inspiration archetype
Use Worked examples to pick the closest emotion, then read only that one example. Learn how its Direction becomes code; never clone it.
Compose the page
Build section by section from the pattern library, within the composition budget below. Adapt each pattern's content and visual tokens to serve your Direction. The pattern is the structure; your Direction is the soul.
The installed landing sections are an alternate skeleton, but they contain known semantic-token violations. The gate will find them; fix rather than suppress every hit.
Fill images, run the grep gate
- Generate atmospheric images through a cataloged image integration; inspect its schema and include
no text, no words, no letters, no writing, no logosin every prompt. - Persist generated images via
useR2Filesif you need a stable URL (otherwise the image regenerates on every render). - Build product mockups as animated React components (inline SVG, styled divs, Framer Motion). Never use AI-generated images for UI screenshots.
- Fill every image slot before finishing.
- Run the complete gate in Anti-AI gate from the app root. Any hit is a bug to fix.
Hide the global navigation on the landing route#
Required if the landing lives under (app)/. Static landings inherit no app chrome, but a landing under (app)/ renders below the app's global <Navigation /> — hide it on that route so it does not stack with landing chrome (two stacked navs are the clearest telltale of a bolted-on landing):
import { useLocation } from 'react-router-dom'
export default function AppLayout() {
const { pathname } = useLocation()
const isLanding = pathname === '/landing'
return (
<div className="flex h-screen flex-col">
{!isLanding && <Navigation />}
<main className="min-h-0 flex-1 overflow-y-auto"><Outlet /></main>
</div>
)
}
Keep the layout's existing providers and suspense boundary around this conditional.
The Direction block lives in source#
Put the Direction in a multi-line comment at the top of the landing page file (src/pages/index.tsx, or src/pages/(app)/landing.tsx on the feature-install path). It stays in source as documentation:
/**
* Design Direction
*
* Product: <one sentence — who it's for, what it does>
* Emotion: <one specific feeling — not "trust" or "excitement">
* Metaphor: <a concrete real-world image>
* References: <three from OUTSIDE this product's category>
* Signature: <the ONE memorable visual this page has>
* Hero: <what animates on screen in the first 5 seconds>
*
* Style Tile
* - Color: <dominant + accent + saturation>
* - Type: <heading font + body font + why>
* - Theme: <light | dark + why>
* - Art direction: <one archetype from the style tile>
* - Motion: <one personality from the style tile>
* - Voice: <three behaviors, semicolon-separated>
*/
The composition budget#
A landing page is a fixed number of sections, not a buffet:
| Section | How many |
|---|---|
| Navigation | 1 (or 0 — some pages need none) |
| Hero | 1 |
| Features | 1 (sometimes 2) |
| Social proof | 0–1 (only if you have real proof) |
| CTA | 1 |
| Footer | 1 |
| Scroll & motion | 0–N (only if your Direction calls for it) |
A typical page uses 4–5 section types. A calm or quiet direction skips scroll choreography entirely.
The sentence test#
Ask of everything you wrote in the Direction block: could this describe any other product? If yes, rewrite.
- Fails: "A modern SaaS tool. Clean and trustworthy. Like Stripe and Linear. A floating mockup."
- Passes: "A post-run journal asks runners one question. It feels like a handwritten postcard on a scratched table; a new cursive question fades in on each visit."
Hard rules (non-negotiable)#
These are grep-checkable. Shipped violations mean a broken landing page.
| # | Rule | Fix |
|---|---|---|
| 1 | Hero headline: 3–8 words. No exceptions. | Shorten; put explanation below. |
| 2 | Body copy: under ~150 words total across the whole page. | If you're writing a paragraph, replace it with a visual. |
| 3 | No 3-identical-cards pattern for features — three of the same thing with the same structure. | Redesign: tabs, alternating rows, bento grid, single showcase, or a typographic list. |
| 4 | No purple-to-indigo, violet, or blue-to-purple gradients. The most-common AI color tell. | Use your accent color in semantic primary shades only, from the app theme. |
| 5 | No hardcoded colors in JSX. No hex, no violet-400, no indigo-500, no rgb() or rgba(). | Semantic tokens only: bg-background, text-foreground, bg-primary, bg-muted, border-border, text-muted-foreground, and friends. |
| 6 | No fractional opacity on foreground. Patterns like bg-foreground/[0.06] or border-foreground/[0.08] are old-template tells. | Use bg-muted, text-muted-foreground, border-border, or bg-card. |
| 7 | Pick a font that's clear, elegant, and fits the product — never gimmicky. The test: would a thoughtful designer ship this font for this product? | Reason about the product's tone first, then pick a font that serves it from the pairing tables and blacklist. |
| 8 | Product mockups must be React components, never AI-generated images. | Build the UI in React/inline SVG; generated images are atmospheric only. |
| 9 | Every AI-generated image prompt must include no text, no words, no letters, no writing, no logos. | Add the clause to any prompt missing it. |
| 10 | Dramatic type scale. Headlines at least 3x the size of body text. | If they look similar, the page looks flat — enlarge the headline. |
| 11 | One commanding visual in the hero. A hero that is just text on a flat background is a failure. | Add an animated React mockup, a full-bleed atmospheric image, a bold environment, or your signature element — something. |
| 12 | Never ship the scaffolded landing feature sections verbatim. Shipping HeroSection + FeaturesGridSection + TestimonialsSection + FAQSection with placeholder copy swapped in reproduces the exact AI-generic look this workflow is designed to break. | The scaffold is a skeleton: rewrite installed sections; worked examples are read-only teaching artifacts. |
| 13 | Animations must respect prefers-reduced-motion. | Wrap the landing tree in <MotionConfig reducedMotion="user"> from framer-motion — that auto-disables transform/layout animations for users who request reduced motion. Manual gates (call useReducedMotion() and short-circuit) are needed only for useTransform from useScroll (parallax, pinned scroll), setInterval/setTimeout/requestAnimationFrame loops, and CSS keyframes. |
| 14 | No pictograph emoji — no rocket ships, sparkles, light bulbs, party poppers, stars, flames, hearts, waving hands, or anything else in the U+1F000–U+1FFFF range. They render inconsistently across platforms and read as AI-generated. | Use lucide-react icons or inline SVG. Plain typographic marks (✓ ✗ → ← ↑ ↓ ★) are allowed as text glyphs — eyeball BMP emoji the gate misses. |
See Anti-AI gate for the complete grep gate commands and the eyeball checklist. Run the gate before declaring the page done.
Next steps#
- Design direction — write the six-prompt brief.
- Style tile — commit to the six visual tokens.
- Patterns — compose the page from proven section structures.
- Worked examples — see five complete Direction-to-code translations.
- Product polish — design the authenticated app surface.