Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
567f6ad
feat: wire all site pages to read content from Hyperindex (plresearch…
daviddao Mar 26, 2026
8809bbc
feat: add floating Edit button on all pages (admin-only), auto-select…
daviddao Mar 26, 2026
19724bc
fix: set NEXT_PUBLIC_ADMIN_DID on Vercel, move edit button to top-right
daviddao Mar 26, 2026
5e7a05c
fix: support multiple admin DIDs — add daviddao.org as admin
daviddao Mar 27, 2026
5389f75
fix: use ADMIN_DIDS array in API routes (pages PUT + curated-list)
daviddao Mar 27, 2026
fe8072a
feat: remove curated accounts — delete curated-list API, feed API, At…
daviddao Mar 27, 2026
1e8dabc
ux: redesign page content editor — collapsible sections, unsaved indi…
daviddao Mar 27, 2026
beec5c4
feat: inline /edit routes — /about/edit, /edit (landing), /areas/[slu…
daviddao Mar 27, 2026
be0361b
feat: adopt standard.site lexicons for blog publishing
daviddao Mar 28, 2026
120b7d4
fix: inline editor — fix click focus, prevent link navigation, always…
daviddao Mar 28, 2026
0ccbef9
fix: fetchPage query — filter by pageId instead of rkey (rkey not a v…
daviddao Mar 28, 2026
9b306f3
fix: about edit page reads from correct data fields (body not subtitl…
daviddao Mar 28, 2026
0432f83
fix: focus area edit pages — add full page structure (breadcrumb, lea…
daviddao Mar 28, 2026
c48236a
feat: add dedicated E&G edit page with all 12 sections (hero, body, 5…
daviddao Mar 28, 2026
03bb964
fix: write page records to plresearch.org repo via app password, not …
daviddao Mar 28, 2026
3b45b47
fix: bust ISR cache after save — revalidateTag('indexer') on PUT, tag…
daviddao Mar 28, 2026
3270bd6
fix: edit pages handle missing indexer data + configurable indexer URL
daviddao Apr 7, 2026
43827a9
feat: add satyam2.climateai.org as admin DID
daviddao Apr 7, 2026
837e8b9
feat: point indexer to plresearch-indexer on Railway
daviddao Apr 7, 2026
a913c99
fix: adapt indexer queries for lex-gql schema (uri instead of rkey)
daviddao Apr 7, 2026
28a0c5e
feat: add momack.bsky.social as admin
daviddao Apr 7, 2026
811f9fe
feat: add co-funders section to impact dashboard — Altérra (warm lead)
daviddao Apr 15, 2026
b3e6c4d
feat(ai-robotics opspaces): indexer-backed data + inline editor
Apr 20, 2026
87a6a0f
feat(opspaces): generalize indexer-backed editor to all 4 focus areas
Apr 20, 2026
65b659e
ui(opspaces editor): make remove buttons always visible
Apr 20, 2026
10dd6ff
feat(opspaces editor): editable hero image URL with live preview
Apr 20, 2026
b7b24ee
feat(opspaces): per-page edit history via org.plresearch.editEvent
Apr 20, 2026
eee2c9d
fix(audit): exclude indexer-synthesized fields (uri/rkey/did/cid) fro…
Apr 20, 2026
48fb939
feat(edit-history): render byline on every CMS-editable page, not jus…
Apr 20, 2026
d02541f
fix(edit-history byline): render right below breadcrumb, not after <E…
Apr 20, 2026
12d402f
npm updates
ericronne Apr 24, 2026
333e9c6
debugs font code
ericronne Apr 24, 2026
196550e
further font debugging
ericronne Apr 24, 2026
1e77344
swaps in Aileron for Inter
ericronne Apr 24, 2026
d924423
Changes headers to Regular font weight
ericronne Apr 24, 2026
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
10 changes: 10 additions & 0 deletions .beads/interactions.jsonl
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,13 @@
{"id":"int-e921c04d","kind":"field_change","created_at":"2026-03-26T03:18:05.041487Z","actor":"plresearch.org","issue_id":"plresearch-c24.3","extra":{"field":"assignee","new_value":"plresearch.org","old_value":""}}
{"id":"int-9a3e4c1b","kind":"field_change","created_at":"2026-03-26T03:20:27.899943Z","actor":"plresearch.org","issue_id":"plresearch-c24.3","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"d44cb58 Add PageEditor component and wire into admin page"}}
{"id":"int-d4e87574","kind":"field_change","created_at":"2026-03-26T04:16:32.191509Z","actor":"plresearch.org","issue_id":"plresearch-wz0.1","extra":{"field":"assignee","new_value":"plresearch.org","old_value":""}}
{"id":"int-34feff8e","kind":"field_change","created_at":"2026-03-26T04:16:42.563464Z","actor":"plresearch.org","issue_id":"plresearch-wz0.1","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"26edf19 feat: add Hyperindex client library"}}
{"id":"int-2e994c9a","kind":"field_change","created_at":"2026-03-26T04:21:51.18019Z","actor":"plresearch.org","issue_id":"plresearch-wz0.2","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"567f6ad landing + about wired"}}
{"id":"int-52d931c4","kind":"field_change","created_at":"2026-03-26T04:21:51.557355Z","actor":"plresearch.org","issue_id":"plresearch-wz0.3","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"567f6ad areas + EG + collaborate wired"}}
{"id":"int-4ad7ed64","kind":"field_change","created_at":"2026-03-26T04:21:51.936682Z","actor":"plresearch.org","issue_id":"plresearch-wz0.4","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"567f6ad [slug] page + API routes wired"}}
{"id":"int-6087ec73","kind":"field_change","created_at":"2026-03-27T15:17:49.038993Z","actor":"plresearch.org","issue_id":"plresearch-auc.1","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"beec5c4 InlineEdit infrastructure"}}
{"id":"int-dc040bc7","kind":"field_change","created_at":"2026-03-27T15:17:49.406993Z","actor":"plresearch.org","issue_id":"plresearch-auc.2","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"beec5c4 about/edit + EditPageButton routes"}}
{"id":"int-d5d24573","kind":"field_change","created_at":"2026-03-27T15:17:49.785997Z","actor":"plresearch.org","issue_id":"plresearch-auc.3","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"beec5c4 /edit + /areas/[slug]/edit"}}
{"id":"int-4b62ca59","kind":"field_change","created_at":"2026-03-28T02:47:58.79708Z","actor":"plresearch.org","issue_id":"plresearch-zk9.1","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"be0361b lexicons + create-publication script"}}
{"id":"int-4572652d","kind":"field_change","created_at":"2026-03-28T02:47:59.171246Z","actor":"plresearch.org","issue_id":"plresearch-zk9.2","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"be0361b .well-known + api/posts"}}
{"id":"int-483dae92","kind":"field_change","created_at":"2026-03-28T02:47:59.542856Z","actor":"plresearch.org","issue_id":"plresearch-zk9.3","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"be0361b fetchAtproPosts + blog page"}}
2 changes: 1 addition & 1 deletion .beads/last-touched
Original file line number Diff line number Diff line change
@@ -1 +1 @@
plresearch-wz0.1
plresearch-zk9.3
17 changes: 17 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Session encryption secret (must be at least 32 characters)
COOKIE_SECRET=your-32-character-secret-here-change-me

# Public URL for production (leave empty for localhost development)
PUBLIC_URL=

# ES256 Private Key in JWK format for confidential client authentication
# Required in production. Generate with scripts/generate-jwk.js
# In development, falls back to public client mode if not set
ATPROTO_JWK_PRIVATE=

# Admin DID — the ATProto identity that can manage the curated list
# NEXT_PUBLIC_ prefix makes it available in both server and client code
NEXT_PUBLIC_ADMIN_DID=did:plc:pgwr6hkosgznfl5nz7egajei

ATPROTO_HANDLE=plresearch.org
ATPROTO_PASSWORD=wqy0FVZ8nfq@gyz9gzj
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ ATPROTO_JWK_PRIVATE=
# Admin DID — the ATProto identity that can manage the curated list
# NEXT_PUBLIC_ prefix makes it available in both server and client code
NEXT_PUBLIC_ADMIN_DID=did:plc:pgwr6hkosgznfl5nz7egajei

# GraphQL indexer URL for org.plresearch.* records
# Default: https://api.hi.gainforest.app/graphql
# INDEXER_URL=http://localhost:4000/graphql
115 changes: 69 additions & 46 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"envalid": "^8.1.1",
"fuse.js": "^7.0.0",
"iron-session": "^8.0.4",
"next": "15.5.9",
"next": "^15.5.15",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-force-graph-2d": "^1.29.1"
Expand Down
Binary file added public/fonts/Aileron-Bold.woff2
Binary file not shown.
Binary file added public/fonts/Aileron-BoldItalic.woff2
Binary file not shown.
Binary file added public/fonts/Aileron-Italic.woff2
Binary file not shown.
Binary file added public/fonts/Aileron-Light.woff2
Binary file not shown.
Binary file added public/fonts/Aileron-LightItalic.woff2
Binary file not shown.
Binary file added public/fonts/Aileron-Regular.woff2
Binary file not shown.
Binary file added public/fonts/Aileron-SemiBold.woff2
Binary file not shown.
Binary file added public/fonts/Aileron-SemiBoldItalic.woff2
Binary file not shown.
36 changes: 36 additions & 0 deletions scripts/create-publication.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env node
// Run: node scripts/create-publication.mjs

import { AtpAgent } from "@atproto/api"
import { TID } from "@atproto/common-web"

const agent = new AtpAgent({ service: "https://bsky.social" })

await agent.login({
identifier: process.env.ATPROTO_HANDLE || "plresearch.org",
password: process.env.ATPROTO_PASSWORD,
})

const rkey = TID.nextStr()

const record = {
$type: "site.standard.publication",
url: "https://www.plresearch.org",
name: "PL R&D",
description: "Protocol Labs R&D — driving research breakthroughs to push humanity forward.",
}

const result = await agent.com.atproto.repo.createRecord({
repo: agent.session.did,
collection: "site.standard.publication",
rkey,
validate: false,
record,
})

console.log("Created publication record:")
console.log("URI:", result.data.uri)
console.log("CID:", result.data.cid)
console.log()
console.log("Add this to your .env:")
console.log(`NEXT_PUBLIC_PUBLICATION_URI=${result.data.uri}`)
14 changes: 14 additions & 0 deletions src/app/.well-known/site.standard.publication/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { NextResponse } from "next/server"

export const dynamic = "force-dynamic"

export async function GET() {
const uri = process.env.NEXT_PUBLIC_PUBLICATION_URI
if (!uri) {
return new NextResponse("Publication record not configured", { status: 404 })
}
// standard.site expects plain text AT-URI
return new NextResponse(uri, {
headers: { "Content-Type": "text/plain" },
})
}
Loading