Welcome
Asembol is a Tetris-style block puzzle game with color matching. It runs entirely in the browser. No server or database needed. This guide walks you through everything from first run to publishing on CodeCanyon.
Requirements
You need Node.js (LTS) and npm to build. A text editor like VS Code helps. For local testing, use Laragon or the Live Server extension.
Quick Start
- Run
npm installonce - Open
index.htmlin a browser or use Live Server - Run
npm run buildto create theout/folder - Upload the
out/folder to your host
The out/ folder is your production build. Everything from config.json gets baked into the HTML. No config or lang files in the output.
VS Code Setup
Download VS Code from code.visualstudio.com. Open the project folder with File > Open Folder.
The project has a build task. Press Ctrl+Shift+B (Windows/Linux) or Cmd+Shift+B (Mac). Or use Terminal > Run Build Task.
Install the Live Server extension. Right-click index.html and choose Open with Live Server for hot reload.
Node.js Setup
Download the LTS version from nodejs.org.
Windows: Add Node to PATH
- Run the Node.js installer
- Check "Add to PATH" during installation
- Restart your terminal after install
- Open a new Command Prompt and run
node -vandnpm -v
If you get "not recognized", Node is not in PATH. Reinstall with "Add to PATH" checked, or add it manually via Environment Variables.
Mac: Add Node to PATH
- Run the Node.js installer
- Restart Terminal
- Run
which nodeto find the install path - Add
export PATH="/usr/local/bin:$PATH"to~/.zshrcif needed - Run
source ~/.zshrc
Laragon Setup
Laragon is a portable dev environment for Windows. Download from laragon.org. Choose Full install.
- Start Laragon and click Menu > Quick app > Blank
- Enter a name (e.g. tetris or asembol)
- Copy the Asembol project files into that folder
- Open
http://tetris.testorhttp://asembol.test
To build: Laragon > Terminal, then cd www\tetris, npm install, npm run build.
Config Guide (config.json)
All customization lives in config.json. Edit it, run npm run build, and your changes appear in out/. The build embeds config into the HTML. No separate config file in production. For a full option list, see docs/config-reference.md in the source.
game
cols and rows set the grid size. Default 10 by 20. cellSize is the pixel size per block (default 28).
hardDropSpeed controls how many cells the piece moves per frame when you hard drop. baseDropInterval is the starting fall speed in milliseconds. minDropInterval is the fastest speed. dropAcceleration reduces the interval each level. fastDropInterval applies when fastDropAfterLevel10 is on.
maxLevel caps the level. previewCount is how many next pieces to show. previewCellSize is their display size.
"rotationDebounce": 200,
"pauseDebounce": 200,
"moveHoldDelay": 200,
"moveRepeatInterval": 80First keypress moves immediately. Hold the key and after moveHoldDelay ms it repeats every moveRepeatInterval ms. Same on desktop and touch.
game.score
scorePerLevel is points needed to level up (default 250). blockBreakScore is base points per block when you match 3+ same color. blockBreakMultiplierByLevel multiplies that by level when true. comboThreshold and comboBonus add extra points when you break 6 or more blocks at once. grayBlockMaxLevel stops adding gray rows after that level.
features
randomColorBlockBreak turns on the 3+ same color match mechanic. grayBlocksEveryLevel adds one unbreakable gray row per level. fastDropAfterLevel10 makes drops faster from level 10 onward.
colors
Theme colors: brandPrimary, brandDark, brandLight, bgDark, menuHoverColor, statValueColor, and more. colors.scrollbar lets you style the scrollbar (track, thumb, thumbHover, width, borderRadius).
audio
bgmUrl is the path to the background music file. bgmVolume is 0 to 1.
developer
disabledebugger runs anti-debug code when DevTools opens. consoleWarning shows a Self-XSS warning in the console. touchControls can be "auto", true, or false. "auto" shows touch controls on mobile or small screens. autoFullscreenOnMobile enters fullscreen when the game starts on mobile.
ui.forceHttps
When true, redirects HTTP to HTTPS. Localhost is skipped.
ui.viewport
disableZoom stops pinch zoom on mobile when true. Useful for game controls.
ui.loader
Loader bar: backgroundColor, barColor, barBackground, barHeight, barWidth, borderRadius, textColor, showText, text. scriptTimeoutMs is how long to wait before the loader gives up.
ui.touchControls
Touch D-pad and buttons: position (bottom, top, or mid), offset, dpadPosition, actionButtonsPosition.
ui.branding
gameName, gameNameUrl, showGameName, subtitle, subtitleUrl, showSubtitle, showDescriptionBanner. descriptionBanner has line1, line2, backgroundColor, borderColor, outlineColor, textColor.
ui.menu
order is an array of button names: shop, docs, info, support, settings, mute. Each can have label and icon.
ui.support
Support modal. cards is an array of links with icon, label, url, buttonText.
ui.credits
About modal. aboutContentUrl loads extra HTML. Developer name, URL, BGM credit, and labels.
ui.docs
Docs button and modal. contentUrl points to the docs HTML file.
ui.shop
Source code or purchase modal. cards lists items with icon, label, url, buyIcon, buttonText.
ui.footer
Footer visibility. left.terms and left.privacy each have show, label, modalTitle, contentUrl. right has the "Made with" text and whether it opens a modal.
seo
Meta tags and Open Graph. siteUrl is your base URL. title, description, keywords, author, creator, category, applicationName, publisher, authorUrl, referrer. verification.google and verification.bing for Search Console. fbAppId for Facebook. themeColor for the browser. ogImage, ogImage4k, ogImageWidth, ogImageHeight, ogImageAlt for social sharing. locale, robots, msapplicationTileColor, msapplicationTileImage. The build creates robots.txt and sitemap.xml from siteUrl.
analytics
enabled turns Google Analytics on. measurementId is your GA4 ID.
ads
AdSense: enabled, clientId, loadForVerification, slotIds, slotPlaceholder, slotEnabled.
lang
Language code like en. Pairs with lang.json for translations.
Translations (lang.json)
lang.json holds all UI strings. Keys stay the same; change the values for your language. Add new keys for new languages (e.g. "es": { ... }) and set config.lang to the key. The build embeds lang into the HTML.
Example keys: score, highScore, level, lines, next, controls, move, rotate, softDrop, hardDrop, pause, mute, unmute, pressSpaceToStart, tapToStart, startGame, gameOver, finalScore, paused, resume, close, settings, colorMatchLabel, hardRocksLabel, fastDropLabel, applyRestart, confirmProgressLost, cancel, confirm, credits, developer, terms, privacy, shareScore, shareScoreTitle, shareScoreDescription, and more. Copy the structure from the default lang.json and translate the values.
Gameplay
Pieces fall and you move, rotate, and drop them. Match 3 or more blocks of the same color in a row or column to break them. Blocks must come from at least 2 different pieces. Gray rows are unbreakable.
Line clears: 100, 300, 500, or 800 points times level (1 to 4 lines). Block breaks: base score times blocks times level. Combo bonus when 6+ blocks match. Level up every `scorePerLevel` points (default 250).
Score Share System
Asembol uses a pure static score share. No server. Score is computed client-side. High score is stored in localStorage. When players share, the game encodes name, score, level, lines, high score, and gameplay options into the URL. The /score page reads the URL and renders the share card. No backend needed.
Copy: Uses execCommand fallback for iOS Safari and Chrome. Clipboard API is tried first on desktop.
Download Image: On mobile, tries Web Share API first (Save to Photos). If that fails, opens the image in a new tab with a long-press hint. On mobile, html2canvas is skipped for faster SVG-based rendering.
Build
Run npm run build. Output goes to out/. The out/ folder is production ready. Config and lang are baked into index.html. Assets use hashed filenames in out/asembol/. Upload only out/ to your host.
Deploy
Upload the entire out/ folder to your host. Set the document root to the folder with index.html. Works with Netlify, Vercel, GitHub Pages, cPanel, and any static host.
Cloudflare: Direct Upload
- Run
npm run build npm i -g wrangler(one-time)npx wrangler pages project create(one-time)npx wrangler pages deploy out
Or use npm run deploy if configured. Site at https://<project>.pages.dev.
Alternatively: Go to Workers & Pages, Deploy site, drag and drop the out/ folder.
SEO: The build outputs sitemap.xml and robots.txt with clean URLs (/, /score, /docs). Cloudflare Pages strips .html automatically, so /docs serves docs.html.
Cloudflare: GitHub
- Workers & Pages > Create application > Pages > Connect to Git
- Select your repo
- Build command:
npm run build. Output directory:out - Save and Deploy
Each push triggers a new deployment. Git integration cannot be switched to Direct Upload later.
Netlify
- Sign up at netlify.com
- Add new site > Import from Git or drag and drop
- If Git: Build command
npm run build, publish directoryout - If drag and drop: Upload the
outfolder after runningnpm run build
Vercel
- Sign up at vercel.com
- Import project from Git
- Build command:
npm run build - Output directory:
out - Deploy
cPanel
- Run
npm run buildlocally - Zip the
outfolder - File Manager > public_html (or your domain folder)
- Upload the zip and extract
- Or upload contents of
outdirectly
Troubleshooting
Build fails or "node not found"
Node.js is not installed or not in PATH. Install from nodejs.org (LTS) and check "Add to PATH". Restart the terminal.
Config changes not showing
Config is baked at build time. Edit config.json, run npm run build, then upload the new out folder.
Game does not load
Check the browser console for errors. Ensure you upload the full out folder including out/asembol/ with all hashed JS, CSS, and assets.
Score share page 404
Configure your host to serve score/index.html for /score. Most static hosts do this automatically. For SPA-style setups, the build includes a 404.html that can redirect.
Share button or Copy not working
Scripts load in order: share-score, ads, main. ShareScore must load before the game. If it still fails, check the browser console. On iOS, Copy uses execCommand fallback.
Download image on mobile opens webpage
On mobile, the game uses Web Share API first. If that fails, it opens the image in a new tab. Long-press the image to save to Photos. This is an iOS limitation; the download attribute is ignored.
Touch controls not showing
Set developer.touchControls to true to force them, or "auto" to show on mobile/small screens.
Project Structure
asembol/
├── index.html — Main game
├── 404.html — Not found page
├── config.json — Settings and branding
├── lang.json — Translations
├── build.js — Build script
│
├── assets/
│ ├── styles/style.css — Styles
│ ├── js/ — asembol, share-score, ads
│ ├── bgm/ — Background music
│ ├── icons/ — Support, Shop, Social icons
│ ├── favicon.ico, etc. — Favicons
│ ├── logo.png — Same as favicon, build copies to out
│ ├── og-banner.webp, etc. — Social share images
│ ├── docs.html — Docs modal content
│ ├── about.html, terms.html, privacy.html — Legal and about pages
│ └── fonts/
│
├── score/index.html — Score share page
├── docs/user-guide.html — This doc
└── out/ — Build outputCodeCanyon and Envato
Before publishing, update config.json: set seo.siteUrl to your live URL, add your Envato and support links in ui.shop.cards and ui.support.cards. Optionally set developer.disabledebugger to true for production. Run npm run build and upload the out/ folder. Include the full source (out/, config.json, lang.json, assets/, docs/, index.html, score/, package.json, build.js, README.md) in your zip for buyers.
Support
Join our Discord for community updates. For direct support, message our Telegram.
More Products at NatadTech