
I Built a Live Event Platform with Google Antigravity, and It Runs for $2 a Month
Five buildathons feeding one showcase event needed a platform nobody had the volunteer hours to build. I built it in a weekend with Google Antigravity: Google auth, role-based access, submissions, moderation, live Q&A and voting, running for about $2 a month on Firebase.
Key Takeaways
- Projects built at a distributed buildathon are seen by the room they were built in and nobody else, unless something collects them. That, not the technology, is why the platform exists.
- Work that would previously have taken 10+ developer volunteers was handled by one person working with AI, over a single weekend.
- The build loop that actually worked was: idea, plan the architecture, let the AI build, test, iterate, ship. The planning step is the one people skip.
- Google Antigravity is fast for scaffolding and features, but the parts that matter most (Security Rules, data modeling, the authorization model) still need engineering judgment.
- The Admittance Agent scored every application against configurable criteria, including the chapter's diversity and inclusion goals, and checked the applicant's real public activity through MCP connections such as GitHub, so selection ran on verifiable signal instead of self-reported signal.
- AI ran as an operational layer across the whole event lifecycle, from registration and participant selection through moderation and certificates, rather than as a chatbot bolted on the side.
- Role-based access rides on signed Firebase custom claims, and Firestore Security Rules, not Cloud Functions, are the real enforcement boundary.
- The whole stack comes to about $2/month (Hosting $1.59, Firestore $0.41, Cloud Functions $0.11), with Hosting, not the database or the functions, being the largest line item.
Build With AI Sri Lanka ran as five buildathons across different communities, feeding into one main showcase event. That shape is wonderful for reach and brutal for visibility. A project built on a Saturday gets seen by the forty people in that room, gets a round of applause, and then quietly disappears. Across five locations and 2000+ builders in total, that means most of the work the community produced would never be seen outside the room it was built in.
That is the actual reason the platform exists. Not "we wanted to build something." We needed one place where every buildathon's projects get submitted, moderated, shown to everyone and voted on, and one main event where all of them stand in front of the same audience.
I build Go backends for a living, so there is a certain irony in what I am about to say: the thing I shipped for this has almost no backend of my own, no servers to keep alive, and no monthly infrastructure bill worth mentioning. It is a live event and project showcase platform for Build With AI Sri Lanka, I built it in a weekend with Google Antigravity, and it runs for about $2 a month on Firebase. I ended up telling that story on stage at the SEAS Community Leads Summit in Bangkok, which is where the photos further down come from.
What the platform does
It is the software layer for a distributed hackathon and the showcase that follows it:
- Project submission so builders from any of the five buildathons push their work into one place.
- Moderation so organizers review what comes in before it goes public.
- A public showcase where every buildathon's projects live together instead of in five separate rooms.
- Project voting with a live leaderboard that updates as votes land.
- Google authentication so attendees, organizers and speakers sign in with one tap.
- Role-based access with five roles (admin, organizer, builder, voter, speaker), and a person can hold several at once. Each surface renders only what that person is allowed to do.
- A live agenda the organizers can update in real time.
- Audience Q&A during sessions, where anyone signed in can ask and only staff can answer.
- Certificates and the smaller event-operations chores that otherwise eat a volunteer's entire weekend.
All of it real-time, all of it multi-role, all of it needing to hold up while a room full of people hit it at once during the event, and then go quiet for the rest of the month.
One thing is deliberately not in that list. Attendee selection happens before any of this, in a separate tool called the Admittance Agent, and it is the piece of the whole program I would rebuild first. More on it below.
The problem was not the event. It was the scale.
Going distributed multiplied everything at once: more builders, more projects, more coordination between locations, and far more moderation. The one thing it did not multiply was engineering capacity. We had no volunteer engineering team standing by to build a showcase platform, and community volunteers have day jobs.

The slide that landed hardest: work that previously required 10+ developer volunteers, handled by one developer working with AI.
I want to be precise about that number, because it is the kind of claim that gets repeated badly. I am not saying AI replaced ten developers. I am saying that work which would previously have needed 10+ developer volunteers and a much longer coordination cycle was handled by one person working with AI, over one weekend. The volunteer hours were the scarce resource. That is what changed.
Built in a weekend with Google Antigravity
I built this agentically: describe what the event actually needed, let Google Antigravity generate and wire it, run it, correct course, repeat. The loop looked like this:
Idea → Plan architecture → AI builds → We test → Iterate → Production

