Games Guide

Build a world-class
Games Hub.

Everything you need to embed, host, and curate unblocked games on your site — from simple iframes to full local game libraries with category filters and search.

  Low Difficulty   ~30 min read   Updated 2026
Let the games begin.
On this page
01

Overview & Architecture

A games hub is the most common type of UBG site. The core idea is simple: you present a curated list of games, and when a user clicks one, it loads inside an iframe or a dedicated game page — bypassing school/work network filters by either using a proxy or loading from a CDN source that isn't blocked.

There are two fundamental approaches: CDN embedding (link to games hosted elsewhere — fast to ship, zero storage cost) and self-hosting (download and serve games yourself — more reliable, no third-party downtime). Most professional sites combine both.

Architecture tip Keep your game data (titles, URLs, thumbnails, categories) in a single JSON file. This makes it trivial to add games later and lets you generate the game grid dynamically via JavaScript — no copy-pasting HTML for every game.

The typical file structure for a games site looks like this:

project structure
my-games-site/
├── index.html          # Home / game grid
├── game.html           # Game viewer page (fullscreen iframe)
├── assets/
│   ├── style.css
│   └── main.js
├── data/
│   └── games.json      # All game metadata
└── games/              # Self-hosted games (optional)
    ├── slope/
    └── 1v1-lol/

02

Game Embed Methods

Pick the right embedding strategy for each game. Most sites use a mix depending on what's available for a given title.

Direct iframe

Load a CDN URL directly inside an <iframe>. The simplest approach — no backend required. Works when the source allows cross-origin framing.

Recommended

Self-hosted ZIP

Download the game's HTML5 bundle, unzip it into your repo, and serve it as a static folder. 100% reliable — no external dependency.

Most Reliable

Proxy iframe

Pass the game URL through your Ultraviolet/Scramjet proxy. Useful for games on domains that block direct iframes.

Advanced

GitHub Raw / jsDelivr

Host game files in a GitHub repo and serve them via cdn.jsdelivr.net. Free, fast CDN without a dedicated server.

Budget-friendly
X-Frame-Options Some sites set X-Frame-Options: DENY or Content-Security-Policy: frame-ancestors 'none', which will block your iframe. You can't override this without a proxy — fall back to the proxy or self-hosted method for these titles.

03

Basic iframe Setup

The game viewer page should be a fullscreen iframe with a minimal chrome overlay for navigation. Here's the standard pattern:

game.html
<!-- game.html — fullscreen game viewer -->
<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <style>
    * { margin:0; padding:0; box-sizing:border-box; }
    body { background:#000; height:100vh; overflow:hidden; }

    #game-frame {
      position: fixed; inset: 0;
      width: 100%; height: 100%;
      border: none;
    }

    /* Minimal top bar */
    #bar {
      position: fixed; top: 0; left: 0; right: 0;
      height: 40px; background: rgba(0,0,0,0.7);
      backdrop-filter: blur(8px);
      display: flex; align-items: center; gap: 10px;
      padding: 0 14px; z-index: 999;
      transform: translateY(-40px);
      transition: transform 0.25s ease;
    }
    body:hover #bar { transform: translateY(0); }

    #game-title {
      color: #fff; font-size: 0.82rem;
      font-family: sans-serif; flex: 1;
    }
    .bar-btn {
      color: rgba(255,255,255,0.7); background: none;
      border: 1px solid rgba(255,255,255,0.15);
      border-radius: 6px; padding: 4px 10px;
      font-size: 0.75rem; cursor: pointer;
      transition: background 0.15s;
    }
    .bar-btn:hover { background: rgba(255,255,255,0.1); }
  </style>
</head>
<body>

  <div id="bar">
    <span id="game-title"></span>
    <button class="bar-btn" onclick="toggleFullscreen()">⛶ Fullscreen</button>
    <a href="index.html" class="bar-btn">← Back</a>
  </div>

  <iframe id="game-frame"
    allowfullscreen
    sandbox="allow-scripts allow-same-origin allow-pointer-lock allow-forms"
  ></iframe>

  <script>
    const params = new URLSearchParams(location.search);
    const src   = params.get('src');
    const title = params.get('title') || 'Game';

    document.getElementById('game-frame').src = src;
    document.getElementById('game-title').textContent = title;
    document.title = title;

    function toggleFullscreen() {
      const frame = document.getElementById('game-frame');
      if (!document.fullscreenElement) {
        frame.requestFullscreen();
      } else {
        document.exitFullscreen();
      }
    }
  </script>
</body>
</html>

Link to this page from your game grid by passing the source URL as a query parameter:

linking to a game
<a href="game.html?src=https://games.cdn.example/slope/index.html&title=Slope">
  Play Slope
</a>
sandbox attribute Always include a sandbox attribute on game iframes. The combination above covers 99% of HTML5 games — it allows scripts, pointer lock (needed for FPS-style games), and form submissions, while still providing a security boundary.

04

Building a Game Library

