Skip to content

Conversation

@mezotv
Copy link
Member

@mezotv mezotv commented Nov 22, 2025

Summary by CodeRabbit

  • Chores

    • Migrated API deployment platform to Vercel and updated build/dev/deploy scripts and tooling
    • Updated packaging and TypeScript build outputs; adjusted ignore rules and environment example
    • Added a VS Code setting for Prisma pinning
    • Improved runtime environment validation and error handling for missing config
  • Documentation

    • Renamed API to "Marble API" and added Vercel prerequisites, development, build, and deploy instructions

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Nov 22, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
marble-api Ready Ready Preview Comment Nov 25, 2025 10:18am
marble-app Ready Ready Preview Comment Nov 25, 2025 10:18am
marble-web Ready Ready Preview Comment Nov 25, 2025 10:18am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 22, 2025

Warning

Rate limit exceeded

@mezotv has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 16 minutes and 26 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between a6c7917 and 8edb62d.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (1)
  • packages/db/src/index.ts (1 hunks)

Walkthrough

Migration from Cloudflare Workers (Wrangler) to Vercel deployment platform. Environment variable access refactored from Hono context (c.env) to Node process.env throughout middleware and routes. API app initialization restructured from app.ts module to inline setup in index.ts. Build tooling and dependencies updated accordingly.

Changes

