Skip to content

chore: move to ViteHub 0.1.0 and let ViteHub own the host glue - #105

Merged
vite-hub[bot] merged 5 commits into
mainfrom
chore/vitehub-0.1.0-backports
Nov 1, 2026
Merged

vite-hub[bot] merged 5 commits into
mainfrom
chore/vitehub-0.1.0-backports

Conversation

@onmax

@onmax onmax commented Nov 1, 2026 •

Copy link
Copy Markdown
Member

Problem

Drop carried its own host glue: a Netlify function wrapper and catch-all redirect, a script that rewrote Vercel's cron after the build, a hook that deduplicated .output/server/wrangler.json, its own preset detection, a hand-mounted Nitro cache on Cloudflare, and an all-zero D1 id. On the Nitro RC the Netlify build broke outright: ViteHub looked for the beta's functions-internal/ entry and failed with INTERNAL_B0040.

ViteHub now has PRs for each of these. Until they ship, this PR carries them as pnpm patches on the published 0.1.0 tarballs and deletes the Drop code they replace.

Moving vite-hub and every @vite-hub/* package to npm 0.1.0, and dropping the 0.0.4 patches, already landed on main in #63. comark-ui and comark-linter were already on npm 0.8.0 (#103).

What changed

pnpm patches (one per package version)

Patch Upstream Fixes
vite-hub@0.1.0 vite-hub/vitehub#3173 Netlify on the Nitro RC: finds .netlify/v1/functions/server/server.mjs, writes no wrapper
vite-hub/vitehub#3175 One Wrangler entry per binding name, flag, and required secret. A real id replaces a placeholder
vite-hub/vitehub#3178 cache: { driver: "kv" } mounts Nitro's cache on the app's KV. The driver lives at vite-hub/_internal/kv-cache, not _internal/kv/cache as in the PR: Nuxt aliases vite-hub/_internal/kv to a file, so the PR's path resolved to kv.js/cache and the Nuxt build failed. The PR needs the same rename
vite-hub/vitehub#3179 detectPreset() from vite-hub/deployment
vite-hub/vitehub#3191 The Console page-tool routes lose the doubled slash in //_vitehub/page/..., which made the Vercel build fail with EACCES: mkdir '/_vitehub'
@vite-hub/database@0.1.0 vite-hub/vitehub#3174 vitehub db migrate on D1 over HTTP uses Wrangler's d1_migrations ledger, without Drizzle Kit
vite-hub/vitehub#3175 A real D1 id replaces the template's all-zero one instead of conflicting
@vite-hub/schedule@0.1.0 vite-hub/vitehub#3177 schedule: { cron } per host build (the Vercel part only)
none yet (see vite-hub/vitehub#3195) Netlify builds emit the scheduled cleanup function through Nitro, so it keeps Nitro's aliases and service bindings. Drop-only for now; #3195 fixes the missing function a different way, and the two must not be combined (both would emit vitehub-schedule-cleanup)
@vite-hub/kv@0.1.0 vite-hub/vitehub#3178 The Nitro cache driver
@vite-hub/auth@0.1.0 vite-hub/vitehub#3214 console.roles.read gives the Console a computed role for its labels, Admins filter and impersonation check, without writing the database
@vite-hub/realtime@0.1.0 vite-hub/vitehub#3215 blobDocument(store) stores a Realtime document as one Blob file, with the same SHA-256 digests Drop used
comark-ui@0.8.0 onmax/comark-ui#326 The preset's shiki: { highlighter, themes, maxBlocks, maxSource } option colors code with the host's own Shiki within a budget

The Nitro 3.0.261029-rc patch (nitrojs/nitro#4967, merged but unreleased) and the nitro override stay as they were.

Host glue removed

  • Netlify: netlify/functions/server.mjs, the [functions] table, and the catch-all redirect are gone. Nitro's server.mjs declares path: "/*" and preferStatic, so static files are now served before the function.
  • Vercel: scripts/vercel-cron.mjs is gone. The Vercel build sets schedule: { cron: { cleanup: "0 0 * * *" } }.
  • Cloudflare: syncCloudflareTemplate and its nitro:init hook are gone. scripts/cloudflare-template.ts only reads cloudflareTemplate (Worker name, D1 fallbacks; the D1 id is optional since fix(deploy): Workers Builds passes again #104). Nitro's cache is cache: { driver: "kv" } instead of the cloudflare-kv-binding mount. Keys keep the nitro-cache: prefix, so existing entries stay valid.
  • Preset detection: scripts/deployment.ts uses detectPreset. It keeps DROP_HOST, the vps name, and Drop's sqlite/d1 choice. A NITRO_PRESET that conflicts with the host now fails in ViteHub's build (VITE_HUB_R0082), not in Drop.
  • Migrations: Vercel and Netlify builds run pnpm db:migrate (vitehub db migrate). Deno's predeploy and the VPS image keep scripts/migrate-d1.mjs, because neither has the sources or the CLI at that point. The self-host docs say so.
  • D1 id: the d1() helper declares databaseId as env({ source: env.source("CLOUDFLARE_D1_DATABASE_ID") }) instead of falling back to 00000000-…. ViteHub 0.1.0 types accept it, the generated database registry reads it at runtime, and vitehub db migrate resolves it.

comark-ui (non-visual)

  • The publish gate uses comark-linter's own severity. Drop keeps its stricter extras: unclosed blocks, malformed attributes, unknown components, and every annotate/* rule.
  • comark-ui's skills come from comark-ui/skills in the installed release. Drop no longer fetches comark-ui.onmax.me at build time, so modules/comark-skills.ts is gone. The package and the site serve the same five skills. The site follows comark-ui main, so it is one unreleased file ahead (comark-ui/references/remark-to-comark.md, and an edited SKILL.md). Drop now serves the files from the release it renders with.
  • The integrity of cached Markdown renders is <comark-ui version>+drop.18, so a comark-ui upgrade rerenders cached docs without a hand bump. Existing renders rerender once on deploy.

Verified

  • pnpm fmt --check, pnpm lint, pnpm knip, pnpm typecheck, pnpm run doctor: pass.
  • Rebased on main after fix(deploy): Workers Builds passes again #104 and refactor: comments on drops live in ViteHub Comments, with the same numbers, replies, and API #64. pnpm install --frozen-lockfile passes.
  • pnpm test: 65 files, 428 passed, 3 skipped. On one earlier run under load, two Playwright tests (Marker, embedded video) timed out at 5 s; they passed when rerun.
  • pnpm build (Cloudflare): .output/server/wrangler.json has one entry for each of d1_databases, kv_namespaces, r2_buckets, and the $DurableObject binding. It also has deduplicated flags and secrets and name: vitehub-drop, and leaves out the all-zero KV id. With CLOUDFLARE_D1_DATABASE_ID set, the one D1 entry carries that id, which is the Workers Builds case fix(deploy): Workers Builds passes again #104 fixed. With the patch, a placeholder id in wrangler.jsonc would no longer clash either. wrangler dev --config .output/server/wrangler.json booted, and /, /api/me, /docs, and /.well-known/skills/index.json answered 200 (the index lists all five comark-ui skills). A cached handler wrote nitro-cache:nitrohandlers…githubstars… into the local KV.
  • DROP_HOST=netlify pnpm build: completes. .netlify/v1/functions/server/server.mjs is there, .netlify/deployment.json records entry: v1/functions/server/server.mjs, and there is no .netlify/functions/ wrapper.
  • DROP_HOST=vercel pnpm build: .vercel/output/config.json has { "path": "/api/vitehub/schedules/vercel/cleanup", "schedule": "0 0 * * *" }, and api/vitehub/schedules/vercel/cleanup.func is there.
  • DROP_HOST=vercel pnpm db:migrate --dry-run with fake credentials goes to D1's HTTP /query endpoint with the database id from the env, and never starts Drizzle Kit.

Fixed since the first push

  • Netlify scheduled cleanup: the schedule patch now emits it through Nitro, and test/deploy/netlify-schedule.test.mjs runs the function from its own folder. Upstream root cause and fix: fix(database): keep other plugins' Provider Output on hosts without a hosted Database runtime vitehub#3195.

  • Vercel build: with the fix(console): mount the page tools routes below the Nuxt app base without a double slash vitehub#3191 backport, DROP_HOST=vercel pnpm build completes (14m 44s on a loaded machine), writes _vitehub/page/session.func, and keeps the daily cleanup cron.

  • Migrations: Vercel and Netlify run pnpm db:migrate --allow-data-loss, because migration 0004 drops the old comment tables on purpose and the check refuses it on a fresh database.

  • Node hosts: nitro.traceDeps: ["mdream"] so the VPS build copies mdream's native binary (until feat: add mdream to native packages unjs/nf3#84 lists it). The Dockerfile no longer copies @libsql (Nitro already traces it) or @mdream by hand. A copied VPS .output booted, migrated libsql, and served /d/<link>/t.md.

  • .pnpmfile.cjs is gone: on npm comark-ui 0.8.0 pnpm no longer installs extra comark-* copies for the linter's optional peers (3491 packages with or without it). knip and pnpm test (430 passed, 3 skipped) pass.

  • Typed generics: the getAuthForRequest double cast and the hostEvent as H3Event casts are gone. ViteHub 0.1.0 already types both (#2682, #2685), so these were leftovers.

  • Console roles: server/auth.ts passes console.roles.read (Drop's roleOf per account), so syncConsoleRoles and its full-table sweep on each Console open are gone. syncRole stays: Better Auth's admin endpoints check the signed-in admin's stored role. The two sweep tests became one that checks opening the Console writes no other account's role.

  • Live drafts: draftDocument is blobDocument(blob). Same Blob keys and digests, so rooms open during the deploy keep saving. A script against the patched dist confirmed that a write from someone else makes the save throw RealtimeDocumentConflict.

  • Code highlighting: Drop's own highlight() plugin and the splice before comark-code are gone; the preset's shiki option uses Drop's shared highlighter with maxSource: 200_000. Two changes: a short block after the budget runs out can still get colors, and each block over the budget adds a warning (never an error, so publishing isn't refused). test/cost/highlight.test.mjs passes.

  • After these: server tsc, lint, knip, and pnpm test (429 passed, 3 skipped) pass. No new host build was run for this round.

Skipped

  • Review seal and view-count key on deriveSecret: skipped. The sealed values are all short-lived (review tokens 12 h, choices 10 min, upload tickets 15 min, app-file grants 12 h). But deriveSecret has no fallback: it throws without VITEHUB_SECRET (or NUXT_APP_SECRET). Quiver's Drop has no VITEHUB_SECRET, and self-hosters only need it for DROP_CONTENT_ORIGIN. Switching would break site review, uploads, and app files there, and would turn view counting into an error. This waits for Quiver's secret.
  • route: false in server/auth.ts: kept. It dates from the first Nuxt rebuild (b82ecfc), with no reason recorded. Turning it off would mount ViteHub's own /api/auth/** handler and its Vite dev middleware, which answers auth requests before Nitro. In nuxt dev that skips Drop's middlewares on those paths (oauth-register, members-only, proxy sign-out, admin-api).
  • comark-content 0.4.3: not bumped. vite-hub and @vite-hub/content 0.1.0 declare comark-content exactly 0.4.1 as a peer.

Follow-ups

  • comark-ui visual moves (Mermaid, typeset, outline) stay as they are in this PR.
  • Upstream #3178 needs the kv-cache rename above. #3173 does not restore Netlify's schedule function on the RC.
  • Waiting on releases, then Drop deletes more: feat(blob): let the serve authorize callback decide signed-out requests vitehub#3198 (anonymous Blob authorize), #3200 (Console page authorize, deletes 0.19.console-pages.ts), #3203 (unavailable services, deletes the #code-image-png/#live-drafts stubs), #3204 (Cloudflare deploy command), #3207 (KV setIfAbsent; Drop should move upload claims to D1 instead), #3208 (migrate on Node start, deletes server/database-migrate.ts); fix(diagrams,math,charts): ignore renderer-only attributes a document writes itself onmax/comark-ui#321 (authored SVG, deletes authored()), #322 (typeset stylesheet, deletes most of shared/typeset.css), #323 (preset tag lists, deletes ALLOWED_TAGS/LINT_COMPONENTS copies), #324 (Mermaid limits, deletes Drop's own Mermaid), #325 (comments CSS, deletes modules/comark-comments-css.ts). A Blob conditional put would make blobDocument atomic; not opened yet.
  • ViteHub gaps: an app MCP server, per-page authorize, stubs for unavailable services, a deploy command, and an upstream decision on Netlify schedules in Nuxt builds (#3195 vs the Nitro-module approach in this PR).

🤖 Generated with Claude Code

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-01T16:27:45.230281Z ed30fea New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

onmax added 3 commits November 1, 2026 17:19
Netlify output on the Nitro RC (vite-hub/vitehub#3173), D1 migrations over HTTP on
Wrangler's ledger (#3174), one Wrangler entry per binding (#3175), a per-host
Schedule cron (#3177), Nitro's cache on KV (#3178), and detectPreset (#3179).
pnpm takes one patch per package version, so vite-hub and @vite-hub/database each
carry several.
Netlify uses Nitro's own .netlify/v1/functions output, without Drop's function
wrapper, [functions] table, or catch-all redirect. Vercel's daily cleanup cron is
schedule.cron instead of scripts/vercel-cron.mjs. ViteHub writes one Wrangler
entry per binding, so syncCloudflareTemplate goes. scripts/deployment.ts reads the
host with detectPreset. Vercel and Netlify migrate D1 with vitehub db migrate
(Deno and the VPS image keep scripts/migrate-d1.mjs). Cloudflare's Nitro cache is
cache: { driver: "kv" } instead of a hand mount, with the same keys. The D1
database id over HTTP is a runtime env declaration instead of an all-zero
placeholder.
…its release

The publish gate takes comark-linter's own severity and keeps Drop's stricter
extras (unclosed blocks, broken attributes, unknown components, annotate rules)
instead of a copied list of the linter's error rules. comark-ui's skills come from
comark-ui/skills in the installed release instead of a build-time fetch of
comark-ui.onmax.me. Cached renders carry comark-ui's version in their integrity,
so an upgrade rerenders them without a hand bump.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

Netlify builds become publishable in this PR, but they are missing the cleanup schedule that the application relies on and still documents as part of the host contract.

Reviewed changes across the complete three-commit diff, including the patched ViteHub deployment and migration packages, removed Drop-owned host glue, generated-host configuration, Comark lint/skills integration, cache integrity, and associated tests.

  • Host glue ownership: moves Netlify output handling, Vercel cron customization, Cloudflare Wrangler deduplication, preset detection, and Nitro KV caching into patched ViteHub packages.
  • D1 migrations: changes Vercel and Netlify builds to vitehub db migrate, with direct D1 HTTP application through Wrangler's d1_migrations ledger.
  • Comark integration: consumes exported lint severity, bundles skills from the installed comark-ui release, and includes that release version in Markdown cache integrity.
  • Deployment configuration: removes the old Netlify wrapper/redirect, Vercel post-build rewrite, and Cloudflare post-compile synchronization while preserving host-specific storage and database choices.

⚠️ Netlify deployments have no cleanup job

The PR makes the previously failing Netlify build complete, but its own verification found that no standalone scheduled function is emitted under .netlify. A deployed Netlify instance therefore never runs the lifecycle work still promised by the host configuration and docs, so this should be fixed before treating Netlify as a supported working target.

Technical details
# Restore Netlify cleanup scheduling

## Affected sites
- `nuxt.config.ts:77-82` — configures Netlify with `schedule: { providerOutput: "standalone" }`, but the generated output contains no cleanup function.
- `server/schedules/cleanup.ts:4-20` — the absent job handles quota reservations, code images, expired drops, public links, OAuth clients, viewer identities, and search indexing backlog.
- `content/docs/self-host/index.md:165-168` — promises hourly Netlify cleanup and explains its retention effects.
- `content/docs/self-host/netlify.md:3,40` — advertises a Netlify scheduled function that is not deployed.

## Required outcome
- A Netlify deployment must include an hourly invocation of the `cleanup` schedule, or Netlify must not be presented as a functioning deployment target until the upstream standalone schedule path supports this Nuxt/Nitro output.
- Add generated-output coverage that fails when the expected Netlify scheduled function or schedule declaration is absent.

Pullfrog  | Fix it ➔ | View workflow run | Using gpt-5.6-sol | 𝕏

@vite-hub

vite-hub Bot commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor
Session Status Started Duration
Pending Completed Not started —
View session Completed 2026-11-01T17:22:51.057Z 17m 9s
View session Last seen running 2026-11-01T16:35:50.299Z 0s

Latest result

Pull request merged.

Final answers

Session

Pull request merged.

Session

Pushed 2c00e13 fixing Knip’s transitive deployment-test imports. `pnpm knip` reproduced the failure and now passes; `pnpm test test/deploy/` passed all 14 tests; focused lint and formatting passed. Prior migration and cleanup findings remain fixed. Host setup failed on the pnpmfile checksum, and automatic prepare hit protected Git config; `pnpm install --frozen-lockfile --ignore-scripts` passed. Awaiting hosted CI.

Session

Pushed 2c00e13 fixing Knip’s transitive deployment-test imports. `pnpm knip` reproduced the failure and now passes; `pnpm test test/deploy/` passed all 14 tests; focused lint and formatting passed. Prior migration and cleanup findings remain fixed. Host setup failed on the pnpmfile checksum, and automatic prepare hit protected Git config; `pnpm install --frozen-lockfile --ignore-scripts` passed. Awaiting hosted CI.

View session

Pushed 2c00e13 fixing Knip’s transitive deployment-test imports. `pnpm knip` reproduced the failure and now passes; `pnpm test test/deploy/` passed all 14 tests; focused lint and formatting passed. Prior migration and cleanup findings remain fixed. Host setup failed on the pnpmfile checksum, and automatic prepare hit protected Git config; `pnpm install --frozen-lockfile --ignore-scripts` passed. Awaiting hosted CI.

Session

Pushed b32b6d8. Fixed Codex P1 deployment migrations and Pullfrog P1 missing Netlify cleanup; resolved the migration thread. `pnpm test test/deploy/` passed 14 tests; focused lint, formatting, and frozen installation passed. Host dependency refresh still fails because --ignore-pnpmfile conflicts with pnpmfileChecksum. Awaiting hosted checks.

Session

Pass interrupted; current webhook state retained.

Session

Pass interrupted; current webhook state retained.

Session

Waiting for review checks before the next pass.

@onmax
onmax force-pushed the chore/vitehub-0.1.0-backports branch from 01a44ed to ed30fea Compare November 1, 2026 16:26

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ed30feafea

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread netlify.toml Resolved

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

No new issue was introduced by this delta, but the previously reported Netlify cleanup-schedule concern remains unresolved, so this review does not approve the PR.

Reviewed changes since the prior Pullfrog review, covering the Cloudflare template schema adjustment.

  • Allowed provisioned D1 IDs to be absent: relaxed scripts/cloudflare-template.ts so the checked-in wrangler.jsonc D1 binding can omit database_id, consistent with the existing environment and local-build fallback chain.

Pullfrog  | Fix it ➔ | View workflow run | Using gpt-5.6-sol | 𝕏

@vite-hub

vite-hub Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

The migration repair keeps ViteHub's default safety gate intact and explicitly opts both deployment commands into Drop's checked-in destructive migrations (0004 and 0009), matching the previous deployment runner's behavior. The new D1 HTTP regression first reproduces DATABASE_MIGRATION_DATA_LOSS without that opt-in, then applies each host command twice to a fresh SQLite-backed D1 mock and verifies the complete schema, migration ledger, and foreign keys without spawning Drizzle Kit.

The cleanup concern in Pullfrog reviews 5729040923 and 5729107732 is repaired in the existing schedule package patch. Nuxt replays Vite config hooks without running the standalone output hooks, so a Nitro module now bundles schedules with Nitro's aliases and generated service bindings and emits an hourly Netlify function with its own server bundle. The generated-output regression copies only that function's directory and successfully invokes cleanup with HTTP 204, while checking that Nitro's native server function still exists. These are both P1 findings; both regressions failed before the repair and pass in b32b6d8.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes since the prior Pullfrog review, covering the Netlify schedule restoration and deployment migration opt-in.

  • Restored Netlify cleanup scheduling: generated a scheduled function from Nitro's bundled server output so aliases and generated service bindings remain available, with focused coverage that executes the copied deployment artifact independently.
  • Allowed intentional deploy migrations: added --allow-data-loss to the Vercel and Netlify migration commands and documented the destructive schema-removal policy, with coverage for rejection without the flag, successful application, idempotency, and foreign-key integrity.

Pullfrog  | View workflow run | Using gpt-5.6-sol | 𝕏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant