add changelog template for dynamic OG images#1776
Conversation
✅ Deploy Preview for hyprnote ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
9bf3214 to
68b4ce8
Compare
📝 WalkthroughWalkthroughAdds changelog variant support to OG image generation with schema validation. Introduces conditional rendering between template and changelog types, dynamic font loading, and development-mode guards to prevent OG generation in dev environments (localhost, 127.0.0.1, or CONTEXT=dev). Updates edge function config with conditional excludedPath. Changes
Sequence DiagramsequenceDiagram
participant Client
participant EdgeFunc as Edge Function
participant Validator as Schema Validator
participant Renderer as Renderer
participant Response
Client->>EdgeFunc: GET /og?type=changelog&version=v1.0
Note over EdgeFunc: Dev mode guard<br/>(localhost check)
alt In Development
EdgeFunc->>Response: 404 (dev guard)
else In Production
EdgeFunc->>Validator: Parse & validate params
alt Valid changelog params
Validator->>EdgeFunc: ✓ version, isNightly
EdgeFunc->>Renderer: renderChangelogTemplate(params)<br/>+ fonts
Renderer->>Response: OG Image Response
else Valid template params
Validator->>EdgeFunc: ✓ template data
EdgeFunc->>Renderer: renderTemplate(params)
Renderer->>Response: OG Image Response
else Invalid params
Validator->>Response: Error Response
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20–30 minutes
Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (4)
apps/web/netlify/edge-functions/og.tsx (4)
14-21: OG schema + parsing look solid; a couple of tiny schema nitsThe discriminated union and
parseSearchParamsbranching behave correctly and fail fast on invalid combinations. Two minor cleanups you could consider:
isNightlyis always constructed as a boolean (=== "true"), soz.boolean().optional().default(false)never actually applies the default. You could simplify toz.boolean()or let Zod handle the default by omitting the explicit boolean in the input.- If
versionis expected to be non‑empty / follow a version pattern, tighteningversion: z.string()to something likez.string().min(1)(or a regex) would give earlier, clearer validation failures.These are non‑blocking and more about tightening intent than functionality.
Also applies to: 28-40
105-215: Changelog template layout is clear; check the screenshot height vs canvasThe overall JSX and styling for the changelog OG look good and match typical 1200×630 dimensions. One layout detail to double‑check:
- Root container height is
630px, but the image section is positioned attop: 157pxwithheight: 707px. That means the bottom ~234px of the screenshot will always be clipped by the canvas. If you intended the full screenshot to be visible, consider aligning these heights (e.g., reducing the image section height) or adjusting the top offset.Optionally, you could also add an
altattribute on the<img>for better tooling support, even though this is only used for OG rendering.
220-225: Dev guards andDeno.envusage are reasonable; ensure they match your build/runtime setupThe hostname/
CONTEXT === "dev"guard plusconfig.excludedPathis a nice belt‑and‑suspenders approach to avoiding OG generation in dev.One thing to keep in mind:
Deno.env.get("CONTEXT")is used both at runtime and at module initialization inconfig. If this file is ever type‑checked or imported in a non‑Deno/Netlify context (e.g., Node‑based tooling that doesn’t provideDenotypes/globals), the newDenoreferences can cause type or runtime issues unless the file is excluded from that toolchain orDenois declared in types.If your TS/build config already treats this as Deno‑only code, you’re fine; otherwise, you may want to explicitly exclude it or gate env access.
Also applies to: 285-285
243-271: Handler branching and font loading work, but you may want to cache fontsThe type‑based branching between
renderChangelogTemplateandrenderTemplateis straightforward and keeps JSX concerns isolated. The per‑request font loading for the changelog variant will work, but it has some overhead:
- Each changelog request refetches both font files and converts them to
ArrayBuffers, even though the font assets are static.- Since
ImageResponseaccepts a staticfontsarray, you could move the font fetching to module scope (or cache promises in module‑level variables) and reuse the loaded fonts across requests to cut latency and external calls.For example, a cached approach could be:
// at module scope const loraFontPromise = fetch("...Lora.ttf").then(r => r.arrayBuffer()); const ibmPlexMonoFontPromise = fetch("...IBM.ttf").then(r => r.arrayBuffer()); // in handler, when params.type === "changelog" const [loraFont, ibmPlexMonoFont] = await Promise.all([ loraFontPromise, ibmPlexMonoFontPromise, ]); const fonts = [ { name: "Lora", data: loraFont, weight: 700, style: "normal" }, { name: "IBM Plex Mono", data: ibmPlexMonoFont, weight: 400, style: "normal" }, ];Not required, but it will make repeated OG generation cheaper.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/web/netlify/edge-functions/og.tsx(4 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Redirect rules - hyprnote
- GitHub Check: Header rules - hyprnote
- GitHub Check: Pages changed - hyprnote
- GitHub Check: fmt
No description provided.