8rooms @ Zora AI
My current work at Zora AI: moving a real-estate website's catalogue onto AWS with server-side rendering, and an MCP server so Claude can manage its listings.
- Role
- Full-Stack Engineer at Zora AI · remote
- Year
- 2026
- Type
- Full-stack
- Status
- In progress
$ cat brief.md# In short
- The problem
- 8rooms' property listings lived in Payload CMS, a listing change needed a rebuild, and search engines and link previews had to get the listing data in the first HTML.
- My contribution
- The catalogue move and migration scripts, server-side rendering on Amplify, the performance work, reliable contact-form delivery and the MCP server. Others on the team worked on the site's design and on separate services.
- Result
- A listing edit now reaches the site in about a minute with no rebuild, and the listings payload dropped from 496 KB to 33 KB.
- Website
- Running on AWS Amplify; work is ongoing. A client system, so there are no screenshots here
$ stats --summary# In numbers
- 496 → 33 KB
- listings payload after compression
- ~1,400
- images moved to S3
- 160
- properties migrated
- ~1 min
- from a listing edit to the live site, no rebuild
$ cat README.md# System overview
8rooms is a bilingual real-estate website in Serbia, and my client project at Zora AI. My work is the path a property takes from the database to a visitor's screen.
The catalogue moved off Payload CMS into a database table served by an edge function, with about 1,400 images across 160 properties moved to S3 and served through CloudFront. Property and listing pages now render on the server on AWS Amplify through a custom adapter, so Google and WhatsApp or Viber link previews see the real listing. On top of that I built an MCP server that lets Claude read and edit listings and images.
$ tree architecture/# How it fits together
Clients
Website
Built SSR
Bilingual site. Property and listing pages render on the server; the rest stays static.
Claude
Reads and edits the catalogue through a connector or Claude Code.
AWS
Amplify compute
Built
Custom adapter, compression and server-side caching.
S3 + CloudFront
Migrated
Property photos and generated thumbnails.
Catalogue
Edge function
Built
Serves published properties and image URLs.
MCP server
Built
Tools for listings and images, with per-person access keys.
Database
Migrated
The catalogue table that replaced Payload CMS for properties.
$ git log --author=amar# My contribution
- Moved the property catalogue off Payload CMS into a database table served by an edge function, so a listing edit reaches the live site in about a minute with no rebuild.
- Wrote the migration scripts that moved the listings and roughly 1,400 images across 160 properties to S3, and redirected old property URLs to the new ones with real 301s.
- Moved property pages, listings and a properties sitemap to server-side rendering on AWS Amplify through my own adapter: only those paths go to the compute, and every other page stays static on the CDN.
- Cut the listings payload from 496 KB to 33 KB by compressing server-rendered responses with brotli or gzip, which Amplify's CDN doesn't do for compute answers.
- Kept pages fast after cache expiry by answering recently seen properties at once and refreshing them in the background, and added a 5-minute warm-up job against cold starts.
- Served images through CloudFront, with generated thumbnails for property cards.
- Made the contact form save every inquiry to the database before emailing it, with a column that flags unsent ones and a honeypot field against bots.
- Built an MCP server that lets Claude read and edit listings and images, through a Claude connector or Claude Code. Each person uses their own access key, and each change is recorded under its owner.
$ cat fixed-bugs.md# Challenges I solved
Search engines and WhatsApp or Viber previews only saw a listing after the browser had fetched it.
Property pages render on request from the live catalogue, so title, description and share image are already in the first HTML.
A listing page arrived as 496 KB of HTML, because the CDN compressed static files but passed server answers through unchanged.
The server now compresses its own answers with brotli or gzip according to the request, bringing that page down to 33 KB.
The first visitor after a quiet spell waited 1.5 to 3 seconds for a cold start.
A scheduled job opens the key pages every 5 minutes, so the compute and the catalogue function stay awake and their caches stay full.
A broad cache rule for HTML overrode the property pages' own header, so the CDN never cached them.
Property paths got their own rule with the server's value, and pages are cached briefly on the CDN and in server memory, with errors left uncached.
$ cat package.json# Stack
TypeScript · Node.js · AWS S3 · CloudFront · Amplify · SSR · Edge functions · MCP · Payload CMS (migrated off)