Cohort / File(s) Summary
Editor & infra settings
\.vscode/settings.json, apps/api/.gitignore, turbo.json
Adds prisma.pinToPrisma6 to VSCode settings; updates .gitignore to add .vercel and remove some Cloudflare/wrangler ignores; adjusts turbo output path to .vercel/output/**.
API project config & docs
apps/api/.env.example, apps/api/README.md, apps/api/package.json, apps/api/tsconfig.json, apps/api/wrangler.toml
Removes/relocates env example lines (ENVIRONMENT removed, POLAR_ACCESS_TOKEN moved); rewrites README for Vercel dev/build/deploy; changes package.json scripts and deps to Vercel/Node toolchain; removes wrangler.toml.
App initialization consolidation
apps/api/src/app.ts, apps/api/src/index.ts
Deletes previous app.ts; builds and exports Hono app inline in index.ts with middleware and v1 route mounting.
Env access & runtime migration
apps/api/src/middleware/ratelimit.ts, apps/api/src/middleware/analytics.ts, apps/api/src/middleware/authorization.ts, apps/api/src/routes/tags.ts, apps/api/src/routes/categories.ts, apps/api/src/routes/posts.ts, apps/api/src/routes/authors.ts
Replaces c.env usage with process.env; adds presence checks (DATABASE_URL / REDIS_* / POLAR_ACCESS_TOKEN) and 500 error paths when required env vars are missing; updates imports from @marble/db/workers to @marble/db.
Libraries & package exports
apps/api/src/lib/redis.ts, packages/db/package.json, packages/db/tsconfig.json
Changes Upstash import to @upstash/redis; updates packages/db exports to point to dist types/runtime, removes ./workers export, adds build script and tsconfig outDir/rootDir.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Vercel as Vercel Runtime
    participant App as Hono App (index.ts)
    participant MW as Global Middleware
    participant Routes as Route Handlers
    participant Env as process.env

    Client->>Vercel: HTTP request
    Vercel->>App: route to app
    App->>MW: run cache-control, ratelimit, analytics, trailing-slash
    MW->>Env: read REDIS_URL / REDIS_TOKEN / DATABASE_URL
    MW-->>App: middleware outcome
    App->>Routes: dispatch to workspace/v1 handlers
    Routes->>Env: check DATABASE_URL / POLAR_ACCESS_TOKEN
    alt required env present
        Routes->>Routes: query DB / emit analytics
        Routes->>Client: 200 + payload
    else missing required env
        Routes->>Client: 500 Internal Server Error
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Pay attention to: apps/api/src/index.ts (ordering of middleware, redirects, and route mounts), removal of apps/api/src/app.ts (ensure no stray imports), env-access guard consistency across route handlers, and packages/db export changes affecting consumers.

Possibly related PRs

Suggested reviewers

  • taqh

Poem

🐇 From Wrangler burrows to Vercel light I steer,
process.env whispers where workers once did appear,
I stitched the app in one warm, tidy nest,
swapped Cloudflare bits for Node — a hop to the west,
The rabbit coded, boxed, and shipped — rejoice, cheer! 🎉

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning No pull request description was provided. The required template sections (Description, Motivation and Context, How to Test, Types of Changes) are all missing. Add a complete PR description following the template: include what changes were made, why the migration to Vercel was necessary, testing instructions, and mark the appropriate change type.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'chore: move api to vercel' directly and accurately reflects the main objective of the PR: migrating the API from Wrangler/Cloudflare to Vercel.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Nov 22, 2025

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
❌ Deployment failed
View logs
marble-api 8edb62d Nov 24 2025, 11:09 PM

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
apps/api/.env.example (1)

1-4: Align .env.example with dotenv-linter expectations

The variable set looks fine. To stay in sync with dotenv-linter (per the hints), consider:

  • Adding a trailing newline at the end of the file.
  • Optionally reordering keys if you want to keep alphabetical ordering enforced, or relaxing that rule in the linter config if intentional.
apps/api/tsconfig.json (1)

3-12: Node/Vercel tsconfig looks good; ensure dist/ is ignored

The shift to "module": "NodeNext", "types": ["node"], and jsxImportSource: "hono/jsx" is consistent with the new runtime. Adding "outDir": "./dist" is fine, but note that dist/ is no longer ignored in apps/api/.gitignore.

If you plan to run tsc locally, consider re‑ignoring apps/api/dist (either here or at the repo root) so build artifacts don’t get committed.

apps/api/src/index.ts (1)

39-41: Confirm analytics behavior on Node/Vercel and ENVIRONMENT usage

Two things to verify around analytics() being mounted on /v1/:workspaceId/*:

  1. executionCtx on Node/Vercel
    The analytics middleware still relies on c.executionCtx?.waitUntil(task());. On a Node/Vercel runtime, executionCtx may not be populated the same way as on Cloudflare Workers. If it’s undefined, the analytics task will never run.

    • If Vercel’s adapter for Hono does not provide executionCtx, consider falling back to invoking task() directly (or adapting to whatever background mechanism Vercel exposes).
  2. ENVIRONMENT vs new env typing
    analytics destructures ENVIRONMENT from c.env, but Env no longer contains that field and .env.example no longer documents it. If you are moving away from a custom ENVIRONMENT variable, you may want to:

    • Switch analytics to use NODE_ENV / VERCEL_ENV instead, or
    • Reintroduce and document ENVIRONMENT so the production/dev Polar behavior is explicit.

Please confirm the intended behavior on the new runtime and adjust analytics accordingly if needed.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 73a62d4 and aa60549.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • .vscode/settings.json (1 hunks)
  • apps/api/.env.example (1 hunks)
  • apps/api/.gitignore (1 hunks)
  • apps/api/README.md (1 hunks)
  • apps/api/package.json (1 hunks)
  • apps/api/src/app.ts (0 hunks)
  • apps/api/src/index.ts (1 hunks)
  • apps/api/src/routes/authors.ts (1 hunks)
  • apps/api/src/types/env.ts (0 hunks)
  • apps/api/tsconfig.json (1 hunks)
  • apps/api/wrangler.toml (0 hunks)
💤 Files with no reviewable changes (3)
  • apps/api/src/types/env.ts
  • apps/api/src/app.ts
  • apps/api/wrangler.toml
🧰 Additional context used
🧬 Code graph analysis (1)
apps/api/src/index.ts (3)
apps/api/src/types/env.ts (1)
  • Env (1-6)
apps/api/src/middleware/ratelimit.ts (1)
  • ratelimit (14-56)
apps/api/src/middleware/analytics.ts (1)
  • analytics (5-100)
🪛 dotenv-linter (4.0.0)
apps/api/.env.example

[warning] 4-4: [EndingBlankLine] No blank line at the end of the file

(EndingBlankLine)


[warning] 4-4: [UnorderedKey] The POLAR_ACCESS_TOKEN key should go before the REDIS_TOKEN key

(UnorderedKey)

🪛 GitHub Actions: Code quality
apps/api/src/routes/authors.ts

[error] 2-8: Ultracite check failed due to formatting issue. Import formatting would be adjusted by formatter (e.g., combining named imports). See diff in the reported content.

🪛 markdownlint-cli2 (0.18.1)
apps/api/README.md

9-9: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


14-14: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


20-20: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


27-27: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ 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). (1)
  • GitHub Check: Workers Builds: marble-api
🔇 Additional comments (4)
.vscode/settings.json (1)

41-41: Clarify the purpose of pinning Prisma to version 6.

The new setting pins the Prisma editor extension to Prisma 6. Please clarify:

  1. Is Prisma 6 the baseline for this project, or a new requirement introduced by the Vercel migration?
  2. Are there version-specific API changes or breaking changes in Prisma that necessitate this pin?
  3. Is this setting documented elsewhere in the project (e.g., README.md, migration guide)?
apps/api/.gitignore (1)

29-29: Ignore .vercel directory – LGTM

Adding .vercel to .gitignore is appropriate for the Vercel-based workflow; no issues here.

apps/api/package.json (1)

3-24: Vercel CLI scripts look consistent; verify tool versions exist

The new vc-based scripts (dev, build, deploy) and the Hono bump to ^4.10.6 look consistent with the move to Vercel.

Please double‑check that the devDependency versions you’re pinning actually exist and are the ones you want to standardize on, especially:

  • "typescript": "^5.8.3"
  • "vc": "^0.1.4"

to avoid npm install failures in CI or on fresh environments.

apps/api/src/index.ts (1)

14-37: Global cache middleware and overall Hono wiring look solid

The stale-if-error middleware is scoped correctly to successful GET/HEAD responses and avoids clobbering existing no-store / stale-if-error directives, and the overall Hono setup (app/v1 separation, health routes, trailing‑slash handling, and workspace routing) reads clean and coherent. No issues from a routing/middleware-order standpoint.

Comment on lines +1 to +30
# Marble API

API endpoints users can fetch data from.
Prerequisites:

- [Vercel CLI](https://vercel.com/docs/cli) installed globally

To develop locally:

```
npm install
vc dev
```

```
open http://localhost:3000
```

To build locally:

```
npm install
vc build
```

To deploy:

```
npm install
vc deploy
```
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Align dev port with scripts and add languages to code fences

Two things to tighten up here:

  1. Port mismatch

    • package.json defines "dev": "vc dev --listen 8787", but the README says to open http://localhost:3000.
    • Please align these so the documented URL matches the actual dev port (or drop --listen and rely on the default if 3000 is intended).
  2. Fenced code block languages

    • The code fences for the CLI commands currently have no language. Adding something like ```bash will satisfy markdownlint and improve readability.

Optionally, you could also show npm run dev, npm run build, and npm run deploy here to mirror the scripts and avoid duplicating the raw vc invocations.

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

9-9: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


14-14: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


20-20: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


27-27: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In apps/api/README.md around lines 1 to 30, the README's dev URL and code fences
are wrong: update the dev instructions so the documented URL matches
package.json (either change the README to open http://localhost:8787 to match
"vc dev --listen 8787" or remove the --listen flag in package.json so the
default 3000 is used), convert the triple-backtick blocks to bash fenced code
blocks (use ```bash) for all CLI examples, and optionally replace raw vc
commands with their npm script equivalents (npm run dev, npm run build, npm run
deploy) so README mirrors package.json scripts.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
apps/api/src/index.ts (2)

40-43: v1 workspace middleware ordering is reasonable; keep future v1 routes in mind

Mounting ratelimit, validateWorkspace, and analytics on /v1/:workspaceId/* ensures all current v1 workspace routes go through the full protection + metrics stack in the intended order.

Just be aware that any future v1 routes that don’t include :workspaceId (e.g. /v1/health) will bypass these middlewares; that may or may not be what you want.


45-66: Limit workspace redirects to safe methods to avoid surprising behavior

The workspace redirect (/:workspaceId/*/v1/:workspaceId/* for tags/categories/posts/authors) is well-scoped and avoids /v1, /, and /status, and its interaction with trimTrailingSlash() is correct.

Right now it runs for all HTTP methods, so a POST /:workspaceId/posts (if ever used) would get a 308 redirect too. Many clients will follow this correctly, but it’s more conventional to only auto-redirect safe methods.

Consider adding a method guard at the top of this middleware:

 app.use("/:workspaceId/*", async (c, next) => {
-  const path = c.req.path;
+  const method = c.req.method;
+  if (method !== "GET" && method !== "HEAD") {
+    return next();
+  }
+  const path = c.req.path;
   const workspaceId = c.req.param("workspaceId");

This keeps redirects purely for read-only traffic.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e8fa9ea and 9bd7492.

📒 Files selected for processing (2)
  • apps/api/package.json (1 hunks)
  • apps/api/src/index.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/api/package.json
🧰 Additional context used
🧬 Code graph analysis (1)
apps/api/src/index.ts (4)
apps/api/src/types/env.ts (1)
  • Env (1-6)
apps/api/src/middleware/ratelimit.ts (1)
  • ratelimit (14-56)
apps/api/src/middleware/workspace.ts (1)
  • validateWorkspace (4-44)
apps/api/src/middleware/analytics.ts (1)
  • analytics (5-100)
⏰ 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). (1)
  • GitHub Check: Workers Builds: marble-api
🔇 Additional comments (2)
apps/api/src/index.ts (2)

15-37: Global stale-if-error cache middleware looks solid

The global middleware correctly:

  • Runs post-handler (await next()).
  • Restricts behavior to GET/HEAD.
  • Only applies to 2xx/3xx responses.
  • Preserves existing Cache-Control while skipping when no-store or an existing stale-if-error directive is present.

This is a good, conservative default and should be safe against most responses without surprising overrides.


68-80: Health endpoints and v1 route mounting are clear and consistent

The health endpoints (/ and /status) are straightforward and cheap, and the v1 router composition (app.route("/v1", v1); with the four workspace subroutes) cleanly isolates versioned API surface. This structure should make future versioning and workspace-specific additions easy to reason about.

Comment on lines 1 to 16
import { Hono } from "hono";
import { trimTrailingSlash } from "hono/trailing-slash";
import { analytics } from "./middleware/analytics";
import { ratelimit } from "./middleware/ratelimit";
import { validateWorkspace } from "./middleware/workspace";
import authorsRoutes from "./routes/authors";
import categoriesRoutes from "./routes/categories";
import postsRoutes from "./routes/posts";
import tagsRoutes from "./routes/tags";
import type { Env } from "./types/env";

const app = new Hono<{ Bindings: Env }>();
const v1 = new Hono<{ Bindings: Env }>();

const staleTime = 3600;

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Align Env bindings with analytics middleware expectations

Env (from ./types/env) no longer includes ENVIRONMENT, but analytics (imported on Line 3) still destructures ENVIRONMENT from c.env. With app and v1 typed as Hono<{ Bindings: Env }>() (Lines 12–13), this will cause TypeScript errors in analytics.ts and/or incorrect assumptions about available bindings at runtime.

Either:

  • Reintroduce ENVIRONMENT into Env, or
  • Update analytics to derive isProduction from something like process.env.NODE_ENV and remove ENVIRONMENT from its c.env usage, and keep Env as-is.
🤖 Prompt for AI Agents
In apps/api/src/index.ts lines 1–16: the app/v1 Hono bindings use Env but
analytics middleware expects c.env.ENVIRONMENT which no longer exists in
./types/env; either add ENVIRONMENT:string to the Env binding type so
c.env.ENVIRONMENT is available, or modify the analytics middleware to stop
destructuring ENVIRONMENT from c.env and instead derive isProduction from
process.env.NODE_ENV (and update any types/usages accordingly) — pick one
approach and make the corresponding change to the Env type or to analytics so
TypeScript and runtime assumptions are consistent.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9bd7492 and f2045d9.

📒 Files selected for processing (1)
  • apps/api/package.json (1 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). (1)
  • GitHub Check: Workers Builds: marble-api
🔇 Additional comments (1)
apps/api/package.json (1)

19-24: Verify build and deployment configuration is present.

The migration adds @types/node, tsx, typescript, and vc to devDependencies, but there's no visibility into supporting configuration files (e.g., vercel.json, tsconfig.json). Ensure that:

  1. vercel.json (or equivalent) exists and correctly configures the build command and function entry points
  2. TypeScript build output is properly directed for Vercel Functions
  3. Environment variables from Cloudflare (removed .dev.vars script) are migrated to Vercel's environment configuration

Comment on lines 5 to 7
"dev": "vc dev --listen 8787",
"build": "vc build",
"deploy": "vc deploy"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify the vc package name and version (Line 23).

The scripts have been updated to use vc dev, vc build, and vc deploy commands, but the vc package at version ^0.1.4 appears suspicious. The standard Vercel CLI is typically the vercel package (not vc), and 0.1.4 suggests an early beta version.

Confirm that:

  1. vc is the intended package (not a typo for vercel)
  2. The package is stable and suitable for CI/CD deployments
  3. The CLI commands match what's in the scripts

🌐 Web query:

What is the vc npm package and what version should be used with Vercel functions?

💡 Result:

Short answer

  • The npm package named "vc" is an old/unrelated utility (years-old tool to bump/change a package.json version). [1]
  • For working with Vercel (local dev, deploy, and Functions) use the official Vercel CLI (the vc commands used in Vercel docs/templates). Install the official CLI per Vercel docs (examples show using vc dev, vc deploy, vc link) rather than the unrelated "vc" npm package. [2]

Sources

  • npm entry for the unrelated "vc" package. [1]
  • Vercel docs/templates using the official CLI (vc dev / vc deploy / vc link). [2]

Remove the vc npm package from devDependencies (Line 23) and install the official Vercel CLI instead.

The npm package vc is an old/unrelated utility for version bumping, not the Vercel CLI. Your scripts reference vc dev, vc build, and vc deploy commands, which are part of the official Vercel CLI, but installing this unrelated vc package will cause those commands to fail. The official CLI should be installed per Vercel docs, not via this unrelated package. Verify the correct installation method in Vercel's documentation to ensure your deployment pipeline works as intended.

🤖 Prompt for AI Agents
In apps/api/package.json around lines 5 to 7 (and devDependencies at line 23),
the project mistakenly installs the unrelated "vc" npm package while scripts use
Vercel CLI commands; remove "vc" from devDependencies and install the official
Vercel CLI instead (e.g., add "vercel" as a devDependency or follow Vercel docs
for global/CI installation), then verify the existing scripts ("vc dev", "vc
build", "vc deploy") are either updated to use "vercel" or that package.json
scripts map to the installed CLI (e.g., use "vercel dev", "vercel build",
"vercel deploy") so the commands run correctly in local and CI environments.

"@upstash/ratelimit": "^2.0.5",
"@upstash/redis": "^1.34.4",
"hono": "^4.10.3",
"hono": "^4.10.6",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify Hono 4.10.6 compatibility with Node.js/Vercel runtime.

The hono dependency was bumped from ^4.10.3 to ^4.10.6 as part of the Wrangler → Vercel migration. Ensure this version is compatible with the Node.js Vercel Functions runtime and the new entry point setup in src/index.ts.


🌐 Web query:

Hono 4.10.6 Node.js Vercel Functions compatibility

💡 Result:

Short answer: Yes — Hono 4.10.6 is compatible with Vercel Node.js Functions, but you must use the appropriate Hono adapter/handler and follow Vercel/Next.js runtime guidance.

Key points and actions

  • Use the Vercel adapter shipped with Hono: import and export the handler from hono/vercel (App Router) or use @hono/node-server/vercel for Next.js Pages Router. [1][2][3]
  • For Next.js App Router set export const runtime = 'nodejs' and export GET/POST = handle(app) (example in docs). [1]
  • For Pages Router install @hono/node-server and use its vercel handle; also set NODEJS_HELPERS=0 in your Vercel environment or .env as the docs instruct. [2][3]
  • Ensure Node.js version >= 18 (Hono documents minimum Node requirements and specific minima per minor Node release). [4]
  • If deploying ESM/TypeScript to Vercel functions, confirm package.json "type":"module" and proper module settings to avoid CJS/ESM mismatch (common Vercel issue). Community guidance suggests using ES module config. [5]

Sources

  • Hono Vercel guide / examples. [1]
  • Hono + Next.js / Pages Router instructions (use @hono/node-server + NODEJS_HELPERS=0). [2][3]
  • Hono Node.js runtime requirements (Node >=18 and specific minimum releases). [4]
  • Vercel community thread re: Node/ESM issues when deploying Hono on Vercel. [5]

If you want, I can: 1) show a minimal working example for App Router or Pages Router on Vercel using Hono 4.10.6, or 2) inspect your project config (package.json, Next.js router type, Node version) to point out any required changes.


🏁 Script executed:

#!/bin/bash
# Check the entry point setup in src/index.ts
echo "=== src/index.ts ===" 
cat src/index.ts 2>/dev/null || echo "File not found"

echo -e "\n=== package.json (relevant fields) ===" 
# Extract relevant fields from package.json
python3 << 'EOF'
import json
try:
    with open('apps/api/package.json', 'r') as f:
        pkg = json.load(f)
    print(f"Type: {pkg.get('type', 'not specified')}")
    print(f"Engines: {pkg.get('engines', {})}")
    print(f"Scripts (main): {pkg.get('scripts', {}).get('build', 'N/A')}")
    if 'hono' in pkg.get('dependencies', {}):
        print(f"Hono version: {pkg['dependencies']['hono']}")
except Exception as e:
    print(f"Error: {e}")
EOF

Length of output: 154


🏁 Script executed:

#!/bin/bash
# Search for entry points and Vercel configuration
echo "=== Directory structure in apps/api ===" 
ls -la apps/api/ 2>/dev/null | head -20

echo -e "\n=== Search for src or api directories ===" 
find apps/api -type d -name "src" -o -name "api" 2>/dev/null

echo -e "\n=== Look for Vercel config and entry points ===" 
find apps/api -maxdepth 2 -type f \( -name "vercel.json" -o -name "*.ts" -o -name "*.js" \) 2>/dev/null | grep -v node_modules | head -15

echo -e "\n=== Check main/exports in package.json ===" 
python3 << 'EOF'
import json
try:
    with open('apps/api/package.json', 'r') as f:
        pkg = json.load(f)
    print(f"Main: {pkg.get('main', 'not specified')}")
    print(f"Exports: {pkg.get('exports', 'not specified')}")
except Exception as e:
    print(f"Error: {e}")
EOF

Length of output: 725


🏁 Script executed:

#!/bin/bash
echo "=== apps/api/src/index.ts ===" 
cat apps/api/src/index.ts

echo -e "\n=== apps/api/tsconfig.json ===" 
cat apps/api/tsconfig.json

Length of output: 2974


Update src/index.ts to use Hono's Vercel adapter for proper Node.js Vercel Functions compatibility.

While Hono 4.10.6 is compatible with Vercel, the entry point in apps/api/src/index.ts exports a raw Hono app instance (export default app) instead of using the required Vercel adapter. For Vercel Node.js Functions, the handler must be exported via hono/vercel. Update the export to use the appropriate Vercel adapter (e.g., export const GET = handle(app) with the Vercel adapter) to ensure compatibility.

🤖 Prompt for AI Agents
In apps/api/src/index.ts (entry export portion), the file currently exports the
raw Hono app instance which is incompatible with Vercel Node.js Functions;
import the Vercel adapter from 'hono/vercel' (handle) and replace the direct app
export with Vercel-compatible handler exports — e.g., export the adapter-wrapped
handlers such as export const GET = handle(app) and export const POST =
handle(app) (and any other HTTP methods your app supports, e.g., OPTIONS) so
Vercel will invoke the app correctly.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/api/package.json (1)

5-7: Minor: Consider using vercel instead of vc in script commands for explicitness.

The scripts currently use vc dev, vc build, and vc deploy. While vc is an alias in the official Vercel CLI package and should work in npm scripts, it's more conventional and explicit to use the full command name vercel.

Consider updating the scripts to use the explicit command name:

-    "dev": "vc dev --listen 8787",
-    "build": "vc build",
-    "deploy": "vc deploy"
+    "dev": "vercel dev --listen 8787",
+    "build": "vercel build",
+    "deploy": "vercel deploy"

This makes it clearer which package provides the commands and aligns with Vercel's official documentation examples.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 58793cc and 30cb307.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (1)
  • apps/api/package.json (1 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). (1)
  • GitHub Check: Workers Builds: marble-api
🔇 Additional comments (2)
apps/api/package.json (2)

20-23: Excellent: Critical issue resolved with official Vercel CLI.

The critical package issue flagged in the past review has been fixed. The package now correctly installs vercel (the official CLI at v48.10.10) instead of the unrelated vc utility. The addition of @types/node, tsx, and typescript also aligns well with the Node.js/Vercel environment.


3-3: Verify Vercel runtime compatibility with Hono 4.10.6.

While the Hono version bump (4.10.3 → 4.10.6) is reasonable, ensure that the entry point in src/index.ts uses Hono's Vercel adapter (hono/vercel) for proper Node.js Vercel Functions compatibility, as noted in the past review. The raw app export will not work with Vercel's function handler invocation model.

Please confirm that src/index.ts exports handlers using the Vercel adapter (e.g., export const GET = handle(app) from hono/vercel), or open a follow-up issue if the adapter integration is still pending.

Also applies to: 15-15

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ mezotv
❌ jeffsee55
You have signed the CLA already but the status is still pending? Let us recheck it.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
apps/api/src/routes/authors.ts (1)

9-13: Extract database client initialization to reduce duplication.

The same environment check and client initialization pattern appears in both route handlers. This creates maintenance overhead and redundant runtime checks on every request.

Consider extracting this logic into a helper function or initializing the client once at module level (with an early check that fails fast if DATABASE_URL is missing).

Example helper approach:

function getDbClient(c: Context) {
  if (!process.env.DATABASE_URL) {
    throw new Error("DATABASE_URL not configured");
  }
  return createClient(process.env.DATABASE_URL);
}

// Then in handlers:
authors.get("/", async (c) => {
  try {
    const db = getDbClient(c);
    // ... rest of handler
  } catch (error) {
    return c.json({ error: "Internal server error" }, 500);
  }
});

Alternatively, initialize at module level:

if (!process.env.DATABASE_URL) {
  throw new Error("DATABASE_URL must be configured");
}
const db = createClient(process.env.DATABASE_URL);

// Then handlers can use `db` directly

Also applies to: 129-134

apps/api/src/middleware/analytics.ts (1)

12-15: Remove redundant DATABASE_URL check inside task function.

The DATABASE_URL check appears twice: once at line 12 (preventing task execution) and again at lines 30-32 (inside the task). Since the outer check at line 12 already prevents the task from being scheduled when DATABASE_URL is missing, the inner check is redundant.

Apply this diff to remove the redundant check:

     const task = async () => {
       try {
-        if (!process.env.DATABASE_URL) {
-          return;
-        }
         const db = createClient(process.env.DATABASE_URL);

Also applies to: 30-32

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9b3db93 and a6c7917.

📒 Files selected for processing (7)
  • apps/api/src/middleware/analytics.ts (4 hunks)
  • apps/api/src/middleware/authorization.ts (2 hunks)
  • apps/api/src/routes/authors.ts (2 hunks)
  • apps/api/src/routes/categories.ts (3 hunks)
  • apps/api/src/routes/posts.ts (3 hunks)
  • apps/api/src/routes/tags.ts (2 hunks)
  • packages/db/package.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/api/src/routes/posts.ts
  • apps/api/src/middleware/authorization.ts
  • apps/api/src/routes/categories.ts
  • apps/api/src/routes/tags.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

**/*.{ts,tsx,js,jsx}: Don't use accessKey attribute on any HTML element
Don't set aria-hidden="true" on focusable elements
Don't add ARIA roles, states, and properties to elements that don't support them
Don't use distracting elements like <marquee> or <blink>
Only use the scope prop on <th> elements
Don't assign non-interactive ARIA roles to interactive HTML elements
Make sure label elements have text content and are associated with an input
Don't assign interactive ARIA roles to non-interactive HTML elements
Don't assign tabIndex to non-interactive HTML elements
Don't use positive integers for tabIndex property
Don't include "image", "picture", or "photo" in img alt prop
Don't use explicit role property that's the same as the implicit/default role
Make static elements with click handlers use a valid role attribute
Always include a title element for SVG elements
Give all elements requiring alt text meaningful information for screen readers
Make sure anchors have content that's accessible to screen readers
Assign tabIndex to non-interactive HTML elements with aria-activedescendant
Include all required ARIA attributes for elements with ARIA roles
Make sure ARIA properties are valid for the element's supported roles
Always include a type attribute for button elements
Make elements with interactive roles and handlers focusable
Give heading elements content that's accessible to screen readers (not hidden with aria-hidden)
Always include a lang attribute on the html element
Always include a title attribute for iframe elements
Accompany onClick with at least one of: onKeyUp, onKeyDown, or onKeyPress
Accompany onMouseOver/onMouseOut with onFocus/onBlur
Include caption tracks for audio and video elements
Use semantic elements instead of role attributes in JSX
Make sure all anchors are valid and navigable
Ensure all ARIA properties (aria-*) are valid
Use valid, non-abstract ARIA roles for elements with ARIA roles
Use valid AR...

