Skip to content

Font debug + Aileron testing#1

Open
ericronne wants to merge 35 commits into
daviddao:mainfrom
ericronne:lumen-design-exploration
Open

Font debug + Aileron testing#1
ericronne wants to merge 35 commits into
daviddao:mainfrom
ericronne:lumen-design-exploration

Conversation

@ericronne

Copy link
Copy Markdown

No description provided.

daviddao and others added 30 commits March 26, 2026 05:21
….org DID only)

- Created src/lib/indexer.ts — typed GraphQL client for hi.gainforest.app
- Landing page, about page, areas listing, collaborate page all fetch from indexer
- E&G pages (main, subareas, impact) fetch from indexer
- Focus area [slug] page fetches from indexer
- API routes (GET /api/pages) switched to indexer reads
- PUT /api/pages still writes to PDS via OAuth
- All pages fall back to hardcoded content on fetch failure
- ISR revalidation every 60 seconds
ADMIN_DIDS replaces ADMIN_DID for isAdmin check, supports comma-separated
list via NEXT_PUBLIC_ADMIN_DIDS env var. daviddao.org DID added to Vercel.
…cator, auto-grow textarea, write/preview per field, human labels
…g]/edit

- InlineEdit.tsx: usePageEdit hook, EditableField (auto-grow textarea that
  looks like surrounding text), EditBar (sticky bottom save/discard),
  useRequireAdmin (auth guard hook)
- EditPageButton now links directly to /page-url/edit routes
- about/edit: fully rendered about page with all ATProto text fields editable
- /edit: landing page with hero, approach section, area cards all editable
- /areas/[slug]/edit: focus area pages editable
- lexicons.ts: add STANDARD_DOCUMENT_COLLECTION, STANDARD_PUBLICATION_COLLECTION,
  PLRESEARCH_CONTENT_TYPE, StandardDocumentRecord, StandardPublicationRecord types
- api/posts: creates site.standard.document records instead of org.plresearch.post
- .well-known/site.standard.publication: returns AT-URI of publication record
- indexer.ts: fetchAtproPosts() fetches site.standard.document from Hyperindex
- blog/page.tsx: shows ATProto-authored posts alongside markdown posts
- scripts/create-publication.mjs: one-off script to create publication record
- Created publication record: at://did:plc:pgwr6hkosgznfl5nz7egajei/site.standard.publication/3mi3mlkepmk2q
… show save bar, add isLoading guard

- EditableField: add stopPropagation on click/mouseDown so clicks don't
  bubble to parent Links; add cursor-text; make ring always slightly
  visible (ring-blue/10) so editable fields are visually discoverable
- Landing /edit: replace Link wrappers with div on area cards so editing
  text doesn't navigate away
- About /edit: add isLoading check so fields don't render empty
- EditBar: always visible in edit mode with 'click any text to edit'
  hint; discard button only shows when dirty
…ds, advisors, body content, publications, talks sections)
… explore cards, 5 engage items, grants, funding pipeline)
…logged-in user's repo

The PUT handler now authenticates as plresearch.org using ATPROTO_HANDLE/PASSWORD
env vars to write records to the correct repo. Previously it wrote to session.did
(e.g. daviddao.org) which meant edits were invisible since the site reads from
plresearch.org's repo.
… all indexer fetches

After saving page edits, the Next.js ISR cache was still serving stale
Hyperindex data for up to 60 seconds. Now the PUT handler calls
revalidateTag('indexer') after a successful write, which invalidates
all cached indexer queries immediately.
- usePageEdit: create skeleton record on 404/error so edit page renders
- usePageEdit: set() creates new sections when sectionId doesn't exist
- indexer URL configurable via INDEXER_URL or NEXT_PUBLIC_INDEXER_URL env var
- Fixes: Focus Area edit pages showing empty content
URL: https://plresearch-indexer-production.up.railway.app/graphql
This replaces the GainForest hyperindexer which didn't support org.plresearch.* collections.
lex-gql uses 'uri' as the system field, not 'rkey'. Extract rkey from URI
for backward compatibility with existing code.
- Switch list + detail pages to fetch org.plresearch.opportunitySpace records
  from the indexer at build/revalidate time, with the static JSON in
  src/data/fa2/ai-opportunityspaces.json as a build-time fallback.
- Add <EditPageButton> on the detail page, pointing at a new inline editor at
  /areas/ai-robotics/opportunity-spaces/<slug>/edit (admin-gated via
  useRequireAdmin).
- Add PUT/GET /api/opportunity-spaces/[rkey] mirroring /api/pages/[rkey] —
  writes to plresearch.org's repo via app password, invalidates the indexer
  cache tag on success.
- Extend <EditPageButton> with an optional href prop so non-page collections
  can override the rkey-based EDIT_ROUTES map.
- Add OpportunitySpaceRecord type and opportunitySpaceRkey() helper in
  src/lib/lexicons.ts (rkeys on the PDS use short per-area prefixes:
  ai--, dhr--, eg--, neuro--).

Only wired for AI & Robotics for now — the other three areas still use the
static JSON path.
- Extract OpportunitySpaceEditor into a shared client component
  (src/components/OpportunitySpaceEditor.tsx). Adds full array editing
  for subfields, tippingSignals, keyAssumptions, observations, and
  fieldSignals (kpi + measurement) on top of the prose fields.
- Refactor the AI & Robotics edit route to use the shared component
  (goes from 224 lines to 10).
- Add /edit routes for the other three areas
  (digital-human-rights, neurotech, economies-governance), each a
  thin wrapper around <OpportunitySpaceEditor>.
- Wire list + detail pages for the three remaining areas to fetch from
  the indexer with the static JSON fallback, and render the EditPageButton
  on detail pages.
- All 15 opportunity-space detail URLs now get an admin-visible Edit
  button that routes to the per-area inline editor.
The per-item 'remove' control in StringArrayEditor and the field-signal
card had opacity-0 + group-hover:opacity-100, which hid it entirely
from keyboard-only and programmatic interactions (e.g. agent-browser
clicks don't trigger a hover transition). Change to always-visible
with a faint gray-300 default that darkens on hover.
Adds a new 'Hero image' section to the shared OpportunitySpaceEditor.
The existing `image: string` field on the org.plresearch.opportunitySpace
record round-trips through the PUT endpoint untouched today; this just
surfaces it as an EditableField plus a 240x128 preview thumbnail that
fades to 25% opacity when the URL fails to load, so editors get fast
feedback on broken URLs without killing the whole UI.

No backend or schema change — the record still stores an arbitrary HTTPS
URL, so external CDN images and future PDS-blob URLs both work with the
same field.
New ATProto record type written to the *editor's* own PDS on every
admin edit of a content record (opportunity space or page). Writing to
the editor's own repo (not plresearch.org's) cryptographically ties
each audit entry to the DID that performed the edit — plresearch.org's
app-password agent can no longer forge attribution.

Pipeline:
1. Lexicon org.plresearch.editEvent added in the indexer repo.
2. PUT /api/{opportunity-spaces,pages}/[rkey] diffs the prior record
   against the next, computes changedFields, then createRecord's an
   editEvent on the editor's PDS via the existing OAuth agent. Audit
   failure is swallowed (logged) so it can't break the primary edit.
3. fetchEditEvents(targetUri) + GET /api/edit-history?target=<uri>
   surface the full log, sorted newest first.

UI:
- <EditHistoryByline targetUri={uri}> on every opspace detail page and
  inside the shared OpportunitySpaceEditor: single-line byline under
  the breadcrumb ("Last edited by @handle · 5 min ago · View history (N)").
- Click → right-side drawer with the full timeline, each row showing
  editor avatar + handle, relative time (absolute on hover), and the
  list of fields that changed. Editor handles link to bsky.app profiles.
- Drawer closes on Esc or backdrop click; body scroll locked while open.

Profiles are hydrated client-side from the public Bluesky API so avatars
and display names render without a server round-trip for each row.
…m diff

Those fields only exist on the prior-record snapshot returned by the
indexer, never on the outgoing record we PUT. Without this exclusion the
diff always reports 'uri' and 'rkey' as changed, which is noise.
…t opspaces

r5 only wired <EditHistoryByline> onto the 4 opportunity-space detail
pages. Extend to every surface that has an <EditPageButton>:

