Repository navigation
feat(sveltekit): add @dualmark/sveltekit adapter - #32
Conversation
|
@yashranaway is attempting to deploy a commit to the Dodo Payments Team on Vercel. A member of the Team first needs to authorize it. |
aagarwal1012
left a comment
There was a problem hiding this comment.
@yashranaway — this is a substantial, high-quality contribution. End-to-end works, tests are thorough, and the example app actually scores 125/125 in my local verify run. A handful of correctness concerns to address before merge.
Verified locally
bun install --frozen-lockfile✓ (lockfile is reproducible despiteconfigVersion: 0— that's just Bun 1.3.x normalizing the format, not corruption. My earlier worry was wrong.)bun run build✓ — all 10 turbo tasks succeed including the sveltekit-blog examplebun run test✓ —@dualmark/sveltekit16/16 pass, no regressions in other packages (329 tests total)bun run typecheck✓- E2E verify on
examples/sveltekit-blog:All 14 checks pass: md.fetch, md.contentType, md.tokensHeader, md.noindex, md.vary, md.body, md.aeoVersion, md.nosniff, html.reachable, html.linkAlternate, html.vary, negotiation.botUa, negotiation.acceptHeader, negotiation.notAcceptable.$ vite dev --port 5173 & $ node packages/cli/dist/cli.js verify http://127.0.0.1:5173/posts/hello Score: 125/125 ✓
PR claim of "125/125 under vite dev" is verified ✅.
🟡 Issues to address before merge
1. converter-registry.ts will drift against PRs #36 and #39
Your packages/sveltekit/src/converter-registry.ts lists the original 12 converters. PR #39 (integration) and PR #36 (status-page) are both adding to the canonical list. Whichever of those merges before this PR will leave SvelteKit users without that converter (unknown built-in converter 'integration' runtime error, etc.).
Action: Either rebase after #39 lands and add the new cases, or coordinate merge order with maintainers. The Astro and Next.js adapters both update their registry switches when a new converter is added — SvelteKit needs to match.
2. plugin.ts writes to disk during Vite configResolved
packages/sveltekit/src/plugin.ts:209-217:
configResolved(config) {
generateDualmarkRoutes(input, config.root);
}configResolved runs on every Vite invocation (dev, build, test, even when Vite is loaded for non-SvelteKit purposes like Vitest). Writing files (mkdirSync, writeFileSync, rmSync) inside this hook means:
- Any
vitestrun inside the user's project mutatessrc/routesunexpectedly - Read-only CI checkouts will fail
- The stale-file cleanup deletes generated files whenever any vite-using tool runs with a different config
Action: Move generation to buildStart (and optionally configureServer for HMR/dev). Use a seen flag to avoid regenerating on every HMR cycle. Most generator plugins follow this pattern (e.g. SvelteKit's own sync, fumadocs, astro:content).
3. The GENERATED_MARKER collision risk
packages/sveltekit/src/plugin.ts:7:
const GENERATED_MARKER = "// @generated by @dualmark/sveltekit; do not edit";A user who manually starts a file with this comment (perhaps copy-pasted from a generated file they wanted to take over) would have their file silently deleted on next config change by removeStaleGeneratedFiles. Pre-1.0 this is probably acceptable, but consider:
- A unique random marker per project (stored in a
.dualmark/lockfile), OR - A magic header that includes a project-specific hash
Not blocking, but worth noting in the README.
4. Catch-all slug edge case is undocumented
packages/sveltekit/src/handlers.ts:106 findCollectionEntry does entry.id === slug — but with slugStrategy: "catch-all", the slug can contain /. If a user has nested IDs like 2024/01/post, they need to make sure their getEntries() returns entries with those exact slash-containing IDs. Worth a sentence in the README about how IDs map to URL slugs.
5. handle.ts:55 skips negotiation for non-GET/HEAD without injecting Link header
function shouldSkip(pathname, ...) {
if (method !== "GET" && method !== "HEAD") return true;
...
}shouldSkip returns true for POST/PUT/etc., which means those responses also bypass injectMarkdownAlternateLink at the end of handleRequest. Astro/Next.js adapters likely still inject the Link header on non-GET HTML responses since browsers can follow them. Probably an edge case (POST forms returning HTML), but worth a unit test to lock the intent.
🟢 Looks good
- 16 tests with great coverage: hook composition with
sequence(), 406 behavior, Link/Vary header injection, refuse-to-overwrite, stale-file cleanup - Config validation is thorough with clear error messages
- Conformance workflow job (
sveltekit-blog) follows the existing nextjs pattern - README is concise and accurate
- Apache-2.0 LICENSE file included in the package
🔴 Earlier concern, retracted
I previously flagged bun.lock removing "configVersion": 1. After verifying with bun install --frozen-lockfile, this is just Bun 1.3.5 normalizing the field to configVersion: 0 — the lockfile is reproducible. Withdrawn.
Required for merge
- Coordinate / rebase against #39 (and #36 if it lands first) to include
integration/status-pagein the converter registry - Move FS generation out of
configResolvedtobuildStart - Add a 1-line note in the README about catch-all slug ↔ entry.id mapping
- (Optional) Unit test for non-GET HTML responses to lock the Link-header behavior
Genuinely well-built PR. Happy to re-review after these.
|
@aagarwal1012 Fixed requested changes |
thepushkaraj
left a comment
There was a problem hiding this comment.
Hey @yashranaway, thanks for this. Two things before merge:
1. Add "integration" to the SvelteKit registry
#39 landed on main. packages/sveltekit/src/converter-registry.ts needs the same import + union entry + case + error-message update that the Astro and Next.js registries already got. Without it, converter: "integration" throws a runtime error in SvelteKit.
2. Rebase against main (don't merge)
Could you please also rebase against main and fix the merge conflicts?
27bb169 to
6fabdf2
Compare
|
@thepushkaraj Added integration to the SvelteKit registry and solved conflicts |
|
Thanks for the SvelteKit adapter — this is a substantial, well-organized PR. Plugin-based route generation, the Everything is green when built via turbo in the proper dependency order. (If you build sveltekit in isolation against stale A few things to address before merge: Blocking
Functional concerns
Nits
Looks good
Could you push fixes for items 1-3 (blocking)? Items 4-8 would be nice follow-ups but aren't strictly required. Happy to re-review. |
Set initial package version to 0.5.2 for linked releases, match monorepo Node engine requirement, and add dualmark.dev integration/package docs. Co-authored-by: Cursor <[email protected]>
|
@thepushkaraj Done |
Automated reviewVerdict: APPROVE (with minor suggestions) Build/Test Results
Spec conformance checklistAll Basic / Standard / Advanced checks pass against the live Architecture highlightsThis is the cleanest adapter in the open-PR set:
Non-blocking suggestions
SummaryBest-implemented adapter in the open-PR set: 125/125 spec score, 17 tests, well-factored use of |
|
nothing left according to dodo-squirrels 👀 |
Resolve conflicts keeping both SvelteKit and Deno conformance jobs, sync docs nav, add status-page to the SvelteKit converter registry, and align package version with linked @dualmark/* releases. Co-authored-by: Cursor <[email protected]>
The committed bun.lock was generated in bun's hoisted mode (configVersion absent), so a frozen install hoists adapter dev binaries (astro/next/vite) to the root node_modules/.bin instead of each example's local .bin. The Conformance (E2E) jobs launch dev servers via ./node_modules/.bin/<bin>, which then fails with "No such file or directory" (md.fetch -> 0/20) for astro-blog, nextjs-app-router and sveltekit-blog. Rebuilt the lockfile from main's (configVersion: 1, isolated) base so the per-example bins are restored under bun install --frozen-lockfile. Co-Authored-By: Claude Opus 4.8 <[email protected]>
addressed in following commits
Summary
Adds
@dualmark/sveltekit— a SvelteKit adapter that generates.mdendpoints,llms.txt, and ships ahandlehook for bot-aware content negotiation. Closes #5.Changes
packages/sveltekitwith a Vite plugin that generates+server.tsmarkdown endpoints for configured collections, static pages, parameterized routes, andllms.txt.createDualmarkHandleserver hook: bot detection + Accept negotiation +Link rel=alternateinjection. Composes with SvelteKit'ssequence().examples/sveltekit-blog— scores 125/125 viadualmark verifyundervite dev.Type
AEO_SPEC_VERSION)Verification
bun run buildpassesbun run testpasses (16/16 in@dualmark/sveltekit)bun run typecheckpassesdualmark verify http://localhost:5173/posts/helloagainstexamples/sveltekit-blogundervite dev→ 125/125Changeset
.changeset/sveltekit-adapter.md(minor bump for@dualmark/sveltekit)