Skip to content

Redesign livepeer.org - #93

Open
adamsoffer wants to merge 83 commits into
mainfrom
claude/livepeer-redesign-plan-110a98
Open

Redesign livepeer.org#93
adamsoffer wants to merge 83 commits into
mainfrom
claude/livepeer-redesign-plan-110a98

Conversation

@adamsoffer

@adamsoffer adamsoffer commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

🚧 Work in progress — not ready to merge. Opened as a draft for review of direction and shape. See Before this can ship for the blocking items.

Rebuilds the marketing site against Peace Node's Livepeer UI registry. The registry theme is now the only token layer.

Pages

Nine linked pages, all built from the mockup set except where noted:

Page Route Notes
Home /
Agent /agent flagship product surface
Ecosystem /ecosystem /[slug], /submit — markdown-driven catalog
Provide GPU compute /compute one page for running + earning
Token /token
Foundation /foundation
Latest /blog nav says "Latest", URL stays /blog
Brand /brand no mockup — designed from design.md + registry Foundations
Roadmap /roadmap no mockup — built from the requirements doc

/primer stays intact and unlinked with its own scoped legacy slice — the one page deliberately left unmigrated.

Content is split on its shape and how often it changes. Page copy is authored in-repo as typed objects matching the registry's content contracts (lib/site.ts) — versioned and reviewed alongside the design it belongs to. Blog and ecosystem are markdown in content/.

