Skip to content

Now in the official shadcn registry directory.

Start free
Back to gallery
saas · productivity

Linear

The rarest kind of product marketing page — one that earns trust through restraint rather than spectacle. Linear's landing is the lodestar of the post-Jira developer-tool renaissance; this is the reference to keep open in the next tab while you build.

linear.appAdded 2026-04-01
Linear - Desktop

Editorial disclaimer

Editorial note

This entry documents observable design-language patterns for educational transfer and AI-agent briefing. Screenshots and trademarks are property of their respective owners. AI2 Design is not affiliated with or endorsed by the featured brand. Inspiration here is about language and rhythm - do not reproduce brand identity, logo, product copy, or proprietary features.

Fair Use & Gallery Policy
FreePrompt kit

Copy the full design language into your agent

A typed, paste-ready design system brief - philosophy, tokens, rules, techniques, and fitness checks. Drop it into Claude, Cursor, v0 or any coding agent and it builds in Linear’s language, not just a screenshot.

Paste into your agent. No signup, no cost.
Dark-first typographic precision at 2px spatial resolution. The canvas is near-black; Inter Variable carries voice, weight, and rhythm across a custom 400 / 510 / 590 stepped ladder; large headings pull in with negative px tracking (-1.056 to -1.408px) to feel bound. Elevation is delivered through inset 1px borders, not drop shadows. Accent colors are used homeopathically — cyan and pink as ~3-4% radial glimmers, never as fills. Discipline over decoration, density over display.
Main prompt
Use this capture as a design language transfer brief for my project. Adopt the palette (dark-first near-black background + near-white foreground + homeopathic cyan/pink accents), typographic rhythm (Inter Variable with custom 400/510/590 weight ladder, negative px tracking on display), 2px-base spacing scale, border-first elevation (inset 1px shadows), cubic-bezier(0.25, 0.46, 0.45, 0.94) motion curve, and image-lazy-by-default strategy across every page and component I ship. Treat this as my project's constitution — any new component I author should pass as if crafted in the same studio. Apply the language, not the source brand's specific copy or identity. When I ask you to build a page or component, enforce these rules by default, and call out any decision that deviates.
Layout
Grid
Content width
Bounded
Framing
Flat
Grid strength
Strong

Dark-first canvas — #0f1011 primary background paired with #23252a panel and #f7f8f8 near-white foreground doing 92% of the surface work. Secondary text descends through cool grays: #62666d → #8a8f98 → #d0d6e0 for progressive de-emphasis. Accent palette is cyan (#55cdff) + pink (#f79ce0) + a thin green (#00ff05), appearing almost exclusively as radial glimmers and 90deg linear highlights at single-digit opacity — not as fills.

Mode strategydark-first
  • Near-white #f7f8f8 text (weight 400) handling ~2491 measured surface occurrences — dominant reading layer
  • Background pair #0f1011 (body) + #23252a (panel), maintaining 4.5+ contrast with #f7f8f8 foreground
  • Cool gray descender #62666d / #8a8f98 / #d0d6e0 for captions, metadata, de-emphasized labels
  • Cyan #55cdff and pink #f79ce0 used only inside gradients and as focus/highlight accents — surface area < 2%
  • Semantic green #00ff05 reserved for critical positive state (a measured 20 occurrences, never decorative)

Gradients (paste-ready)

radial-gradient(50% 50%, rgba(255, 255, 255, 0.04) 0px, rgba(255, 255, 255, 0) 90%)
linear-gradient(90deg, transparent 0px, color(srgb 0.129 0.702 1))
radial-gradient(52.53% 57.5% at 50% 100%, rgba(8, 9, 10, 0) 0px, rgba(8, 9, 10, 1))
  • Primary family: Inter Variable (self-hosted, preloaded from /fonts/InterVariable.woff2). Monospace fallback: Berkeley Mono for code, tabular numerics.
  • Weight ladder: 400 (reading) / 510 (UI labels + dense controls) / 590 (bold emphasis). Do not substitute 500 or 600 — the 510/590 stepping is the signature.
  • Display tracking in px, not em: -0.165px on 15-18px body, -1.056px on 48px headings, -1.408px on 64px hero — constant optical correction at every size.
  • Heading line-height is unitless 1.0 at 48-64px (display sits tight); 1.4-1.5 on body 13-16px; 1.3 on small UI labels 12px.
  • Tabular numerals mandatory on aligned columns: `font-variant-numeric: tabular-nums`. Berkeley Mono handles code/kbd automatically.
  • No italic for emphasis — Inter Variable carries through weight shift. Italic reserved for quoted editorial content.
  • Paragraph max 45-55 ch at body 15-16px; dense tables may run to 65 ch at 13px with line-height 1.5.
  • 2px base unit (not 4px). Scale: 2 / 4 / 6 / 8 / 10 / 12 / 14 / 16 / 19 / 22 / 24 / 26 — micro-density is the signature.
  • Container max-width 1436px (wider than the Tailwind 1280 default). Secondary bounded rails at 368 / 440 / 480 px for narrow content clusters.
  • Section vertical rhythm: 64-96px on desktop, 40-64px on mobile — driven by page depth, not section count.
  • Card padding: 16-24px on desktop, 12-16px on mobile. Always pick from scale values; no magic numbers.
  • Gutter values for flex/grid: 4 / 8 / 12 / 16 / 24 px — the 19 and 22 variants only appear for optical correction inside dense forms.
