Portfolio Backend API
A REST and WebSocket API for a developer’s portfolio site. One PostgreSQL database feeds the public site, the CMS and an AI assistant that handles leads in live chat.
Overview
The API stores posts, services, projects, work experience, categories and tags. It also holds a media library, editable site copy, subscribers, newsletter campaigns, contact requests and page-view analytics. The same server is a Socket.io hub for the chat between visitor, owner and AI agent: messages, presence (“is Ivan online”), history, feedback on answers and a visitor’s right to delete their own conversation. Eight feature flags (blog, services, contact form, newsletter, chat, AI chat, AI lead analysis, analytics) switch whole sections off without a deploy.
Challenge & approach
The aim was a backend that one person can run alone, where AI helps with content and leads but never becomes a single point of failure:
Architecture — Domain-sliced layout on Express 5 and TypeScript: entities hold data, features hold routes and orchestration. It runs directly through tsx with no build step. Each domain has its own table, and passthrough fields from the Zod schemas go into a jsonb column, so the schema grows without migrations for every field. Media is stored as bytea in the database, so no file volume is needed.
AI around content — After a post, project or service is saved, empty SEO fields are filled in the background by the agent. Manual edits always win, and an empty update never erases AI values. When someone submits the contact form with a website, the lead can be analysed automatically.
Chat with handoff — Every agent reply carries signals (grounding, lead saved, needs a human). The gateway stores them per message and marks the conversation for the owner’s attention until he answers. A metrics endpoint tracks lead conversion, handoffs, returning visitors and likes.
Security — JWT with token versioning, so changing the password revokes every session. Scrypt password hashing with no extra dependencies. Rate limits on forms, subscriptions, tracking, chat and AI calls. HMAC-signed unsubscribe links. Zod validation on every write.
Operations — Schema and default admin created on first start, Docker Compose for db, API and agent, pg_dump/pg_restore runbook. Newsletters go through SMTP, falling back to Ethereal for previews in development.