Store all game metadata in a games.json file and render cards dynamically. This is far easier to maintain than hardcoded HTML.

data/games.json
[
  {
    "id": "slope",
    "title": "Slope",
    "description": "Dodge obstacles as your ball speeds down an endless slope.",
    "thumbnail": "assets/thumbs/slope.webp",
    "src": "https://your-cdn.example/slope/index.html",
    "categories": ["arcade", "popular"],
    "featured": true
  },
  {
    "id": "1v1-lol",
    "title": "1v1.LOL",
    "description": "Build, battle, and outplay your opponents.",
    "thumbnail": "assets/thumbs/1v1lol.webp",
    "src": "https://your-cdn.example/1v1lol/index.html",
    "categories": ["shooter", "popular"],
    "featured": false
  }
]

Then render the grid from JavaScript:

assets/main.js — game grid renderer
let allGames = [];
let activeCategory = 'all';

// Fetch game data and render
async function init() {
  const res   = await fetch('data/games.json');
  allGames = await res.json();
  renderGrid(allGames);
  buildCategoryTabs(allGames);
}

function renderGrid(games) {
  const grid = document.getElementById('game-grid');
  grid.innerHTML = games.map(g => `
    <a class="game-card" href="game.html?src=${encodeURIComponent(g.src)}&title=${encodeURIComponent(g.title)}">
      <img src="${g.thumbnail}" alt="${g.title}" loading="lazy">
      <div class="game-info">
        <h3>${g.title}</h3>
        <p>${g.description}</p>
        <div class="game-cats">
          ${g.categories.map(c => `<span class="chip">${c}</span>`).join('')}
        </div>
      </div>
    </a>
  `).join('');
}

function filterByCategory(cat) {
  activeCategory = cat;
  const filtered = cat === 'all'
    ? allGames
    : allGames.filter(g => g.categories.includes(cat));
  renderGrid(filtered);
}

function filterBySearch(query) {
  const q = query.toLowerCase();
  const filtered = allGames.filter(g =>
    g.title.toLowerCase().includes(q) ||
    g.description.toLowerCase().includes(q)
  );
  renderGrid(filtered);
}

function buildCategoryTabs(games) {
  const cats = ['all', ...new Set(games.flatMap(g => g.categories))];
  const bar = document.getElementById('cat-bar');
  bar.innerHTML = cats.map(c => `
    <button class="cat-btn" onclick="filterByCategory('${c}')">${c}</button>
  `).join('');
}

init();

05

Game Source: GitHub + jsDelivr

The recommended way to host your own game files is to commit them to a GitHub repository and serve them through jsDelivr — a free, globally distributed CDN that mirrors GitHub content. You get a fast, reliable URL for every file with zero server costs and no extra configuration.

The URL pattern is straightforward:

jsDelivr URL pattern
# Pattern
https://cdn.jsdelivr.net/gh/{user}/{repo}@{branch}/{path/to/file}

# Example — serve slope's index.html from a repo called "game-files"
https://cdn.jsdelivr.net/gh/yourname/game-files@main/slope/index.html

Here's the complete workflow from repo setup to a working game URL:

1

Create a public GitHub repo for game files

Make a new repo (e.g. game-files) and set it to public — jsDelivr only mirrors public repositories. You can keep your main site repo private and have a separate public repo just for game assets.

2

Add game folders and commit

Each game lives in its own folder: slope/index.html, slope/game.js, etc. Commit all files to the main branch. jsDelivr will cache them within minutes of the push.

3

Reference the jsDelivr URL in games.json

Point each game's "src" field to the CDN URL. Use @main to always serve the latest commit, or pin a specific commit hash for stability.

4

Purge the cache after updates

If you update a game file, jsDelivr may serve a stale version for up to 24 hours. Force an instant purge at https://www.jsdelivr.com/tools/purge by entering the file URL.

File size limits jsDelivr won't serve individual files over 50 MB. HTML5 games are typically well under that, but if you have large asset bundles (audio, video), split them or use Cloudflare R2 / a self-hosted server for those specific assets.
Respect game licenses Many HTML5 games are free to play but not free to redistribute. Before committing a game to your repo, check its license. Games published under MIT, CC0, or similar open licenses are safe. When in doubt, use LuminSDK (section 06) or link to a CDN source instead of hosting the files yourself.

06

LuminSDK — 1,000+ Games Instantly

LuminSDK is the fastest way to add a complete, fully-featured game library to any site. One script tag, one function call, and you get 1,000+ browser games with built-in search, categories, and a fullscreen player — no accounts, no API keys, no build tools required.

Full documentation The LuminSDK docs (including the Configuration reference, Methods API, and interactive Playground) live at docs.luminsdk.com.

The complete integration is just three lines of HTML:

Minimal setup — paste this anywhere in your page
<!-- 1. A container div where the game grid will render -->
<div id="games"></div>

<!-- 2. Load the SDK from jsDelivr -->
<script src="https://cdn.jsdelivr.net/gh/luminsdk/script@latest/lumin.min.js"></script>

