Most "deploy your side project" tutorials end with you juggling three dashboards: one for the frontend, one for the backend, one for the database. Three hosts, three sets of env vars, three billing pages, three things that can silently break.
I built a full realtime app — a mobile-first World Cup live-score + fan chat platform — and deployed the whole thing (React PWA, Node.js/Socket.io backend, and database) on a single platform: PocketBase Cloud.
This post is about that setup: what the app is, how it's built, and why running the entire stack on one platform turned deployment from the worst part of the project into a non-event.
Code is open source 👉 github.com/HoangTien0204/apprealtime
What the app does
- 📺 Follow matches with live score updates as they happen
- 💬 Realtime fan chat per match, with presence and typing indicators
- 🏆 Fill out brackets and make predictions
- 📱 Installable PWA — feels native on mobile, works offline
The stack
- Frontend — React 19 + Vite + TailwindCSS + Framer Motion, built as a PWA
- Backend — Express 5 + Socket.io 4 (Node.js), with a live-match simulator
- Database — PocketBase, for persisting chat messages and predictions
Three services, cleanly separated. And all three deployed on PocketBase Cloud.
Why PocketBase Cloud for the whole stack
Here's the thing people don't realize about PocketBase Cloud: despite the name, it isn't just a place to park a PocketBase instance. On the Pro plan it hosts:
- 🗄️ The PocketBase database — managed, with SSL and backups handled
- 🌐 The frontend — static hosting for the React PWA build
- ⚙️ A Node.js / Deno / Bun backend — so my Express + Socket.io server runs right there too
That covers every layer of my app. So instead of wiring my frontend on Vercel to a backend on Railway to a database on some VPS — and debugging CORS and env vars across all three — everything sits behind one dashboard, on one dedicated server.
| Layer | Where it runs |
|---|---|
| React PWA (frontend) | PocketBase Cloud — frontend hosting |
| Express + Socket.io (backend) | PocketBase Cloud — Node.js backend hosting |
| PocketBase (database) | PocketBase Cloud — managed instance |
Full disclosure: PocketBase Cloud is a product I also build. I run this real project on it precisely because I built it to solve this exact pain — and dogfooding it on something with a live Socket.io backend and a real database is the best way to keep it honest. If a deploy step is annoying, I feel it before my users do.
How the realtime part works (and where each tool fits)
The one design decision I want to highlight: realtime transport and realtime persistence are two different jobs.
┌─────────────┐ Socket.io ┌──────────────┐ writes ┌─────────────┐
│ React PWA │◄──────────────►│ Express + │────────────►│ PocketBase │
│ (browser) │ REST /api │ Socket.io │ │ (database) │
└─────────────┘ └──────────────┘ └─────────────┘
live scores · chat · presence chat history · predictions
- Socket.io does the live layer — pushing score changes, match events, chat messages, presence, and typing indicators to every connected client at once.
- PocketBase does persistence — every chat message and prediction gets written so history survives a reload or a restart. Single binary, admin UI, SQLite underneath, JS migrations. Zero database setup.
And all of it — the Socket.io process and the PocketBase database — lives on PocketBase Cloud. The Node backend talks to the database over a local POCKETBASE_URL on the same platform, which keeps latency low and config simple.
The live-match simulator
So the app isn't dead outside match days (and so I don't burn API quota while building), the backend ships with a match simulator: 8 seconds = 1 in-game minute, generating goals and events and pushing them over Socket.io exactly like real data. For production you swap it for a real feed via an API_FOOTBALL_KEY env var — and since it's all on one platform, that's a single env var change in one dashboard.
Running it locally
npm run install:all # install deps in each subproject
npm run dev # frontend :5173, backend :4000, pocketbase :8090
The PocketBase binary auto-downloads on first launch — no manual database install. Migrations create the chat_messages, predictions, and favorites collections for you. Then deploying to PocketBase Cloud is just pointing each service at the platform instead of localhost.
What I learned
Two takeaways:
- "Realtime" isn't one problem, it's two — transport (Socket.io shines) and persistence (PocketBase is a joy). Keep them separate and every piece stays simple.
- Deploying a multi-service app doesn't have to mean multi-platform — putting the frontend, the Node backend, and the database on PocketBase Cloud collapsed my deploy story from three dashboards to one. That's the part that surprised me most.
Try it
- 🧑💻 Read / clone the code: github.com/HoangTien0204/apprealtime
- 🚀 Deploy your own full stack in ~30 seconds: pocketbasecloud.com (Free plan works to try it)
If you build on it or spot something I could do better, I'd love to hear it in the comments — and a ⭐ on the repo never hurts. ⚽
Curious how a Node/Socket.io backend runs on PocketBase Cloud, or how to migrate a scattered stack onto one platform? Ask below — happy to go deeper.
Top comments (1)
Hi tienbuilds, I saw your post about deploying your real-time app. I think Clypify could help you streamline your content management and deployment process. Our tool can help you aggregate RSS feeds and publish to WordPress and Medium with ease. Free plan at clypify.com — no card needed.