feat(website): native ?renderJson support in the Fresh handler - #1613
feat(website): native ?renderJson support in the Fresh handler#1613marcoferreiradev wants to merge 4 commits into
Conversation
fresh.ts gains a structured-JSON exit alongside the existing ?asJson one:
?renderJson (legacy alias ?appJson — remove once consumers switch) resolves
the page with hooks that short-circuit sections opted out of JSON rendering
(their loaders never run), serializes the tree via @deco/deco
serializeResolvedSection honoring each section's `renderJson` export, and
responds { name, path, sections } with lazy sections as
{ component, lazyUrl } placeholders. One-shot JSON responses never use
async render (firstByteThreshold guards extended); renderJson takes
precedence when both params are sent; legacy ?asJson is untouched.
The website app gains `renderJson.sectionsToIgnore` (admin-configurable):
app-owned sections excluded by resolveType suffix — site-owned sections
should prefer `export const renderJson = false` in their own file.
Replaces the site-level wrapper pattern (handler + pages-loader fork) that
oficina-reserva ran as v1 — the default website/loaders/pages.ts now works
unchanged for renderJson consumers.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
renderJson is the replacement, not a sibling — consumers adopt ?renderJson directly (validation happens on PR previews, nothing in production speaks ?appJson). Only the legacy ?asJson remains as a separate, untouched mode. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThe Fresh handler gains a ChangesrenderJson one-shot JSON mode
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Tagging OptionsShould a new tag be published when this PR is merged?
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@website/handlers/fresh.ts`:
- Around line 183-187: The sectionsToIgnore array can contain empty or blank
strings, which causes the endsWith check in the isDroppedSection function to
match all section names (since every string ends with an empty string),
inadvertently dropping entire pages. Modify the line where sectionsToIgnore is
assigned to filter and trim the array, removing any blank suffixes before the
array is used in the isDroppedSection condition. This ensures only valid
non-empty suffixes are checked when determining if a section should be dropped.
- Around line 293-299: The handler function in fresh.ts casts appContext as any
and accesses fields like revision, release, vary, and deco.ctx.deploymentId that
are not declared in the appContext parameter's Pick type. Update the Pick type
in the appContext parameter definition to explicitly include these fields:
revision, release, vary, and deco, in addition to the currently declared fields
(monitoring, response, caching, firstByteThresholdMS, isBot, flavor,
renderJson). After updating the Pick type to include all accessed fields, remove
the as any cast so the type system properly enforces that these dependencies are
available.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 630726b5-5660-4c29-9008-34a93faeab66
📒 Files selected for processing (2)
website/handlers/fresh.tswebsite/mod.ts
There was a problem hiding this comment.
1 issue found across 2 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
A blank entry in renderJson.sectionsToIgnore made resolveType.endsWith("")
match every section, so ?renderJson could drop an entire page. Trim each
configured suffix and discard empties before the isDroppedSection check.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
sectionsToIgnore comes from admin config (external JSON) and is not
type-guaranteed at runtime. The previous `.map(s => s.trim())` would throw
a TypeError (500) on a non-string entry — the old `endsWith` tolerated it
via coercion. Filter to strings before trimming, and keep only non-empty
suffixes (a blank entry would make endsWith("") drop the whole page).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
What is this Contribution About?
Native
?renderJsonsupport in the website Fresh handler — the consumer side of the section-controlled JSON rendering introduced in deco-cx/deco#1209.website/handlers/fresh.ts: a native?renderJsonbranch (sibling of?asJson, withrenderJsontaking precedence, guarded by!isJsonOneShot). Serves the JSON projection produced by each section'srenderJsonexport via the runtime'sserializeResolvedSection/computeRenderCb.website/mod.ts: arenderJson.sectionsToIgnoreadmin prop so a site can override which sections are dropped from the JSON payload, instead of a hardcoded denylist.?appJsonalias —?renderJsonis its replacement. The standalone?asJsonmode is left untouched.Issue Link
Companion to the runtime feature — depends on it:
renderJsonexport,serializeResolvedSection,computeRenderCb,ResolvedSection,sectionModuleLookup,SerializeContext.Status / dependency
Important
Draft — blocked on deco-cx/deco#1209. This PR imports
computeRenderCb,serializeResolvedSection,ResolvedSection,sectionModuleLookupandSerializeContextfrom@deco/deco. Until #1209 is merged and published to JSR,deno task checkfails with 5×TS2305: has no exported member ...for those symbols.deno fmt --checkanddeno lintare clean.Test plan
deno fmt --checkcleandeno check— blocked on Avoid loops on slack mcp #1209 (5× TS2305 for the not-yet-published runtime exports)?asJsonand HTML byte-identical to baseline,?renderJsonmatches the runtime serialization, lazy fetch applies the per-section projection.Loom Video / Demonstration
Validated on the oficina-reserva storefront preview (pinned to the fork build). Loom/demo available on request.
🤖 Generated with Claude Code
Summary by cubic
Add native
?renderJsonto the website Fresh handler to return a structured JSON view of pages, honoring each section’srenderJsonexport. AddsrenderJson.sectionsToIgnorein app props and removes the?appJsonalias;?asJsonstays as-is.New Features
website/handlers/fresh.ts: new?renderJsonpath serializes sections viaserializeResolvedSectionandcomputeRenderCbfrom@deco/deco, returning{ name, path, sections }.export const renderJson = false; app-owned sections can be ignored viarenderJson.sectionsToIgnore(matched by resolveType suffix).?renderJsontakes precedence over?asJson; JSON responses bypass async render (first-byte threshold).Bug Fixes
renderJson.sectionsToIgnorehandling: filter to strings, trim, and drop empties to prevent TypeErrors and accidental full-page drops.Written for commit 75cdee2. Summary will update on new commits.
Summary by CodeRabbit