The deck compressed the loop into "idea, instructions, AI builds". The honest version has a planning step in the middle, and it is the step that made the rest work.
That middle step matters more than anything else on this page. The version of the loop that goes straight from a prompt to generated code is the version that produces a demo you cannot operate. Planning the architecture first, in particular the roles, the data model and the authorization boundary, is what made every later feature a small change instead of a rewrite.
A few honest observations from building this way:
Where it flew. Scaffolding the Next.js app, standing up the Firebase SDK wiring, building out the submission, showcase, agenda, Q&A and leaderboard UI, and turning "add a page that does X" into working screens. This is where an agent earns its keep. The loop from idea to something-on-screen was short enough that I could actually explore designs instead of committing to the first one.
Where I stayed in the driver's seat. The things that would hurt if they were wrong did not get delegated. The Security Rules were mine to own, because in this architecture they are the authorization model: which role can read which document, which fields each role may change, and how a vote is validated. So was the data model: getting Firestore documents shaped so counters and roles are server-owned and immutable, so the leaderboard stays consistent under concurrent votes, and so real-time listeners do not fan out into a surprise bill. And cost: keeping work on the client and in cheap reads and writes rather than reaching for heavier services.
The honest summary is that Antigravity moved the typing to near-zero and left the engineering, the security and data-modeling judgment, exactly where it should be. That is a good division of labour, not a threat to it.
AI across the whole event lifecycle
The platform is the visible part, but it is not where most of the leverage came from. AI ended up running as an operational layer across the entire lifecycle of the program.
Before the event. Registration was AI-assisted, and the piece I would rebuild first for any future program is the Admittance Agent, an AI-powered tool we built for GDG Sri Lanka that automates attendee selection. The name comes from Harry Potter, from the Book of Admittance and the Quill of Acceptance: the pair of enchanted objects kept in a tower at Hogwarts that between them decide which children get a letter. Naming an attendee selection tool after them is not subtle, and that was the point.
A distributed buildathon gets far more registrations than it has seats, and the usual fallback is either first-come-first-served, which rewards whoever refreshes fastest, or a volunteer reading hundreds of forms at midnight and getting steadily less consistent with every one. The Admittance Agent evaluates each application instead, and scores candidates across configurable criteria: stated experience level, what the person said they wanted to build, prior community participation, location relative to each buildathon, and the balance of the cohort we were trying to assemble. Those criteria and their weights are configuration rather than something baked into the code, which matters more than it sounds. A buildathon aiming for first-timers and one aiming for advanced builders want genuinely different cohorts, and retuning the agent for each is a config change, not a rewrite.
Diversity and inclusion sit inside that scoring rather than getting bolted on at the end. GDG chapters care a great deal about who is actually in the room: first-time participants, women builders, builders from communities well outside the main cities, people who have never found a way in before. Those are goals organizers can configure like any other criterion, and the agent reports how a shortlist looks against them while there is still time to do something about it. The alternative, which most of us have lived through, is noticing the imbalance on event day when the only remaining option is to feel bad about it.
The part that made it worth building is that it does not stop at the form. Through MCP connections to services like GitHub, the agent looks at what an applicant has actually shipped in public, so "I have built things with AI before" is something it can go and check rather than something it has to take on faith. Self-reported signal becomes verifiable signal.
It produced a ranked shortlist with its reasoning attached, and organizers made the final call. It did not remove human judgment from selection. It gave the humans a consistent starting point instead of decision fatigue, and it made the selection defensible when someone asked why they did or did not get a seat. The same approach then carried into selecting which projects moved forward to the main showcase.
During the event. Q&A moderation, session support, and automated communication across the locations.
After the event. Project submissions, the showcase, voting, moderation, certificates, and the long tail of event operations.
The part that turned this from "useful chatbot" into something operational was MCP. I will not go deep on the protocol here. What it gave us is simple to state: the AI could work directly with the tools and data we were already using to run the event, so it could take actions inside our workflows instead of answering questions in a chat window and leaving the doing to us. The Admittance Agent is the clearest example of the difference: an AI that asks you about a candidate is a chatbot, and an AI that can go and look at their GitHub is an assistant.
That is the shift worth naming. GenAI was not a feature in the platform. It was an operational layer across the community lifecycle.
Architecture
Nothing exotic, but one detail shapes everything: the app is a Next.js static export. There is no Next.js server. The browser talks to Firebase directly through the Web SDK, Firebase Auth handles identity, Firestore is the real-time database, and a small set of Cloud Functions is the only trusted compute. GitHub Actions ships the front end.
architecture-beta
group fb(logos:google-cloud)[Firebase]
service user(internet)[User browser]
service host(logos:nextjs)[Hosting Nextjs static export] in fb
service auth(logos:google-icon)[Auth Google sign in and custom claims] in fb
service db(logos:firebase)[Firestore and Security Rules] in fb
service fn(logos:firebase)[Cloud Functions] in fb
service ci(logos:github-actions)[GitHub Actions]
user:R --> L:host
ci:B --> T:host
host:R --> L:auth
host:B --> T:db
fn:L --> R:db
The important design decision is where authorization lives, and it is not where people usually assume. Because there is no server in the request path, Firestore Security Rules are the enforcement boundary: every read and write the browser attempts is authorized live against the Rules, independent of anything the client believes. Cloud Functions exist only for the two things that genuinely cannot happen in the browser, no matter how much you trust it: setting a user's role (a signed custom claim only the Admin SDK can write) and maintaining vote counts. There are exactly three of them (syncUser, setUserRole, onUserVoteWrite). Project approval, agenda edits and Q&A replies are plain Firestore writes, gated entirely by Rules.
Here is the voting path, which is the part that most needed to be tamper-resistant. Notice there is no callable in it:
architecture-beta
group fb(logos:firebase)[Firebase]
service voter(internet)[Participant]
service rules(logos:firebase)[Security Rules one vote valid target] in fb
service votes(database)[userVotes one per user] in fb
service trig(logos:firebase)[onUserVoteWrite trigger] in fb
service board(database)[projects voteCount leaderboard] in fb
voter:R --> L:rules
rules:R --> L:votes
votes:B --> T:trig
trig:R --> L:board
A participant writes their single userVotes/{uid} document straight to Firestore. The Rules do the guarding: one document per user means one vote total, and the vote must target a project that actually exists, is approved, is not soft-deleted, and is not the voter's own. The count itself is never written by the client. A Firestore trigger, onUserVoteWrite, recomputes projects.voteCount transactionally on every change, so the leaderboard reads a number the browser cannot forge.
The discipline behind the "vibe coding"
"Building agentically" gets a reputation for being sloppy, so it is worth being specific about what actually kept this honest. The git history (52 commits from the first README to this session) reads less like vibe coding and more like a normal, disciplined build that happened to have an agent doing the typing:
- The backend was designed before it was built. This is the
Plan architecturestep of the loop, made concrete. The first Firebase-related commit is not code, it isdocs/FIREBASE_ARCHITECTURE.md: the RBAC model, data model, Security Rules, vote integrity and hardening plan, all written up front. The security model was the starting point, not something improvised feature by feature. - It shipped in deliberate, reviewable phases. Static UI port, then a shadcn/ui migration, then the CI and deploy pipeline, then Google sign-in and custom-claims RBAC, then live Firestore data (behind a flag first), then hardening, then the feature layer (submissions, Q&A, leaderboard, agenda, scheduling). No giant "add everything" commit. Each step stands on its own.
- Defense in depth, never UI-only gating. Every feature was checked against "does a Rule enforce this," not "is the button disabled." Roles come from server-issued custom claims, the Rules are the authorization boundary, and Cloud Functions are the only trusted writer for roles and counts.
- I pentested my own production app. One commit, "Harden security rules and fix 6 open GitHub issues," came out of a live pentest against production with disposable accounts (cleaned up afterward). It surfaced real problems:
javascript:/data:URI injection, self-voting, votes for non-approved projects, missing rate limits. They were fixed proactively rather than after an incident, tracked as real GitHub issues and referenced by number in the commits, not just patched from memory. - Scaffolding got deleted when it stopped earning its keep. The Remote Config demo-mode toggle that served dummy data early on was removed once the app matured, instead of living on as dead weight.
- The static-export constraint stayed honest the whole way. Despite a full Firestore, Auth and Functions backend, the front end never sprouted an API route or a server component.
next buildverified that on every change. - No test suite, so the build was the gate. With no tests,
npx tsc --noEmit,npm run build, and checking real production Firestore state became the actual definition of "done," run after essentially every change rather than declared from reading the diff.
The common thread: front-load the security and architecture, enforce them at the data layer, ship in increments you can actually review, and verify "done" against the running system. The agent makes that faster. It does not make it optional.
Security, the honest version
Access control rides on Firebase custom claims. A user's roles live as a signed roles array on their ID token, set only by the Admin SDK inside a Cloud Function. The Rules authorize against request.auth.token.roles, which is tamper-proof because Firebase signs it and only server code can set it. There is a mirror copy in users/{uid}.roles too, but it exists purely for display and admin queries. The Rules never read it for authorization, so even if it drifted it could not become a privilege-escalation path.
Two of the sharpest rules came out of a pentest, not the original design:
- No self-votes, no fake targets. A
voteTargetOK()check in the Rules requires every vote to point at a project that exists, is approved, is not soft-deleted, and is not owned by the voter. Before that, the door was open to voting for a project that should not have been eligible, or for your own. - No
javascript:URLs. Projects carry demo, repo and video links that get rendered as anchors. AurlOK()check pins those fields to empty orhttp(s)://, so a storedjavascript:ordata:URI can never execute as an<a href>. That is a stored-XSS class of bug closed in the Rules layer, where the client cannot opt out of it.
And the honest gap: there is no App Check yet. The anti-abuse layer in production today is per-uid rate limiting on the two callables plus the Rules themselves. The Rules still fully authorize every read and write regardless, but nothing yet blocks a scripted, non-browser client at the edge. It is the highest-value piece of hardening still on the list, and I would rather say that plainly than imply the thing is bulletproof.
The $2 economics
Here is why a platform like this is so cheap to run: a buildathon showcase is bursty. It does real work for a few hours on event day and essentially nothing the rest of the month, so you only ever pay for the traffic the events actually generate. For this one, the whole monthly bill came to about $2:
| Firebase service | What it does here | Monthly cost |
|---|---|---|
| Hosting | Serves the Next.js app + static assets | $1.59 |
| Firestore | Real-time data (votes, agenda, Q&A) | $0.41 |
| Cloud Functions | Role claims and the vote counter | $0.11 |
| Authentication | Google sign-in | $0.00 |
| Total | ≈ $2.11 |
The surprise, at least to me, is the shape of it: Hosting is the biggest line at $1.59, not the database, not the functions. Firestore's real-time reads and writes during the event came to $0.41, and the three Cloud Functions doing role claims and vote counting cost all of $0.11. Google sign-in was free.
No servers to keep warm, nothing to right-size, nothing to scale down after the event because there was never anything running between events. For a live app with auth, roles, real-time data and server-side validation, ~$2 is a remarkable price.
Taking it to the Community Leads Summit

