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
15 changes: 8 additions & 7 deletions apps/landing/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ import { Faq } from './sections/Faq';
import { Footer } from './sections/Footer';

/**
* The mx landing + docs site: a single scrolling page that teaches mx from zero
* — hook (Hero), problem (Why), the core agent pitch (Agents), vocabulary
* (Concepts), hands-on (Quickstart), capabilities (Features), reference
* (Commands), objections (Faq), then a closing CTA (Footer). Ordered so each
* section builds on the last. Workflow (after Quickstart) shows one concrete
* end-to-end setup for using it day to day.
* The mx landing + docs site: a single scrolling page that teaches mx from zero.
* The story opens concrete — hook (Hero, with the Mission Control board), the
* pain (Why), then immediately the day-to-day Mission Control workflow
* (Workflow) so a newcomer "gets it" fast. Only then does it go into detail:
* the agent pitch (Agents), vocabulary (Concepts), hands-on (Quickstart),
* capabilities (Features), reference (Commands), objections (Faq), and a closing
* CTA (Footer).
*/
export function App() {
const { theme, toggle } = useTheme();
Expand All @@ -27,10 +28,10 @@ export function App() {
<main>
<Hero />
<Why />
<Workflow />
<Agents />
<Concepts />
<Quickstart />
<Workflow />
<Features />
<Commands />
<Faq />
Expand Down
7 changes: 3 additions & 4 deletions apps/landing/src/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export const CONCEPTS: Concept[] = [
term: 'Runtime',
plain: 'One folder on your machine where mx keeps everything.',
detail:
'Think of it as mx’s home base (default ~/mx). It holds your cloned repos and one folder per feature you’re working on. You can have several runtimes and switch with an environment variable.',
'Think of it as mx’s home base (default ~/mx) — one runtime for everything. It holds your cloned repos and one folder per feature you’re working on.',
},
{
icon: 'box',
Expand Down Expand Up @@ -186,7 +186,7 @@ export const STEPS: Step[] = [
title: 'Start a feature and dive in',
cmd: 'mx work new my-feature app',
comment: 'creates a worktree of "app" on branch my-feature',
body: 'This creates a feature and a git worktree for it. cd into works/my-feature/wt/app and you’re in a normal checkout on your feature branch — build, run, commit, push as usual. Start a second feature the same way; both stay isolated.',
body: 'This creates the feature and a worktree of app. Start your coding-agent session from the feature folder (works/my-feature) — it sees every worktree the feature has. The code lives in wt/app, a normal checkout on your branch; cd there when you want to run the dev server or git commands. Start a second feature the same way; both stay isolated.',
},
];

Expand Down Expand Up @@ -359,9 +359,8 @@ export const FAQS: Faq[] = [
*/
export const NAV_LINKS: { label: string; href: string }[] = [
{ label: 'Why mx', href: '#why' },
{ label: 'Workflow', href: '#workflow' },
{ label: 'Agents', href: '#agents' },
{ label: 'Concepts', href: '#concepts' },
{ label: 'Quickstart', href: '#quickstart' },
{ label: 'Workflow', href: '#workflow' },
{ label: 'Commands', href: '#commands' },
];
28 changes: 14 additions & 14 deletions apps/landing/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
@custom-variant dark (&:where([data-theme='dark'], [data-theme='dark'] *));

/*
* Semantic design tokens — a calm, mostly-monochrome grayscale base with a warm
* amber/yellow accent drawn from the Tailwind palette (amber for the UI accent;
* the logo itself stays multi-pastel — teal/amber/rose with a violet source
* node). Emphasis comes from ink
* Semantic design tokens — a calm, mostly-monochrome grayscale base with a teal
* accent drawn from the Tailwind palette (teal for the UI accent, tying into the
* logo, which stays multi-pastel — teal/amber/rose with a violet source node).
* Emphasis comes from ink
* weight and gray steps; the accent is used sparingly for the logo, one hero
* phrase, prompts, links, icon chips, and the primary button. Light values are
* the base; the dark override block below swaps them when
Expand All @@ -37,13 +37,13 @@
--text-soft: #3f3f46;
--muted: #71717a;
--faint: #a1a1aa;
--accent: #d97706; /* amber-600 (readable amber on white) */
--accent-ink: #b45309; /* amber-700 (readable link on white) */
--accent-2: #d97706;
--accent-soft: rgba(245, 158, 11, 0.14); /* amber-500 @ 14% */
--accent: #0d9488; /* teal-600 (readable teal on white) */
--accent-ink: #0f766e; /* teal-700 (readable link on white) */
--accent-2: #0d9488;
--accent-soft: rgba(20, 184, 166, 0.12); /* teal-500 @ 12% */
--accent-strong: #18181b;
--on-accent: #ffffff;
--cta: #f59e0b; /* amber-500 button, white text */
--cta: #0d9488; /* teal-600 button, white text */
--on-cta: #ffffff;
--amber: #71717a;
--code-bg: #f6f6f7;
Expand All @@ -60,13 +60,13 @@
--text-soft: #c8c8ce;
--muted: #9a9aa4;
--faint: #63636d;
--accent: #fbbf24; /* amber-400 (bright gold on the dark canvas) */
--accent-ink: #fcd34d; /* amber-300 */
--accent-2: #fbbf24;
--accent-soft: rgba(251, 191, 36, 0.16); /* amber-400 @ 16% */
--accent: #2dd4bf; /* teal-400 (bright teal on the dark canvas) */
--accent-ink: #5eead4; /* teal-300 */
--accent-2: #2dd4bf;
--accent-soft: rgba(45, 212, 191, 0.16); /* teal-400 @ 16% */
--accent-strong: #fafafa;
--on-accent: #18181b;
--cta: #f59e0b; /* amber-500 button, white text */
--cta: #0d9488; /* teal-600 button, white text */
--on-cta: #ffffff;
--amber: #a1a1aa;
--code-bg: #0d0d11;
Expand Down
11 changes: 11 additions & 0 deletions apps/landing/src/sections/Hero.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CopyButton, Icon, Logo } from '../ui';
import { MissionControlStrip } from './MissionControlStrip';
import { PKG, REPO_URL } from '../content';

/**
Expand Down Expand Up @@ -64,6 +65,16 @@ export function Hero() {
Why mx?
</a>
</div>

{/* The Mission Control board: every feature is its own Space, grouped by
stage — the whole "many parallel features" idea in one glance. */}
<div className="mt-16 text-left">
<MissionControlStrip />
<p className="mt-3 text-center text-sm text-muted">
Your whole board in macOS Mission Control — a Space per feature, grouped by stage with{' '}
<span className="font-mono text-ink-soft">mx divider</span>.
</p>
</div>
</div>
</section>
);
Expand Down
71 changes: 71 additions & 0 deletions apps/landing/src/sections/MissionControlStrip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* The ordered contents of the Mission Control Spaces board: either a labeled
* `mx divider` Space (a group header) or one or more feature Spaces (small
* thumbnails) belonging to the preceding group. Kept compact so the whole board
* — every stage label — fits within the content width without horizontal
* scrolling. Mirrors a real board: MAIN, then in-progress features, then review
* stages.
*/
const STRIP: ({ divider: string } | { spaces: number })[] = [
{ divider: 'IN PROGRESS' },
{ spaces: 4 },
{ divider: 'IN REVIEWS' },
{ spaces: 2 },
{ divider: 'PR REVIEWS' },
{ spaces: 2 },
];

