Add @fedify/nuxt package for Nuxt integration#674
Add @fedify/nuxt package for Nuxt integration#6742chanhaeng wants to merge 11 commits intofedify-dev:mainfrom
@fedify/nuxt package for Nuxt integration#674Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a new Changes
Sequence DiagramsequenceDiagram
participant Client
participant Nitro as Nitro/H3_Event_Handler
participant FedifyMiddleware as Fedify_Middleware
participant FedifyFetch as fetchWithFedify
participant Federation as Federation_Instance
participant Framework as Nuxt_Handler
participant Plugin as Deferred_Response_Plugin
Client->>Nitro: HTTP Request
Nitro->>FedifyMiddleware: Invoke handler (H3 event)
FedifyMiddleware->>FedifyMiddleware: toWebRequest / compute contextData
FedifyMiddleware->>FedifyFetch: fetchWithFedify(fetch, request, contextData)
FedifyFetch->>Federation: federation.fetch(request, { onNotFound, onNotAcceptable, ... })
alt federation handled (ActivityPub)
Federation-->>FedifyFetch: ActivityPub Response (e.g., 200, application/activity+json)
FedifyFetch-->>FedifyMiddleware: { kind: "handled", response }
FedifyMiddleware->>Nitro: return federation response
Nitro-->>Client: federation response
else not-found
Federation-->>FedifyFetch: NotFound sentinel (internal)
FedifyFetch-->>FedifyMiddleware: { kind: "not-found" }
FedifyMiddleware->>Nitro: return undefined (delegate)
Nitro->>Framework: continue to Nuxt handler
Framework-->>Nitro: framework response
Nitro-->>Client: framework response
else not-acceptable
Federation-->>FedifyFetch: NotAcceptable sentinel (internal)
FedifyFetch-->>FedifyMiddleware: { kind: "not-acceptable" }
FedifyMiddleware->>FedifyMiddleware: set deferred flag in event.context
FedifyMiddleware->>Nitro: return undefined (delegate)
Nitro->>Framework: continue to Nuxt handler
Framework-->>Nitro: framework response
Nitro->>Plugin: beforeResponse hook
Plugin->>Plugin: resolveDeferredNotAcceptable(deferred, frameworkStatus)
alt returns 406
Plugin->>Nitro: set status, headers, body -> 406 Not Acceptable
else undefined
Plugin->>Nitro: leave framework response intact
end
Nitro-->>Client: final response
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces the @fedify/nuxt package to integrate Fedify with the Nuxt framework, providing a module, Nitro middleware, and a plugin for deferred 406 Not Acceptable handling. It also updates documentation, agent skills, and workspace configurations. Feedback recommends improving TypeScript type safety by using specific types from @nuxt/kit and h3, and suggests extracting the "Not acceptable" response body into a shared constant to prevent duplication across the runtime logic and plugin.
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.agents/skills/create-example-app-with-integration/SKILL.md (1)
180-193:⚠️ Potential issue | 🟠 MajorClose the bash fence immediately after the curl example.
Line 180 opens a fence, but it is only closed at Line 193. That makes the “Lint, format, and final checks” section render as code.
Suggested fix
~~~~ bash curl -H "Accept: application/activity+json" http://localhost:0000/users/demo +~~~~ Lint, format, and final checks ------------------------------ @@ -~~~~🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.agents/skills/create-example-app-with-integration/SKILL.md around lines 180 - 193, The markdown code fence opened with "~~~~ bash" around the curl example is left open; close that fence immediately after the curl command so the following "Lint, format, and final checks" section is not rendered as code—i.e., move or add the matching closing fence "~~~~" directly after the line with `curl -H "Accept: application/activity+json" http://localhost:0000/users/demo` (refer to the fenced block starting with "~~~~ bash" in SKILL.md) and ensure subsequent text is plain markdown outside the fence.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.agents/skills/create-example-app-with-integration/SKILL.md:
- Line 178: Update the wording in SKILL.md where the sentence reads "If the
`test:examples` can not be run, just run the server and test with curl:" to use
the standard single-word form "cannot" (i.e., change "can not" to "cannot") so
the line becomes "If the `test:examples` cannot be run, just run the server and
test with curl:".
In `@docs/manual/integration.md`:
- Around line 397-418: The Nuxt docs use inconsistent path styling; update the
Nuxt section so all file and module paths are wrapped in asterisks instead of
underscores or backticks—replace occurrences like _server/federation.ts_,
_nuxt.config.ts_, and `~/server/federation` with *server/federation.ts*,
*nuxt.config.ts*, and *~/server/federation* respectively (in the block that
shows createFederation / MemoryKvStore and the module enablement) so path
styling matches the repo guideline.
In `@packages/nuxt/README.md`:
- Around line 71-72: Replace the inline code backticks around the default module
path with asterisks: change the instance that reads "`@fedify/nuxt` loads your
Federation instance from `~/server/federation`" so that the module and path use
asterisk wrapping (e.g., *@fedify/nuxt* and *~/server/federation*) to comply
with the repo Markdown rule; update the README line containing "@fedify/nuxt"
and "~/server/federation" accordingly.
In `@packages/nuxt/src/mod.test.ts`:
- Line 2: Replace the runtime-specific import of the test entrypoint by
importing the test function from the runtime-agnostic package: change the import
of test from "node:test" to "@fedify/fixture" (i.e., replace the existing import
statement that references node:test with one that imports test from
`@fedify/fixture`), ensuring any usages of the test identifier remain unchanged.
In `@packages/nuxt/src/runtime/server/logic.ts`:
- Around line 47-53: Add a JSDoc block above the exported function
resolveDeferredNotAcceptable that documents its purpose (handle deferred
requests that should return a 406 Not Acceptable when the framework routed to
404), describes parameters isDeferred:boolean and frameworkStatus:number,
explains the return type Response|undefined and the conditions when
createNotAcceptableResponse() is returned, and notes that this is part of the
deferred 406 handling pattern for public API consumers; keep the comment concise
and follow existing project JSDoc style.
- Around line 22-45: Add a JSDoc block to the exported function fetchWithFedify
describing its purpose, parameters (fetcher: (request: Request, options:
FederationFetchOptions<unknown>) => Promise<Response>, request: Request,
contextData: unknown) and return value (Promise<FetchResult>), and note the
behavior/assumption that a response equal to DUMMY_NOT_FOUND_RESPONSE maps to {
kind: "not-found" } and any Response with status 406 is treated as { kind:
"not-acceptable" } (which relies on user handlers not returning 406 for
unrelated reasons); reference DUMMY_NOT_FOUND_RESPONSE and
createNotAcceptableResponse in the doc so callers understand the special-case
mappings.
In `@packages/nuxt/src/runtime/server/middleware.ts`:
- Around line 20-23: Add a JSDoc block above the exported createFedifyMiddleware
function that documents its parameters and return value: describe the
"federation" parameter type/expected shape (unknown but clarify expected usage),
the optional "contextDataFactory" callback signature ((event: unknown, request:
Request) => unknown) and when it is invoked, the middleware behavior (what the
returned function does, side effects, and that it returns a
Connect/Node/Fetch-style middleware handler), and the return type expectations
(e.g., middleware function or handler). Use the function name
createFedifyMiddleware and mention the contextDataFactory callback to make the
doc discoverable.
---
Outside diff comments:
In @.agents/skills/create-example-app-with-integration/SKILL.md:
- Around line 180-193: The markdown code fence opened with "~~~~ bash" around
the curl example is left open; close that fence immediately after the curl
command so the following "Lint, format, and final checks" section is not
rendered as code—i.e., move or add the matching closing fence "~~~~" directly
after the line with `curl -H "Accept: application/activity+json"
http://localhost:0000/users/demo` (refer to the fenced block starting with "~~~~
bash" in SKILL.md) and ensure subsequent text is plain markdown outside the
fence.
🪄 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: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 833b06e0-e342-4d98-af3c-fa0f0c532116
⛔ Files ignored due to path filters (2)
deno.lockis excluded by!**/*.lockpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (24)
.agents/skills/add-to-fedify-init/SKILL.md.agents/skills/create-example-app-with-integration/SKILL.md.agents/skills/create-example-app-with-integration/example/README.md.agents/skills/create-example-app-with-integration/example/src/logging.ts.agents/skills/create-integration-package/SKILL.md.hongdown.tomlAGENTS.mdCHANGES.mdCONTRIBUTING.mdcspell.jsondeno.jsondocs/manual/integration.mdmise.tomlpackages/fedify/README.mdpackages/nuxt/README.mdpackages/nuxt/deno.jsonpackages/nuxt/package.jsonpackages/nuxt/src/mod.test.tspackages/nuxt/src/mod.tspackages/nuxt/src/runtime/server/logic.tspackages/nuxt/src/runtime/server/middleware.tspackages/nuxt/src/runtime/server/plugin.tspackages/nuxt/tsdown.config.tspnpm-workspace.yaml
Codecov Report✅ All modified and coverable lines are covered by tests.
... and 1 file with indirect coverage changes 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.agents/skills/add-to-fedify-init/SKILL.md:
- Around line 37-39: Replace the inline link and plain file paths in the
sentence that mentions WebFrameworkDescription, changing `./init/framework.ts`
and `packages/init/src/types.ts` to wrapped paths (*./init/framework.ts*,
*packages/init/src/types.ts*) and convert the inline link to a reference-style
link (e.g., [init/framework.ts][init-framework]) with the corresponding
reference entry placed at the end of the section; update the sentence to refer
to the reference label and ensure the symbol WebFrameworkDescription remains
mentioned so you can find the exact line to edit.
In `@packages/nuxt/deno.json`:
- Line 24: The "check" npm script currently only runs deno check on "src/*.ts"
which skips nested runtime files (e.g., src/runtime/server/); update the "check"
script (the "check" key value that currently contains "deno fmt --check && deno
lint && deno check src/*.ts") to use a recursive glob such as "src/**/*.ts" or
explicitly include the runtime folder (for example add
"src/runtime/server/**/*.ts") so that deno check covers all nested runtime
TypeScript files.
🪄 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: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 44c494fa-0e71-490b-ad31-ac3a6bde1a5c
⛔ Files ignored due to path filters (2)
deno.lockis excluded by!**/*.lockpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (25)
.agents/skills/add-to-fedify-init/SKILL.md.agents/skills/create-example-app-with-integration/SKILL.md.agents/skills/create-example-app-with-integration/example/README.md.agents/skills/create-example-app-with-integration/example/src/logging.ts.agents/skills/create-integration-package/SKILL.md.hongdown.tomlAGENTS.mdCHANGES.mdCONTRIBUTING.mdcspell.jsondeno.jsondocs/manual/integration.mdmise.tomlpackages/fedify/README.mdpackages/nuxt/README.mdpackages/nuxt/deno.jsonpackages/nuxt/package.jsonpackages/nuxt/src/mod.test.tspackages/nuxt/src/mod.tspackages/nuxt/src/runtime/server/lib.tspackages/nuxt/src/runtime/server/logic.tspackages/nuxt/src/runtime/server/middleware.tspackages/nuxt/src/runtime/server/plugin.tspackages/nuxt/tsdown.config.tspnpm-workspace.yaml
- Use @fedify/fixture instead of node:test in mod.test.ts - Type event parameter as H3Event instead of unknown in middleware.ts Co-Authored-By: Claude (claude-opus-4-20250514)
Move NOT_ACCEPTABLE_BODY and DEFERRED_NOT_ACCEPTABLE_CONTEXT_KEY into a shared lib.ts to avoid string duplication across logic.ts and plugin.ts. Co-Authored-By: Claude (claude-opus-4-20250514)
…chema` to `@fedify/nuxt`
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/nuxt/src/mod.ts`:
- Around line 87-93: The current contextFactoryResolver silently treats a
non-function export from contextDataFactoryModule as undefined, causing hidden
misconfiguration; update the resolver logic around contextFactoryResolver to
check whether contextDataFactoryModule.default ??
contextDataFactoryModule.contextDataFactory is present and is a function, and if
it exists but is not a function throw a descriptive Error (mentioning
contextDataFactoryModule and the expected function export) instead of assigning
undefined, otherwise assign the function to contextDataFactory as before.
🪄 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: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: d6eaeee1-e713-4a85-9ec6-0ff5fd614e21
📒 Files selected for processing (2)
packages/nuxt/deno.jsonpackages/nuxt/src/mod.ts
| const contextFactoryResolver = contextDataFactoryModule == null | ||
| ? "const contextDataFactory = undefined;" | ||
| : [ | ||
| "const contextDataFactory =", | ||
| " contextFactoryModule.default ??", | ||
| " contextFactoryModule.contextDataFactory;", | ||
| ].join("\n"); |
There was a problem hiding this comment.
Fail fast when contextDataFactoryModule does not export a function.
At Lines 90-93, a non-function export is treated as undefined, so misconfiguration is silently ignored and request context data disappears unexpectedly. Add a runtime type check and throw a descriptive error.
🔧 Proposed fix
const contextFactoryResolver = contextDataFactoryModule == null
? "const contextDataFactory = undefined;"
: [
"const contextDataFactory =",
" contextFactoryModule.default ??",
" contextFactoryModule.contextDataFactory;",
+ "if (contextDataFactory != null && typeof contextDataFactory !== 'function') {",
+ " throw new TypeError(",
+ " '@fedify/nuxt: contextDataFactoryModule must export a function as default export or named export \"contextDataFactory\".',",
+ " );",
+ "}",
].join("\n");📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const contextFactoryResolver = contextDataFactoryModule == null | |
| ? "const contextDataFactory = undefined;" | |
| : [ | |
| "const contextDataFactory =", | |
| " contextFactoryModule.default ??", | |
| " contextFactoryModule.contextDataFactory;", | |
| ].join("\n"); | |
| const contextFactoryResolver = contextDataFactoryModule == null | |
| ? "const contextDataFactory = undefined;" | |
| : [ | |
| "const contextDataFactory =", | |
| " contextFactoryModule.default ??", | |
| " contextFactoryModule.contextDataFactory;", | |
| "if (contextDataFactory != null && typeof contextDataFactory !== 'function') {", | |
| " throw new TypeError(", | |
| " '@fedify/nuxt: contextDataFactoryModule must export a function as default export or named export \"contextDataFactory\".',", | |
| " );", | |
| "}", | |
| ].join("\n"); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/nuxt/src/mod.ts` around lines 87 - 93, The current
contextFactoryResolver silently treats a non-function export from
contextDataFactoryModule as undefined, causing hidden misconfiguration; update
the resolver logic around contextFactoryResolver to check whether
contextDataFactoryModule.default ?? contextDataFactoryModule.contextDataFactory
is present and is a function, and if it exists but is not a function throw a
descriptive Error (mentioning contextDataFactoryModule and the expected function
export) instead of assigning undefined, otherwise assign the function to
contextDataFactory as before.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
packages/nuxt/src/mod.ts (1)
87-93:⚠️ Potential issue | 🟠 MajorValidate
contextDataFactoryModuleexport type instead of silently ignoring bad config.At Line 90–93, a non-function export is accepted and later treated as
undefined, which hides configuration errors and drops context data unexpectedly.🔧 Proposed fix
const contextFactoryResolver = contextDataFactoryModule == null ? "const contextDataFactory = undefined;" : [ "const contextDataFactory =", " contextFactoryModule.default ??", " contextFactoryModule.contextDataFactory;", + "if (contextDataFactory != null && typeof contextDataFactory !== 'function') {", + " throw new TypeError(", + " '@fedify/nuxt: contextDataFactoryModule must export a function as default export or named export \"contextDataFactory\".',", + " );", + "}", ].join("\n");🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/nuxt/src/mod.ts` around lines 87 - 93, The current resolver silently treats a non-function export from contextDataFactoryModule as undefined; update the contextFactoryResolver logic to validate that the resolved export (contextDataFactoryModule.default ?? contextDataFactoryModule.contextDataFactory) is a function and throw a clear error (or call Nuxt's logger/error) if it's not; specifically, in the code that builds contextFactoryResolver, replace the unconditional assignment to contextDataFactory with a runtime type-check that verifies typeof contextDataFactory === "function" and fails fast referencing contextDataFactoryModule/contextDataFactory to surface misconfiguration instead of silently dropping context data.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.agents/skills/create-integration-package/SKILL.md:
- Line 250: Update the final validation command text that currently reads "mise
run fmt && mise run check" to the repository-standard "mise run fmt && mise
check"; locate the string in SKILL.md (the sentence starting "After
implementation, run") and replace the second invocation "mise run check" without
changing surrounding wording or formatting so the documented convention matches
the CI-style check.
In `@packages/nuxt/src/runtime/server/plugin.ts`:
- Around line 32-43: The current deferred 406 rewrite uses only the final status
(via resolveDeferredNotAcceptable/getResponseStatus) and thus converts
legitimate downstream 404 responses into 406; change the logic to only apply the
negotiated 406 when there is an actual route-miss signal rather than any 404.
Concretely, update the call/site using resolveDeferredNotAcceptable/deferred
(and related code paths) so you first check a route-miss indicator (e.g., a
boolean on deferred such as deferred.routeMiss or an explicit framework "not
found" flag on the event/context) and only proceed to setResponseStatus,
setResponseHeader and payload.body = NOT_ACCEPTABLE_BODY when negotiatedResponse
is non-null AND that route-miss flag is true; leave responses alone when a
downstream handler legitimately returned 404 but the route was matched.
---
Duplicate comments:
In `@packages/nuxt/src/mod.ts`:
- Around line 87-93: The current resolver silently treats a non-function export
from contextDataFactoryModule as undefined; update the contextFactoryResolver
logic to validate that the resolved export (contextDataFactoryModule.default ??
contextDataFactoryModule.contextDataFactory) is a function and throw a clear
error (or call Nuxt's logger/error) if it's not; specifically, in the code that
builds contextFactoryResolver, replace the unconditional assignment to
contextDataFactory with a runtime type-check that verifies typeof
contextDataFactory === "function" and fails fast referencing
contextDataFactoryModule/contextDataFactory to surface misconfiguration instead
of silently dropping context data.
🪄 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: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: c7d0ca7b-05f4-4d60-9211-cd5a98f3de04
⛔ Files ignored due to path filters (2)
deno.lockis excluded by!**/*.lockpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (25)
.agents/skills/add-to-fedify-init/SKILL.md.agents/skills/create-example-app-with-integration/SKILL.md.agents/skills/create-example-app-with-integration/example/README.md.agents/skills/create-example-app-with-integration/example/src/logging.ts.agents/skills/create-integration-package/SKILL.md.hongdown.tomlAGENTS.mdCHANGES.mdCONTRIBUTING.mdcspell.jsondeno.jsondocs/manual/integration.mdmise.tomlpackages/fedify/README.mdpackages/nuxt/README.mdpackages/nuxt/deno.jsonpackages/nuxt/package.jsonpackages/nuxt/src/mod.test.tspackages/nuxt/src/mod.tspackages/nuxt/src/runtime/server/lib.tspackages/nuxt/src/runtime/server/logic.tspackages/nuxt/src/runtime/server/middleware.tspackages/nuxt/src/runtime/server/plugin.tspackages/nuxt/tsdown.config.tspnpm-workspace.yaml
| the `.hongdown.toml`. | ||
|
|
||
| After implementation, run `mise run fmt && mise check`. | ||
| After implementation, run `mise run fmt && mise run check`. |
There was a problem hiding this comment.
Use the standard final validation command format.
Line 250 should use mise run fmt && mise check to match the repository’s documented convention.
✏️ Proposed fix
-After implementation, run `mise run fmt && mise run check`.
+After implementation, run `mise run fmt && mise check`.Based on learnings, “for the standard final validation/CI-style checks, use mise run fmt && mise check.”
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| After implementation, run `mise run fmt && mise run check`. | |
| After implementation, run `mise run fmt && mise check`. |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.agents/skills/create-integration-package/SKILL.md at line 250, Update the
final validation command text that currently reads "mise run fmt && mise run
check" to the repository-standard "mise run fmt && mise check"; locate the
string in SKILL.md (the sentence starting "After implementation, run") and
replace the second invocation "mise run check" without changing surrounding
wording or formatting so the documented convention matches the CI-style check.
| const negotiatedResponse = resolveDeferredNotAcceptable( | ||
| deferred, | ||
| getResponseStatus(event), | ||
| ); | ||
| if (negotiatedResponse == null) return; | ||
|
|
||
| setResponseStatus(event, negotiatedResponse.status); | ||
| negotiatedResponse.headers.forEach((value: string, key: string) => { | ||
| setResponseHeader(event, key, value); | ||
| }); | ||
|
|
||
| payload.body = NOT_ACCEPTABLE_BODY; |
There was a problem hiding this comment.
Don't treat every downstream 404 as “Nuxt had no matching page”.
resolveDeferredNotAcceptable() only looks at the final status code, so any shared HTML route that intentionally returns 404 will be rewritten to 406 whenever Fedify matched the path but the client did not accept ActivityPub. That breaks legitimate framework responses for cases like “known route, missing user/content”.
Please gate the deferred 406 on an actual route miss signal, not on frameworkStatus === 404 alone.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/nuxt/src/runtime/server/plugin.ts` around lines 32 - 43, The current
deferred 406 rewrite uses only the final status (via
resolveDeferredNotAcceptable/getResponseStatus) and thus converts legitimate
downstream 404 responses into 406; change the logic to only apply the negotiated
406 when there is an actual route-miss signal rather than any 404. Concretely,
update the call/site using resolveDeferredNotAcceptable/deferred (and related
code paths) so you first check a route-miss indicator (e.g., a boolean on
deferred such as deferred.routeMiss or an explicit framework "not found" flag on
the event/context) and only proceed to setResponseStatus, setResponseHeader and
payload.body = NOT_ACCEPTABLE_BODY when negotiatedResponse is non-null AND that
route-miss flag is true; leave responses alone when a downstream handler
legitimately returned 404 but the route was matched.
Add
@fedify/nuxtpackage for Nuxt integrationCloses #149
Changes
New package:
@fedify/nuxtsrc/mod.ts: Defines the Nuxt module (defineNuxtModule) that:federationModuleand optionalcontextDataFactoryModulepathsinto a Nitro server handler
src/runtime/server/middleware.ts: Creates the Fedify middleware(
defineEventHandler) that intercepts incoming requests, convertsthem via
toWebRequest, and delegates tofederation.fetch().Non-federation requests fall through to Nuxt routing.
src/runtime/server/logic.ts: Pure-logic helpers(
fetchWithFedify,resolveDeferredNotAcceptable) that determinewhether Fedify handled the request, the framework should take over
(404 fallthrough), or a deferred 406 should be returned.
src/runtime/server/plugin.ts: NitrobeforeResponsehookplugin that resolves deferred 406 Not Acceptable responses when
Fedify owns the route but the client does not accept ActivityPub and
Nuxt itself returns 404.
src/mod.test.ts: Unit tests covering:(
onNotFoundfallthrough)framework route matches
Documentation
docs/manual/integration.md: Added Nuxt section withinstallation instructions, module configuration, and context data
factory usage example.
Configuration updates
@fedify/nuxtto workspace configs (deno.json, deno.lock,pnpm-workspace.yaml, pnpm-lock.yaml)
@fedify/nuxtto AGENTS.md, CONTRIBUTING.md, andpackages/fedify/README.md package listings
tunneltask to mise.tomlAgent skill improvements (non-functional)
create-integration-package,add-to-fedify-init, andcreate-example-app-with-integrationskill docs with clarifiedguidance on version verification, fallthrough/406 behavior, template
file references, and host restriction configuration.
Co-Authored-By: GPT-5.3-codex