Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ jobs:

- run: bun install --frozen-lockfile

# Shared design tokens live in packages/ui/src/styles/tokens.css;
# fails if an app re-declares one (landing ↔ web drift guard).
- run: bun run check:tokens

- run: bun turbo typecheck test build --filter='!@maple/ingest'

knip:
Expand Down
12 changes: 8 additions & 4 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ description: Open-source OpenTelemetry observability platform — terminal-nativ
colors:
primary: "oklch(0.714 0.154 59)"
primary-foreground: "oklch(0.207 0.008 67)"
primary-light: "oklch(0.59 0.14 242)"
primary-light-foreground: "oklch(0.98 0.01 237)"
primary-light: "oklch(0.66 0.16 59)"
primary-light-foreground: "oklch(0.21 0.008 67)"
background: "oklch(0.207 0.008 67)"
foreground: "oklch(0.91 0.016 74)"
card: "oklch(0.224 0.009 75)"
Expand Down Expand Up @@ -147,12 +147,16 @@ The shared visual posture is **Linear / Vercel / Axiom adjacent**: compact app s

## 2. Colors: The Operator Palette

The palette is **theme-divergent on purpose**. Light mode anchors on a vivid blue primary (`oklch(0.59 0.14 242)`); dark mode rebases on a warm amber-gold primary (`oklch(0.714 0.154 59)`). Both are correct — neither is the "true" Maple color. The dark theme is canonical for the frontmatter (matches `<body class="dark">`); light tokens travel alongside in the `.dark` ↔ `:root` swap.
The palette is **theme-tuned, same hue**. Both themes anchor on Maple's warm amber (hue ~59): dark mode uses `oklch(0.714 0.154 59)`, light mode the same hue tuned slightly deeper (`oklch(0.66 0.16 59)`) so it reads on a white canvas. The dark theme is canonical for the frontmatter (matches `<body class="dark">`); light tokens travel alongside in the `.dark` ↔ `:root` swap.

### Token source of truth

All shared design tokens (color, radius, fonts, severity/service/chart palettes, the `@theme inline` mapping) live in **`packages/ui/src/styles/tokens.css`** and are imported by both `apps/web` and `apps/landing` via `@import "@maple/ui/styles/tokens.css"` (after `@import "tailwindcss"`). Apps must never re-declare a shared token name — `bun run check:tokens` fails CI if they do. App-local tokens stay in the apps: web's Sugar High `--sh-*` set, landing's marketing set (`--bg-elevated`, `--bg-deep`, `--amber-deep`, `--amber-soft`). Landing is dark-only: it pins `class="dark"` on `<html>` instead of maintaining its own token copy. The ReactFlow controls chrome (flat, square corners, `border-radius: 0`) is part of the shared file — the product rendering is the reference for landing mockups.

### Primary

- **Amber Signal** (`oklch(0.714 0.154 59)`, dark canonical): the accent used on primary actions, the active sidebar item, `chart-1` / `chart-p95`, and severity-warn. Warm enough to read at low ambient light without burning. (Note: `chart-throughput` used to share this hue, but was split to purple — `oklch(0.66 0.14 290)` — so the built-in alert signal chips can distinguish throughput from p95.)
- **Blue Beacon** (`oklch(0.59 0.14 242)`, light counterpart): the same role under light theme. Vivid blue, full chroma at a mid-lightness — feels appropriate in daylight, would feel hostile in a dim room (hence the swap).
- **Amber Signal, daylight cut** (`oklch(0.66 0.16 59)`, light counterpart): the same role and hue under light theme, a touch deeper and more chromatic so it holds contrast on white. (An earlier draft used a blue light primary; it shipped briefly as stale shadcn tokens and was rebased to amber.)

### Secondary: Severity Ramp (the system's loudest semantic color)