Templated content that gets updated frequently moves to Notion, and the roadmap register is the first of it. It is maintained by people across several organisations who do not open pull requests, and a commitment whose state is a week stale is worse than no page at all. The blog is planned next; scope is those two for now, not a general move of the site into a CMS. So this PR is the pattern as much as the page. lib/notion.ts reads it over plain fetch with ISR at a minute; content/roadmap/*.md is the fallback when no workspace token is present, so a clone still builds. Every record carries an owner, a target and a checkable link, and anything missing one fails the build rather than rendering a card that claims less than it should.

Cleanup

globals.css 1209 → 585 lines. Removed the second --color-* token layer, the Holographik grid, hero classes, .blog-prose, 19 keyframes and 37 custom properties. Chart/sidebar/radius tokens are kept — unused today, but they're the registry's theme contract.

Deleted ~73 files: components/home/*, components/legacy/*, components/ecosystem/* (superseded by components/livepeer-ui/*), the PascalCase components/ui/* visuals, lib/constants.ts, and the five app/use-cases/* routes — redirects in next.config.ts already served those URLs, so the pages were unreachable.

Share images

Rebuilt on the registry's own og item. / renders the brand card verbatim — the lockup centred on #000000. Every other page renders the same canvas with a page title, from one shared lib/og.tsx. Two bugs fixed along the way:

  • Only the root had a twitter-image, and metadata files cascade — so /foundation and /blog served their own og:image but the root's Twitter card. Every segment now has a re-export beside its opengraph-image.
  • Ecosystem project pages had no share image at all: their generateMetadata declares an openGraph object without images, which drops the inherited card. All 12 projects now get their own titled card.

Incidental fixes

  • app/not-found.tsx styled its link text-green — green as an affordance colour, which the design system explicitly rules out. Rebuilt on the registry type scale.
  • sitemap.ts advertised the five dead /use-cases URLs and never listed /agent or /compute. Rewritten, with ecosystem projects added.
  • Instrument Serif was downloaded on every page load with zero consumers. Removed.
  • package-lock.json deleted. Six deps had been added via npm in a pnpm-pinned repo, leaving pnpm-lock.yaml stale — pnpm install --frozen-lockfile was failing, which would have broken the Vercel build. Lockfile regenerated and verified.

Verification

pnpm typecheck, pnpm lint (0 warnings) and pnpm build (130 static pages) all clean, against both the Notion register and the markdown fallback. Pages verified in light and dark at 390px, sm, md and wide desktop.

Before this can ship

  • agentAppOrigin is the console's Vercel preview (lib/site.ts) — livepeer-console.vercel.app, not its final address. It feeds the most prominent CTA on every page, so it still needs one edit before launch. The Agent playbooks link is the one product link left on livepeer.peaceno.de: the console has no playbooks page, and a mockup beats a 404.
  • Blog art hotlinks Peace Node's Sanity CDN — confirm permanence or vendor the assets.
  • Placeholder people in the register. Names, portraits and rosters are stand-ins except Doug Petkanics. Replacing them is a Notion edit, not a deploy.
  • Commitment links mostly cite venue roots — 11 of 19 point at forum.livepeer.org/ or similar rather than a permalink.
  • The Notion webhook is not subscribed yet — needs an integration admin and the production domain. Until then the one-minute window is what carries edits to the site, which is sufficient but serves one stale reload.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Aug 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
website Ready Ready Preview Sep 11, 2026 9:50pm UTC

Request Review

@adamsoffer adamsoffer changed the title WIP: Redesign livepeer.org on the Livepeer UI design system WIP: Redesign livepeer.org Aug 8, 2026
adamsoffer and others added 2 commits September 10, 2026 09:22
The register cut by the body answerable for each commitment: every
owner as a heading linking to its page, its commitments beneath with
what needs attention first — off track, at risk, silent, on track, then
committed work with no health yet by target — and the bodies ordered by
the worst thing under them, so the page opens on whoever has something
to answer for. In the URL as ?group=owner, so it is a link you can send.
Roadmap only; Shipped keeps its months.

The control sits at the far end of the view tabs from lg up and inside
the Filters panel below that, where a second line in the tab row would
have slid the sticky bands under it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Shipped by owner is a track record per body, most recent first. The
"Nothing is committed past …" line answers when, so it shows under the
quarter cut and not the owner cut, which is answering who.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It’s a large, cross-cutting redesign (routing, metadata/sharing, content sources, and new endpoints), so it needs careful human validation beyond the specific issues flagged.

Review details

Suppressed comments (2)

app/ecosystem/submit/page.tsx:51

  • fs.readFileSync runs during render, so this page will re-read content/ecosystem-template.md every time it’s requested (or every time the server component is evaluated). Since the template is static, cache the computed GitHub “new file” URL at module scope (or behind a simple in-module memo) to avoid repeated synchronous I/O.
    app/people/[slug]/opengraph-image.tsx:22
  • This people share-card is rendered with ogArt.organizations, which means people pages will share the Organizations background art (and any future changes intended for org pages will also affect people). If this is accidental (copy/paste from the org route), consider adding a dedicated ogArt.people entry in lib/og.tsx (or selecting an existing non-org art constant) and using it here.
  • Files reviewed: 127/338 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The change set is a full-site redesign with many new routes/components and content model changes, so it warrants final human validation despite only a couple of concrete issues found in the reviewed hunks.

Review details

Suppressed comments (1)

app/people/[slug]/opengraph-image.tsx:22

  • This person card uses ogArt.organizations, which will make every /people/ share image look like an organization page. There isn’t a dedicated people art token in lib/og.tsx; using the roadmap art is a closer match for people being a roadmap-adjacent surface.
  • Files reviewed: 127/338 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

The four words of the scale with their counts, always all four — Off
track 0 is news — read as a filter the way Linear filters projects by
health. It doubles as the tally the accountability board kept in its
footer, and puts the silent ones one click away. Roadmap only, in the
URL as ?health=, dropped on the way to Shipped like the state flag.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The change set is a broad redesign touching routing, UI primitives, and dynamic data/metadata surfaces, and it includes at least one correctness issue that should be fixed and then re-verified end-to-end.

Review details

Suppressed comments (1)

app/ecosystem/[slug]/opengraph-image.tsx:17

  • This OG image implementation renders the same generic renderArtCard(ogArt.ecosystem) for every project. That contradicts the PR description (“All 12 projects now get their own titled card”) and makes different ecosystem project links indistinguishable in timelines.

Use renderTitledCard(...) and the project’s name (from the slug) so each project gets a unique share image.

  • Files reviewed: 127/338 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

adamsoffer and others added 2 commits September 10, 2026 09:49
A route and a tick for the two views, a calendar and a building for
the two cuts, the way Linear marks its filters.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The change set is a broad site redesign spanning routing, content sourcing, build/runtime behavior, and security-sensitive endpoints, which warrants focused human validation beyond automated review.

Review details

Suppressed comments (2)

app/api/revalidate/route.ts:2

  • The token check should use a constant-time comparison; timingSafeEqual (node:crypto) is a straightforward way to do that, but it needs to be imported.
    app/api/revalidate/route.ts:47
  • Bearer token validation uses a plain string comparison (offered !== secret), which can leak information via timing differences. Compare in constant time (and check equal length) before allowing revalidation.
  • Files reviewed: 127/338 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment on lines +138 to +145
<a
key={item.label}
href={item.href}
target="_blank"
rel="noreferrer"
onClick={close}
className={className}
>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are user-visible regressions/discrepancies in the ecosystem surface (share cards not titled per project and loss of URL-deep-linking for filters/search) that should be resolved before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

app/ecosystem/[slug]/opengraph-image.tsx:17

  • This OpenGraph image generator returns renderArtCard(ogArt.ecosystem), so every ecosystem project page gets the same lockup-only card with no project title. The PR description states each project should get its own titled card; as written, shared links won’t be distinguishable in a timeline.
  • Files reviewed: 127/338 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread app/ecosystem/page.tsx
Comment on lines +41 to 62
export default function EcosystemPage() {
const apps: EcosystemListingApp[] = getAllApps().map((app) => ({
slug: app.slug,
name: app.name,
url: app.url,
hostname: app.hostname,
displayUrl: app.displayUrl,
description: app.description,
categories: app.categories,
logo: app.logo,
logoBg: app.logoBg,
logoMonochrome: app.logoMonochrome,
}));
const categories = getEcosystemCategories();

return (
<EcosystemListingClient
<EcosystemListing
apps={apps}
categories={categories}
initialCategories={
catsParam ? catsParam.split(",").map(decodeURIComponent) : []
}
initialSearch={q ?? ""}
categories={getEcosystemCategories()}
heading={ecosystem.heading}
searchPlaceholder={ecosystem.searchPlaceholder}
emptyMessage={ecosystem.emptyMessage}
submitLabel={ecosystem.submitLabel}
submitHref={ecosystem.submitHref}
/>
adamsoffer and others added 2 commits September 10, 2026 10:02
A post on a commitment now has a kind: the monthly update while the
work is under way, or the one retrospective once it has shipped. Marked
in Notion with a Kind select rather than inferred from its date, because
a retro is often written the day something ships and an "it's out"
update lands after; a retrospective carries no health, since "on track"
means nothing about something finished.

- Shipped cards read "Retro done" or "No retro" after the state.
- A shipped record leads with its retrospective, or with the fact that
  none has been written, and the activity log runs in date order so the
  retro sits where it happened rather than under a pinned "shipped it".
- The changelog's shipped rows carry the retro's line where one existed
  by the month's end, and roundup.json lists the month's shipped work
  without a retro as noRetro beside the silent.
- Both readers accept the kind; the fallback gains a seed retro.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The tick disc and "Retrospective" where one exists, a hollow ring and
"No retrospective" in the foreground where not. Not a checkbox, which
on a card looks clickable; this is a fact.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The PR is a large WIP site redesign touching many routes, content sources, and metadata/share-image behaviors, so it needs targeted manual validation of key user flows and deploy/runtime behavior beyond automated review.

Review details

Suppressed comments (3)

app/ecosystem/[slug]/opengraph-image.tsx:17

  • This project share-image route renders an art-only card (renderArtCard), but the PR description says ecosystem project pages now get a titled card. As written, the OG image will not include the project name, so shared links are harder to distinguish in a feed.
    app/api/revalidate/route.ts:46
  • The bearer token check uses a direct string comparison (offered !== secret). For secret validation endpoints, a constant-time compare is safer to avoid leaking information via timing differences.
    app/changelog/roundup.json/route.ts:54
  • The JSON payload always advertises url: https://livepeer.org/changelog/<month>, but roundup.json defaults to the current month (r.current=true) and the changelog month pages intentionally do not publish the current month. For the default case, this URL will point at a 404.
  • Files reviewed: 127/339 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

adamsoffer and others added 3 commits September 10, 2026 10:11
In medium weight above the muted write-up, in the log and on the card,
so it reads as the lead rather than a paragraph that forgot its colour.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The row's header has already said who, what and when, and a second
title fought the write-up's bold lead-ins. The card keeps the title
treatment, having no header row to lean on.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Weight alone left it level with the write-up's bold lead-ins; at the
body's size it was a paragraph in a different colour. One step up, in
the log and on the card.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Several routes hard-disable dynamic params for Notion-backed records (risking permanent 404s for newly added rows) and there is at least one inconsistent shipped date that can misgroup changelog output.

Review details

Suppressed comments (3)

Previously missed (3) — in code that hasn't changed since the last review.

app/organizations/[slug]/page.tsx:25

  • dynamicParams = false prevents organization pages for new org rows added in Notion after the last build, even if the roadmap starts crediting/owning work under that org. Leaving dynamic params enabled keeps unknown slugs 404ing via notFound() while allowing new orgs to be served on first request.
    app/people/[slug]/page.tsx:19
  • With dynamicParams = false, any new person added in Notion after the last build will 404 permanently (until a rebuild), even if commitments start linking to them. Consider leaving dynamic params enabled and relying on notFound() for unknown slugs so the People table can grow without a deploy.
    app/roadmap/[slug]/page.tsx:32
  • dynamicParams = false means any new commitment added in Notion after the last build can appear on /roadmap but its detail page will still 404 because it wasn’t in generateStaticParams() at build time. Leaving dynamic params enabled allows new slugs to be served on first request while still 404ing unknown slugs via notFound().
  • Files reviewed: 127/339 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

adamsoffer and others added 2 commits September 10, 2026 10:18
The expanded body started on the header's line and the title's leading
was tight. More above the title, a looser line, a beat more below.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

There’s at least one confirmed functional issue (checkbox ::after never renders without content) plus a verified mismatch between the PR description and the ecosystem project OG card behavior (art-only vs titled card).

Review details

Suppressed comments (1)

app/ecosystem/[slug]/opengraph-image.tsx:17

  • The PR description says ecosystem project pages now get “their own titled card”, but this opengraph image currently renders the generic art-only card (no project title). Either update the description or render a titled card using the project’s name (similar to blog post cards).
  • Files reviewed: 127/339 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

This is a wide-ranging site redesign touching many routes/content systems, and there are unresolved review findings (security + UI class issue) that should be addressed alongside final human verification.

Review details

Suppressed comments (1)

app/api/revalidate/route.ts:46

  • The bearer token check uses a direct string comparison (offered !== secret), which is vulnerable to timing attacks. For a shared-secret auth check, use a constant-time comparison to avoid leaking information about the secret via response timing.
  • Files reviewed: 127/339 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

adamsoffer and others added 8 commits September 11, 2026 12:15
Tailwind's preflight resets a bare <button> to the arrow cursor, and the registry's Button sets the pointer, so the view tabs, the group-by radios, the two Clear filters buttons and the brand page's ink switch were the odd ones out. The header menu's two buttons are registry code and stay as they are.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The register can be drawn as a list: the same rows without their covers
and teasers, one line each with the title, where it stands, the owner and
the target in columns under a header row naming them, so the whole
register fits on a screen. Linear's projects view; the cards stay the
site's. ?display=list, a pair of glyphs after the group-by pair in the tab
row, with their words under a facet heading in the Filters panel below lg.
Below md the rows fold to a title over one muted line, each separator
travelling with the field after it so a wrapped line never ends on a dot.

A third grouping, by health: the four words of the scale as headings,
worst first, then Committed, only headings with something under them.
Roadmap view only; Shipped drops it on the way. Declined while cards were
the only display, where a heading over one card repeats its mark; earns
its place in the list.

The rail narrows to 12rem with a 3rem gutter at lg (13rem and 5rem from
xl) because the tab row with both pairs on it needs about 704px and the
register had 656.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The toggle comes off the tab row and out of the Filters panel, and the
rail goes back to 13rem with its 5rem gutter, which it only gave up to
make room for the toggle. The rows and their header stay in code behind
?display=list, so the list can be tried by link and brought back with one
control; the toggle is in 8192000. One way of reading the page for now.
The cut by health stays.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The register's Target was free text ("Q4 2026") with a formula beside it
checking the format: nothing to pick from, a typo failed the build, and a
real date could not be stated at all. It is now the pair Linear stores:
Target date, from Notion's picker, and Target precision (Day, Month,
Quarter, Half-year, Year; empty means Quarter).

lib/target.ts turns the pair into the window the date falls in: its label
("Q3 2026", "July 2026", "September 15, 2026"), the quarter it sits under
when the roadmap is cut by quarter, so a day or a month does not get a
heading of its own, and a sort by the window's start then its end. Both
readers use it; the markdown copy carries targetDate and targetPrecision.

In Notion, all fourteen rows now hold the last day of their old window at
its old precision, checked to read back exactly as the text did. A Target
window formula shows leads the site's label, checked at all five
precisions, and replaces Target check. The views show the new properties,
and Target and Target check are dropped. No other branch reads them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Everything on the register is a commitment, so a status called Committed
said nothing; it means one not started yet, which is Linear's Planned.
The card's state word, the record's Status row, the organization page's
section and the health cut's last heading all read Planned now.

The reader maps both Notion option names to the same state until the
option is renamed in Notion, so the two edits need not land together;
Committed comes out of STATE_BY_NOTION after that.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Status option is Planned in Notion, with every not-started row still
on it, so the reader no longer needs to accept Committed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A row's health or Shipped moves from beside the title to the line under
it, after the owner and the date: "Livepeer Foundation · Aug 27 · At
risk". There it reads as what was said that day rather than what the
item is now, which is what an entry is: the month as it ended. The
silent rows read "Owner · No update" in the same place. Each middot is
held to the field after it, so a wrapped line never ends on a dot.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Inside an expanded Activity row the post's one-liner is set at the log's
own size, since a size above outranked the row header it sits under, and
the write-up runs entirely in the muted voice, bold lead-ins included, so
the title is the only dark text and weight and colour carry the order.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved security, cache invalidation, routing, validation, and share-card issues remain.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (10)

app/agent/opengraph-image.tsx:8

  • This page still uses renderArtCard, so its share image contains no page headline. The PR's share-image contract says every non-root page gets a titled card; switch this route to renderTitledCard with the Agent page headline.
    app/blog/category/[slug]/page.tsx:43
  • Category pages define their own Open Graph/Twitter metadata, but this segment has no opengraph-image or twitter-image files. That overrides the blog card without supplying a replacement, so /blog/category/<slug> has no share image; add a category image route or preserve the parent image metadata.
    app/blog/opengraph-image.tsx:8
  • The Latest/Blog landing card is still rendered with renderArtCard, so it carries no page title despite the stated non-root share-card contract. Use the titled renderer with the page's current Latest headline.
    app/brand/opengraph-image.tsx:8
  • The Brand share image still calls renderArtCard, leaving the card without any page-identifying headline. The stated share-image behavior requires a titled non-root card; use renderTitledCard with the Brand page headline.
    app/compute/opengraph-image.tsx:8
  • The Compute page's share image is also an untitled renderArtCard, so it does not identify the page in a feed. Replace it with a titled card using the Compute headline as required for non-root pages.
    app/contribute/opengraph-image.tsx:8
  • The Contribute page still emits only the artwork and lockup, with no page title. That leaves this non-root page outside the PR's stated titled-card behavior; use renderTitledCard with the Contribute headline.
    app/ecosystem/[slug]/opengraph-image.tsx:16
  • Project detail share images also call renderArtCard without the project name, so all ecosystem project URLs produce the same indistinguishable card. Generate this image from the route slug with renderTitledCard (using the project's name) so the promised per-project share card is actually distinct.
    app/ecosystem/opengraph-image.tsx:8
  • The ecosystem index's share image still uses the untitled renderer, so its card contains only the lockup and artwork instead of identifying the Ecosystem page. The PR's share-image contract says non-root pages carry their page title; use the titled renderer here.
    app/foundation/opengraph-image.tsx:8
  • The Foundation share image remains an untitled art card. This contradicts the PR's requirement that every non-root page image include its page title; render the Foundation headline with renderTitledCard instead.
    app/token/opengraph-image.tsx:8
  • The Token share image remains an untitled art card and therefore does not identify the page in social previews. The non-root share-image contract calls for a titled card; render the Token headline with renderTitledCard.
  • Files reviewed: 127/340 changed files
  • Comments generated: 16
  • Review effort level: Lite

Comment on lines +34 to +38
console.log(
`[notion-webhook] verification_token=${token}\n` +
`[notion-webhook] Save this as NOTION_WEBHOOK_SECRET, then paste it ` +
`into Notion's Webhooks tab to confirm the subscription. Events are ` +
`rejected until it is set.`
Comment thread lib/ecosystem.ts
@@ -50,23 +63,27 @@ export function getAppBySlug(slug: string): EcosystemApp {
const { data, content } = matter(fileContents);
Comment thread lib/notion.ts
Comment on lines +317 to +320
function readLinks(prop: Json | undefined, where: string): CommitmentLink[] {
const links = richText(prop).flatMap((run) => {
const label = (run.plain_text ?? "").trim();
return run.href && label ? [{ label, href: run.href }] : [];
Comment on lines +22 to +23
/** Only the register reads Notion, so this is the only path worth clearing. */
const PATH = "/roadmap";
Comment on lines +24 to +25
/** Only the register reads Notion, so this is the only path worth clearing. */
const PATH = "/roadmap";
Comment thread lib/notion.ts
Comment on lines +659 to +667
// One body per row, in parallel: fourteen small requests that would
// otherwise run end to end.
const details = await Promise.all(
rows.map((row) =>
readDetail(
row.id as string,
`Roadmap commitments → ${text(props(row).Name)}`
)
)
Comment thread lib/notion.ts
Comment on lines +763 to +764
cover:
coverProp?.type === "external" ? coverProp.external?.url : undefined,
Comment thread lib/notion.ts
Comment on lines +841 to +842
cover:
coverProp?.type === "external" ? coverProp.external?.url : undefined,
Comment thread lib/roadmap.ts
Comment on lines +286 to +287
function readCover(value: unknown, file: string): string | undefined {
if (value === undefined || value === null || value === "") return undefined;
Comment on lines +23 to +39
const SELF_HOSTS = new Set(["livepeer.org", "www.livepeer.org"]);

const isSelf = (url) => {
try {
return SELF_HOSTS.has(new URL(url).hostname);
} catch {
return false;
}
};

const entries = readdirSync(ecosystemDir)
.filter((f) => f.endsWith(".md"))
.map((f) => matter(readFileSync(join(ecosystemDir, f), "utf-8")).data)
.filter((app) => app.url);

const skipped = entries.filter((app) => isSelf(app.url));
const apps = entries.filter((app) => !isSelf(app.url));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants