feat(website): copy states what Paseo does, plugins section and comparison tables (#6270)

The homepage, README, sponsor copy and comparison pages now say plainly
what Paseo is: a one-click desktop app with the daemon bundled, a native
mobile app with full parity, parallel agents in worktrees, and plugins
that add panels and functionality on desktop, web and mobile.

Every comparison page uses one table with the same rows so readers can
compare products row by row. The product columns use a fixed layout so
column widths no longer follow the longest cell.

Sponsor copy opens with the project's size before the one-person fact,
so a reader does not take "one person" to mean a side project.
This commit is contained in:
Mohamed Boudra
2026-10-07 00:59:14 +01:00
committed by GitHub
parent 2d85fe4e04
commit 93bfb34e21
16 changed files with 369 additions and 265 deletions
@@ -32,7 +32,9 @@ function AlternativePageContent({ slug }: { slug: string }) {
return (
<SiteShell width="default">
<DocsMarkdown>{page.content}</DocsMarkdown>
<div className="comparison-prose">
<DocsMarkdown>{page.content}</DocsMarkdown>
</div>
</SiteShell>
);
}
@@ -4,13 +4,12 @@ import {
ArrowRight,
Blocks,
Bot,
BookOpen,
Braces,
Coffee,
Compass,
ExternalLink,
Gem,
GitFork,
LayoutPanelLeft,
Laptop,
Lock,
Merge,
@@ -19,6 +18,7 @@ import {
Smartphone,
Terminal,
Users,
Workflow,
type LucideIcon,
} from "lucide-react";
import {
@@ -477,7 +477,7 @@ function TurnkeySection() {
<div className="space-y-0.5">
<h3 className="text-xl font-medium text-white/90">Desktop app</h3>
<p className="max-w-lg text-sm leading-relaxed text-white/50">
The one click experience, download the app and it just works
The one click experience, download the app and it just works, no server required
</p>
</div>
</div>
@@ -487,8 +487,8 @@ function TurnkeySection() {
<div className="grid gap-4 md:grid-cols-3">
<TurnkeyExtensionCard
icon={Smartphone}
title="Mobile and web"
description="Connect to the same workspaces from any client"
title="Mobile"
description="Full client and native, not a WebView"
ctaHref="/download"
ctaLabel="Download"
/>
@@ -793,92 +793,105 @@ function SdkAutomationExample() {
function ExtensibleSection() {
return (
<FeatureSection title="Make it yours" description="Extend Paseo to work just the way you want">
<div className="grid gap-4 md:grid-cols-2">
<ExtensibleCard
icon={Puzzle}
title="Plugins"
description="Plugins can add server-side functionality and modify the client with custom components. They work across all clients, including mobile"
links={PLUGIN_CARD_LINKS}
/>
<ExtensibleCard
icon={GitFork}
title="Fork the repo"
description="Paseo is licensed under Apache 2.0. You can inspect the implementation, fork the project, and adapt it to your workflow or organization"
links={FORK_CARD_LINKS}
/>
<FeatureSection
title="Extend it with plugins"
description="Add new panels and functionality that work in desktop, web and mobile"
>
<div className="overflow-hidden rounded-2xl border border-white/10 bg-white/[0.02]">
<div className="flex flex-col gap-6 border-b border-white/10 p-6 sm:flex-row sm:items-center sm:justify-between md:p-8">
<div className="flex items-center gap-4">
<div className="rounded-xl border border-white/10 bg-white/[0.06] p-3 text-muted-foreground">
<Puzzle className="h-6 w-6" strokeWidth={1.5} />
</div>
<h3 className="text-xl font-medium text-white/90">Plugins</h3>
</div>
<div className="flex shrink-0 items-center gap-3">
<a
href={PLUGINS_BROWSE.href}
{...(PLUGINS_BROWSE.external ? { target: "_blank", rel: "noopener noreferrer" } : {})}
className="inline-flex items-center gap-1.5 rounded-full bg-foreground px-3 py-1.5 text-xs text-background transition-colors hover:bg-foreground/90"
>
Browse plugins
<ArrowRight className="h-3.5 w-3.5" />
</a>
<a
href="/docs/plugins"
className="inline-flex items-center gap-1.5 rounded-full border border-white/12 px-3 py-1.5 text-xs text-white/80 transition-colors hover:bg-white/10"
>
Plugin docs
</a>
</div>
</div>
<div className="p-6 md:p-8">
<div className="grid gap-4 md:grid-cols-3">
{PLUGIN_CAPABILITIES.map((capability) => (
<PluginCapabilityCard key={capability.title} {...capability} />
))}
</div>
</div>
<div className="flex flex-col gap-3 border-t border-white/10 px-6 py-5 sm:flex-row sm:items-center sm:justify-between md:px-8">
<p className="text-sm text-white/45">Paseo is Apache 2.0.</p>
<a
href="https://github.com/getpaseo/paseo"
target="_blank"
rel="noopener noreferrer"
className="inline-flex shrink-0 items-center gap-2 text-sm text-muted-foreground transition-colors hover:text-foreground"
>
<GitFork className="h-4 w-4" strokeWidth={1.5} />
Fork the repo
<ExternalLink className="h-3.5 w-3.5 opacity-70" />
</a>
</div>
</div>
</FeatureSection>
);
}
interface ExtensibleCardLink {
href: string;
label: string;
icon: React.ComponentType<{ className?: string }>;
external?: boolean;
/** Accent links stand out without hover, for destinations worth noticing. */
accent?: boolean;
}
const PLUGINS_BROWSE = PLUGINS_LINKED
? { href: "/plugins", external: false }
: { href: "https://paseo.cafe", external: true };
const PLUGIN_CARD_LINKS: ReadonlyArray<ExtensibleCardLink> = [
{ href: "/docs/plugins", label: "Plugin documentation", icon: BookOpen },
PLUGINS_LINKED
? { href: "/plugins", label: "Community plugins", icon: Blocks, accent: true }
: {
href: "https://paseo.cafe",
label: "Community plugins",
icon: Coffee,
external: true,
accent: true,
},
];
const FORK_CARD_LINKS: ReadonlyArray<ExtensibleCardLink> = [
const PLUGIN_CAPABILITIES: ReadonlyArray<{
icon: LucideIcon;
title: string;
description: string;
}> = [
{
href: "https://github.com/getpaseo/paseo",
label: "View the repository",
icon: GitHubIcon,
external: true,
icon: LayoutPanelLeft,
title: "UI",
description: "Screens, workspace panels, sidebar items, slash commands, and themes",
},
{
icon: Workflow,
title: "Agent lifecycle",
description:
"Change configuration, environment, and MCP servers. Answer permissions. Follow up when a turn ends",
},
{
icon: Bot,
title: "Providers",
description: "Add a coding agent as a provider, used the same way as the built-in ones",
},
];
function ExtensibleCard({
function PluginCapabilityCard({
icon: Icon,
title,
description,
links,
}: {
icon: LucideIcon;
title: string;
description: string;
links: ReadonlyArray<ExtensibleCardLink>;
}) {
return (
<div className="flex min-h-64 flex-col rounded-xl border border-white/10 bg-white/[0.025] p-6">
<div className="mb-8 text-muted-foreground">
<Icon className="h-6 w-6" strokeWidth={1.5} />
<div className="flex flex-col rounded-xl border border-white/10 bg-white/[0.025] p-5">
<div className="mb-5 text-muted-foreground">
<Icon className="h-5 w-5" strokeWidth={1.5} />
</div>
<h3 className="text-lg font-medium text-white/85">{title}</h3>
<h3 className="font-medium text-white/85">{title}</h3>
<p className="mt-2 text-sm leading-relaxed text-white/45">{description}</p>
<div className="mt-auto flex flex-col items-start gap-3 pt-6">
{links.map((link) => (
<a
key={link.href}
href={link.href}
{...(link.external ? { target: "_blank", rel: "noopener noreferrer" } : {})}
className={
link.accent
? "inline-flex items-center gap-2 text-sm text-emerald-300/85 transition-colors hover:text-emerald-200"
: "inline-flex items-center gap-2 text-sm text-muted-foreground transition-colors hover:text-foreground"
}
>
<link.icon className="h-4 w-4" />
{link.label}
{link.external ? <ExternalLink className="h-3.5 w-3.5 opacity-70" /> : null}
</a>
))}
</div>
</div>
);
}
@@ -902,8 +915,7 @@ const PRINCIPLES: ReadonlyArray<{ icon: LucideIcon; title: string; description:
{
icon: Merge,
title: "Unified",
description:
"Claude Code, Codex, OpenCode, Pi, Antigravity, Muse Code, and more, all used the same way.",
description: "Every coding agent, used the same way. Switch providers any time.",
},
{
icon: Blocks,
@@ -923,17 +935,17 @@ function PhilosophySection() {
title="Philosophy"
description="What Paseo stands for, and what every feature is built on"
>
<div className="grid gap-4 md:grid-cols-2">
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{PRINCIPLES.map((principle) => (
<div
key={principle.title}
className="rounded-xl border border-white/10 bg-white/[0.025] p-6"
className="rounded-xl border border-white/10 bg-white/[0.025] p-5"
>
<div className="mb-8 text-extra-muted-foreground">
<principle.icon className="h-6 w-6" strokeWidth={1.5} />
<div className="flex items-center gap-3">
<principle.icon className="h-5 w-5 text-extra-muted-foreground" strokeWidth={1.5} />
<h3 className="font-medium text-white/85">{principle.title}</h3>
</div>
<h3 className="text-lg font-medium text-white/85">{principle.title}</h3>
<p className="mt-2 text-sm leading-relaxed text-white/45">{principle.description}</p>
<p className="mt-3 text-sm leading-relaxed text-white/45">{principle.description}</p>
</div>
))}
</div>
@@ -53,9 +53,10 @@ const MAINTAINER_LINK = (
export function FounderNote() {
return (
<div className="max-w-2xl space-y-5 leading-relaxed text-white/70">
<p>Paseo is an independent project used by tens of thousands of developers daily.</p>
<p>
I build Paseo on my own. There are no investors, no board and no company behind it, and I
have turned down funding offers to keep it that way.
It is built by one person, full time, with no investors, no board and no company behind it.
I have turned down funding offers to keep it that way.
</p>
<p>
A tool that sits between you and your code, your keys and your machines has to stay neutral,
@@ -67,7 +68,7 @@ export function FounderNote() {
<a href="/hub" className="underline hover:text-white/90">
Paseo Hub
</a>
, an optional hosted service. Your support is what lets me work on Paseo full time.
, an optional hosted service. Your support is what lets me keep working on it.
</p>
<p className="text-white/50">{MAINTAINER_LINK}, maintainer</p>
</div>
@@ -79,7 +80,6 @@ interface BackingOption {
name: string;
icon: React.ComponentType<{ className?: string }>;
external: boolean;
primary?: boolean;
}
const BACKING_OPTIONS: ReadonlyArray<BackingOption> = [
@@ -88,7 +88,6 @@ const BACKING_OPTIONS: ReadonlyArray<BackingOption> = [
name: "GitHub Sponsors",
icon: GitHubIcon,
external: true,
primary: true,
},
{
href: OPEN_COLLECTIVE_URL,
@@ -127,11 +126,7 @@ export function BackingOptions() {
key={option.href}
href={option.href}
{...(option.external ? { target: "_blank", rel: "noopener noreferrer" } : {})}
className={`flex items-center gap-4 rounded-xl border p-4 transition-colors ${
option.primary
? "border-white/25 bg-white/[0.06] hover:border-white/40 hover:bg-white/[0.08]"
: "border-white/10 bg-white/[0.02] hover:border-white/20 hover:bg-white/[0.05]"
}`}
className="flex items-center gap-4 rounded-xl border border-white/10 bg-white/[0.02] p-4 transition-colors hover:border-white/20 hover:bg-white/[0.05]"
>
<option.icon className="h-6 w-6 shrink-0 text-white/60" />
<p className="flex items-center gap-1.5 font-medium text-white">
@@ -237,9 +232,10 @@ export function SponsorSection() {
<SectionHeading as="h2" title="Sponsor Paseo" />
<div className="space-y-10">
<div className="max-w-2xl space-y-5 leading-relaxed text-white/70">
<p>Paseo is an independent project used by tens of thousands of developers daily.</p>
<p>
I build Paseo on my own, with no investors and no company behind it, and I have turned
down funding offers to keep it that way. A tool that sits between you and your code,
It is built by one person, full time, with no investors and no company behind it. I have
turned down funding to keep it that way. A tool that sits between you and your code,
your keys and your machines has to stay neutral, and funding creates pressure to
monetize.
</p>
@@ -248,7 +244,7 @@ export function SponsorSection() {
<a href="/hub" className="underline hover:text-white/90">
Paseo Hub
</a>
, and your support is what lets me work on it full time.
. Your support is what lets me keep working on it.
</p>
<p className="text-white/50">{MAINTAINER_LINK}, maintainer</p>
</div>