/**
* A mock of the macOS Mission Control Spaces board: big block-text divider
* Spaces (from `mx divider`) act as group headers, with small feature-Space
* thumbnails clustered under each. Recreated as markup (not a screenshot) so it
* stays crisp and theme-aware. Wraps (rather than scrolls) on narrow screens so
* every stage stays visible. Shared by the hero and the workflow section.
*/
export function MissionControlStrip() {
return (
<div className="rounded-xl border border-line bg-surface-2 p-4">
<div className="flex flex-wrap items-stretch justify-center gap-2">
{STRIP.map((item, i) =>
'divider' in item ? (
<div
key={i}
className="flex h-14 shrink-0 items-center justify-center rounded-md border border-line-strong bg-surface px-3 font-mono text-[10px] font-bold tracking-widest text-ink"
>
{item.divider}
</div>
) : (
Array.from({ length: item.spaces }).map((_, j) => <SpaceThumb key={`${i}-${j}`} />)
),
)}
</div>
</div>
);
}

/**
* One feature-Space thumbnail in the Mission Control board — a tiny split-pane
* window (terminal | editor) rendered abstractly with a few faint lines.
*/
function SpaceThumb() {
return (
<div className="flex h-14 w-16 shrink-0 flex-col overflow-hidden rounded-md border border-line bg-surface">
<div className="flex items-center gap-1 border-b border-line px-1.5 py-0.5">
<span className="h-1 w-1 rounded-full bg-line-strong" />
<span className="h-1 w-1 rounded-full bg-line-strong" />
</div>
<div className="grid flex-1 grid-cols-2">
<div className="flex flex-col gap-1 border-r border-line p-1.5">
<span className="h-0.5 w-6 rounded bg-line-strong" />
<span className="h-0.5 w-4 rounded bg-line" />
<span className="h-0.5 w-5 rounded bg-line" />
</div>
<div className="flex flex-col gap-1 p-1.5">
<span className="h-0.5 w-4 rounded bg-line" />
<span className="h-0.5 w-5 rounded bg-line" />
<span className="h-0.5 w-4 rounded bg-line" />
</div>
</div>
</div>
);
}
8 changes: 5 additions & 3 deletions apps/landing/src/sections/Quickstart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ export function Quickstart() {

<div className="mt-10 rounded-xl border border-line bg-surface p-6">
<p className="text-sm leading-relaxed text-muted">
Now <Mono>cd works/my-feature/wt/app</Mono> and you’re in a normal git checkout on your
feature branch. Build it, run it, commit, push, open a PR — all the usual way. Start a
second feature with another <Mono>mx work new</Mono> and the two stay completely isolated.
Your coding-agent session runs from the feature folder (<Mono>works/my-feature</Mono>) —
its home base, with all the worktrees in view. The code itself lives in{' '}
<Mono>wt/app</Mono>, a normal git checkout on your branch; <Mono>cd</Mono> there to start
the dev server, commit, or push. Spin up another feature with <Mono>mx work new</Mono> and
the two stay completely isolated.
</p>
</div>
</Section>
Expand Down
110 changes: 18 additions & 92 deletions apps/landing/src/sections/Workflow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ import { Section, Command, Icon } from '../ui';
import { WORKFLOW_STEPS } from '../content';

/**
* The "In practice" section: one concrete, opinionated daily workflow — a
* fullscreen macOS Space per feature (terminal split with the editor), the
* agent in the first terminal tab, and a three-finger swipe to switch. It opens
* with a visual of the split layout, then the numbered steps. The lede stresses
* that mx doesn't mandate any of this; it's a starting shape to copy.
* The workflow section — the concrete story of how a feature goes from new to
* merged with mx: one fullscreen macOS Space per feature (terminal split with
* the editor), the coding agent in the first terminal tab, a three-finger swipe
* to switch, and archive on merge. Told as *the* workflow (not a hedged "one of
* many"), with the it-doesn't-have-to-be-this-way note saved for the end.
*/
export function Workflow() {
return (
<Section
id="workflow"
eyebrow="In practice"
title="A workflow that works"
lede="mx is deliberately workflow-agnostic — it manages the folders, branches, and ports, and leaves the rest to you. But a blank page is hard, so here’s one setup that works well: a fullscreen Space per feature, with the agent and editor side by side."
eyebrow="The workflow"
title="A day with mx"
lede="One fullscreen Space per feature — your coding agent and editor side by side — and a swipe to move between them. Here’s the whole loop, from a fresh feature to a merged one."
tinted
>
<SpaceMock />
Expand Down Expand Up @@ -43,92 +43,21 @@ export function Workflow() {
))}
</ol>

<div className="mt-14">
<h3 className="text-lg font-semibold text-ink">Grouped in Mission Control</h3>
<p className="mt-1.5 mb-5 max-w-2xl text-sm leading-relaxed text-muted">
Swipe up with three fingers and your whole board appears: feature Spaces clustered between{' '}
<span className="font-mono text-ink-soft">mx divider</span> labels, so you always know what’s
in progress, in review, and merged.
{/* The flexibility note lives at the END — so the story reads as concrete
first, and "you don't have to do it this way" is the closing reassurance. */}
<div className="mt-12 rounded-xl border border-line bg-surface p-6">
<p className="text-sm leading-relaxed text-muted">
<span className="font-semibold text-ink">This is the setup mx was built around — not a
requirement.</span>{' '}
Use any editor, terminal, or window manager you like; mx just owns the folders, branches,
and ports underneath and stays out of the way. Once you have the loop, bend it to your own
tools.
</p>
<SpacesStrip />
</div>
</Section>
);
}

/**
* The ordered contents of the Mission Control Spaces strip: either a labeled
* `mx divider` Space (a group header) or one or more feature Spaces (small
* thumbnails) that belong to the preceding group. Mirrors the real layout a
* user arranges — MAIN, then in-progress features, then review stages.
*/
const STRIP: ({ divider: string } | { spaces: number })[] = [
{ divider: 'MAIN' },
{ spaces: 3 },
{ divider: 'IN PROGRESS' },
{ spaces: 4 },
{ divider: 'IN REVIEWS' },
{ spaces: 2 },
{ divider: 'PR REVIEWS' },
{ spaces: 1 },
{ divider: 'MX' },
{ spaces: 1 },
];

/**
* A horizontally-scrolling mock of the macOS Mission Control Spaces bar: big
* block-text divider Spaces (from `mx divider`) act as group headers, with small
* feature-Space thumbnails clustered under each. Recreates the user's real
* board rather than a screenshot, so it stays crisp and theme-aware.
*/
function SpacesStrip() {
return (
<div className="overflow-x-auto rounded-xl border border-line bg-surface-2 p-4">
<div className="flex items-stretch gap-2.5">
{STRIP.map((item, i) =>
'divider' in item ? (
<div
key={i}
className="flex h-16 shrink-0 items-center justify-center rounded-md border border-line-strong bg-surface px-4 font-mono text-xs font-bold tracking-widest text-ink"
>
{item.divider}
</div>
) : (
Array.from({ length: item.spaces }).map((_, j) => <SpaceThumb key={`${i}-${j}`} />)
),
)}
</div>
</div>
);
}

/**
* One feature-Space thumbnail in the Mission Control strip — a tiny split-pane
* window (terminal | editor) rendered abstractly with a few faint lines.
*/
function SpaceThumb() {
return (
<div className="flex h-16 w-24 shrink-0 flex-col overflow-hidden rounded-md border border-line bg-surface">
<div className="flex items-center gap-1 border-b border-line px-1.5 py-1">
<span className="h-1 w-1 rounded-full bg-line-strong" />
<span className="h-1 w-1 rounded-full bg-line-strong" />
</div>
<div className="grid flex-1 grid-cols-2">
<div className="flex flex-col gap-1 border-r border-line p-1.5">
<span className="h-0.5 w-8 rounded bg-line-strong" />
<span className="h-0.5 w-6 rounded bg-line" />
<span className="h-0.5 w-7 rounded bg-line" />
</div>
<div className="flex flex-col gap-1 p-1.5">
<span className="h-0.5 w-5 rounded bg-line" />
<span className="h-0.5 w-8 rounded bg-line" />
<span className="h-0.5 w-6 rounded bg-line" />
</div>
</div>
</div>
);
}

/**
* A stylized mock of one feature's fullscreen Space: a terminal pane on the left
* (tab 1 = the agent session, tab 2 = the dev server) and the editor on the
Expand Down Expand Up @@ -216,10 +145,7 @@ function TermTab({ label, active }: { label: string; active?: boolean }) {
function SwipeArrow({ direction }: { direction: 'left' | 'right' }) {
return (
<div className="hidden shrink-0 flex-col items-center gap-1 text-faint sm:flex">
<Icon
name="arrow"
className={`h-5 w-5 ${direction === 'left' ? 'rotate-180' : ''}`}
/>
<Icon name="arrow" className={`h-5 w-5 ${direction === 'left' ? 'rotate-180' : ''}`} />
<span className="w-14 text-center text-[10px] leading-tight">
{direction === 'left' ? 'prev feature' : 'next feature'}
</span>
Expand Down
Loading