Files:

  • apps/api/src/routes/authors.ts
  • apps/api/src/middleware/analytics.ts
🧠 Learnings (1)
📚 Learning: 2025-11-24T22:28:24.921Z
Learnt from: CR
Repo: usemarble/marble PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-24T22:28:24.921Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Enforce strict type safety using Ultracite's linter and formatter

Applied to files:

  • apps/api/src/routes/authors.ts
🧬 Code graph analysis (2)
apps/api/src/routes/authors.ts (1)
apps/api/src/types/env.ts (1)
  • Env (1-7)
apps/api/src/middleware/analytics.ts (3)
packages/db/src/index.ts (1)
  • db (29-29)
apps/api/src/lib/polar.ts (1)
  • createPolarClient (3-8)
apps/cms/src/lib/polar/client.ts (1)
  • createPolarClient (5-18)
⏰ 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). (1)
  • GitHub Check: Workers Builds: marble-api
🔇 Additional comments (5)
apps/api/src/routes/authors.ts (1)

1-1: LGTM! Import path updated correctly.

The import path change from "@marble/db/workers" to "@marble/db" correctly aligns with the package.json export updates.

packages/db/package.json (1)

5-12: Breaking change: "./workers" export removed.

The "./workers" export has been removed, which is a breaking change for any consumers using that import path. The PR correctly updates internal usages (authors.ts, analytics.ts, etc.) from "@marble/db/workers" to "@marble/db".