- / (landing, rkey=landing)
- /about (about)
- /areas (areas)
- /areas/[slug] (area-<slug>, covers the three generic areas)
- /areas/economies-governance (area-economies-governance)
- /areas/economies-governance/subareas (area-eg-subareas)
- /areas/economies-governance/impact (area-eg-impact)
- /outreach/collaboration (collaborate)

Adds two small convenience exports to EditHistoryByline:
  - <PageEditHistoryByline rkey> for org.plresearch.page records
  - <OpportunitySpaceEditHistoryByline rkey> for opspace records
so callers pass the rkey and the helper builds the AT-URI.

Surfaces the edit attribution daviddao.org's test edit (Apr 20 21:55Z
on area-economies-governance, 'sections' changed) already generated
on their PDS but which had no UI to render against.
…ditPageButton>

<EditPageButton> is position:fixed and almost always placed near the end
of its parent JSX. Making the byline <div> its sibling put the byline
at the bottom of the page (top ~2500px in the compiled layout) —
cosmetically invisible.

Move the byline to sit directly under <Breadcrumb> in each file.
Keeps the opspace detail pages unchanged (they already had
EditPageButton right after Breadcrumb by coincidence of structure).
Drop the byline entirely from the homepage: it has no breadcrumb and
no natural anchor, and a 'Last edited by' chip above a full-bleed
hero looks out of place.
Newsreader variable was wrong
Tailwind can't handle variables in the way they were written
Experimenting with Aileron as the body font, to strengthen the brand connection to PL
Sizing suffices to make the headers work well. Bolder weights in Newsreader look overly heavy.
@vercel

vercel Bot commented Apr 27, 2026

Copy link
Copy Markdown

@ericronne is attempting to deploy a commit to the gainforest Team on Vercel.

A member of the Team first needs to authorize it.

@daviddao

Copy link
Copy Markdown
Owner

Thank you so much! :) Will look into it and merge

@daviddao

Copy link
Copy Markdown
Owner

Hi @ericronne — flagging this PR for a rebase + scope-cut before it can land. Full integration audit at https://pi-eval.vercel.app/reports/plresearch-org/open-prs-integration-audit/, but the short version:

The branch was opened on April 27 and main has moved a lot since. The PR doesn't conflict in the git sense (a 3-way merge succeeds), but the resulting tree would silently ship three regressions:

1. Renames Tailwind v4 theme tokens → breaks font-serif site-wide

In src/app/globals.css the @theme block is rewritten from --font-body / --font-serif to --font-family-body / --font-family-serif. Tailwind v4 generates utilities from the --font-<name> namespace, not --font-family-<name>, so font-serif stops resolving silently at six call sites currently on main:

src/app/edit/page.tsx                   line 54
src/app/page.tsx                        line 114   (landing hero "Driving R&D…")
src/components/FundingPipeline.tsx      lines 101, 103, 158, 224

All of them would fall back to the body font without anyone noticing in code review.

2. Deletes the hex-mosaic hover animation CSS

The PR's globals.css is missing the ~75-line block (.hex-cloud-svg, .hex-cloud-card:hover .hex-cloud-svg, .hex-cloud-hex) that landed on main after this PR was opened — it drives the pulse-on-hover animation on the four landing-page focus-area cards. Diff:

< .hex-cloud-svg { filter: saturate(0.55); ... }   ← deleted by PR #1
< .hex-cloud-card:hover .hex-cloud-svg { ... }      ← deleted by PR #1
< .hex-cloud-hex { ... }                            ← deleted by PR #1

The hex clouds would still render (SVGs are inline in page.tsx) but go dead — no hover saturate, no per-hex pulse.

3. Reverts unrelated work that landed on main since April

The diff also touches files that other merged PRs have since changed — looks clean to git but is a real regression to a human reader:

  • public/images/authors/adam-marblestone/avatar.png reverts from 370 KB → 48 KB (undoes the avatar refresh from 7fbc307)
  • Deletes public/images/banners/about-banner.webp
  • Deletes four public/images/fa2/mosaics/*.svg (ai-robotics, dhr, eg, neurotech)
  • Re-introduces next.config.ts lines that were already reconciled on main

Suggested fix path

Close + reopen with a focused, rebased PR that:

  1. only adds the public/fonts/Aileron-*.woff2 files and the localFont(...) block in layout.tsx,
  2. sets --font-body: var(--font-aileron), sans-serif in the existing @theme block (keeps the --font-<name> naming),
  3. doesn't touch --font-serif (Newsreader stays as the heading/serif font),
  4. is rebased on a fresh main and squashed (the 5-commit npm updatesdebugs font codefurther font debuggingswaps in Aileron for InterChanges headers to Regular font weight history can collapse to one commit).

That brings the change from 13 files down to ~15 lines + 8 font files.

Closing + reopening to bump this so it stays on your radar — happy to pair on the rebase if useful. PRs #4 and #6 integrated cleanly alongside each other on integration/open-prs-audit with one small conflict resolution and are good to merge.

@nalacateria

Copy link
Copy Markdown
Collaborator

Preview screenshot captured from the PR branch (local preview, 1280×577):

PR #1 preview: homepage font / Aileron test

@ericronne

Copy link
Copy Markdown
Author

Hi @ericronne — flagging this PR for a rebase + scope-cut before it can land. Full integration audit at https://pi-eval.vercel.app/reports/plresearch-org/open-prs-integration-audit/, but the short version:

The branch was opened on April 27 and main has moved a lot since. The PR doesn't conflict in the git sense (a 3-way merge succeeds), but the resulting tree would silently ship three regressions:

1. Renames Tailwind v4 theme tokens → breaks font-serif site-wide

In src/app/globals.css the @theme block is rewritten from --font-body / --font-serif to --font-family-body / --font-family-serif. Tailwind v4 generates utilities from the --font-<name> namespace, not --font-family-<name>, so font-serif stops resolving silently at six call sites currently on main:

src/app/edit/page.tsx                   line 54
src/app/page.tsx                        line 114   (landing hero "Driving R&D…")
src/components/FundingPipeline.tsx      lines 101, 103, 158, 224

All of them would fall back to the body font without anyone noticing in code review.

2. Deletes the hex-mosaic hover animation CSS

The PR's globals.css is missing the ~75-line block (.hex-cloud-svg, .hex-cloud-card:hover .hex-cloud-svg, .hex-cloud-hex) that landed on main after this PR was opened — it drives the pulse-on-hover animation on the four landing-page focus-area cards. Diff:

< .hex-cloud-svg { filter: saturate(0.55); ... }   ← deleted by PR #1
< .hex-cloud-card:hover .hex-cloud-svg { ... }      ← deleted by PR #1
< .hex-cloud-hex { ... }                            ← deleted by PR #1

The hex clouds would still render (SVGs are inline in page.tsx) but go dead — no hover saturate, no per-hex pulse.

3. Reverts unrelated work that landed on main since April

The diff also touches files that other merged PRs have since changed — looks clean to git but is a real regression to a human reader:

  • public/images/authors/adam-marblestone/avatar.png reverts from 370 KB → 48 KB (undoes the avatar refresh from 7fbc307)
  • Deletes public/images/banners/about-banner.webp
  • Deletes four public/images/fa2/mosaics/*.svg (ai-robotics, dhr, eg, neurotech)
  • Re-introduces next.config.ts lines that were already reconciled on main

Suggested fix path

Close + reopen with a focused, rebased PR that:

  1. only adds the public/fonts/Aileron-*.woff2 files and the localFont(...) block in layout.tsx,
  2. sets --font-body: var(--font-aileron), sans-serif in the existing @theme block (keeps the --font-<name> naming),
  3. doesn't touch --font-serif (Newsreader stays as the heading/serif font),
  4. is rebased on a fresh main and squashed (the 5-commit npm updatesdebugs font codefurther font debuggingswaps in Aileron for InterChanges headers to Regular font weight history can collapse to one commit).

That brings the change from 13 files down to ~15 lines + 8 font files.

Closing + reopening to bump this so it stays on your radar — happy to pair on the rebase if useful. PRs #4 and #6 integrated cleanly alongside each other on integration/open-prs-audit with one small conflict resolution and are good to merge.

@daviddao do you need me for anything in order to remedy the font issue? Thanks

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.

3 participants