Skip to content

fix: Substack essays working in CI + iframe fallback + improved essay cards - #3

Merged
Korede-TA merged 7 commits into
mainfrom
claude/fix-substack-preview-O2Cap
May 14, 2026
Merged

fix: Substack essays working in CI + iframe fallback + improved essay cards#3
Korede-TA merged 7 commits into
mainfrom
claude/fix-substack-preview-O2Cap

Conversation

@Korede-TA

Copy link
Copy Markdown
Contributor

Problem

Substack essays were never fetching in CI because the code gated the entire API call behind if (substackHandle && substackApiKey). The Substack /api/v1/posts endpoint is a public API that doesn't require authentication — the API key was never actually needed for the fetch to work. Since SUBSTACK_API_KEY wasn't in GitHub Secrets (or was invalid), CI always skipped the fetch and rendered an empty list.

Changes

Bug fix — always fetch from public API (pages/index.tsx)

Removed the substackApiKey requirement from the fetch gate. The API key is still passed through as an optional header if present, but the fetch now happens unconditionally when a handle is available.

- if (substackHandle && substackApiKey) {
+ if (substackHandle) {
    substackEssays = await getSubstackEssays(substackHandle, 10, substackApiKey);
- } else {
-   log("ERROR", "Missing Substack handle or API key")
  }

Fallback — Substack iframe embed

When the combined essay list (local posts + Substack) is empty (e.g. fetch blocked by network policy), the page now renders the official Substack embed widget instead of a blank section.

Improved essay cards

  • Cover image: Substack posts with a cover_image now show a 72×56px thumbnail
  • Source badge: Substack essays display a subtle SUBSTACK pill badge inline with the title
  • Flex layout: image + text content sit side by side for a cleaner scan

netlify.toml

Added so Netlify deploy previews trigger automatically on PRs. The build command matches the existing GitHub Actions setup (npm run build && npm run export, publish dir out).

Test plan

  • Netlify deploy preview shows essays from Substack (API path working)
  • If API fetch is blocked/empty, iframe embed renders in place of the essay list
  • Cover images appear on Substack posts that have a cover_image
  • SUBSTACK badge appears on all Substack-sourced essays
  • Local Notion posts still render correctly alongside Substack essays

https://claude.ai/code/session_01P9Bn6gkWtM15yEzGf79XCQ


Generated by Claude Code

… + improved essay cards

- Remove API key gate: public Substack /api/v1/posts works without auth,
  so skip the substackApiKey check that was blocking all CI fetches
- Pass substackHandle through to component for use in fallback
- Iframe embed fallback: when API returns no essays (e.g. blocked fetch),
  render the Substack embed widget instead of an empty list
- Essay cards: cover image thumbnail, inline Substack source badge,
  flex layout so image+text sit side by side
- Add netlify.toml so Netlify deploy previews trigger on PRs

https://claude.ai/code/session_01P9Bn6gkWtM15yEzGf79XCQ
@netlify

netlify Bot commented May 4, 2026

Copy link
Copy Markdown

Deploy Preview for soft-swan-5d0ce7 failed. Why did it fail? →

Name Link
🔨 Latest commit c44f108
🔍 Latest deploy log https://app.netlify.com/projects/soft-swan-5d0ce7/deploys/6a052365cdbd2500087af60b

@netlify

netlify Bot commented May 4, 2026

Copy link
Copy Markdown

Deploy Preview for darling-dusk-441006 failed. Why did it fail? →

Name Link
🔨 Latest commit c44f108
🔍 Latest deploy log https://app.netlify.com/projects/darling-dusk-441006/deploys/6a052365cb69140009ddfdf9

Korede-TA and others added 6 commits May 4, 2026 22:20
Seems to be breaking the deploys
Iframe now renders as a supplement below local posts when substackEssays
is empty, rather than replacing the whole list. Local posts always show.

https://claude.ai/code/session_01P9Bn6gkWtM15yEzGf79XCQ
- deploy.yml: replace actions/deploy-pages (GitHub Actions source) with
  peaceiris/actions-gh-pages so production lands on the gh-pages branch.
  Required for PR preview subdirs to coexist with the production root.
- pr-preview.yml: new workflow using rossjrw/pr-preview-action. Builds
  the site with NEXT_PUBLIC_BASE_PATH=/pr-preview/pr-{N} so Next.js
  basePath/assetPrefix resolve correctly inside the subdir. Posts the
  preview URL as a PR comment automatically; cleans up on PR close.

NOTE: requires one settings change in the GitHub repo →
Settings > Pages > Source → "Deploy from a branch" → gh-pages / root

https://claude.ai/code/session_01P9Bn6gkWtM15yEzGf79XCQ
…LIC_BASE_PATH are unset

Both getEnv() calls lacked a default value, causing an immediate throw at
module load time during next build — before getStaticProps even runs.

- resolve-arena-channels.ts: ARENA_PERSONAL_ACCESS_TOKEN defaults to ""
  so the module loads; empty token skips auth (API call fails gracefully
  inside the existing try/catch that returns [])
- _document.tsx: NEXT_PUBLIC_BASE_PATH defaults to ""; base href tag is
  only rendered when the value is actually set, avoiding a pointless
  <base href=""> as well as the throw

https://claude.ai/code/session_01P9Bn6gkWtM15yEzGf79XCQ
tsconfig.json reformatted by Next.js (no semantic change); package.json
has a few ^ ranges resolved to exact versions by npm during install.

https://claude.ai/code/session_01P9Bn6gkWtM15yEzGf79XCQ
Reverts the peaceiris/actions-gh-pages change back to the original
actions/upload-pages-artifact + actions/deploy-pages two-job setup.
PR preview via rossjrw/pr-preview-action requires this to change but
will be revisited separately.

https://claude.ai/code/session_01P9Bn6gkWtM15yEzGf79XCQ
@Korede-TA
Korede-TA merged commit 1fbe5db into main May 14, 2026
0 of 9 checks passed
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