Guide 2 of 3
How to publish a browser game
Where to host it, what a custom domain actually costs you, how embedding works, why mobile input will eat a day, and the load-time budget that decides whether anyone plays it.
On this page7 sections
Publishing a browser game is genuinely easy and almost everyone still loses a day to it, because the easy part is the upload and the hard parts are the four things nobody mentions: what happens to your URL in two years, how the game behaves inside an iframe, what a thumb can actually reach, and how long a stranger will stare at a blank canvas before closing the tab.
Where to host it
All four of these will serve a static build for free and none of them will fall over if your game does well. They differ on ownership, audience and what happens when you need a server.
| Compare | itch.io, opens in a new tabGame host with a storefront | GitHub Pages, opens in a new tabStatic hosting off a repo | Vercel, opens in a new tabStatic plus functions | Netlify, opens in a new tabStatic plus functions |
|---|---|---|---|---|
| Cost | Free. Optional pay-what-you-want with a revenue split you set. | Free, no bandwidth meter you will realistically hit. | Free hobby tier. Commercial use needs a paid plan. | Free tier with a monthly bandwidth cap. |
| Default URL | you.itch.io/game | you.github.io/game | game.vercel.app, plus a URL per deploy | game.netlify.app |
| Built-in audience | Yes. Browse pages, jam listings and a following system. The only one on this list where people arrive on their own. | None whatsoever. | None. | None. |
| Server-side code | None. Static uploads only. | None. Anything dynamic needs a separate service. | Yes. Edge and serverless functions, enough for a leaderboard, a daily seed or a save endpoint. | Yes. Functions, plus form handling that is genuinely useful for an in-game feedback box. |
| Watch out for | Your game runs inside their iframe, so focus, fullscreen and scroll behave differently to your own page. Test there, not just locally. | The project-subdirectory path breaks absolute asset URLs. Use relative paths or set a base, and expect a cache that takes a few minutes to catch up. | Functions cold-start. A leaderboard write that takes 800ms on the first call after a quiet hour feels broken to a player. | The bandwidth cap is the one on this list you can actually hit. A 20 MB Unity export and a good launch day is a real combination. |
| Pick it when | You want payments, jam visibility and a page you do not have to design. | The game is static, the source is already on GitHub, and you want a link that still resolves in five years. | The game needs a backend, or you want a preview URL for every commit while you tune it. | You want functions and forms without configuring anything, and your build is small. |
Free tiers as of mid-2026. Every one of these is a fine choice; the differences only matter once you know which of them you care about.
Game host with a storefront
- Cost
- Free. Optional pay-what-you-want with a revenue split you set.
- Default URL
you.itch.io/game- Built-in audience
- Yes. Browse pages, jam listings and a following system. The only one on this list where people arrive on their own.
- Server-side code
- None. Static uploads only.
- Watch out for
- Your game runs inside their iframe, so focus, fullscreen and scroll behave differently to your own page. Test there, not just locally.
Pick it when: You want payments, jam visibility and a page you do not have to design.
Static hosting off a repo
- Cost
- Free, no bandwidth meter you will realistically hit.
- Default URL
you.github.io/game- Built-in audience
- None whatsoever.
- Server-side code
- None. Anything dynamic needs a separate service.
- Watch out for
- The project-subdirectory path breaks absolute asset URLs. Use relative paths or set a base, and expect a cache that takes a few minutes to catch up.
Pick it when: The game is static, the source is already on GitHub, and you want a link that still resolves in five years.
Static plus functions
- Cost
- Free hobby tier. Commercial use needs a paid plan.
- Default URL
game.vercel.app, plus a URL per deploy- Built-in audience
- None.
- Server-side code
- Yes. Edge and serverless functions, enough for a leaderboard, a daily seed or a save endpoint.
- Watch out for
- Functions cold-start. A leaderboard write that takes 800ms on the first call after a quiet hour feels broken to a player.
Pick it when: The game needs a backend, or you want a preview URL for every commit while you tune it.
Static plus functions
- Cost
- Free tier with a monthly bandwidth cap.
- Default URL
game.netlify.app- Built-in audience
- None.
- Server-side code
- Yes. Functions, plus form handling that is genuinely useful for an in-game feedback box.
- Watch out for
- The bandwidth cap is the one on this list you can actually hit. A 20 MB Unity export and a good launch day is a real combination.
Pick it when: You want functions and forms without configuring anything, and your build is small.
Custom domains
A domain costs roughly fifteen dollars a year and buys you exactly two things. First, portability: if your host changes its terms or vanishes, you repoint a DNS record and every link anybody ever shared still works. Second, credibility, which sounds soft but is measurable. A link to yourgame.com gets clicked more than a link to a subdomain of a platform, especially in group chats where nobody recognises the host.
What it does not buy you is speed or search ranking. Do not buy one for your first prototype. Buy one when you have two or three games and can put them at yourname.com/game-one. A small portfolio at one address compounds in a way that three scattered subdomains never do.
The setup is the same everywhere and takes about ten minutes:
Buy the domain somewhere boring
5 minA registrar with free WHOIS privacy and no upsell funnel. Skip the hosting, email and site-builder add-ons entirely; you need DNS and nothing else.
Point DNS at the host
5 minA
CNAMErecord forwwwpointing at your host, and either anALIAS/ANAMErecord or the host's A records for the bare domain. Every host on the list above documents the exact values.Wait for HTTPS, then check the redirect
Up to an hourCertificates are automatic and usually take minutes. Then pick one canonical form (with or without
www) and make the other redirect to it. Two live copies of your game at two URLs splits every share link you will ever get.
Embedding and iframes
Your game will end up inside an iframe whether you plan for it or not: itch.io does it, portfolio sites do it, and aggregators do it. Three things break, always the same three.
Keyboard input needs focus. An iframe does not receive key events until something inside it is focused, so a player who loads your page and immediately presses an arrow key gets nothing and concludes the game is broken. The fix is a click-to-start screen: it gives you focus, and it also satisfies the browser gesture requirement for audio. One screen, two problems.
Sizing is not automatic. An iframe has no idea how big your game wants to be. Give it explicit dimensions and make your canvas scale to its container rather than to window, or you will get a game that renders correctly on your site and is cropped on everyone else's.
Permissions are opt-in. Fullscreen, gamepad, pointer lock and autoplay all need to be granted by the embedding page:
<iframe
src="https://yourgame.com/"
width="960" height="540"
allow="autoplay; fullscreen; gamepad; xr-spatial-tracking"
title="Neon Drift: a browser racing game"
></iframe>If you would rather not be embedded at all, a Content-Security-Policy: frame-ancestorsheader on your host settles it. Most makers should not bother. An embed on somebody else's portfolio is free distribution.
Mobile input
More than half the people who open a link from a phone are on a phone. A keyboard-only game is a perfectly legitimate choice, but it should be a choice, and it should be labelled. On vibedgame the platform field and the mobile tag are exactly for this, and mislabelling costs you far more than admitting the game needs a keyboard.
If you do want touch to work, the checklist is short and unforgiving:
touch-action: noneon the canvas element. Without it, every swipe scrolls the page instead of steering.- Use pointer events, not mouse events. One code path covers mouse, touch and stylus, and multi-touch stops being a special case.
- Controls no smaller than 44 CSS pixels, positioned in the bottom corners where thumbs already are. Not centred, where a hand covers the game.
- Never put a control within a thumb-width of the bottom edge. That is where the browser gesture bar lives and you will lose the input to it.
- Listen to
visualViewportrather thanwindow.innerHeight, because the browser chrome hides and reappears while people play and your layout will jump if you do not. - Add a short haptic on meaningful hits if the device supports it. It is two lines and it changes how a touch game feels more than anything else on this list.
The load-time budget
This is the number that decides how many people play your game, and it is the one nobody measures. The target: something interactive on screen within three seconds on a mid-range phone over 4G. In practice that means about 500 KB transferred before the first frame.
A big build is not automatically fatal, but a big build behind a blank screen is. The move is to reorder rather than to shrink:
- Show something in the first 500 ms. A title screen with your own logo drawn in code weighs nothing and turns dead time into anticipation. A real progress bar beats a spinner, and both beat white.
- Load level one, not all thirty. Fetch the rest while the player is reading the title screen. Almost nobody does this and almost everybody could.
- Compress the art properly. WebP or AVIF over PNG, and a texture atlas over forty separate sprite requests. A 2 MB spritesheet is usually a 200 KB spritesheet that nobody ran through a compressor.
- Audio is where the megabytes hide. A two-minute WAV loop is 20 MB. The same loop as a 96 kbps OGG is 1.4 MB and nobody will hear the difference over laptop speakers.
- Check what your engine ships. Godot and Unity web exports carry a runtime measured in megabytes. That is a legitimate trade. Just budget the rest of the game around it, and put a real loading screen in front of it.
The pre-launch check
Ten minutes, once, in this order. It catches nearly everything that gets reported in a launch-day comment thread.
- Open the deployed URL in a private window. No cache, no localStorage, no logged-in anything.
- Watch the network tab for 404s. Case-sensitive filenames are the single most common deploy bug and they only appear here.
- Confirm HTTPS with no mixed-content warnings. One
http://asset and browsers block it silently. - Play it on a real phone, on cellular, not on your wifi.
- Resize the window mid-game. Then do it again while something is moving.
- Die and restart. Confirm the restart is instant and does not reload the page.
- Check the volume at a normal system level, on headphones.
- Set an
og:imageand a title. When somebody pastes your link in a Discord, that preview is your first screenshot. - Send the URL to one person and watch them open it. Say nothing.
Once that passes, you have a game anyone in the world can play in one click, which is the whole point of the browser. What is left is getting people to click, and that is the next guide.