SEAS Community Leads Summit 2026, Bangkok. Explaining how GenAI changed the way we run community programs.
I gave a lightning talk about this at the SEAS Community Leads Summit 2026 in Bangkok, to a room of community leads from across South and Southeast Asia. The point I made was this: we did not scale the team, we scaled the workflow.
Four things I would hand to any other community organizer:
- Automate the repetitive. Registration, selection, moderation, communication, coordination. These are the tasks that quietly consume volunteers, and they are the ones AI is genuinely good at.
- Connect AI to real workflows. MCP and tool access are what turn an AI from a chatbot into an operational assistant that can act in the systems you already run the event on.
- Build instead of waiting for resources. You do not always need a large volunteer engineering team to create useful community infrastructure. That assumption was true for a long time. It is much less true now.
- Scale impact, not complexity. The goal is not to run more events with more people. It is to build systems that let communities grow without multiplying operational overhead.
The reaction in the room was not really about the platform. It was about the permission. Most community leads have a list of things they would build if only someone had the time, and that list has been frozen for years.
The takeaway
Three things surprised me building this. How much of the grunt work Google Antigravity could carry while I kept my hands on the parts that actually needed an engineer. How little a genuinely useful, real-time, multi-role event platform costs when you lean into serverless and let free tiers absorb bursty traffic. And how much of the value ended up outside the platform entirely, in the selection, moderation and communication work that used to be somebody's whole weekend.
AI does not replace community. It amplifies it. The biggest change is not that AI can build our tools. It is that it lets community organizers think bigger about what they can build.
Five buildathons. 2000+ builders. One showcase where all of that work is actually visible. A Next.js app, a handful of Cloud Functions, and a $2 invoice.
Links: the live platform is at bwai.gdgsrilanka.org (Build With AI Sri Lanka).

Chamod Shehanka
Software Engineer II at Circles building cloud-native systems with Go and Kubernetes. CNCF & CD Foundation Ambassador, Jenkins GSoC mentor, and lead of Kubernetes Sri Lanka & GDG Sri Lanka.