Expand Down
955 changes: 568 additions & 387 deletions apps/landing/src/components/AppMock.astro

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions apps/landing/src/components/ComparisonTable.astro
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const sections = featureCategories
<!-- Header row -->
<div class="grid grid-cols-[1fr_100px_100px] sm:grid-cols-[1fr_140px_140px] border-b border-border px-4 pb-3 pt-3">
<span class="text-[10px] uppercase tracking-wider text-fg-muted">Feature</span>
<span class="text-[10px] uppercase tracking-wider text-accent text-center">Maple</span>
<span class="text-[10px] uppercase tracking-wider text-primary text-center">Maple</span>
<span class="text-[10px] uppercase tracking-wider text-fg-muted text-center">{competitorName}</span>
</div>

Expand All @@ -36,7 +36,7 @@ const sections = featureCategories
{/* Category header */}
{section.name && (
<div class:list={[
"px-4 py-3 border-l-2 border-l-accent bg-accent/5",
"px-4 py-3 border-l-2 border-l-primary bg-primary/5",
sectionIndex > 0 && "border-t border-border",
]}>
<span class="text-[11px] font-semibold text-fg uppercase tracking-wider">{section.name}</span>
Expand All @@ -54,7 +54,7 @@ const sections = featureCategories
!isLast && "border-b border-border",
]}>
<span class="py-4 text-sm text-fg">{featureName}</span>
<div class="py-4 flex items-center justify-center bg-accent/5">
<div class="py-4 flex items-center justify-center bg-primary/5">
{typeof feature.maple === "boolean" ? (
feature.maple ? (
<svg class="w-4 h-4 text-green-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 6L9 17l-5-5"/></svg>
Expand Down
2 changes: 1 addition & 1 deletion apps/landing/src/components/FAQ.astro
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const faqJsonLd = {

<section class="py-24 md:py-32">
<div class="mx-auto max-w-3xl px-6">
<span class="text-[11px] text-accent uppercase tracking-wider">FAQ</span>
<span class="text-[11px] text-primary uppercase tracking-wider">FAQ</span>
<h2 class="mt-3 font-display text-2xl md:text-3xl font-bold text-fg mb-12 tracking-tight">Frequently asked questions</h2>

<div class="divide-y divide-border border-t border-border">
Expand Down
7 changes: 4 additions & 3 deletions apps/landing/src/components/FeatureHero.astro
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
---
import { buttonVariants } from "@maple/ui/components/ui/button";
import { HeroCta } from "./HeroCta";

interface Props {
Expand All @@ -23,7 +24,7 @@ const { label, title, subtitle } = Astro.props;
<div class="relative mx-auto max-w-6xl px-6 pt-24 md:pt-32 pb-16 md:pb-24">
<!-- Badge -->
<div class="mb-6">
<span class="inline-flex items-center rounded-full border border-border bg-card px-2.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-accent">
<span class="inline-flex items-center rounded-full border border-border bg-card px-2.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-primary">
{label}
</span>
</div>
Expand All @@ -40,8 +41,8 @@ const { label, title, subtitle } = Astro.props;

<!-- Dual CTAs -->
<div class="mt-8 flex flex-wrap items-center gap-3">
<HeroCta client:load className="inline-flex h-9 items-center justify-center rounded-lg bg-primary px-3 text-xs font-medium text-primary-foreground transition-all hover:bg-primary/80" />
<a href="https://github.com/Makisuo/maple" target="_blank" rel="noopener noreferrer" class="inline-flex h-9 items-center justify-center rounded-lg border border-input bg-input/30 px-3 text-xs font-medium text-fg transition-all hover:bg-input/50">
<HeroCta client:load className={buttonVariants({ size: "default" })} />
<a href="https://github.com/Makisuo/maple" target="_blank" rel="noopener noreferrer" class={buttonVariants({ variant: "outline", size: "default" })}>
View on GitHub
</a>
</div>
Expand Down
5 changes: 3 additions & 2 deletions apps/landing/src/components/Hero.astro
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
---
import { buttonVariants } from "@maple/ui/components/ui/button";
import AppMock from './AppMock.astro';
import * as m from "../paraglide/messages";
import { HeroCta } from "./HeroCta";
Expand Down Expand Up @@ -36,8 +37,8 @@ import { HeroCta } from "./HeroCta";

<!-- Dual CTAs -->
<div class="mt-10 flex flex-wrap items-center gap-3">
<HeroCta client:load className="inline-flex h-11 items-center justify-center rounded-lg bg-primary px-5 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90" />
<a href="https://github.com/Makisuo/maple" target="_blank" rel="noopener noreferrer" class="inline-flex h-11 items-center justify-center rounded-lg border border-border bg-transparent px-5 text-sm font-medium text-fg transition-colors hover:bg-bg-elevated">
<HeroCta client:load className={buttonVariants({ size: "xl" })} />
<a href="https://github.com/Makisuo/maple" target="_blank" rel="noopener noreferrer" class={buttonVariants({ variant: "outline", size: "xl" })}>
{m.cta_github()}
</a>
</div>
Expand Down
2 changes: 1 addition & 1 deletion apps/landing/src/components/LanguageSwitcher.astro
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const pathWithoutLocale = Astro.url.pathname
class:list={[
"block px-3 py-1.5 text-xs transition-colors",
locale.code === currentLocale
? "text-accent font-medium"
? "text-primary font-medium"
: "text-muted hover:text-fg hover:bg-white/5",
]}
>
Expand Down
4 changes: 2 additions & 2 deletions apps/landing/src/components/MigrationSteps.astro
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const { competitorName, steps } = Astro.props;
<section class="py-24 md:py-32">
<div class="mx-auto max-w-5xl px-6">
<div class="mb-12">
<span class="inline-flex items-center rounded-full border border-border bg-card px-2.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-accent mb-4">
<span class="inline-flex items-center rounded-full border border-border bg-card px-2.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-primary mb-4">
Migration
</span>
<h2 class="font-display text-2xl sm:text-3xl font-bold text-fg tracking-tight">Switch from {competitorName} in minutes</h2>
Expand All @@ -19,7 +19,7 @@ const { competitorName, steps } = Astro.props;
<div class="grid grid-cols-1 md:grid-cols-3 gap-px bg-border border border-border">
{steps.map((step, index) => (
<div class="bg-bg p-6 md:p-8">
<div class="text-[11px] text-accent font-medium mb-4">{String(index + 1).padStart(2, '0')}</div>
<div class="text-[11px] text-primary font-medium mb-4">{String(index + 1).padStart(2, '0')}</div>
<h3 class="text-base font-semibold text-fg mb-2">{step.title}</h3>
<p class="text-sm text-fg-muted leading-relaxed">{step.description}</p>
</div>
Expand Down
26 changes: 15 additions & 11 deletions apps/landing/src/components/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import {
NavigationMenuContent,
NavigationMenuLink,
} from "@maple/ui/components/ui/navigation-menu"
import { buttonVariants } from "@maple/ui/components/ui/button"
import { Sheet, SheetContent, SheetHeader, SheetTitle } from "@maple/ui/components/ui/sheet"
import { cn } from "@maple/ui/utils"
import * as m from "../paraglide/messages"
import { broadcastSignedIn } from "./auth-signal"
import { ClerkProvider } from "./ClerkProvider"
Expand Down Expand Up @@ -37,7 +39,7 @@ function CTAButton() {
}

function Eyebrow({ children }: { children: React.ReactNode }) {
return <span className="text-[11px] uppercase tracking-wider font-medium text-accent">{children}</span>
return <span className="text-[11px] uppercase tracking-wider font-medium text-primary">{children}</span>
}

function MegaLink({ link }: { link: MenuLink }) {
Expand All @@ -46,7 +48,7 @@ function MegaLink({ link }: { link: MenuLink }) {
href={link.href}
className="group/link flex flex-col items-start gap-0.5 rounded-lg p-2 hover:bg-muted/20"
>
<span className="text-xs font-medium text-fg transition-colors group-hover/link:text-accent">
<span className="text-xs font-medium text-fg transition-colors group-hover/link:text-primary">
{link.label()}
</span>
<span className="text-[11px] leading-snug text-fg-muted">{link.desc()}</span>
Expand Down Expand Up @@ -176,8 +178,8 @@ function NavBarInner({ locale = "en", stars }: { locale?: string; stars?: number
{/* Left group: Logo + Navigation */}
<div className="flex items-center gap-1">
<a href={l("/")} className="flex items-center gap-3 mr-2">
<div className="w-7 h-7 bg-accent flex items-center justify-center">
<span className="text-accent-foreground text-sm font-bold">M</span>
<div className="w-7 h-7 bg-primary flex items-center justify-center">
<span className="text-primary-foreground text-sm font-bold">M</span>
</div>
<span className="text-fg font-medium text-sm">Maple</span>
</a>
Expand Down Expand Up @@ -246,7 +248,7 @@ function NavBarInner({ locale = "en", stars }: { locale?: string; stars?: number
<span className="text-xs font-medium text-fg">
{m.nav_product_footer()}
</span>
<span className="inline-flex items-center gap-1 text-xs text-accent transition-transform group-hover/cta:translate-x-0.5">
<span className="inline-flex items-center gap-1 text-xs text-primary transition-transform group-hover/cta:translate-x-0.5">
{m.nav_product_footer_cta()}
</span>
</NavigationMenuLink>
Expand Down Expand Up @@ -290,11 +292,13 @@ function NavBarInner({ locale = "en", stars }: { locale?: string; stars?: number

<a
href="https://app.maple.dev"
className={`inline-flex h-8 items-center justify-center overflow-hidden whitespace-nowrap rounded-lg bg-primary text-xs font-medium text-primary-foreground transition-all duration-300 hover:bg-primary/80 ${
className={cn(
buttonVariants({ size: "sm" }),
"overflow-hidden transition-all duration-300",
ctaCollapsed
? "pointer-events-none max-w-0 px-0 opacity-0 -ml-3"
: "max-w-40 px-2.5 opacity-100 ml-0"
}`}
? "pointer-events-none max-w-0 border-0 px-0 opacity-0 -ml-3"
: "max-w-40 opacity-100 ml-0",
)}
aria-hidden={ctaCollapsed}
tabIndex={ctaCollapsed ? -1 : undefined}
>
Expand Down Expand Up @@ -329,7 +333,7 @@ function NavBarInner({ locale = "en", stars }: { locale?: string; stars?: number
</SheetHeader>
<nav className="flex flex-col px-4 pb-6">
<div className="py-4 border-b border-border">
<span className="text-[11px] text-accent uppercase tracking-wider font-medium">
<span className="text-[11px] text-primary uppercase tracking-wider font-medium">
{m.nav_product()}
</span>
<div className="mt-3 flex flex-col gap-5">
Expand Down Expand Up @@ -394,7 +398,7 @@ function NavBarInner({ locale = "en", stars }: { locale?: string; stars?: number
</a>
<a
href="https://app.maple.dev"
className="inline-flex h-8 items-center justify-center rounded-lg bg-primary px-3 text-xs font-medium text-primary-foreground transition-all hover:bg-primary/80"
className={buttonVariants({ size: "sm" })}
>
<CTAButton />
</a>
Expand Down
4 changes: 2 additions & 2 deletions apps/landing/src/components/PainPoints.astro
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const { competitorName, painPoints } = Astro.props;
<section class="py-24 md:py-32">
<div class="mx-auto max-w-5xl px-6">
<div class="mb-10">
<span class="inline-flex items-center rounded-full border border-border bg-card px-2.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-accent mb-4">
<span class="inline-flex items-center rounded-full border border-border bg-card px-2.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-primary mb-4">
Common challenges
</span>
<h2 class="font-display text-2xl sm:text-3xl font-bold text-fg tracking-tight">
Expand Down Expand Up @@ -39,7 +39,7 @@ const { competitorName, painPoints } = Astro.props;
</svg>
</div>
<div>
<span class="text-[10px] uppercase tracking-wider text-accent block mb-1.5">Maple</span>
<span class="text-[10px] uppercase tracking-wider text-primary block mb-1.5">Maple</span>
<p class="text-sm text-fg leading-relaxed">{point.solution}</p>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion apps/landing/src/components/PricingCalculatorSection.astro
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const subtitle = competitor
<section class="py-24 md:py-32">
<div class="mx-auto max-w-5xl px-6">
<div class="mb-10">
<span class="inline-flex items-center rounded-full border border-border bg-card px-2.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-accent mb-4">
<span class="inline-flex items-center rounded-full border border-border bg-card px-2.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-primary mb-4">
{eyebrow}
</span>
<h2 class="font-display text-2xl sm:text-3xl font-bold text-fg tracking-tight">
Expand Down
4 changes: 2 additions & 2 deletions apps/landing/src/components/PricingTable.astro
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ const maxWidthClass = cards.length >= 3 ? "max-w-6xl" : "max-w-4xl"
<div class="flex items-center gap-2">
<span class="text-[11px] uppercase tracking-widest text-fg-muted">{plan.name}</span>
{plan.hasTrial && plan.trialDuration && (
<span class="inline-flex items-center rounded-full bg-accent/10 px-2 py-0.5 text-[10px] font-medium text-accent">
<span class="inline-flex items-center rounded-full bg-primary/10 px-2 py-0.5 text-[10px] font-medium text-primary">
{m.pricing_trial_badge({ duration: String(plan.trialDuration) })}
</span>
)}
Expand Down Expand Up @@ -272,7 +272,7 @@ const maxWidthClass = cards.length >= 3 ? "max-w-6xl" : "max-w-4xl"
<div class="mt-4 space-y-3">
{plan.platformFeatures.map((label) => (
<div class="flex items-center gap-2.5">
<svg class="w-4 h-4 text-accent shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="square"><path d="M8 2L16 2"/><path d="M8 22L16 22"/><path d="M2 8L2 16"/><path d="M22 8L22 16"/><path d="M6 4L6 4.01"/><path d="M4 6L4 6.01"/><path d="M18 4L18 4.01"/><path d="M20 6L20 6.01"/><path d="M6 20L6 20.01"/><path d="M4 18L4 18.01"/><path d="M18 20L18 20.01"/><path d="M20 18L20 18.01"/><path d="M8 12L11 15L16 9"/></svg>
<svg class="w-4 h-4 text-primary shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="square"><path d="M8 2L16 2"/><path d="M8 22L16 22"/><path d="M2 8L2 16"/><path d="M22 8L22 16"/><path d="M6 4L6 4.01"/><path d="M4 6L4 6.01"/><path d="M18 4L18 4.01"/><path d="M20 6L20 6.01"/><path d="M6 20L6 20.01"/><path d="M4 18L4 18.01"/><path d="M18 20L18 20.01"/><path d="M20 18L20 18.01"/><path d="M8 12L11 15L16 9"/></svg>
<span class="text-sm text-fg">{label}</span>
</div>
))}
Expand Down
2 changes: 1 addition & 1 deletion apps/landing/src/components/PrivacyContent.astro
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
<h2 class="text-fg text-base font-medium mb-3">10. Contact</h2>
<p>
If you have questions about this Privacy Policy, contact us at
<a href="mailto:privacy@getmaple.dev" class="text-fg underline underline-offset-4 hover:text-accent transition-colors">privacy@getmaple.dev</a>.
<a href="mailto:privacy@getmaple.dev" class="text-fg underline underline-offset-4 hover:text-primary transition-colors">privacy@getmaple.dev</a>.
</p>
</section>
</div>
Expand Down
Loading
Loading