Your portfolio, as a conversation.
Nobody reads resumes. With AskMe, visitors chat with an AI version of you — it knows your career, answers questions in your voice, checks your Google Calendar, books calls, and takes messages. Clone it, drop in your CV, and deploy.
- AI chat — career-aware conversations powered by OpenAI (or any model via the OpenKBS proxy)
- Calendar + bookings — real-time availability from Google Calendar, with a two-phase approve/reject flow
- Contact form — rate-limited messages straight to your inbox
- Agent-assisted setup — open in Claude Code, Cursor, or Codex and say "set up this project"
- All features optional — toggle calendar, bookings, and contact form independently
Built with React, Vite, Tailwind CSS, and Node.js serverless functions. Runs locally with zero external dependencies (PGlite for Postgres), deploys to OpenKBS in one command.
Cost note: The AI chat makes real LLM API calls. Each conversation costs tokens. Monitor your usage and set billing limits on your provider account.
- Node.js 24+ (LTS recommended)
- npm 10+
- An OpenAI API key or an OpenKBS account (includes proxy credits)
- (Optional) Google Cloud project with OAuth 2.0 Client ID + Service Account for calendar/booking features
git clone https://github.com/open-kbs/askme.git my-site
cd my-site
npm installOpen the repo in a coding agent (Claude Code, Cursor, Codex) and say "set up this project". The agent reads SETUP.md and walks you through profile, avatar, LLM key, and optional Google credentials — one question at a time.
- Copy
.env.exampleto.env.localand fill in your keys. - Edit
config.jsonwith your name, title, timezone, and branding. - Edit
assets/career.jsonwith your experience, skills, and projects. - (Optional) Place an avatar image at
assets/avatar.png.
Then start the dev server:
npm run devThis starts two processes:
- API server at
http://localhost:8787(Hono + PGlite for local Postgres) - Frontend at
http://localhost:5173(Vite + React)
config.json # Owner profile, feature flags, system prompt, email templates
.env.local # Secrets (gitignored)
assets/
career.json # Structured career data (fed into AI system prompt)
avatar.png # Profile photo
functions/
api/ # Main Lambda — chat, bookings, calendar, contact
api-cleanup/ # Hourly cron — cleans expired rate-limit rows
_shared/ # Shared modules (db, auth, emails, availability, …)
site-src/ # Vite + React + Tailwind frontend
local/
server.mjs # Local dev server (Hono, PGlite)
setup.mjs # First-time setup API (loopback only)
scripts/
bundle-functions.sh # Pre-deploy: copies _shared + config into each function
All requests go to POST /api with a JSON body. The action field selects the endpoint.
{
"action": "chat",
"messages": [
{ "role": "user", "content": "Tell me about your work" }
]
}Returns { "text": "...", "toolParts": [...] }. The AI can call tools during the conversation:
| Tool | Description |
|---|---|
checkAvailability |
Returns 7 days of 30-min free/busy slots |
createBooking |
Creates a pending booking request |
sendMessage |
Sends a contact message to the site owner |
Requires Authorization: Bearer <google-id-token>.
{ "action": "get-availability" }Returns { "days": [{ "date": "01-05-2026", "dayOfWeek": "Fri", "slots": [...] }] }.
Requires Authorization: Bearer <google-id-token>.
{
"action": "create-booking",
"name": "Jane Doe",
"email": "jane@example.com",
"date": "01-05-2026",
"startTime": "14:00",
"duration": 30
}{
"action": "send-contact",
"name": "John Smith",
"email": "john@example.com",
"message": "I'd like to work together."
}| Section | What it controls |
|---|---|
features |
Toggle calendar, bookings, contactForm independently |
owner |
Name, title, location, timezone, working hours |
branding |
Site name, logo text, meta description, avatar/CV URLs |
social |
LinkedIn, GitHub, Twitter, website links in nav |
starterPrompts |
Quick-action buttons shown in empty chat |
systemPrompt |
AI persona, guidelines, scope rules |
emails |
Mustache-lite templates for booking and contact emails |
See .env.example for all supported variables. Key ones:
| Variable | Required | Description |
|---|---|---|
OPENAI_API_KEY |
One of these | Direct OpenAI access |
OPENKBS_API_KEY |
One of these | OpenKBS proxy (multi-vendor) |
GOOGLE_OAUTH_CLIENT_ID |
For calendar | Google OAuth client ID |
GOOGLE_SERVICE_ACCOUNT_KEY |
For calendar | Base64-encoded service account JSON |
GOOGLE_CALENDAR_IDS |
For calendar | Comma-separated calendar emails |
BOOKING_SECRET |
For bookings | HMAC key for approve/reject links |
npm run deployThis builds the frontend, bundles shared modules into each function, and deploys via the OpenKBS CLI. See openkbs.json for the deployment configuration.
Chat returns an error about the API key
Check that .env.local has either OPENAI_API_KEY or OPENKBS_API_KEY set. Restart the dev server after changing env vars.
Google sign-in button doesn't appear
Ensure GOOGLE_OAUTH_CLIENT_ID is set. In Google Cloud Console, verify that http://localhost:5173 (no trailing slash, http not https) is listed under "Authorized JavaScript origins". If your OAuth consent screen is in "Testing" mode, your Google account must be listed as a test user.
Calendar shows no availability The service account must be shared on the target Google Calendar (Calendar Settings → Share → add the service account email with "See all event details"). Also verify the Google Calendar API is enabled in your Cloud Console project.
Booking approval link says "expired"
Approval links expire after 7 days. The booking must also still be in pending status.
npm run dev fails on first run
Run npm install first — postinstall also installs site-src dependencies.
- AI chat with career-aware system prompt
- Google Calendar availability + booking flow
- Two-phase booking approval via email
- Contact form with rate limiting
- Dark/light theme
- Local dev with PGlite (zero external dependencies)
- Custom themes and color schemes
- Multi-language support
- Analytics dashboard for site owners
MIT — see LICENSE.