<!-- 3. Initialize with your container and preferred theme -->
<script>
  Lumin.init({
    container: '#games',
    theme: 'dark'
  });
</script>

That's it. LuminSDK renders the entire game grid — thumbnails, search bar, category tabs, and a fullscreen player — directly into your #games div. No games.json to maintain, no iframe wiring to write.

The theme option accepts 'dark' or 'light' and matches automatically to your site's color scheme. Additional configuration options are available via Lumin.init():

Lumin.init() — common options
Lumin.init({
  container: '#games',   // CSS selector or DOM element
  theme:     'dark',     // 'dark' | 'light'

  // See full options at docs.luminsdk.com/configuration
});

LuminSDK also exposes a JavaScript API for deeper integration — search, loading specific games programmatically, and fetching game metadata. See the Methods reference in the LuminSDK docs for the full API.

Zero to live in 2 minutes

No build step, no accounts, no API keys. Copy the three lines above, paste into your page, and you have 1,000+ games immediately.

Easiest Method

Search & categories included

The SDK ships with a fully functional search bar and category filter system — you don't need to build any of the UI from section 07.

Batteries Included

Works with any stack

Plain HTML, React, Vue, Svelte — LuminSDK is a vanilla JS library with no dependencies. Drop it in anywhere.

Framework Agnostic

Served via jsDelivr

The SDK script itself is hosted at cdn.jsdelivr.net/gh/luminsdk/script@latest/lumin.min.js — the same CDN used for your game files in section 05.

Fast CDN
When to use your own game library instead LuminSDK is the fastest path, but if you need full control over which specific games appear, custom thumbnails, or integration with a user account/favorites system, build your own games.json library using sections 04–05. Both approaches can coexist on the same site — e.g. LuminSDK for the main grid, a custom-curated section for featured titles.

07

Self-Hosting Games

Self-hosting gives you full control — games load even if the original CDN goes down. The workflow is:

1

Obtain the game bundle

Download the HTML5 build from the developer's itch.io page, GitHub releases, or an open-source repository. You're looking for a folder containing an index.html and associated JS/asset files.

2

Place it in your games/ folder

Add the folder to your repo. Keep names lowercase with hyphens — e.g. games/cookie-clicker/. Commit the entire folder including assets.

3

Update games.json

Point the "src" field to the relative path: "src": "games/cookie-clicker/index.html". The viewer page will load it in the iframe just like any other URL.

4

Test locally and deploy

Run a local server (npx serve .) to verify the game loads correctly, then push to Cloudflare Pages or your host of choice. The Deploy guide covers this in detail.

quick local server
# Requires Node.js — serves the current directory on port 3000
npx serve . -p 3000

08

UI & Category Filtering

A polished game grid with search and category filters dramatically improves the user experience. Here's a minimal but complete implementation:

index.html — game grid markup
<!-- Search bar -->
<input type="text" id="search" placeholder="Search games..."
  oninput="filterBySearch(this.value)">

<!-- Category tabs (built dynamically from games.json) -->
<div id="cat-bar"></div>

<!-- Game grid -->
<div id="game-grid" class="game-grid"></div>
CSS — game card styles
.game-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 16px;
}

.game-card {
  border-radius: 14px;
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  background: var(--glass);
  border: 1.5px solid var(--glass-border);
  transition: transform 0.22s, box-shadow 0.22s;
}
.game-card:hover {
  transform: translateY(-5px) scale(1.02);
  box-shadow: 0 16px 40px rgba(0,0,0,0.15);
}

.game-card img {
  width: 100%; aspect-ratio: 16/9;
  object-fit: cover; display: block;
}

.game-info { padding: 12px 14px 14px; }
.game-info h3 { font-size: 0.9rem; font-weight: 600; margin-bottom: 4px; }
.game-info p  { font-size: 0.75rem; opacity: 0.65; line-height: 1.5; }
Thumbnail tip Generate thumbnails at 640×360px (16:9) and save as .webp for best performance. You can screenshot any game at that resolution or find official artwork in the game's itch.io or GitHub page assets. Use the loading="lazy" attribute on all thumbnail images so they don't slow your initial page load.

09

Next Steps

You now have a fully functional games hub. Here's where to go from here:

Add an AI chatbot

Drop a free LLaMA or GPT integration into your site. The AI guide covers the full setup — no API cost to your users.

AI Guide

Add background music

Let users play music while they game. The Music guide shows how to integrate a player with zero server cost.

Music Guide

Deploy to Cloudflare

Push your site live with DDoS protection, CDN caching, and analytics all set up in under 15 minutes.

Deploy Guide

Add a proxy tab

Extend your games hub with a full web proxy so users can browse the open web — the highest-traffic feature of any UBG site.

Proxy Guide

Ready to ship your games site?

The Deploy guide walks you through Cloudflare Pages, WAF, and analytics — get your site live in under 15 minutes.