Skip to content

Now in the official shadcn registry directory.

Start free
Back to gallery
saas · productivity

Cal.com

Open-source scheduling that refuses to look open-source — Cal Sans display, ink-on-paper minimalism, classic-blue link. A Calendly alternative with the source in your hands.

cal.comAdded 2026-06-23
Cal.com - 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 Cal.com’s language, not just a screenshot.

Paste into your agent. No signup, no cost.
Light-first monochrome with one decisive accent. The canvas is paper-white (#ffffff) under near-black ink (#000000 → #242424); a single saturated brand blue (#0000ee — the browser's own hyperlink color, worn on purpose) is the only chromatic pointer. Personality lives in the Cal Sans display face on the wordmark and headings, while Inter and the Matter family carry every dense reading layer. Elevation comes from soft, stacked low-opacity shadows — not hard borders — giving a stark page tactile warmth. Spacing runs tight (2px floor, 10px workhorse gap) under a comfortable 24px section rhythm. Open-source craft that looks like a finished product.
Main prompt
Use this capture as a design language transfer brief for my project. Adopt the palette (light-first paper-white #ffffff background + near-black #000000/#242424 ink + a single saturated #0000ee brand-blue accent used only as the pointer/link/primary color), the typographic rhythm (Cal Sans display face for wordmark + headings, Inter / Matter for body and UI), the granular radius scale (2/4/6/8/10/12/16px), soft multi-layer shadow elevation instead of hard borders, a tight 2px-floor spacing scale with a 10px workhorse gap, and a restrained Framer-Motion-grade motion posture 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, wordmark, 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
Soft

Light-first monochrome — #ffffff paper under #000000 primary ink (a measured 3631 occurrences, dominant reading layer) descending through #242424 secondary text. Neutral structure is carried by warm-cool grays #e0e0e0 / #e5e7eb / #898989. The entire chromatic identity is a single saturated brand blue #0000ee (the un-overridden browser hyperlink color, isBrandTier), used exclusively as accent / link / primary — never as a fill across large surface area. Deeper grays #374151 / #9ca3af handle de-emphasized UI text.

Mode strategylight-first
  • Near-black #000000 ink (~3631 measured occurrences) is the dominant reading layer; #242424 for slightly de-emphasized body (~360 occurrences)
  • Paper-white #ffffff is the default canvas; #e0e0e0 and #e5e7eb provide hairline dividers, input fills, and disabled surfaces
  • Brand blue #0000ee reserved for links, primary CTA, and focus accents — surface area stays well under ~5%, never a section background
  • Cool gray descender #374151 / #9ca3af for captions, metadata, placeholder text
  • #898989 mid-gray for secondary borders, icon strokes, and muted controls — never for body copy on white (fails AA below large sizes)

Gradients (paste-ready)

linear-gradient(rgb(41, 41, 41) 0%, rgb(36, 36, 36) 100%)
linear-gradient(rgb(252, 252, 252) 0%, rgb(255, 255, 255) 100%)
linear-gradient(rgb(247, 247, 248) 0%, rgb(234, 234, 235) 100%)
radial-gradient(50% 50%, rgba(255, 255, 255, 0) 87.1499%, rgb(255, 255, 255) 100%)
  • Display family: Cal Sans (self-host from the project's /fonts, woff2 + display:swap). Used for the wordmark and large headings only — it is the brand's personality, not a body face.
  • Workhorse families: Inter (UI labels, dense controls, captions) and the Matter family (Regular / Medium / SemiBold / Bold) for marketing body copy. One display face, a small set of neutral workhorses.
  • Observed weight set: Cal Sans 600 on headings; Inter 400 / 500; Matter 400 (Regular/Medium) and SemiBold for headings. Do not introduce a second display weight ladder — let Cal Sans carry one bold register.
  • Heading sizes observed: Cal Sans 24px / line-height 31.2px (heading-large), 18px (heading-3 via Cal Sans UI Variable Light, weight 300, tracking -0.2px), 12px Cal Sans 600 for eyebrow/label headings.
  • Body sizes cluster at 14px (Inter 500 / line-height 16px; Matter 400 / line-height 21px) and 16px (line-height 24px). Captions descend to 12px (line-height 18px) and 9.71px for fine print (Inter, line-height 11.1px).
  • Tracking is near-default — only the Cal Sans UI Variable Light 18px heading carries a measured -0.2px. Do not invent aggressive negative tracking; this brand sits close to normal letter-spacing.
  • Paragraph max ~55-65 ch at body 14-16px. No italic for emphasis — shift to Matter Medium/SemiBold or Cal Sans instead.
  • 2px base floor. Observed scale: 2 / 4 / 6 / 8 / 10 / 12 / 16 / 20 / 24 / 28 / 32 / 40 px. The 10px value is the single most-used gap (478 occurrences) — treat it as the workhorse rhythm, with 4px (413) and 24px (200) close behind.
  • Section/card padding leans on 24px (200 occurrences) for comfortable blocks and 16px for tighter cards; micro-padding uses 2-8px inside dense controls.
  • Flex/grid gutters observed at 10 / 4 / 12 / 8 / 16 px (descending frequency); larger 24 / 32 / 48 px gaps appear between major sections only.
  • Container max-width observed at 1224px (44 occurrences) as the primary bound, with 1280 / 1200 / 960 / 640 px secondary rails. Default page bound to ~1224px, not the generic 1280.
  • Always pick from the observed ladder; no magic numbers. The 6px and 12px steps are the connective tissue between micro and macro spacing.
Surface styleElevated
  • Primary elevation is a soft multi-layer drop shadow, not a hard 1px border — e.g. `box-shadow: rgba(19, 19, 22, 0.7) 0px 1px 5px -4px, rgba(34, 42, 53, 0.08) 0px 0px 0px 1px, rgba(34, 42, 53, 0.05) 0px 4px 8px 0px`. The thin 1px-spread layer acts as a faux-border in the same shadow declaration.
  • Shadow opacities stay low (0.05-0.16 on the color stops, the 0.7 only on a tight 1px-blur -4px-spread sliver). Never a heavy bloom or dark halo — warmth, not drama.
  • Inset highlights are used for tactility: `rgba(255, 255, 255, 0.15) 0px 2px 0px 0px inset` and `rgb(255, 255, 255) 0px 2px 0px 0px inset` give buttons a subtle top-edge sheen.
  • Layering depth is delivered through stacked shadow tiers (shadow-xs → shadow-sm → shadow-lg), each adding one more soft layer, rather than through border weight.

Techniques

Layered card shadow with faux-border

Cards default to the three-part `rgba(19,42,53…) 0 1px 5px -4px, rgba(34,42,53,0.08) 0 0 0 1px, rgba(34,42,53,0.05) 0 4px 8px` stack. The middle 1px-spread layer reads as a hairline border while the outer layers float the card off the page — one declaration, two jobs.

Inset top-edge sheen on buttons

Primary and accent buttons add `rgba(255,255,255,0.15) 0px 2px 0px 0px inset` (or the opaque `rgb(255,255,255) … inset`) to catch a light top edge, giving a tactile, slightly raised feel against the flat white canvas.

Radii2 / 4 / 6 / 7 / 8 / 10 / 12 / 16Icon treatmentLinearIcon setsLucide, Heroicons, Remix Icon
  • Radius scale is granular: 2 / 4 / 6 / (6.94 optical) / 8 / 10 / 12 / 16 px. The 8px (72 occurrences), 12px (53) and 16px (44) steps dominate; 2px and 4px handle chips and inner controls.
  • The 6.94px value is a real optical-correction radius (4 occurrences) — round it to 7 in implementation; it exists to nest a button cleanly inside a 8px-radius input.
  • Buttons default to 8px radius, chips/badges 4-6px, cards 12px, larger panels/modals 16px. No fully-rounded pills except small status indicators.
  • Icons are stroke-based, ~1.5-2px weight, sized 14-24px (observed display sizes 14×14 and 24×24). No filled or duotone icon variants.
  • Tap targets keep a comfortable 40×40px minimum on pointer, 44×44 on touch.
  • button-primary
    backgroundColor
    #000000
    textColor
    #ffffff
    radius
    8px
    padding
    8px 16px
    border
    none
    boxShadow
    rgba(255, 255, 255, 0.15) 0px 2px 0px 0px inset
    fontFamily
    Inter, sans-serif
    fontWeight
    500
    fontSize
    14px
    lineHeight
    16px

    Tailwind

    inline-flex min-h-[40px] items-center gap-2 rounded-[8px] bg-[#000000] px-4 py-2 text-[14px] font-medium leading-[16px] text-[#ffffff] shadow-[rgba(255,255,255,0.15)_0px_2px_0px_0px_inset] transition-colors duration-200 ease-out hover:bg-[#242424] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#0000ee] focus-visible:ring-offset-2
  • button-secondary
    backgroundColor
    #ffffff
    textColor
    #242424
    radius
    8px
    padding
    8px 16px
    border
    none
    boxShadow
    rgba(19, 19, 22, 0.7) 0px 1px 5px -4px, rgba(34, 42, 53, 0.08) 0px 0px 0px 1px, rgba(34, 42, 53, 0.05) 0px 4px 8px 0px
    fontFamily
    Inter, sans-serif
    fontWeight
    500
    fontSize
    14px

    Tailwind

    inline-flex min-h-[40px] items-center gap-2 rounded-[8px] bg-[#ffffff] px-4 py-2 text-[14px] font-medium text-[#242424] shadow-[rgba(19,19,22,0.7)_0px_1px_5px_-4px,rgba(34,42,53,0.08)_0px_0px_0px_1px,rgba(34,42,53,0.05)_0px_4px_8px_0px] transition-colors duration-200 ease-out hover:bg-[#f7f7f8] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#0000ee] focus-visible:ring-offset-2
  • card-surface
    backgroundColor
    #ffffff
    textColor
    #000000
    radius
    12px
    padding
    24px
    border
    none
    boxShadow
    rgba(19, 19, 22, 0.7) 0px 1px 5px -4px, rgba(34, 42, 53, 0.1) 0px 0px 0px 1px, rgba(34, 42, 53, 0.05) 0px 4px 8px 0px

    Tailwind

    rounded-[12px] bg-[#ffffff] p-6 text-[#000000] shadow-[rgba(19,19,22,0.7)_0px_1px_5px_-4px,rgba(34,42,53,0.1)_0px_0px_0px_1px,rgba(34,42,53,0.05)_0px_4px_8px_0px] transition-shadow duration-200 ease-out hover:shadow-[rgba(19,19,22,0.7)_0px_1px_5px_-4px,rgba(34,42,53,0.12)_0px_0px_0px_1px,rgba(34,42,53,0.08)_0px_8px_16px_0px]
  • input-field
    backgroundColor
    #ffffff
    textColor
    #000000
    radius
    8px
    padding
    10px 12px
    border
    none
    boxShadow
    rgba(34, 42, 53, 0.08) 0px 0px 0px 1px
    fontFamily
    Inter, sans-serif
    fontWeight
    400
    fontSize
    14px
    lineHeight
    16px

    Tailwind

    w-full rounded-[8px] bg-[#ffffff] px-3 py-2.5 text-[14px] leading-[16px] text-[#000000] shadow-[rgba(34,42,53,0.08)_0px_0px_0px_1px] placeholder:text-[#9ca3af] transition-shadow duration-200 ease-out focus-visible:outline-none focus-visible:shadow-[rgb(0,0,238)_0px_0px_0px_2px]
  • link-inline
    color
    #0000ee
    textDecoration
    underline
    textDecorationThickness
    1px
    textUnderlineOffset
    2px
    fontFamily
    Inter, sans-serif
    transition
    color 200ms ease-out

    Tailwind

    text-[#0000ee] underline decoration-[1px] underline-offset-2 transition-colors duration-200 ease-out hover:text-[#242424] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#0000ee] focus-visible:ring-offset-1
  • badge-chip
    backgroundColor
    #e5e7eb
    textColor
    #374151
    radius
    6px
    padding
    2px 8px
    border
    none
    fontFamily
    Inter, sans-serif
    fontWeight
    500
    fontSize
    12px
    lineHeight
    18px

    Tailwind

    inline-flex items-center gap-1 rounded-[6px] bg-[#e5e7eb] px-2 py-0.5 text-[12px] font-medium leading-[18px] text-[#374151]
LevelmoderateDurations0.2s

Easings

ease-outease
Hoverbackground-color shift on buttons (~0.2s ease-out) — black ↔ #242424, color shift on links (~0.2s ease-out) — #0000ee → #242424, soft shadow-tier lift on cards (~0.2s ease-out) — add one shadow layer, never translate dramatically

Scroll patterns

  • Intersection-triggered opacity + small translateY reveals (Framer Motion `whileInView`)
  • Subtle stagger between grouped cards/feature tiles
  • No parallax beyond a few px of translateY — restrained, never theatrical
  • MOTION DATA GAP: extraction.motion.easings and .durations came back empty — Framer Motion is confirmed present (window.MotionIsMounted) but specific CSS transition timing was not captured. The durations/easings above are conservative conventional defaults, NOT measured tokens. Do not present them as observable.
  • Default to short, restrained transitions (~150-250ms) on ease-out for state changes; reach for Framer Motion `whileInView` for scroll reveals.
  • useReducedMotion mandatory: all animations collapse to opacity-only or disable.
  • Spring animations allowed only if Framer Motion springs are used elsewhere in the project; otherwise prefer deterministic ease-out tweens.
  • No loop animations except explicit loaders (the observed `__framer-loading-spin` / `pulse` keyframes).
  • Primary CTA is a solid black button with inset top sheen; secondary actions are white with the layered card shadow. The single blue is reserved for inline links and focus, not button fills.
  • Segmented controls / toggles for binary choices (monthly↔yearly pricing) rather than checkboxes.
  • Accordion: single-open for FAQ; multi-open only for nested documentation.
  • Tooltips reveal on hover + focus; dismiss instantly on blur.
  • Modals for confirmations and embed/scheduling flows; drawers for mobile expansions; never nested modals.
  • Form validation inline below the field on blur; submit stays enabled with clear error messaging.
  • Empty states: small caption icon + one-line copy + a primary action. Restrained, no large illustrations.
  • Loading states: skeleton shimmer for content, inline spinner for buttons (the observed framer loading spin).
Approachdesktop-first

Desktop-first marketing surface bounded to ~1224px, reflowing cleanly into a single mobile rail. The observed media queries (810px and 1199px Framer breakpoints plus the standard 640/768/1024 set) confirm a three-tier mobile→tablet→desktop reflow. The page is the page at every width — no hamburger-revealed alternate architecture, just the same content reorganized.

  • Breakpoints: sm 640 / md 768 / lg 1024 / xl 1280 / 2xl 1536 — standard Tailwind ladder (matches the extracted breakpoint set).
  • Container max-width bounds at ~1224px primary, with 1200 / 960 / 640 rails for narrower content tiers.
  • Framer-specific tablet band observed at 810-1199px — collapse multi-column feature grids to two columns here, single column below 810px.
  • Hide-on-mobile is discouraged — controls present on desktop should reach mobile via reflow.
  • Tap target minimum 44×44 on touch; 40×40 on pointer.
  • Typography scales down proportionally: headings drop roughly one step per tier, body holds at 14-16px.
  • focus-visible: 2px ring in brand blue #0000ee (or an inset 2px blue shadow on inputs). Mandatory on every interactive element — never rely on the default browser outline being removed without replacement.
  • All interactive elements reachable via Tab in logical reading order; never rely on hover to expose actions.
  • Color contrast: #000000 on #ffffff ≈ 21:1 (AAA); #242424 on #ffffff ≈ 15.3:1 (AAA). #9ca3af on #ffffff ≈ 2.5:1 — restrict to large text or decorative use only, never body copy.
  • Brand blue #0000ee on #ffffff ≈ 8.6:1 (AAA) — safe for link text at body sizes.
  • ARIA labels on icon-only buttons; aria-expanded on collapsible regions; aria-live='polite' on toasts 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.
  • Form errors announced via aria-describedby on the associated input; never color-only signaling — pair the blue/red with text and an icon.
Framer MotionNext/ImageLucide

Framer Motion is directly observable (window.MotionIsMounted) and the marketing site is Framer-built (assets on framerusercontent.com). Images are mostly small PNG/SVG icons with lazy loading on below-fold assets and `loading='auto'` on the above-fold hero icon. Icons are stroke-based at ~1.5-2px weight, sized 14-24px.

  • Framer Motion `motion.div` with `whileInView` + `viewport={{ once: true, margin: '-10%' }}` for scroll reveals
  • Keep transitions short and ease-out; wrap every animation primitive in useReducedMotion
  • Next/Image with `sizes` always set; `priority` only on the LCP / above-fold hero candidate
  • Self-host Cal Sans + Inter via next/font; do NOT pull the Framer-hosted Matter/Cal-Sans-UI woff2 URLs into a non-Framer build
  • No canvas, no WebGL, no Lottie observed — static-first, animated-discreet
  • Keep the canvas light-first: #ffffff paper, #000000/#242424 ink, and let #0000ee be the only chromatic pointer.
  • Reserve the brand blue for links, primary accent, and focus — keep its surface area well under ~5%.
  • Use soft multi-layer shadows (with a 1px-spread faux-border layer) for elevation before reaching for a hard 1px border.
  • Pull spacing from the observed ladder (2/4/6/8/10/12/16/20/24/28/32/40); favor 10px for gaps and 24px for section padding.
  • Use Cal Sans for the wordmark/headings only; carry body and UI with Inter / Matter.
  • Round the 6.94px optical radius to 7 and reserve it for nesting controls inside inputs.
  • Pass every page through useReducedMotion before shipping.
  • Never spread the brand blue #0000ee across large fills or section backgrounds — it is a pointer color, not a surface color.
  • Never replace the soft layered shadows with flat 1px borders — the warmth of the page lives in those shadow tiers.
  • Never introduce a second display font alongside Cal Sans — one personality face is the boundary.
  • Never import the Framer-hosted font URLs (framerusercontent.com Matter/Cal Sans UI) into a self-hosted build — self-host the real Cal Sans + Inter instead.
  • Never use #9ca3af or #898989 for body copy on white — they fail AA below large sizes; restrict to borders, icons, and large/decorative text.
  • Never invent precise motion durations/easings as if measured — the extraction's motion timing came back empty; treat motion values as conventional defaults, not tokens.
  • Never coarsen the 2px spacing floor to a 4-or-8-only grid — the micro-density on dense controls depends on it.
  • Tailwind v4 @theme inline only — no runtime style concatenation, no CSS-in-JS.
  • Spacing base 2px, observed scale 2/4/6/8/10/12/16/20/24/28/32/40.
  • Container max ~1224px primary (1200/960/640 secondary rails) — do not default to a wider bound.
  • Display font Cal Sans (headings/wordmark only) + Inter / Matter workhorses. One display face.
  • Single brand accent: #0000ee. Ink #000000/#242424 on #ffffff paper.
  • Radius scale: 2 / 4 / 6 / 7 / 8 / 10 / 12 / 16 px.
  • Elevation via soft layered shadows (opacities 0.05-0.16, the 1px-spread layer as faux-border). No hard 1px borders as the primary delimiter.
  • Motion: Framer Motion present; specific durations/easings NOT measured — use restrained conventional defaults, no springs unless project-wide.
  • Palette grep: only #ffffff backgrounds, #000000/#242424 ink, neutral grays, and the single #0000ee accent appear — no second saturated hue.
  • Accent surface audit: #0000ee covers well under ~5% of the page and never serves as a section background.
  • Spacing grep: no values outside the 2/4/6/8/10/12/16/20/24/28/32/40 ladder; 10px and 24px dominate.
  • Container width: primary bound at ~1224px, not the generic 1280 default.
  • Radius grep: only 2/4/6/7/8/10/12/16 px appear; 8/12/16 dominate.
  • Shadow audit: every elevation uses a soft multi-layer shadow with a 1px-spread faux-border; no standalone hard 1px borders as the primary delimiter; opacities stay ≤ 0.16 (the 0.7 only on the tight -4px-spread sliver).
  • Font audit: Cal Sans appears only on wordmark/headings; Inter / Matter carry body and UI; no second display face.
  • Contrast audit: body text on white ≥ 4.5:1 (AA); #9ca3af/#898989 used only for large/decorative text or borders.
  • Motion honesty audit: no fabricated cubic-bezier/duration tokens presented as measured; animations gated by useReducedMotion.

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. 2 nodes across 2 levels, shallow to deep by color.

  • body1
    • div

Accessibility

Contrast matrix

160 combinations - 80 pass AA - 56 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
#000000
bg
#FFFFFF
APCA Lc
+106
Use
foreground on background
Normal text passes AAALarge text passes AAA
fg
#FFFFFF
bg
#000000
APCA Lc
-108
Use
background on foreground
Normal text passes AAALarge text passes AAA
fg
#000000
bg
#D6ECFE
APCA Lc
+93
Use
foreground on background
Normal text passes AAALarge text passes AAA
fg
#D6ECFE
bg
#000000
APCA Lc
-94
Use
background on foreground
Normal text passes AAALarge text passes AAA
fg
#000000
bg
#E5E7EB
APCA Lc
+92
Use
foreground on background
Normal text passes AAALarge text passes AAA
fg
#E5E7EB
bg
#000000
APCA Lc
-92
Use
background on foreground
Normal text passes AAALarge text passes AAA
fg
#000000
bg
#E9DDFD
APCA Lc
+89
Use
foreground on background
Normal text passes AAALarge text passes AAA
fg
#E9DDFD
bg
#000000
APCA Lc
-89
Use
background on foreground
Normal text passes AAALarge text passes AAA
fg
#000000
bg
#E0E0E0
APCA Lc
+88
Use
foreground on background

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
41%
Format mix
  • png33 · 45%
  • svg28 · 38%
  • jpg5 · 7%
  • webp4 · 5%
  • 532 · 3%
  • unknown1 · 1%

Hero image

https://framerusercontent.com/images/1bvk9THj74PqBkpBJDHFbQS9om4.png?width=64&height=96
Format
PNG
Dimensions
64x96
Loading
auto
srcset
no
Industry
saas
Industry
productivity
Theme
Light
Added
2026-06-23

FAQ

Questions people ask about Cal.com

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