A Vercel backend + Cloudflare-hosted frontend for a bring-your-own-endpoint AI chat.
unchartedali.ir/ai/→ static page on Cloudflare Pages.api.unchartedali.ir→ Vercel Functions.- Neon Postgres → users, sessions, encrypted connections, conversations and messages.
- Google OAuth → sign-in and durable account identity.
- User API keys → encrypted at rest with AES-256-GCM; never returned to the browser after save.
- AI requests → server-side streaming proxy to the user's HTTPS OpenAI-compatible endpoint.
Vercel currently documents Neon as a native integration and provides serverless Postgres setup guidance. See the official Vercel/Neon integration before deployment.
Create/connect a Neon Postgres database to the Vercel project, then run db/schema.sql in the Neon SQL editor.
Create a Google OAuth Web Application and add this exact redirect URI:
https://api.unchartedali.ir/api/auth/google/callback
Set the client ID and secret in Vercel environment variables.
Copy .env.example and set:
DATABASE_URLGOOGLE_CLIENT_IDGOOGLE_CLIENT_SECRETGOOGLE_REDIRECT_URI=https://api.unchartedali.ir/api/auth/google/callbackSESSION_SECRET(long random secret)ENCRYPTION_KEY(base64 of exactly 32 random bytes)FRONTEND_ORIGIN=https://unchartedali.ir
Generate the encryption key with:
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"From this folder:
npm install
npx vercelAttach the production domain api.unchartedali.ir to the Vercel project.
Copy:
cloudflare/ai/index.html
to your existing Cloudflare site as:
ai/index.html
Do not change the API constant in that file unless your backend domain changes.
- HTTPS-only upstream endpoints.
- Local/private IPs are rejected before proxying.
- API keys are encrypted at rest and are never sent back to the browser.
- Session cookies are HttpOnly, Secure and scoped to
.unchartedali.ir. - OAuth state is stored server-side and checked against an HttpOnly cookie.
- CORS is restricted to
FRONTEND_ORIGIN.
This proxy is intentionally for public OpenAI-compatible endpoints. Do not use it as a tunnel to private infrastructure.
GET /api/auth/meGET /api/auth/google/startGET /api/auth/google/callbackPOST /api/auth/logoutGET /api/connectionsPOST /api/connectionsDELETE /api/connectionsGET /api/conversationsPOST /api/conversationsGET /api/messages?conversationId=...POST /api/messagesPOST /api/chat