feat(website): show sponsors on paseo.sh and at the top of the README (#6956)

This commit is contained in:
Mohamed Boudra
2026-10-15 11:19:32 +07:00
committed by GitHub
parent 8ff2424da1
commit 9ab99a6e1e
15 changed files with 271 additions and 93 deletions
+13 -4
View File
@@ -53,6 +53,17 @@
- **クロスデバイス:** iOS、Android、デスクトップ、Web、CLI に対応。机で作業を始め、スマートフォンで確認し、ターミナルから自動化できます。
- **プライバシー優先:** Paseo にはテレメトリー・トラッキング・強制ログインは一切ありません。
## スポンサー
<!-- Sponsors: one cell per sponsor in the order of packages/website/src/data/sponsors.ts, then "become a sponsor" cells up to three. -->
<table>
<tr>
<td align="center" width="33%"><a href="https://hoplite.sh/?utm_source=paseo&utm_medium=readme&utm_campaign=sponsor"><picture><source media="(prefers-color-scheme: dark)" srcset="packages/website/public/sponsors/hoplite-on-dark.svg"><img src="packages/website/public/sponsors/hoplite-on-light.svg" alt="Hoplite" height="40"></picture></a><br><sub>Cloud coding agents</sub></td>
<td align="center" width="33%"><a href="https://paseo.sh/sponsor">Paseo のスポンサーになる</a></td>
<td align="center" width="33%"><a href="https://paseo.sh/sponsor">Paseo のスポンサーになる</a></td>
</tr>
</table>
## はじめかた
Paseo はコーディングエージェントを管理するローカルサーバー(デーモン)を起動します。デスクトップアプリ・モバイルアプリ・Web アプリ・CLI などのクライアントがこのデーモンに接続します。
@@ -151,11 +162,9 @@ npm run build:server
npm run typecheck
```
## スポンサー
## Paseo を支援する
Paseo は一人で開発しており、使ってくれる人たちの支援で成り立っています。[GitHub Sponsors](https://github.com/sponsors/boudra) で支援できます。企業として毎月[スポンサー](https://paseo.sh/sponsor#spot)になっていただくと、ロゴをここと paseo.sh のホームページに掲載します。
<!-- Sponsor logos go here, in the same order as packages/website/src/data/sponsors.ts -->
Paseo は一人で開発しており、使ってくれる人たちの支援で成り立っています。[GitHub Sponsors](https://github.com/sponsors/boudra) で支援できます。企業として毎月[スポンサー](https://paseo.sh/sponsor#spot)になっていただくと、ロゴをこの README の冒頭と、paseo.sh のトップページおよびドキュメントに掲載します。
## 関連プロジェクト
+13 -4
View File
@@ -47,6 +47,17 @@
- **여러 기기 지원:** iOS, Android, 데스크톱, 웹, CLI를 지원합니다. 데스크톱에서 시작해 휴대폰으로 확인하고 터미널에서 자동화할 수 있습니다.
- **개인정보 보호 우선:** Paseo는 텔레메트리, 추적, 강제 로그인을 사용하지 않습니다.
## 스폰서
<!-- Sponsors: one cell per sponsor in the order of packages/website/src/data/sponsors.ts, then "become a sponsor" cells up to three. -->
<table>
<tr>
<td align="center" width="33%"><a href="https://hoplite.sh/?utm_source=paseo&utm_medium=readme&utm_campaign=sponsor"><picture><source media="(prefers-color-scheme: dark)" srcset="packages/website/public/sponsors/hoplite-on-dark.svg"><img src="packages/website/public/sponsors/hoplite-on-light.svg" alt="Hoplite" height="40"></picture></a><br><sub>Cloud coding agents</sub></td>
<td align="center" width="33%"><a href="https://paseo.sh/sponsor">Paseo 스폰서 되기</a></td>
<td align="center" width="33%"><a href="https://paseo.sh/sponsor">Paseo 스폰서 되기</a></td>
</tr>
</table>
## 시작하기
Paseo는 코딩 에이전트를 관리하는 로컬 서버인 데몬을 실행합니다. 데스크톱 앱, 모바일 앱, 웹 앱, CLI 같은 클라이언트가 이 데몬에 연결합니다.
@@ -161,11 +172,9 @@ npm run build:server
npm run typecheck
```
## 스폰서
## Paseo 후원하기
Paseo는 한 사람이 개발하며, 사용하는 분들의 후원으로 운영됩니다. [GitHub Sponsors](https://github.com/sponsors/boudra)로 후원할 수 있습니다. 회사는 매월 [Paseo를 후원](https://paseo.sh/sponsor#spot)하고 로고를 이곳과 paseo.sh 홈페이지에 게재할 수 있습니다.
<!-- Sponsor logos go here, in the same order as packages/website/src/data/sponsors.ts -->
Paseo는 한 사람이 개발하며, 사용하는 분들의 후원으로 운영됩니다. [GitHub Sponsors](https://github.com/sponsors/boudra)로 후원할 수 있습니다. 회사는 매월 [Paseo를 후원](https://paseo.sh/sponsor#spot)하고 로고를 이 README 상단과 paseo.sh 홈페이지 및 문서에 게재할 수 있습니다.
## 관련 프로젝트
+13 -4
View File
@@ -52,6 +52,17 @@ Paseo is an open source agentic development environment for desktop, mobile, web
[Run parallel tasks in Paseo](https://paseo.sh/docs/parallel-development): start agents in separate worktrees, review their diffs, run each app, and check it in the built-in browser.
## Sponsors
<!-- Sponsors: one cell per sponsor in the order of packages/website/src/data/sponsors.ts, then "become a sponsor" cells up to three. -->
<table>
<tr>
<td align="center" width="33%"><a href="https://hoplite.sh/?utm_source=paseo&utm_medium=readme&utm_campaign=sponsor"><picture><source media="(prefers-color-scheme: dark)" srcset="packages/website/public/sponsors/hoplite-on-dark.svg"><img src="packages/website/public/sponsors/hoplite-on-light.svg" alt="Hoplite" height="40"></picture></a><br><sub>Cloud coding agents</sub></td>
<td align="center" width="33%"><a href="https://paseo.sh/sponsor">Become a sponsor</a></td>
<td align="center" width="33%"><a href="https://paseo.sh/sponsor">Become a sponsor</a></td>
</tr>
</table>
## Plugins
Plugins run on the daemon and show up in every client you connect, with the same UI on desktop, web,
@@ -207,11 +218,9 @@ npm run build:server
npm run typecheck
```
## Sponsors
## Support Paseo
Paseo is an independent project used by tens of thousands of developers daily, built by one person and funded by the people who use it. Support the work on [GitHub Sponsors](https://github.com/sponsors/boudra). Companies can [sponsor Paseo](https://paseo.sh/sponsor#spot) monthly and have their logo shown here and on the paseo.sh homepage.
<!-- Sponsor logos go here, in the same order as packages/website/src/data/sponsors.ts -->
Paseo is an independent project used by tens of thousands of developers daily, built by one person and funded by the people who use it. Support the work on [GitHub Sponsors](https://github.com/sponsors/boudra). Companies can [sponsor Paseo](https://paseo.sh/sponsor#spot) monthly and have their logo shown at the top of this README and on the paseo.sh homepage and docs.
## Related projects
+13 -4
View File
@@ -53,6 +53,17 @@
- **跨设备:** 支持 iOS、Android、桌面端、Web 和 CLI。在桌前开始工作,用手机查看进度,也可以从终端脚本化操作。
- **隐私优先:** Paseo 没有遥测、追踪,也不会强制登录。
## 赞助商
<!-- Sponsors: one cell per sponsor in the order of packages/website/src/data/sponsors.ts, then "become a sponsor" cells up to three. -->
<table>
<tr>
<td align="center" width="33%"><a href="https://hoplite.sh/?utm_source=paseo&utm_medium=readme&utm_campaign=sponsor"><picture><source media="(prefers-color-scheme: dark)" srcset="packages/website/public/sponsors/hoplite-on-dark.svg"><img src="packages/website/public/sponsors/hoplite-on-light.svg" alt="Hoplite" height="40"></picture></a><br><sub>Cloud coding agents</sub></td>
<td align="center" width="33%"><a href="https://paseo.sh/sponsor">成为 Paseo 赞助商</a></td>
<td align="center" width="33%"><a href="https://paseo.sh/sponsor">成为 Paseo 赞助商</a></td>
</tr>
</table>
## 快速开始
Paseo 会运行一个名为 daemon 的本地服务,用来管理你的 coding agents。桌面 app、移动 app、Web app 和 CLI 等客户端都会连接到它。
@@ -151,11 +162,9 @@ npm run build:server
npm run typecheck
```
## 赞助
## 支持 Paseo
Paseo 由一个人开发,靠使用它的人来资助。你可以通过 [GitHub Sponsors](https://github.com/sponsors/boudra) 支持这项工作。公司也可以按月[赞助 Paseo](https://paseo.sh/sponsor#spot),logo 会展示在这里和 paseo.sh 首页上。
<!-- Sponsor logos go here, in the same order as packages/website/src/data/sponsors.ts -->
Paseo 由一个人开发,靠使用它的人来资助。你可以通过 [GitHub Sponsors](https://github.com/sponsors/boudra) 支持这项工作。公司也可以按月[赞助 Paseo](https://paseo.sh/sponsor#spot),logo 会展示在本 README 顶部,以及 paseo.sh 的首页和文档中。
## 相关项目
+20
View File
@@ -0,0 +1,20 @@
import { expect, test } from "playwright/test";
const PAGES = ["/", "/docs/connectivity", "/changelog"];
for (const path of PAGES) {
test(`${path} shows the sponsors and invites the next one`, async ({ page }) => {
await page.goto(path);
const sponsors = page.getByRole("region", { name: /^(Sponsors|Sponsored by)$/ });
await expect(sponsors.getByRole("link", { name: "Hoplite" })).toHaveAttribute(
"href",
"https://hoplite.sh/?utm_source=paseo&utm_medium=website&utm_campaign=sponsor",
);
await expect(sponsors.getByText("Cloud coding agents", { exact: true })).toBeVisible();
await expect(sponsors.getByRole("link", { name: "Become a sponsor" })).toHaveAttribute(
"href",
"/sponsor#spot",
);
});
}
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.4 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.4 KiB

@@ -1,3 +1,4 @@
import { ExternalLink } from "lucide-react";
import type { Doc } from "~/docs";
const GITHUB_BASE_URL = "https://github.com/getpaseo/paseo/blob/main";
@@ -6,9 +7,15 @@ export function DocsSourceFooter({ doc }: { doc: Doc }) {
const sourceUrl = `${GITHUB_BASE_URL}/${doc.sourcePath}`;
return (
<footer className="docs-source-footer">
<a href={sourceUrl} target="_blank" rel="noreferrer">
View this page on GitHub
<footer className="mt-12 border-t border-white/10 py-8 text-sm">
<a
href={sourceUrl}
target="_blank"
rel="noreferrer"
className="inline-flex items-center gap-1.5 font-medium text-white/60 underline-offset-4 transition-colors hover:text-foreground hover:underline"
>
View on GitHub
<ExternalLink aria-hidden="true" className="size-3.5" />
</a>
</footer>
);
@@ -134,11 +134,11 @@ export function LandingPage({ title, subtitle }: LandingPageProps) {
<ExtensibleSection />
<FAQ />
<PhilosophySection />
<SponsorsSection placement="page" />
<SponsorSection />
<SponsorsSection />
</div>
</main>
<SiteFooter />
<SiteFooter sponsors={false} />
</div>
</CursorFieldProvider>
);
@@ -1,9 +1,12 @@
import { PLUGINS_LINKED } from "~/plugins/launch";
import { getAlternativePages } from "~/data/alternative-pages";
import { appStoreUrl, playStoreUrl, webAppUrl } from "~/downloads";
import { SponsorsSection } from "~/components/sponsorship";
interface SiteFooterProps {
width?: "default" | "prose" | "wide";
/** Pages that show the sponsors in their content turn the footer band off. */
sponsors?: boolean;
}
const WIDTH_CLASSES: Record<NonNullable<SiteFooterProps["width"]>, string> = {
@@ -12,11 +15,12 @@ const WIDTH_CLASSES: Record<NonNullable<SiteFooterProps["width"]>, string> = {
wide: "max-w-7xl p-6 md:p-20 md:pt-0",
};
export function SiteFooter({ width = "default" }: SiteFooterProps) {
export function SiteFooter({ width = "default", sponsors = true }: SiteFooterProps) {
const widthClasses = WIDTH_CLASSES[width];
const alternatives = getAlternativePages();
return (
<footer className={`${widthClasses} mx-auto mt-12 md:mt-16`}>
{sponsors ? <SponsorsSection placement="footer" /> : null}
<div className="border-t border-white/10 pt-8 pb-4 grid grid-cols-2 sm:grid-cols-5 gap-8 text-sm">
<div className="space-y-3">
<p className="text-extra-muted-foreground">Product</p>
+72 -40
View File
@@ -3,12 +3,13 @@ import { BuyMeACoffeeIcon, GitHubIcon, OpenCollectiveIcon } from "~/components/b
import {
BUY_ME_A_COFFEE_URL,
GITHUB_SPONSORS_URL,
HOMEPAGE_SPONSORS,
HOMEPAGE_SPOT_PRICE,
OPEN_COLLECTIVE_URL,
SPONSORS,
SPONSOR_CONTACT_EMAIL,
SPONSOR_SPOT_CHECKOUT_URL,
SPONSOR_SPOT_PRICE,
openSpotCount,
sponsorHref,
} from "~/data/sponsors";
function SectionHeading({
@@ -148,30 +149,11 @@ export function BackingOptions() {
);
}
function SponsorLogoRow() {
return (
<ul className="grid grid-cols-2 gap-4">
{HOMEPAGE_SPONSORS.map((sponsor) => (
<li key={sponsor.href}>
<a
href={sponsor.href}
target="_blank"
rel="noopener noreferrer sponsored"
className="flex h-32 items-center justify-center rounded-xl border border-white/10 bg-white/[0.02] px-6 transition-colors hover:border-white/20 hover:bg-white/[0.05]"
>
<img src={sponsor.logo} alt={sponsor.name} className="max-h-10 max-w-full opacity-80" />
</a>
</li>
))}
</ul>
);
}
const SPOT_FEATURES: ReadonlyArray<string> = [
"Your logo on the homepage of paseo.sh, around 70,000 visitors a month",
"Your logo on the paseo.sh homepage and docs, around 70,000 visitors a month",
"Your logo in the GitHub README, around 30,000 visitors a month",
"An announcement in the Discord, around 2,000 members",
"A mention in the changelog",
"An announcement from me on X",
];
export function SponsorSpotSection() {
@@ -181,11 +163,11 @@ export function SponsorSpotSection() {
<SectionHeading
as="h2"
title="Sponsor as a company"
description="If your team relies on Paseo, a monthly sponsorship funds its development directly. As a thank you, your logo goes on the homepage and in the README."
description="Support Paseo financially and get visibility for your company"
/>
<div className="space-y-8">
<div className="flex items-end gap-2">
<span className="text-4xl font-medium tracking-tight">{HOMEPAGE_SPOT_PRICE}</span>
<span className="text-4xl font-medium tracking-tight">{SPONSOR_SPOT_PRICE}</span>
<span className="mb-1 text-sm text-white/45">a month</span>
</div>
<ul className="grid max-w-2xl gap-3 text-white/70">
@@ -259,23 +241,73 @@ export function SponsorSection() {
);
}
/** Homepage: the companies sponsoring Paseo. Renders nothing until there is one. */
export function SponsorsSection() {
if (HOMEPAGE_SPONSORS.length === 0) return null;
const SPONSORS_PLACEMENTS = {
page: {
title: "Sponsors",
section: "space-y-10",
heading: "text-3xl font-medium tracking-tight",
link: "",
logo: "h-14",
description: "mt-2 text-sm text-white/55",
button: "h-12 px-5 text-sm",
},
footer: {
title: "Sponsored by",
section: "space-y-5 border-t border-white/10 py-8",
heading: "text-sm text-extra-muted-foreground",
link: "opacity-85 transition-opacity hover:opacity-100",
logo: "h-10",
description: "mt-1.5 text-xs text-white/45",
button: "h-9 px-3.5 text-sm",
},
} as const;
interface SponsorsSectionProps {
/** `page` is a homepage section; `footer` is the band above other pages' footers. */
placement: keyof typeof SPONSORS_PLACEMENTS;
}
/**
* The companies sponsoring Paseo: one monochrome logo per sponsor and, while
* spots are open, a quiet invitation. Every page shows it once.
*/
export function SponsorsSection({ placement }: SponsorsSectionProps) {
const style = SPONSORS_PLACEMENTS[placement];
const open = openSpotCount();
return (
<section>
<SectionHeading as="h2" title="Sponsors" />
<div className="space-y-4">
<SponsorLogoRow />
{openSpotCount() > 0 ? (
<a
href="/sponsor#spot"
className="inline-block text-sm text-white/50 underline transition-colors hover:text-white/80"
>
Become a sponsor
</a>
<section aria-labelledby="sponsors-heading" className={style.section}>
<h2 id="sponsors-heading" className={style.heading}>
{style.title}
</h2>
<ul className="flex flex-wrap items-center gap-x-14 gap-y-8">
{SPONSORS.map((sponsor) => (
<li key={sponsor.url}>
<a
href={sponsorHref(sponsor, "website")}
target="_blank"
rel="noopener noreferrer sponsored"
className={`block ${style.link}`}
>
<img
src={sponsor.logo.onDark}
alt={sponsor.name}
className={`${style.logo} w-auto`}
/>
</a>
<p className={style.description}>{sponsor.description}</p>
</li>
))}
{open > 0 ? (
<li>
<a
href="/sponsor#spot"
className={`inline-flex items-center rounded-md border border-dashed border-white/15 text-white/45 transition-colors hover:border-white/30 hover:text-white/75 ${style.button}`}
>
Become a sponsor
</a>
</li>
) : null}
</div>
</ul>
</section>
);
}
@@ -0,0 +1,64 @@
import { existsSync, readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { describe, expect, it } from "vitest";
import { SPONSORS, sponsorHref } from "./sponsors";
const REPO_ROOT = fileURLToPath(new URL("../../../../", import.meta.url));
const WEBSITE_PUBLIC = fileURLToPath(new URL("../../public", import.meta.url));
const READMES = ["README.md", "README.zh-CN.md", "README.ja.md", "README.ko.md"];
const README_SPONSOR_CELLS = 3;
const SPONSOR_PAGE_URL = "https://paseo.sh/sponsor";
describe("sponsorHref", () => {
it("tags the link with the placement it is shown in", () => {
const sponsor = {
name: "Acme",
url: "https://acme.dev",
logo: { onDark: "", onLight: "" },
description: "",
};
expect(sponsorHref(sponsor, "website")).toBe(
"https://acme.dev/?utm_source=paseo&utm_medium=website&utm_campaign=sponsor",
);
expect(sponsorHref(sponsor, "x")).toBe(
"https://acme.dev/?utm_source=paseo&utm_medium=x&utm_campaign=sponsor",
);
});
});
function readmeSponsorCells(readme: string) {
const text = readFileSync(`${REPO_ROOT}${readme}`, "utf8");
const table = text.slice(text.indexOf("<!-- Sponsors:")).split("</table>")[0];
return [...table.matchAll(/<td[^>]*>(.*?)<\/td>/g)].map(([, cell]) => {
const logo = cell.match(
/^<a href="([^"]+)"><picture><source media="\(prefers-color-scheme: dark\)" srcset="([^"]+)"><img src="([^"]+)"[^>]*><\/picture><\/a><br><sub>([^<]+)<\/sub>$/,
);
if (logo) {
const [, href, onDark, onLight, description] = logo;
return { href, onDark, onLight, description };
}
return { invite: cell.match(/^<a href="([^"]+)">/)?.[1] };
});
}
describe("SPONSORS", () => {
it.each(SPONSORS)("ships both logo inks for $name", (sponsor) => {
expect(existsSync(`${WEBSITE_PUBLIC}${sponsor.logo.onDark}`)).toBe(true);
expect(existsSync(`${WEBSITE_PUBLIC}${sponsor.logo.onLight}`)).toBe(true);
});
it.each(READMES)("fill the sponsors table in %s, followed by invitations", (readme) => {
const openCells = Math.max(0, README_SPONSOR_CELLS - SPONSORS.length);
expect(readmeSponsorCells(readme)).toEqual([
...SPONSORS.map((sponsor) => ({
href: sponsorHref(sponsor, "readme"),
onDark: `packages/website/public${sponsor.logo.onDark}`,
onLight: `packages/website/public${sponsor.logo.onLight}`,
description: sponsor.description,
})),
...Array.from({ length: openCells }, () => ({ invite: SPONSOR_PAGE_URL })),
]);
});
});
+42 -14
View File
@@ -1,31 +1,59 @@
/**
* Homepage sponsor spots. This file is the inventory: the site shows one open
* placeholder for every spot not listed in `HOMEPAGE_SPONSORS`.
* Company sponsors. This file is the inventory: every page of the site shows
* these logos above the footer, and the open spots invite the next sponsor.
*
* Approving a sponsor means three edits, or the site promises something it does
* not deliver:
*
* 1. Add the entry below and drop its logo in `public/sponsors/`.
* 2. Add the logo under the `## Sponsors` marker in `README.md`,
* `README.zh-CN.md`, `README.ja.md` and `README.ko.md`, in this same order.
* 1. Add the entry below and drop both logo inks in `public/sponsors/`.
* 2. In the sponsors table after the intro of `README.md`, `README.zh-CN.md`,
* `README.ja.md` and `README.ko.md`, replace a "become a sponsor" cell with
* the logo and its description, in this same order, linked to `sponsorHref(sponsor, "readme")`
* with both inks referenced from `packages/website/public`, so the README
* renders from the repository and never waits on a site deploy.
* `sponsors.test.ts` fails until they match.
* 3. Remove all of it when the subscription ends.
*
* The Stripe payment link caps itself at `HOMEPAGE_SPOT_COUNT` completed
* The Stripe payment link caps itself at `SPONSOR_SPOT_COUNT` completed
* checkouts, and a checkout you decline and refund still counts against that
* cap. When you refund one, raise the link's completed-session limit by one, or
* the page will offer a spot the link refuses to sell.
*/
export interface HomepageSponsor {
export interface Sponsor {
name: string;
href: string;
/** Path under `public/`, e.g. `/sponsors/acme.svg`. Keep logos monochrome white. */
logo: string;
/** The sponsor's own URL, without tracking. Links go through `sponsorHref`. */
url: string;
/** Paths under `public/`, one per ground. Use the sponsor's official lockup. */
logo: { onDark: string; onLight: string };
/** What the product is, in a few words from the sponsor's own site. Shown under the logo. */
description: string;
}
export const HOMEPAGE_SPONSORS: ReadonlyArray<HomepageSponsor> = [];
export const SPONSORS: ReadonlyArray<Sponsor> = [
{
name: "Hoplite",
url: "https://hoplite.sh",
logo: {
onDark: "/sponsors/hoplite-on-dark.svg",
onLight: "/sponsors/hoplite-on-light.svg",
},
description: "Cloud coding agents",
},
];
export const HOMEPAGE_SPOT_COUNT = 4;
export const HOMEPAGE_SPOT_PRICE = "$500";
/** Where a sponsor link is shown. Becomes the link's `utm_medium`. */
export type SponsorPlacement = "website" | "readme" | "discord" | "x";
export function sponsorHref(sponsor: Sponsor, placement: SponsorPlacement): string {
const url = new URL(sponsor.url);
url.searchParams.set("utm_source", "paseo");
url.searchParams.set("utm_medium", placement);
url.searchParams.set("utm_campaign", "sponsor");
return url.toString();
}
export const SPONSOR_SPOT_COUNT = 4;
export const SPONSOR_SPOT_PRICE = "$500";
/** Stripe Payment Link for the monthly spot subscription. */
export const SPONSOR_SPOT_CHECKOUT_URL = "https://buy.stripe.com/8x24gBczR7LNaokcve2sM00";
@@ -38,5 +66,5 @@ export const OPEN_COLLECTIVE_URL =
export const BUY_ME_A_COFFEE_URL = "https://buymeacoffee.com/paseo";
export function openSpotCount(): number {
return Math.max(0, HOMEPAGE_SPOT_COUNT - HOMEPAGE_SPONSORS.length);
return Math.max(0, SPONSOR_SPOT_COUNT - SPONSORS.length);
}
+2
View File
@@ -4,6 +4,7 @@ import { useCallback, useMemo, useState } from "react";
import { DocsBreadcrumbs } from "~/components/docs-breadcrumbs";
import { DocsNav } from "~/components/docs-nav";
import { DocsOutline } from "~/components/docs-outline";
import { SponsorsSection } from "~/components/sponsorship";
import { buildDocsNavTree, getDoc, getDocs } from "~/docs";
import "~/styles.css";
@@ -63,6 +64,7 @@ function DocsLayout() {
<div className="max-w-prose mx-auto">
{doc && <DocsBreadcrumbs doc={doc} tree={tree} />}
<Outlet />
<SponsorsSection placement="footer" />
</div>
</main>
-17
View File
@@ -561,23 +561,6 @@
margin-bottom: 2rem;
}
.docs-source-footer {
border-top: 1px solid var(--color-border);
margin-top: 3rem;
padding-top: 1.25rem;
font-size: 0.875rem;
}
.docs-source-footer a {
color: rgba(255, 255, 255, 0.5);
font-weight: 500;
text-decoration: none;
}
.docs-source-footer a:hover {
color: var(--color-foreground);
}
/* Blog post prose styles — adapted from moboudra.com */
.blog-prose {
color: rgba(250, 250, 250, 0.82);