fix: remove OG-only server loads to stop profile/recipe 500s#454
Conversation
The CF Pages worker build OOMs, leaving a stale/dead worker in production. __data.json requests that escape the service worker fall through to that worker and 500 on server loads whose only job was to build Open Graph meta tags. Remove the OG-only +page.server.ts from user/[slug], recipe/[slug], r/[naddr], reads/[naddr], premium/recipe/[slug], market/kitchen/[npub] and [nip19], so these load-less page nodes no longer request server __data.json. OG/title/description/image are now derived client-side in <svelte:head> from data already fetched over NDK. The [nip19] route keeps its NIP-05 username -> /user/<npub> redirect, reimplemented client-side via /.well-known/nostr.json. Also raise the build Node heap (NODE_OPTIONS=--max-old-space-size=6144) so the cloudflare worker bundle stops OOMing during CI. Verified against `wrangler pages dev` (workerd): the affected routes issue no __data.json, the /api/counts/* endpoints return real counts, and the [nip19] redirect/render/404 paths behave with no loops or 500s. Co-authored-by: Cursor <[email protected]>
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ❌ Deployment failed View logs |
zapcooking-frontend | 1268389 | Jun 19 2026, 12:21 PM |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ❌ Deployment failed View logs |
frontend | 1268389 | Jun 19 2026, 12:23 PM |
Deploying frontend with
|
| Latest commit: |
1268389
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://a22704bb.frontend-hvd.pages.dev |
| Branch Preview URL: | https://fix-profile-500-remove-og-se.frontend-hvd.pages.dev |
There was a problem hiding this comment.
Pull request overview
This PR aims to prevent production 500s caused by SvelteKit __data.json requests hitting a stale/dead Cloudflare Pages worker by removing OG-only server load functions on several routes and shifting OG meta generation into client-derived <svelte:head> data. It also increases the Node heap size for builds to avoid OOM during the worker bundle build step.
Changes:
- Removed multiple route-level
+page.server.tsfiles that were only used for OG metadata/redirect behavior, reducing server__data.jsonfetches. - Reworked several pages to derive OG/title/description/image from client-fetched NDK data and set tags via
<svelte:head>. - Updated build scripts to run Vite with a larger Node old-space heap (
--max-old-space-size=6144).
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/routes/user/[slug]/+page.svelte | Removes dependency on server-provided ogMeta; uses client-derived defaults/NDK profile data for head meta. |
| src/routes/user/[slug]/+page.server.ts | Deleted OG-only server load (and relay WebSocket OG fetch logic). |
| src/routes/recipe/[slug]/+page.svelte | Removes server ogMeta usage and computes head meta from client-fetched recipe event. |
| src/routes/recipe/[slug]/+page.server.ts | Deleted OG/redirect server load (tracking-param redirects + relay OG fetch). |
| src/routes/reads/[naddr]/+page.svelte | Removes server ogMeta usage and computes article head meta from client-fetched event. |
| src/routes/reads/[naddr]/+page.server.ts | Deleted OG/redirect server load (tracking-param redirects + relay OG fetch). |
| src/routes/r/[naddr]/+page.svelte | Removes server ogMeta usage and computes recipe head meta from client-fetched event. |
| src/routes/r/[naddr]/+page.server.ts | Deleted OG/redirect server load (tracking-param redirects + relay OG fetch). |
| src/routes/premium/recipe/[slug]/+page.server.ts | Deleted premium recipe OG/redirect server load. |
| src/routes/market/kitchen/[npub]/+page.svelte | Replaces server ogMeta with kitchen-derived client values in <svelte:head>. |
| src/routes/market/kitchen/[npub]/+page.server.ts | Deleted kitchen OG server load (relay WebSocket OG fetch logic). |
| src/routes/[nip19]/+page.svelte | Removes server ogMeta usage, adds client-side OG meta derivation + username resolution via /.well-known/nostr.json. |
| src/routes/[nip19]/+page.server.ts | Deleted OG/redirect server load (tracking-param redirects + relay OG fetch). |
| package.json | Increases Node heap for build scripts to reduce OOM risk on worker bundle build. |
Comments suppressed due to low confidence (3)
src/routes/recipe/[slug]/+page.svelte:21
- The deleted +page.server.ts used to 301-redirect away common tracking params (utm_*, fbclid, etc.). With it removed, these URLs will now persist and be shared/bookmarked, which can lead to duplicate-canonical URLs and cache fragmentation. Consider stripping them client-side for parity (using
goto(..., { replaceState: true })).
<script lang="ts">
import { browser } from '$app/environment';
import { page } from '$app/stores';
import { ndk } from '$lib/nostr';
import type { NDKEvent } from '@nostr-dev-kit/ndk';
import { nip19 } from 'nostr-tools';
import { goto } from '$app/navigation';
import Recipe from '../../../components/Recipe/Recipe.svelte';
import PanLoader from '../../../components/PanLoader.svelte';
import { GATED_RECIPE_KIND } from '$lib/consts';
let event: NDKEvent | null = null;
let naddr: string = '';
let loading = true;
let error: string | null = null;
$: {
if (browser && $page.params.slug) {
loadData();
}
}
src/routes/r/[naddr]/+page.svelte:21
- The removed +page.server.ts used to strip tracking params via a 301 redirect. Without a replacement,
/r/<naddr>?utm_…will now remain as-is, increasing duplicate URLs and reducing cache hit rates. Consider stripping tracking params on the client for parity and canonicalization.
<script lang="ts">
import { browser } from '$app/environment';
import { page } from '$app/stores';
import { ndk } from '$lib/nostr';
import type { NDKEvent } from '@nostr-dev-kit/ndk';
import { nip19 } from 'nostr-tools';
import Recipe from '../../../components/Recipe/Recipe.svelte';
import PanLoader from '../../../components/PanLoader.svelte';
import { GATED_RECIPE_KIND, RECIPE_TAGS } from '$lib/consts';
import ArrowLeftIcon from 'phosphor-svelte/lib/ArrowLeft';
let event: NDKEvent | null = null;
let naddr: string = '';
let loading = true;
let error: string | null = null;
$: {
if (browser && $page.params.naddr) {
loadData();
}
}
src/routes/reads/[naddr]/+page.svelte:22
- The deleted +page.server.ts stripped common tracking params via redirect. Without a client-side equivalent,
/reads/<naddr>?utm_…will persist and can cause duplicate-canonical URLs and cache fragmentation. Consider stripping them client-side before loading the article.
<script lang="ts">
import { browser } from '$app/environment';
import { page } from '$app/stores';
import { ndk } from '$lib/nostr';
import type { NDKEvent } from '@nostr-dev-kit/ndk';
import { nip19 } from 'nostr-tools';
import Recipe from '../../../components/Recipe/Recipe.svelte';
import PanLoader from '../../../components/PanLoader.svelte';
import { RECIPE_TAGS } from '$lib/consts';
import { validateMarkdownTemplate } from '$lib/parser';
import ArrowLeftIcon from 'phosphor-svelte/lib/ArrowLeft';
let event: NDKEvent | null = null;
let naddr: string = '';
let loading = true;
let error: string | null = null;
$: {
if (browser && $page.params.naddr) {
loadData();
}
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
|
|
||
| // Resolve the author's display name for the OG title once the note loads. | ||
| $: if (event?.author) { |
| import NoteActionBar from '../../components/NoteActionBar.svelte'; | ||
| import ClientAttribution from '../../components/ClientAttribution.svelte'; | ||
| import type { NDKEvent } from '@nostr-dev-kit/ndk'; | ||
| import type { PageData } from './$types'; | ||
| import { createCommentFilter } from '$lib/commentFilters'; | ||
| import PostActionsMenu from '../../components/PostActionsMenu.svelte'; |
| // Plain zap.cooking NIP-05 username (not a NIP-19 identifier): resolve to | ||
| // a pubkey via /.well-known/nostr.json and redirect to the profile page. | ||
| // This mirrors the behavior the deleted +page.server.ts used to provide. | ||
| const isNip19 = /^(?:npub1|nprofile1|note1|nevent1|naddr1)/.test(nip19Id); | ||
| if (!isNip19 && /^[a-zA-Z0-9_]{3,20}$/.test(nip19Id)) { | ||
| const username = nip19Id.toLowerCase(); | ||
| try { | ||
| const res = await fetch('/.well-known/nostr.json?name=' + encodeURIComponent(username)); | ||
| if (res.ok) { |
The deleted OG-only +page.server.ts loads used to 301-redirect away tracking params (utm_*, fbclid, gclid, ref, source, ...) for URL canonicalization. Restore that behavior client-side via a shared stripTrackingParams() helper that removes them and replaceState()s to the clean URL, on the five routes that previously did this: recipe/[slug], r/[naddr], reads/[naddr], premium/recipe/[slug], and [nip19]. Addresses Copilot review feedback on PR #454. Co-authored-by: Cursor <[email protected]>
Summary
Production CF Pages is serving a stale/dead worker because the worker build OOMs.
__data.jsonrequests that escape the service worker fall through to the dead worker and 500 — crashing on server loads whose only purpose was building Open Graph meta tags.This PR fixes it at the source:
+page.server.tsfromuser/[slug],recipe/[slug],r/[naddr],reads/[naddr],premium/recipe/[slug],market/kitchen/[npub], and[nip19]. These page nodes are now load-less, so SvelteKit no longer requests server__data.jsonfor them — which removes the SW-race 500 class entirely.<svelte:head>, derived client-side from data already fetched over NDK.[nip19]NIP-05 username redirect preserved: the bare-username →/user/<npub>redirect (previously done by the server load) is reimplemented client-side via/.well-known/nostr.json.NODE_OPTIONS=--max-old-space-size=6144) so the Cloudflare worker bundle stops OOMing during the build. (/api/*routes are still served by the worker, so adapter-static is not an option — the OOM had to be fixed.)Net: −2,044 / +136 lines, 7 server loads deleted.
Verification (local
wrangler pages dev/ workerd, same runtime as prod)__data.jsonrequest./api/counts/[eventId]and/api/counts/batchreturn real, non-zero counts (outboundnew WebSocketworks in the pinned workerd; calls aretry/catch-guarded so worst case is silent-degrade, never 500).[nip19]headless-browser checks:/seth→ client-redirects to/user/<npub>✓note1/nevent1→ render the note view ✓npub1/naddr1→ "Note not found" (parity with prior behavior)Test plan
/<username>still redirects to the profile.Notes / follow-ups (out of scope)
npub1/naddr1at the[nip19]catch-all show "Note not found" rather than redirecting; optional future enhancement to redirect them to/userand/rrespectively.Made with Cursor