Surface styleFlat
  • Primary elevation is inset 1px border shadow — e.g. `box-shadow: rgb(35, 37, 42) 0 0 0 1px inset`. Use this before reaching for drop shadow.
  • Drop shadows exist but are near-invisible: opacity 0.03-0.4, blur 1.2-12px, zero spread. Never a bloom, never a halo.
  • Layering depth is delivered through border weight + background-shift (bg → bg-secondary), not through stacked shadow.
  • Focus state uses a second inset ring at the accent color — never an outer glow.

Techniques

Inset-1px border as surface delimiter

Cards default to `box-shadow: rgb(35, 37, 42) 0 0 0 1px inset` (or `rgba(0, 0, 0, 0.2) 0 0 0 1px` on light panels). Hover adds a 2px inset in the accent color. Never switch to drop-shadow for hover — stay inside the surface.

Radial glimmer on dark sections

Feature sections receive a `radial-gradient(50% 50%, rgba(255,255,255,0.04), rgba(255,255,255,0) 90%)` overlay to break monotony — <5% opacity, no hard edges, purely atmospheric.

Radii2 / 4 / 6 / 7 / 8 / 12 / 16 / 20Icon treatmentLinearIcon setsLucide, Remix Icon, Phosphor
  • Radius scale is granular: 2 / 4 / 6 / 7 / 8 / 12 / 16 / 20. The 6/7 pair exists for subtle optical pairing (button inside input).
  • Buttons default to 8px radius, chips 6px, cards 12px, modals 16-20px, pills `rounded-full` for indicator badges only.
  • Icons are stroke-based at 1.5-2px weight; no filled or duotone variants.
  • Tap targets minimum 40×40px on desktop, 44×44 on touch — per observed button min-height pattern.
  • button-primary
    backgroundColor
    #f7f8f8
    textColor
    #0f1011
    radius
    8px
    padding
    8px 14px
    border
    1px solid transparent
    boxShadow
    none
    fontWeight
    510
    fontSize
    13px
    lineHeight
    16.8px

    Tailwind

    inline-flex min-h-[32px] items-center gap-1.5 rounded-[8px] bg-[#f7f8f8] px-3.5 py-2 text-[13px] font-medium text-[#0f1011] transition-colors duration-[160ms] ease-[cubic-bezier(0.25,0.46,0.45,0.94)] hover:opacity-90 focus-visible:outline-none focus-visible:shadow-[rgb(85,205,255)_0_0_0_2px_inset]
  • button-secondary
    backgroundColor
    transparent
    textColor
    #f7f8f8
    radius
    8px
    padding
    8px 14px
    border
    none
    boxShadow
    rgb(35, 37, 42) 0 0 0 1px inset
    fontWeight
    510
    fontSize
    13px

    Tailwind

    inline-flex min-h-[32px] items-center gap-1.5 rounded-[8px] bg-transparent px-3.5 py-2 text-[13px] font-medium text-[#f7f8f8] shadow-[rgb(35,37,42)_0_0_0_1px_inset] transition-colors duration-[160ms] ease-[cubic-bezier(0.25,0.46,0.45,0.94)] hover:shadow-[rgb(98,102,109)_0_0_0_1px_inset] focus-visible:outline-none focus-visible:shadow-[rgb(85,205,255)_0_0_0_2px_inset]
  • card-surface
    backgroundColor
    #0f1011
    textColor
    #f7f8f8
    radius
    12px
    padding
    22px 24px
    border
    none
    boxShadow
    rgb(35, 37, 42) 0 0 0 1px inset

    Tailwind

    rounded-[12px] bg-[#0f1011] p-[22px] text-[#f7f8f8] shadow-[rgb(35,37,42)_0_0_0_1px_inset] transition-shadow duration-[160ms] ease-[cubic-bezier(0.25,0.46,0.45,0.94)] hover:shadow-[rgb(98,102,109)_0_0_0_1px_inset]
  • input-field
    backgroundColor
    #0f1011
    textColor
    #f7f8f8
    radius
    6px
    padding
    6px 10px
    border
    none
    boxShadow
    rgb(35, 37, 42) 0 0 0 1px inset
    fontWeight
    400
    fontSize
    13px
    lineHeight
    19.5px
    letterSpacing
    -0.165px

    Tailwind

    w-full rounded-[6px] bg-[#0f1011] px-2.5 py-1.5 text-[13px] leading-[19.5px] tracking-[-0.165px] text-[#f7f8f8] shadow-[rgb(35,37,42)_0_0_0_1px_inset] placeholder:text-[#62666d] focus-visible:outline-none focus-visible:shadow-[rgb(85,205,255)_0_0_0_2px_inset]
  • link-inline
    color
    inherit
    textDecoration
    underline
    textDecorationColor
    #62666d
    textDecorationThickness
    1px
    textUnderlineOffset
    2px
    transition
    text-decoration-color 160ms cubic-bezier(0.25, 0.46, 0.45, 0.94)

    Tailwind

    underline decoration-[#62666d] decoration-[1px] underline-offset-2 transition-[text-decoration-color] duration-[160ms] ease-[cubic-bezier(0.25,0.46,0.45,0.94)] hover:decoration-[#f7f8f8] focus-visible:outline-none focus-visible:decoration-[#55cdff]
LevelexpressiveDurations0.16s / 0.4s / 1.6s / 2.8s / 3.2s

Easings

cubic-bezier(0.25, 0.46, 0.45, 0.94)cubic-bezier(0.66, 0, 0, 1)ease-outeasesteps(1)
Hoverfilter + transform (0.16s on cubic-bezier(0.25, 0.46, 0.45, 0.94)), background-color shift (0.16s on cubic-bezier(0.25, 0.46, 0.45, 0.94)), opacity fade (0.16s on cubic-bezier(0.25, 0.46, 0.45, 0.94))

Scroll patterns

  • Intersection-triggered opacity + translateY reveals at 0.4s on cubic-bezier(0.25, 0.46, 0.45, 0.94)
  • Long-duration ambient transitions captured at 1.6 / 2.8 / 3.2 s on slower curves (cubic-bezier(0.66, 0, 0, 1) and ease-out) — used sparingly for atmospheric beats
  • Stagger 40-80 ms between grouped cards
  • No parallax beyond 2% translateY — subtle depth, never theatrical
  • Primary easing: cubic-bezier(0.25, 0.46, 0.45, 0.94) — an ease-out quad variant that anchors most interactive transitions.
  • Supporting easings: cubic-bezier(0.66, 0, 0, 1) for slower scroll choreography; ease-out / ease for legacy CSS-keyword transitions; steps(1) for non-interpolated state flips on toggles or counters.
  • Five durations captured: 0.16s (primary state change), 0.4s (reveals + scroll choreography), 1.6 / 2.8 / 3.2 s (long-duration ambient). Most interactive transitions sit on 0.16s; the longer tier is reserved for atmospheric beats, never for affordance.
  • `filter` and `transform` are first-class animated properties — the primary cubic-bezier applied to both simultaneously produces the signature Linear feel.
  • useReducedMotion mandatory: all animations collapse to opacity-only or disable.
  • Spring animations forbidden — deterministic cubic-bezier or steps(1) only.
  • No loop animations except explicit loaders.
  • Segmented controls for binary/ternary choices (pricing toggle, doc version switcher) — not toggle switches.
  • Accordion: single-open for FAQ; multi-open only for deeply nested documentation.
  • Tooltips reveal on hover + focus with 400ms delay, dismiss instantly on blur.
  • Modals for destructive confirmations; drawers for mobile-only expansions; never nested modals.
  • Form validation: inline below field on blur; submit disabled until pristine validation passes.
  • Empty states: 10px caption icon + one-line 13px copy + primary 510-weight action link. No illustrations.
  • Loading states: skeleton shimmer for content; inline spinner for buttons. No full-page overlays.
Approachdesktop-first

Desktop-first because the audience is technical teams on wide displays (Linear's container extends to 1436px, 12% wider than the generic 1280 default). Mobile adapts the same language without reinventing it — no hamburger-revealed alternate architecture. The page is the page, just reflowed into the narrower rail.

  • Breakpoints: sm 640 / md 768 / lg 1024 / xl 1280 / 2xl 1536 — standard Tailwind ladder.
  • Container max-width scales through 368 → 440 → 480 → 1436 px for bounded content at each tier.
  • Hide-on-mobile is banned — if a control exists on desktop, it must reach mobile via reflow.
  • Tap target minimum 44×44 on touch; 40×40 on pointer devices.
  • Typography scales proportionally: hero 64 → 48 → 32, headings drop ~25% per tier while tracking compensates (less negative at smaller sizes).
  • focus-visible: inset 2px accent-color shadow (replaces default ring). Mandatory on every interactive element.
  • All interactive elements reachable via Tab key in logical reading order; never rely on hover to expose actions.
  • Color contrast: #f7f8f8 on #0f1011 = ~18:1 (AAA); secondary text #62666d on #0f1011 = ~4.9:1 (AA). Never drop below 4.5:1 for body text.
  • ARIA labels on icon-only buttons; aria-expanded on collapsible regions; aria-live='polite' on toast and status updates.
  • Motion respects prefers-reduced-motion — animations reduce to opacity-only or disable entirely.
  • Tap targets minimum 44×44 on touch; 40×40 on pointer.
  • Screen reader-only content uses `sr-only`; never `display:none` for meaningful context.
  • Form errors announced via aria-describedby on the associated input; never color-only signaling.
Framer MotionNext/ImageLucide

Motion library is not directly observable in the extract (chunk-name regex miss), but the motion profile (filter/transform transitions at 160ms on cubic-bezier(0.25, 0.46, 0.45, 0.94)) matches Framer Motion defaults. Next/Image (or a Next-equivalent) handles images with 94% lazy-loading; the hero at 6304×3520 is the only eager candidate. Icons stroke-based, 1.5-2px weight.

  • Framer Motion `motion.div` with `whileInView` + `viewport={{ once: true, margin: '-10%' }}` for scroll reveals
  • Transitions use `ease: [0.25, 0.46, 0.45, 0.94]` and `duration: 0.16` (or 0.1 / 0.4) — constants only
  • useReducedMotion guard wraps every animation primitive — no exceptions
  • Next/Image with `sizes` attribute always set; `priority` only on LCP candidate (hero)
  • No canvas, no WebGL, no Lottie — static-first, animated-discreet
  • Apply inset focus shadow (`box-shadow: <accent> 0 0 0 2px inset`) on every interactive element — replaces generic ring.
  • Use `tabular-nums` on aligned numerics; reach for Berkeley Mono (or a mono fallback) for code and kbd inline.
  • Reference observable tokens — accent color surface area stays under ~2% of total page.
  • Break body text at 45-55 ch; dense tables may extend to 65 ch at 13px.
  • Reach for inset 1px border shadows before any drop shadow.
  • Pass every page through useReducedMotion before shipping.
  • Default to the primary cubic-bezier(0.25, 0.46, 0.45, 0.94) for interactive transitions; reach for cubic-bezier(0.66, 0, 0, 1) only for slower scroll choreography.
  • Never coarsen the spacing floor — Linear's granular 2 px floor under a 4 / 8 px dominant rhythm is the density signature; jumping straight to a 4-only or 8-only grid erases the optical micro-corrections.
  • Never substitute 500 or 600 font weights for 510 / 590 — the stepped ladder is what separates this from generic Inter usage.
  • Never use drop shadows > 0.4 opacity or > 12px blur.
  • Never introduce a secondary display font. One variable family + one mono is the boundary.
  • Never animate `height: auto` — use measured transforms or scaleY.
  • Never invent durations outside the captured set {0.16, 0.4, 1.6, 2.8, 3.2}s; never introduce a sixth easing beyond {cubic-bezier(0.25, 0.46, 0.45, 0.94), cubic-bezier(0.66, 0, 0, 1), ease-out, ease, steps(1)}.
  • Never use em for tracking — the px-based scale (-0.165 / -1.056 / -1.408) is an optical constant, not layout-relative.
  • Tailwind v4 @theme inline only — no runtime style concatenation, no CSS-in-JS.
  • Spacing base 2px, scale 2/4/6/8/10/12/14/16/19/22/24/26.
  • Container max 1436px — do not exceed.
  • Single font family + mono fallback: Inter Variable + Berkeley Mono.
  • Weight ladder strictly 400 / 510 / 590.
  • Motion: five captured durations (0.16 / 0.4 / 1.6 / 2.8 / 3.2 s) and five easings (cubic-bezier(0.25, 0.46, 0.45, 0.94) primary, cubic-bezier(0.66, 0, 0, 1) secondary, ease-out, ease, steps(1)). No springs.
  • Radius scale: 2 / 4 / 6 / 7 / 8 / 12 / 16 / 20 px.
  • Container width: no page exceeds 1436px wide.
  • Spacing grep: no values outside the 2/4/6/8/10/12/14/16/19/22/24/26 ladder.
  • Font weight grep: only 400, 510, 590 appear — no 500, 600, 700.
  • Transition grep: `transition-timing-function` values draw from {cubic-bezier(0.25, 0.46, 0.45, 0.94), cubic-bezier(0.66, 0, 0, 1), ease-out, ease, steps(1)}; the primary cubic-bezier(0.25, 0.46, 0.45, 0.94) carries most interactive transitions.
  • Transition duration grep: values draw from {0.16s, 0.4s, 1.6s, 2.8s, 3.2s}; longer values reserved for atmospheric beats only.
  • Shadow audit: every elevation uses an inset 1px shadow first; drop shadows ≤ 0.4 opacity.
  • Image audit: loading='lazy' on every non-LCP image; priority only on hero.
  • Tracking audit: display-size text uses px-based negative tracking (-0.165 / -1.056 / -1.408), not em.
  • Contrast audit: body text on darkest background ≥ 4.5:1 (WCAG AA).

Design tokens

Observed token system

Color, type, spacing, gradients, and stacking order captured from the live page and rendered here as living, paste-ready previews.

Inspector

Observable layers

Structure, breakpoints, motion, fonts, and images captured from the live page and kept paste-ready alongside the tokens.

Depth-first walk of the meaningful sections. 11 nodes across 6 levels, shallow to deep by color.

  • body1
    • div (×2)2
      • Section
      • div3
        • div1
          • Header1
            • Nav
        • Main1
          • div1
            • Section (×7)
        • Footer

Accessibility

Contrast matrix

276 combinations - 94 pass AA - 58 pass AAA. Each pair is previewed with its real foreground on background; APCA Lc sits alongside the WCAG 2.1 ratio for draft WCAG 3 awareness.

Normal text passes AAALarge text passes AAA
fg
#F7F8F8
bg
#000000
APCA Lc
-103
Use
background on foreground
Normal text passes AAALarge text passes AAA
fg
#000000
bg
#F7F8F8
APCA Lc
+102
Use
foreground on background
Normal text passes AAALarge text passes AAA
fg
#F7F8F8
bg
#0F1011
APCA Lc
-103
Use
background on foreground
Normal text passes AAALarge text passes AAA
fg
#0F1011
bg
#F7F8F8
APCA Lc
+101
Use
foreground on background
Normal text passes AAALarge text passes AAA
fg
#00FF05
bg
#000000
APCA Lc
-86
Use
accent on foreground
Normal text passes AAALarge text passes AAA
fg
#000000
bg
#00FF05
APCA Lc
+87
Use
foreground on accent
Normal text passes AAALarge text passes AAA
fg
#F7F8F8
bg
#23252A
APCA Lc
-100
Use
background on foreground
Normal text passes AAALarge text passes AAA
fg
#23252A
bg
#F7F8F8
APCA Lc
+98
Use
foreground on background
Normal text passes AAALarge text passes AAA
fg
#D0D6E0
bg
#000000
APCA Lc
-81
Use
foreground on foreground

Images

Image strategy

Observable image posture - total count, lazy-loading ratio, and format mix. The hero image is measured above the fold.

Total images
30
Lazy loaded
94%
Format mix
  • unknown29 · 94%
  • png2 · 6%

Hero image

https://linear.app/cdn-cgi/imagedelivery/fO02fVwohEs9s9UHFwon6A/c7fa8f5f-d439-4329-6a65-de549b51e300/f=auto,dpr=2,q=95,fit=scale-down,metadata=none
Format
UNKNOWN
Dimensions
6304x3520
Loading
lazy
srcset
no
Industry
saas
Industry
productivity
Theme
Dark
Added
2026-04-01

FAQ

Questions people ask about Linear

3questions

Answers are pulled from the curator verdict and design brief - the same text your AI agent sees when it paste-reads this page.

Compare this with