This is intentional and all internal references have been updated consistently across the codebase.

apps/api/src/middleware/analytics.ts (3)

64-97: LGTM! Conditional Polar client creation handles missing token gracefully.

The Polar client creation properly checks for POLAR_ACCESS_TOKEN availability and logs when skipping Polar ingestion. The error handling for Polar API failures (which can return 500 in dev but still process events) is appropriate.


1-1: LGTM! Import path updated correctly.

The import path change from "@marble/db/workers" to "@marble/db" correctly aligns with the package.json export updates.


103-103: Code uses correct Cloudflare Workers API; Vercel deployment assumption appears incorrect.

The code correctly uses c.executionCtx?.waitUntil() which is the standard Cloudflare Workers pattern for background tasks. Evidence indicates this app is deployed to Cloudflare Workers, not Vercel:

  • Hono initialized as new Hono<{ Bindings: Env }>() — the Bindings type parameter is specific to Cloudflare Workers adapter
  • No Vercel configuration (vercel.json) found in apps/api
  • No @vercel/functions dependency in apps/api/package.json
  • The executionCtx API accessed via Hono context is the correct pattern for Cloudflare Workers

The review comment assumes Vercel deployment and recommends checking @vercel/functions, but the codebase design indicates Cloudflare Workers as the deployment target. For Cloudflare Workers, the current implementation is correct. If the actual deployment target is Vercel, the entire app structure and adapter would need to change (which appears unlikely given the current setup).

