Skip to content

votes-api: minimal Vercel entry (hono/vercel) + vercel.json - #1

Merged
LVLUP-tech merged 1 commit into
mainfrom
fix/votes-api-vercel-entry
Oct 1, 2026
Merged

LVLUP-tech merged 1 commit into
mainfrom
fix/votes-api-vercel-entry

Conversation

@LVLUP-tech

Copy link
Copy Markdown
Owner

Adds services/votes-api/api/index.ts (exports hono/vercel handle of the existing createApp) and services/votes-api/vercel.json (rewrite all -> /api). src/index.ts / PM2 / nginx self-hosted path untouched. No creds or env values included. Vercel project votes-api (team xbookings) now has rootDirectory=services/votes-api + include source files outside root (needs ../../content, ../../dist). Without DATABASE_URL etc. the function loads but DB routes return errors (health -> db:down); env must be set in Vercel by Mark. tsc --noEmit passes locally.

@vercel

vercel Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
votes-api Ready Ready Preview Oct 1, 2026 4:13pm UTC
weeklyplate Error Error Oct 1, 2026 4:13pm UTC

Request Review

@cursor cursor 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.

Already merged (b8a07ed) before this review. The three new files are a faithful Hono→Vercel adapter of src/index.ts (same createApp wiring, pool max=1, PM2 path untouched, no secrets in git). That is not enough to treat the Vercel host as a working votes API.

What I ran

  • npm ci in services/votes-api; npx tsc --noEmit -p tsconfig.json green. Same check with api/**/*.ts added to include is also green — the committed tsconfig.json does not include api/, so the PR claim that tsc --noEmit covers this entry is vacuously true.
  • npm test: 14 unit tests passed. Both integration files failed at migrate with ECONNREFUSED 127.0.0.1:54390 (no Postgres in this environment; not introduced here).
  • Invoked the new GET/POST/OPTIONS handlers locally via hono/vercel handle():
    • GET /api/v1/health → 503 {"ok":false,"service":"grokbot-votes-api","db":"down"} (matches the PR write-up; import does not crash).
    • GET /api and GET /v1/health → 404 not_found. If Vercel applies the rewrite by handing the function the destination URL (/api) instead of the original path, every real route 404s.
    • GET /api/v1/votes/counts?slugs=account-expert and POST /api/v1/identity → 500 text/plain Internal Server Error (uncaught postgres ECONNREFUSED), not the health-style JSON. Other DB routes do not fail closed the way health does.
    • OPTIONS /api/v1/health → 404; no Access-Control-Allow-Origin on a request with Origin: https://grokbot.dev. The site clients (src/scripts/upvote-button.ts, vote-counts.ts, submit-form.ts) call same-origin /api/v1/*. This host is not a drop-in replacement without a grokbot.dev proxy or CORS + cookie-domain work.
  • Live preview https://votes-api-git-fix-votes-api-vercel-entry-xbookings.vercel.app/api/v1/health is Vercel Authentication (GET 302 / POST 401). Could not smoke the Ready deploy.
  • Checks on this SHA: Vercel – votes-api success; Vercel – weeklyplate + Vercel Deployments – xbookings failed (could not read the weeklyplate inspect log). ci/validate, merge-gate, and Deno/test are red on this SHA and were already red on main (Create deno.yml) for pre-existing color-literal / community-label / deno-lint reasons — not caused by these three files.

Blocking

  1. vercel.json rewrite destination is /api with no path capture, and there is no includeFiles / SLUGS_URL. Locally a request whose URL is /api 404s. Slug load defaults to ../../content/use-cases then ../../dist/api-meta/use-case-slugs.json with no slugsUrl fallback (submissionsManifestUrl has a URL; the slug registry does not). File tracing will not pack those trees unless they are imported. Votes/counts will 500 on Vercel even after DATABASE_URL is set, unless a dashboard toggle actually bundles them — that toggle is not in the repo.
  2. Module-scope loadConfig() keeps the local-dev fail-opens. Unset VOTES_HMAC_PEPPER → local-dev-only-replace-me. Unset TURNSTILE_SECRET_KEY → Cloudflare always-pass test secret (identity POST with token x reached the DB insert locally). Preview is SSO-gated today; a production/public deploy without those env vars is an open signer + open Turnstile. Also missing the Hono-documented export const config = { runtime: 'nodejs' } next to the Node fs/net/crypto imports.

Residual

  • In-memory MemoryRateLimiter (3 identities / IP / 24h, etc.) is per isolate on serverless; nginx limit_req is not in front of this host.
  • installCommand: "npm install" ignores the lockfile (npm ci).
  • Sibling weeklyplate deploy on this repo connection failed; status context is red even though votes-api is Ready.
  • No CORS / cookie Domain work, so this cannot serve grokbot.dev as a different origin.
  • Integration tests were not re-run against a real DB here.
Open in Web View Automation 

Sent by Cursor Automation: Mark’s Automation

"installCommand": "npm install",
"buildCommand": "",
"outputDirectory": "public",
"rewrites": [{ "source": "/(.*)", "destination": "/api" }]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Locally, handle(app) 404s when the request URL is /api or /v1/health and only matches the real routes when the URL is still /api/v1/…. This rewrite sends every path to /api with no $1 capture. If Vercel gives the function the destination URL (not the original path), the Ready deploy is a 404 farm.

This file also never packs the slug sources the registry actually reads. Defaults are ../../content/use-cases and ../../dist/api-meta/use-case-slugs.json; slugsUrl is unset unless SLUGS_URL is in the Vercel project. NFT will not include those trees (they are readdir'd, not imported). The dashboard “include source files outside root” note is not reproducible from git. Add functions["api/index.ts"].includeFiles (or set SLUGS_URL / SLUGS_FILE in committed docs + project env) and use a rewrite that preserves the path, e.g. destination: "/api/$1" or keep this rewrite and prove with an unauthenticated GET /api/v1/health that the function still sees /api/v1/health.

Comment on lines +17 to +20
const cfg = loadConfig();
const logger = createLogger(cfg.logLevel);
// Serverless: keep the pool tiny; each instance handles few concurrent requests.
const db = connect(cfg.databaseUrl, 1);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is the right factory, and GET /api/v1/health does return 503 db: down without crashing import. Two holes vs src/index.ts + vs a public Vercel host:

  1. loadConfig() still fail-opens to VOTES_HMAC_PEPPER=local-dev-only-replace-me and TURNSTILE_SECRET_KEY=1x0000000000000000000000000000000AA. I posted {"turnstileToken":"x"} to this handler; Turnstile did not 403 (test secret + Cloudflare always-pass) and the handler proceeded to insert into identities (then 500 on ECONNREFUSED). If Vercel Auth is off and those env vars are missing, this is a public signer.
  2. No export const config = { runtime: 'nodejs' }. This graph uses node:fs, postgres TCP, and node:crypto. Hono's Vercel guide sets Node explicitly so the function cannot land on Edge.

src/index.ts also await slugRegistry.load(true) before serve. Lazy has() is fine on serverless, but the first vote/counts call will throw no use-case slugs loaded unless content/dist or SLUGS_URL is actually in the bundle (see vercel.json).

This branch had an error being deployed

1 failed and 1 active deployments
Preview – weeklyplate — 67fb623a Deployed Oct 1, 2026 by vercel[bot]
Preview – votes-api — 67fb623a Deployed Oct 1, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant