Software designed, built and shipped.
Everything below is live. Each one is a thing you can open and use, most of them take real payments, and none is a mockup or a case study written after the fact. Each project starts with a summary; "How it's built" has the technical details.
Limassol, Cyprus
Symposio Live
The going-out app for Cyprus: what is on, tickets, tables and the bill.
A going-out app for Cyprus and the platform behind it. Customers find events, buy tickets, book tables, order and pay from their table, split the bill, and book rides and stays. Venues and organisers manage floor plans, door check-in, menus, staff and events in it, and artists and 105 trades take bookings and get paid through it. On the App Store and Google Play, in four languages.
- Tickets, tables, ordering and paying at the table, split bills, rides, stays and delivery, in one app.
- A marketplace where the seller, not the platform, is the merchant of record: destination charges on Stripe Connect, each seller under its own merchant category from a closed list of 28.
- Real-time features: a live map of who is at each event, and voice calls and event rooms on in-house WebRTC, with native call screens on Android and iOS.
- About 120 screens, 443 API endpoints and 51 Cloud Functions, over 12,000 strings in each of four languages, and over 900 test files.
How it's built
For customers
Events are shown on a map and on city pages, with natural-language search. A ticket carries a QR code that is scanned at the door; tables can be booked or waitlisted; at the table the menu is on the phone, orders go straight to the venue, and the bill can be split. Symposio Balance, messages, reviews and tips are in the same account.
For venues, organisers, artists and trades
Venues build a floor plan and take reservations on it, check guests in at the door by QR code, and publish their menu. AI reads a photo of a paper menu into a digital menu, and reads an existing floor plan (an architect's drawing, a fire-evacuation plan or a POS table map) into draft tables. Staff, rotas, deals and paid promotion are managed in the same place, on eight subscription tiers. Organisers book performers for a lineup; artists and 105 trades take bookings and track earnings and payouts.
Rides, stays and delivery
Community ride sharing, with no money passing through Symposio by design; ride requests home after an event; accommodation bookings with calendar sync and payment by Balance; and delivery run by the venue.
Payments
Sellers are Stripe Connect Custom accounts on the Accounts v2 controller API, onboarded inside the app with Stripe's embedded components. Every payment is a destination charge made on behalf of the seller, so the seller is the merchant of record under its own category. The platform fee is set per provider and split between the two sides of a booking. Symposio Balance and venue Ad Credit are closed-loop credit, never cash: promotional and purchased credit are tracked separately, and refundable amounts are calculated from the transaction ledger, not from a balance.
Real time
The live map uses the Realtime Database: each person's location is written every eight seconds, and only people with a ticket or a role at the event can share it. Calls, group calls and event rooms are WebRTC written in-house, signalled through Firestore, peer to peer, and relayed through Cloudflare TURN only when a network requires it.
The apps
Android and iOS wrap the same web codebase, with native code where it is needed: 36 Kotlin files on Android (sign-in, bookings, messages, earnings, calling, and an integration with Google's Navigation SDK) and, on iOS, a call manager, trip navigation, and notification and share extensions, built with XcodeGen.
Infrastructure
51 Cloud Functions in europe-west1, each loading only the modules it needs, a change made after a 128 MiB out-of-memory error once stopped all push notifications. One scheduler function replaced 22 scheduled jobs; jobs that move money keep their own schedules. The server verifies an App Check token from every client, the database is a named one in the EU, and the security rules have their own tests. Text, images and ads are moderated by AI before they are published. Server-side AI runs keyless on Vertex AI; image AI runs on the phone, so photos of a venue never reach Symposio's servers. An admin console monitors system health and requires re-authentication for any action involving money, and the deploy script detects and deploys every function a change affects.
Integrations
Sign in with Symposio is an OpenID Connect provider, with a published discovery document and key set; the Arcade uses it for sign-in. Venues and artists can embed their Symposio card on their own website with one snippet.
Built with React 19, React Router 7, Firebase (Auth, Firestore, Realtime Database, Cloud Functions, Storage, App Check), Stripe Connect, Gemini on Vertex AI and Firebase AI Logic, WebRTC, Leaflet, Cloudflare R2 and TURN, react-i18next, and Kotlin and Swift for the native apps.
On the App Store (apps.apple.com/app/id6767295521) and Google Play (play.google.com/store/apps/details?id=net.symposio.app).
ARGO Live
Operations software for estate agencies in Cyprus: property, yachts and cars.
One system for an estate agency's listings, buyers, documents and sales, from first enquiry to completion. It reads each enquiry, matches it against the agency's listings and drafts a reply in the buyer's language, which a person approves before it is sent.
- Sales tracked through seven stages from first interest to completion, with listings imported from the XML feeds agencies already publish.
- Replies drafted in six languages: English, Greek, Russian, Chinese, Hebrew and Arabic. The property matching is deterministic; the AI model only writes the text.
- Nothing an AI model writes is sent without human approval: the approval queue is the only code path that sends messages.
- Self-serve onboarding: an agency signs up, imports its listings, adds one script tag to its website and goes live on a trial. 1,591 tests, including one that runs the whole path from signup to an approved, emailed reply.
How it's built
What it covers
Listings, imported from Kyero-style XML feeds and checked hourly for new ones; buyers, each with a saved brief shared across every channel they use; documents; deals, tracked through seven stages from interest to completion; and a daily morning summary for the agency, where the facts are computed in code and the model only writes the text, with a plain list as the fallback if the model is unavailable.
The AI
Three Claude models, chosen per task: Haiku 4.5 for extraction and classification, Sonnet 5 for valuations and summaries, and Opus 5 for all customer-facing text, chosen after comparing output in four languages. Deterministic matching decides which properties are mentioned; the model only writes the text, is instructed not to invent anything, and includes the AI disclosure required by the EU AI Act. A test fails the build if any model is referenced outside the single gateway, and each agency has daily and monthly AI spending limits, checked before every call.
The website widget
One script tag on the agency's own website. It renders inside a shadow root, so the site's CSS cannot affect it, and only responds to domains the agency has registered.
Infrastructure and security
14 Cloud Functions and two scheduled jobs in europe-west1. Agencies are isolated from each other by 329 lines of Firestore security rules, tested against the emulator; the single secret is bound only to the functions that need it; the feed fetcher is protected against server-side request forgery, with 44 attack tests; and six tests check that every feature is actually connected and reachable.
Built with Firebase (Firestore, Cloud Functions, Hosting) in europe-west1, Claude (Haiku 4.5, Sonnet 5, Opus 5) behind one gateway, the Meta and WhatsApp Business platforms for messaging, Resend for email, and a human approval step before anything is sent.
Philokalia Live
An interactive encyclopedia of Eastern Orthodox Christianity, navigated as a 3D galaxy with real orbital physics, or as atoms and molecules.
An encyclopedia of Eastern Orthodoxy with 388 topics and 1,482 connections, every claim sourced. It is navigated as a 3D galaxy: selecting a topic makes it the centre of a planetary system, with its connected topics orbiting under Kepler's laws, and the eleven most important topics are drawn as black holes with physically based light bending. A switch changes the whole map to an atomic view, with each topic drawn as an atom.
- 388 topics and 148 saints, the 274 canons in Greek with an English translation made for the site, and the feasts and saints of all 366 days.
- Orbits follow Kepler's three laws, with orbital resonances, Trojan points and Schwarzschild precession; black holes are rendered with Beloborodov's light-bending approximation.
- Atomic view: Bohr-Sommerfeld atoms with electrons filled by the Madelung rule, the Pauli exclusion principle and Hund's rule, and molecules shaped by electron-pair repulsion (VSEPR).
- No framework and no runtime dependencies; 28 test suites, each test verified by reintroducing the bug it checks for.
How it's built
Content
388 topics, from the Trinity and the Ecumenical Councils to 148 saints, with 1,482 connections. Every claim cites a patristic, conciliar or scholarly source, and the content was reviewed for doctrinal accuracy against Orthodox sources. It includes the 274 canons of the Apostles and the Ecumenical Councils in Greek with an English translation, a liturgical calendar with the feasts, fasts and saints of every day of the year, 260 hand-selected icons and photographs, a quiz generated from the map, and a prayer-rope counter.
Navigation and orbits
Each topic is a point in a 3D galaxy: colour shows its category, size its number of connections, and brightness its importance. The camera uses true perspective: zooming flies toward the point under the cursor or finger, and dragging rotates about the screen's axes, including upside down. Selecting a topic makes it the star of a planetary system, with its connected topics on elliptical orbits that follow Kepler's laws: the star at one focus, faster motion close to it, and orbital periods proportional to orbit size to the power 1.5. An orbit's eccentricity reflects how closely the two topics are related. Each category orbits in its own plane, related planets fall into orbital resonances, paired topics sit at Trojan points 60 degrees apart, and topics linked by opposition, such as a heresy and its condemnation, orbit in the opposite direction.
Black holes
The eleven most important topics are drawn as black holes when selected, using physically based optics: a Schwarzschild shadow; a thin accretion disc starting at the innermost stable circular orbit, whose image is bent by Beloborodov's light-bending approximation so the far side of the disc appears above the shadow; a photon ring and a secondary image; Doppler beaming and gravitational redshift in the disc's colour and brightness; and gravitational lensing of the stars and orbits behind. Orbits around a black hole precess (Schwarzschild precession), as observed for the star S2 around the black hole at the centre of the Milky Way.
Atomic view
A switch changes the map to an atomic view. A selected topic is drawn as an atom with one proton per connection and the neutron count of that element's most abundant stable isotope. Its electrons fill subshells by the Madelung rule, the Pauli exclusion principle and Hund's rule, including the measured exceptions, and each moves on the Bohr-Sommerfeld orbit given by its quantum numbers. The whole map becomes a set of molecules: two topics are bonded when each is among the other's four closest relations, and molecular shapes follow VSEPR (linear, trigonal, tetrahedral).
Built with hand-written JavaScript on a 2D canvas, with no framework and no runtime dependencies: the renderer, camera and physics are all written from scratch and covered by 28 test suites, each test verified by reintroducing the bug it checks for. A Node build step prerenders every page; Firebase Hosting, and Cloud Functions for readers' messages and a daily post of the day's saints. No analytics, and a strict content security policy.
Arcade Live
Nineteen arcade games in a browser, ten of them for two players at once.
Browser games written from scratch on canvas, with no game engine. Each game has a shared top-ten leaderboard, and ten support real-time two-player matches, joined by link or QR code.
- Two multiplayer models: shared-world games, simulated by the host with client-side prediction for the guest, and race games, where both players run the same seeded game and only scores are synced, so latency does not matter.
- Scores are validated by database security rules: a new score must beat the player's previous one, stay under the game's maximum, respect a three-second cooldown and use the server timestamp.
- Sign in with Symposio over OpenID Connect with PKCE, or play as a guest and keep scores on that device.
- A QR code encoder written from scratch and tested against an independent library; the whole arcade runs within Firebase's free tier.
How it's built
The games
Tetris, Snake, Flappy, Bricks, Paddle, Invaders, Rocks, Muncher, 2048, Minesweeper, Crossing, Echo, Lander, Cycles, Missiles, Battleship, Noughts and Crosses, Four in a Row and Reversi, each written from scratch on a canvas. The two-player games are Tetris, Snake, Bricks, Paddle, 2048, Cycles, Battleship, Noughts and Crosses, Four in a Row and Reversi.
Multiplayer
Each match is a Realtime Database room identified by a five-letter code. Player presence uses a heartbeat rather than message traffic, so briefly switching apps does not make a player look disconnected. Invite links open directly into the match and show a preview card in chat apps; a QR code does the same in person. Rooms are removed when the players leave, and anything older than six hours is deleted by a free Cloudflare cron job instead of a paid scheduler.
The leaderboard
One row per game and player, written only if it beats that player's previous score, never above the game's maximum, no more often than every three seconds, and with a timestamp set by the server.
Accounts
Every player is signed in anonymously on the first visit, so guest scores are still attributed. Sign in with Symposio is standard OpenID Connect (authorisation code flow with PKCE, verified against Symposio's published keys) and syncs scores across devices.
Testing
Ten suites and about 460 checks, including two real clients playing each other through the live database, every game played by a headless browser, and the QR encoder compared against an independent library.
Built with vanilla JavaScript and canvas, Firebase Realtime Database, Auth and Cloud Functions, and a Cloudflare Worker for the cleanup job. Runs within the free tier.
sisamos.net Live
My personal site and the entry point to these projects, with an animated background of falling Greek letters that form quotes.
A hand-coded single page with a canvas animation of falling Greek letters that assemble into quotes from Greek philosophers and then fall apart. Section titles are drawn the same way, the New Rome audiobook plays with its text appearing in the animation word by word, and a paid project review, including file uploads, is sold directly on the page.
- Quotes and section titles are assembled from the falling letters; while a title is on screen, some of its letters are replaced with the same word in another language, always in a non-Latin script different from the title's own.
- Glass panels with a physics-simulated outline: a ring of points on damped springs, so a touch propagates around the edge as a wave.
- Card, Apple Pay and Google Pay on the page; the payment authorises the file upload, and the server re-verifies it with Stripe before issuing signed upload URLs.
- Live statistics from five repositories (lines of code, files, commits, live sites), recomputed daily by a GitHub Actions job.
How it's built
The animation
All animation is drawn on canvas. A quote assembles letter by letter, holds, then breaks back into falling letters; section titles are drawn the same way on separate layers, up to three at once for fast scrolling. The tests count what is drawn in each frame, because these bugs are hard to see by eye but easy to measure.
Glass panels
Each section sits on a panel whose outline is a physics simulation: a closed ring of points connected by damped springs, with a 2.5 Hz natural frequency, heavily damped while the pointer is on it and lightly damped after release, so a touch propagates around the edge as a wave rather than a local dent. The background blur is clipped to the same outline.
The book
The New Rome cover animates from the header into its card with the Web Animations API. When the free chapter is playing, its words appear in the animation one at a time, spaced across each paragraph's duration in the recording.
The review
A written review of a project, bought on the page with Stripe's Payment Element and Express Checkout. The payment authorises the upload: the server confirms with Stripe that the payment has settled before issuing signed upload URLs, so no endpoint accepts files from anyone who has not paid. Without JavaScript, the same purchase works through a plain HTML form and a signed upload policy.
The statistics
A daily GitHub Actions job goes through five repositories, counts lines, comments, files and commits, checks which sites are up, and publishes the totals to the page.
Performance and testing
Frame times are measured on a real mid-range phone. With JavaScript blocked, the page falls back to a complete static version. Analytics are cookie-free, so no consent banner is needed. 32 test files, 21,256 lines.
Built with hand-written HTML, CSS and JavaScript, canvas and SVG, the Web Animations API, Firebase Hosting and Cloud Functions, Stripe Payment Element and Express Checkout, Cloud Storage signed URLs, and GitHub Actions.
The studio Live
A crew of AI agents that work on my businesses every day, each named after a figure from Greek stories, in a building anyone can visit.
About twenty agents, each a scheduled Claude Code session with a written job: a chief of staff who reads every report each morning and puts the day's three most useful things at the top, builders and testers who open pull requests, scouts who prepare visits, and a review every Sunday that reads the whole week and opens one pull request to fix the crew itself. I run it from one private desk on my phone; anyone can visit the building, knock on a door and talk with whoever is free.
- Everything that moves in the building comes from real data: a crew member at work types, one who has finished turns his own thing in his hand, and one who has something for a colleague walks it over.
- Nothing the crew does reaches the world without me: they never send, publish, deploy, merge or decide money, and the desk enforces closed shapes, daily limits and its own list of allowed links whatever a crew member asks.
- The weekly review runs on Claude Opus with a guard on every tool call: it may read the week and open its own pull request, and nothing else.
- Visitors talk with each crew member's public persona through a Cloudflare Worker on Workers AI's free plan, limited per visitor and per day; the page never carries a client's name or any private work.
How it's built
The crew
Each crew member is a Claude Code routine: a schedule, a model chosen for the job (Opus, Sonnet or Haiku), a job description and a prompt kept in one repository, and only the tools the job needs. They report each run's start, progress and end to the desk, file what they need from me, and read the words I leave them at their next run.
The desk
One Cloud Function and Firestore behind a phone-first web app, paired to my devices with single-use codes. Every write passes a closed validator: an unknown field is refused, links must point to the studio's own sites, and each key writes only for its own crew and businesses. It sends at most one morning notification and three urgent ones a day.
The building
Drawn in SVG from code, the heroes in the manner of Greek vase painting, each seated in the pose of their state, with jointed arms so a change of pose moves through the joints instead of jumping. Anyone walking goes through doors, aisles and a lift, never through a wall.
Testing
242 tests, and 231 deliberately planted defects that the tests must catch before anything ships.
Built with Claude Code routines (Opus, Sonnet, Haiku), Firebase (Cloud Functions, Firestore, Hosting) in europe-west1, SVG and CSS animation, a Cloudflare Worker with a Durable Object and Workers AI, and web push.
Why We Subscribe Live
MSc dissertation: why people subscribe, and why they stay.
My MSc dissertation in digital marketing at the University of West London, How to Create Effective Marketing Strategies for Subscription-Based Businesses, revised and expanded in a 2026 second edition of 83 pages, with an audiobook in two voices: a clone of my own voice and a synthetic studio voice. The first chapter is free; the rest of the audiobook is fifteen euro.
- Five chapters and 24,824 words: 2 hours 35 minutes in my voice, 2 hours 55 minutes in the studio voice.
- My voice is cloned with Chatterbox and generated locally on one GPU; the studio voice is Kokoro, a synthetic voice not cloned from anyone, which runs on a CPU.
- Paid files are not publicly accessible: a Cloud Function verifies the payment with Stripe, then issues a short-lived signed link to the PDF in Cloud Storage or to a chapter in Cloudflare R2.
- A pre-deploy check blocks any release whose manifest lists a chapter missing from storage, and a smoke test creates a real access grant in production and downloads a file with it.
How it's built
The study
A study of why people in Cyprus take up subscriptions and why they cancel them: an online questionnaire answered by 50 people in 2023, closed questions analysed descriptively and open ones thematically, ending in a four-stage framework and eleven recommendations. The second edition is revised and expanded throughout.
The voice
Chatterbox takes a voice's timbre from the first ten seconds of a reference recording, so the choice of those ten seconds matters more than the recording's length; the clip was chosen by listening as well as by similarity score. It runs locally on an RTX 4070 Ti at about nine seconds per chunk. Two jobs on the same GPU were measured at thirty minutes per chunk, so they never run together.
Payments and access
Unlocking converts a settled payment into an access grant stored where no browser can read it; the grant is exchanged for short-lived signed links, one file at a time. A lost grant can be restored from the buyer's email and the receipt reference, and refunds are detected within a day.
Release checks
Added after a renamed chapter was unavailable to paying listeners for about a day and a half: a pre-deploy check blocks any release whose manifest lists a chapter missing from storage, and a smoke test creates a real grant in production, downloads a file with it and deletes it.
Built with Chatterbox and Kokoro for the voices, one Cloud Function holding the entitlement, Cloud Storage and Cloudflare R2 behind signed links, and Stripe Payment Element.
New Rome Live
A philosophical novel in dialogue, published and narrated one chapter at a time.
A philosophical novel in dialogue in the tradition of Plato's Republic: eleven conversations about what a just state would be, each set in a real place in Cyprus. Seven are written, in English and Greek (59,284 words), and all seven are narrated, read by the character Myrto in a voice cloned from my grandmother's. The first chapter is free; twelve euro buys the rest as they are published, plus the finished book.
- Over six hours of narration in each language.
- A margin marker tracks the narration through each paragraph, timed sentence by sentence, and the reading position is kept between sisamos.net and the book's site.
- Greek question intonation is checked automatically: each question is generated several times and the take with the correct pitch contour is kept (57 of 57 wh-questions fall at the end, 50 of 51 yes/no questions rise).
- Failed takes, overlong, mostly silent or stalling mid-sentence, are detected and regenerated, using thresholds measured over 6,187 audio chunks.
How it's built
The chapters
The Ground We Sit On, above Kourion; Do Not Erase, in an empty primary-school classroom in Episkopi; The Line, at a National Guard post and on Ledra Street in Nicosia; Noise, in a server room in Limassol; The Ward, in a surgical ward at night; The Mountain of the Cross, at Stavrovouni; and The Tomb, at Tymvos Makedonitissas. Each chapter is built around one question, from "What is a citizen?" to "What may a just state ask a man to die for?"
The narration
Chatterbox again, generated locally one line at a time. Each Greek question is generated several times, and the take whose pitch falls at the end (questions with a question word) or rises (yes/no questions) is kept. Takes that hit the model's 40-second limit, are mostly silence, or stall mid-line are detected and regenerated.
Read-along
Audio timing is recorded against the exact paragraphs the build produces, so text and audio stay in sync. On the page, a marker beside the current paragraph grows as it is read, timed a sentence or two at a time, and a column of Roman numerals jumps to any section of the chapter.
Payments and access
Twelve euro, paid on the page by card or digital wallet. Each payment adds to the buyer's access grant, stored in a session cookie shared across sisamos.net's sites; a lost grant can be recovered by email or Google sign-in. Paid recordings are served through 30-minute signed links to Cloudflare R2; the free chapter is public.
The build
A Python build generates the whole site, the reader and the timing maps from the manuscript in both languages, without altering the text.
Built with Python, Chatterbox, Firebase Hosting, Cloud Functions for access, signed links and recovery, Stripe Payment Element and Express Checkout, and Cloudflare R2 (no egress fees).
Working together
Fixed stages, a price and a date on each, agreed before anything begins.
It does not start with a meeting. Send me what you have, a brief, a specification, a folder of documents, a half-built product, and I read all of it and send back a written plan: the system I would build, in stages, with a price and a date on each stage, what I would cut, what it costs to run, and where it goes wrong. Three working days, one hundred and fifty euro, and it comes off the first invoice if we go on to build it.
The plan is yours either way. Take it to any developer, or to me.
sisamos.net/review chris@sisamos.net