Likely an incorrect or invalid review comment.

Comment on lines +5 to +12
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"./client": {
"types": "./dist/client.d.ts",
"default": "./dist/client.js"
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Ensure build artifacts exist before package consumption.

The exports now point to ./dist/* paths, but there's no guarantee these files exist. The "build": "tsc" script is added but not automatically run before publish or when the package is consumed by workspace dependents.

Consider adding a "prepublishOnly" script to ensure the build runs before publishing, or document that consumers must run the build step manually.

Run the following to verify the build process and check if dist files are generated:


🏁 Script executed:

#!/bin/bash
# Verify build process and dist output

# Check if dist directory exists
if [ -d "packages/db/dist" ]; then
  echo "✓ dist directory exists"
  fd . packages/db/dist --type f --max-depth 2
else
  echo "✗ dist directory missing"
fi

# Check for build-related scripts in root or workspace
rg -n "\"build\".*@marble/db|turbo.*build" package.json apps/api/package.json -A 2 -B 2

# Verify tsconfig for db package
cat packages/db/tsconfig.json | jq '.compilerOptions | {outDir, rootDir, declaration}'

Length of output: 375


I'll continue verification to understand the complete build setup and the declaration configuration issue.


---

🏁 Script executed:

```shell
#!/bin/bash
# Deeper verification of build and tsconfig configuration

# Get full packages/db/package.json
echo "=== packages/db/package.json (scripts section) ==="
cat packages/db/package.json | jq '.scripts'

# Get full tsconfig to understand declaration setting
echo -e "\n=== packages/db/tsconfig.json (full compilerOptions) ==="
cat packages/db/tsconfig.json | jq '.compilerOptions'

# Check turbo.json for build task configuration
echo -e "\n=== turbo.json build configuration ==="
if [ -f "turbo.json" ]; then
  cat turbo.json | jq '.pipeline.build // "not found"'
else
  echo "turbo.json not found"
fi

# Check if @marble/db is a workspace dependency elsewhere
echo -e "\n=== Checking workspace dependents of @marble/db ==="
rg -l "@marble/db" --type json packages/*/package.json apps/*/package.json 2>/dev/null | head -10

Length of output: 337


I need to re-run the verification with repository access enabled.


---

🏁 Script executed:

```shell
#!/bin/bash
# Deeper verification of build and tsconfig configuration

# Get full packages/db/package.json
echo "=== packages/db/package.json (scripts section) ==="
cat packages/db/package.json | jq '.scripts'

# Get full tsconfig to understand declaration setting
echo -e "\n=== packages/db/tsconfig.json (full compilerOptions) ==="
cat packages/db/tsconfig.json | jq '.compilerOptions'

# Check turbo.json for build task configuration
echo -e "\n=== turbo.json build configuration ==="
if [ -f "turbo.json" ]; then
  cat turbo.json | jq '.pipeline.build // "not found"'
else
  echo "turbo.json not found"
fi

# Check if @marble/db is a workspace dependency elsewhere
echo -e "\n=== Checking workspace dependents of @marble/db ==="
rg -l "@marble/db" --type json packages/*/package.json apps/*/package.json 2>/dev/null | head -10

Length of output: 597


Final verification to confirm workspace setup and build orchestration:


---

🏁 Script executed:

```shell
#!/bin/bash
# Final verification of workspace setup

# Check root turbo.json
echo "=== Root turbo.json ==="
ls -la turbo.json 2>&1

# Check apps/cms and apps/api dependency declarations
echo -e "\n=== apps/cms/package.json @marble/db reference ==="
cat apps/cms/package.json | jq '.dependencies["@marble/db"], .devDependencies["@marble/db"]'

echo -e "\n=== apps/api/package.json @marble/db reference ==="
cat apps/api/package.json | jq '.dependencies["@marble/db"], .devDependencies["@marble/db"]'

# Check if dist is in .gitignore
echo -e "\n=== Checking .gitignore for dist ==="
rg "dist" .gitignore 2>/dev/null || echo "No dist pattern found in .gitignore"

# Verify full tsconfig declaration setting
echo -e "\n=== Full packages/db/tsconfig.json ==="
cat packages/db/tsconfig.json

Length of output: 534


Let me verify the extended tsconfig configuration:


---

🏁 Script executed:

```shell
#!/bin/bash
# Check extended tsconfig for declaration setting
echo "=== Checking for @marble/tsconfig package ==="
find . -name "base.json" -path "*/tsconfig/*" 2>/dev/null | head -5

echo -e "\n=== Root turbo.json build pipeline ==="
cat turbo.json | jq '.pipeline'

Length of output: 120



---

🏁 Script executed:

```shell
#!/bin/bash
# Final checks on tsconfig and turbo configuration
echo "=== packages/tsconfig/base.json compilerOptions ==="
cat packages/tsconfig/base.json | jq '.compilerOptions | {declaration, declarationMap, emitDeclarationOnly}'

echo -e "\n=== Full turbo.json ==="
cat turbo.json

Length of output: 1652


Add prepublishOnly script to ensure build artifacts exist.

The exports reference ./dist/* files, but dist is gitignored and won't exist on fresh checkout or when the package is consumed via npm. While turbo orchestrates builds in the monorepo context, there's no guarantee build runs before consumption, especially if this package is ever published independently.

Add to packages/db/package.json:

"prepublishOnly": "tsc"

Alternatively, document that consumers must run the root build step first.

🤖 Prompt for AI Agents
In packages/db/package.json around lines 5 to 12, the package exports point to
./dist/* files but dist is gitignored and may not exist when the package is
installed or published; add a "prepublishOnly" script that runs the TypeScript
build (e.g., "prepublishOnly": "tsc") so dist artifacts are produced before
publishing, or alternatively document that consumers must run the monorepo root
build step first.

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.

4 participants