How a run works
A ViberBlitz speedrun has five stages. Understanding each one helps you avoid surprises during submission.
Start the timer
Click Start on a challenge card. The clock begins the moment you click — this is your official start time. Build your app using any AI tool or combination of tools.
Build and push to GitHub
Build the required app, push it to a public GitHub repository. The repo must be public so the verifier can download it.
Submit
Click Finish, paste your GitHub repo URL, select the AI tool(s) you used, and optionally add a replay link. Submitting stops the clock.
Automated verification
ViberBlitz downloads your repo, installs dependencies, starts your app, and runs a Playwright test suite against it. This takes 30–90 seconds.
Result
If all tests pass, your time is recorded on the leaderboard. If any test fails, you see the full test output so you can fix and resubmit.
Repository requirements
Plain HTML / CSS / JS (no build step)
If your app has no package.json, the verifier serves it as a static site automatically. No configuration needed — just make sure your entry point is index.html in the repo root.
my-calculator/
├── index.html ← entry point (required)
├── style.css
└── script.jsNode.js apps (React, Vue, Next.js, etc.)
Your package.json must include a start script that launches the app. The verifier runs npm install then npm start.
{
"scripts": {
"start": "node server.js"
}
}$PORT environment variable. The verifier assigns a random available port and passes it via process.env.PORT. Hard-coding port 3000 will cause a timeout if that port is already in use.// ✅ Correct — reads PORT from environment
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Listening on ${port}`));
// ❌ Wrong — hard-coded port will fail if 3000 is taken
app.listen(3000);Vite / React dev server
For Vite apps, use vite preview (not vite dev) for the start script, and pass the port:
{
"scripts": {
"build": "vite build",
"start": "vite preview --port $PORT --host 0.0.0.0"
}
}dev script but no start script, add one manually before pushing. The verifier looks for start first, then dev as a fallback.How the verifier works
The ViberBlitz verifier is a server-side pipeline that runs automatically when you submit. Here is exactly what it does:
- 1.Downloads your repo as a ZIP archive from the GitHub API (no git binary required).
- 2.Extracts the ZIP and detects whether a package.json is present.
- 3.If no package.json: serves the directory as a static site using the serve package.
- 4.If package.json exists: runs npm install --legacy-peer-deps, then detects the correct start command (start → dev → vite preview → vite dev).
- 5.Starts the app on a randomly assigned port and waits up to 60 seconds for it to respond to HTTP requests.
- 6.Launches a headless Chromium browser via Playwright and navigates to the app.
- 7.Runs the challenge-specific test suite (see below for each challenge).
- 8.Returns pass/fail + full test output. On pass, records your elapsed time on the leaderboard.
- 9.Cleans up the temp directory.
Selector strategy
The verifier uses a multi-strategy approach to find elements in your app. For each element it needs to interact with, it tries these strategies in order:
data-testid attribute
e.g. data-testid="btn-5" — always wins if present
ARIA role + name
e.g. role="button" with text "5"
Visible text content
any element whose visible text matches
data-testid attributes to your key elements (see per-challenge specs below). This bypasses all selector ambiguity and guarantees the verifier finds your elements regardless of DOM structure.Challenge: Calculator (Beginner)
Build a functional calculator that supports addition, subtraction, multiplication, and division. The verifier runs 5 automated tests.
Test suite
Guaranteed PASS — recommended data-testid attributes
<!-- Display element -->
<div id="display" data-testid="display">0</div>
<!-- Number buttons -->
<button data-testid="btn-0">0</button>
<button data-testid="btn-1">1</button>
<button data-testid="btn-2">2</button>
<button data-testid="btn-3">3</button>
<button data-testid="btn-4">4</button>
<button data-testid="btn-5">5</button>
<button data-testid="btn-6">6</button>
<button data-testid="btn-7">7</button>
<button data-testid="btn-8">8</button>
<button data-testid="btn-9">9</button>
<!-- Operator buttons -->
<button data-testid="btn-+">+</button>
<button data-testid="btn--">−</button>
<button data-testid="btn-*">×</button>
<button data-testid="btn-/">÷</button>
<button data-testid="btn-=">=</button>Challenge: Todo App (Intermediate)
Build a todo list app where users can add tasks, mark them as complete, and delete them. The verifier runs 5 automated tests.
Test suite
Guaranteed PASS — recommended data-testid attributes
<!-- Task input field -->
<input data-testid="todo-input" placeholder="Add a task..." />
<!-- Submit button (or press Enter in the input) -->
<button data-testid="todo-submit">Add</button>
<!-- Each task item in the list -->
<li data-testid="todo-item">
<!-- Checkbox or complete button -->
<input type="checkbox" data-testid="todo-complete" />
<!-- Task text -->
<span data-testid="todo-text">Buy groceries</span>
<!-- Delete button -->
<button data-testid="todo-delete">Delete</button>
</li>text-decoration: line-through, an opacity change, a CSS class like completed, or the checkbox being checked. Any visible change works.Challenge: PDF Analyzer (Advanced)
Build an app that accepts a PDF file upload and extracts or displays its text content. The verifier runs 5 automated tests.
Test suite
Guaranteed PASS — recommended data-testid attributes
<!-- File upload input (must be visible — do NOT use opacity:0 or display:none) -->
<input
type="file"
accept=".pdf,application/pdf"
data-testid="file-input"
/>
<!-- Drag-and-drop upload zone (optional but recommended) -->
<div data-testid="upload-area">
Drop PDF here or click to browse
</div>
<!-- Output area (must be visible at page load — use placeholder text) -->
<div data-testid="extracted-text">
Extracted text will appear here...
</div>PDF.js (loaded from CDN or bundled locally) to extract text entirely in the browser — no backend required. If you use a CDN, note that the verifier sandbox has no internet access, so bundle the library locally in a libs/ folder and reference it with a relative path.Common pitfalls
The verifier assigns a random available port. If you hard-code 3000 and that port is taken, your app will fail to start.
The verifier looks for a start script. If only dev is present it will try it as a fallback, but start is more reliable.
The verifier downloads your repo via the GitHub API without authentication. Private repos return a 404.
For plain HTML apps with no package.json, the verifier serves the repo root. Your index.html must be at the root, not inside a subdirectory.
If your app requires a build step, either commit the dist/ folder or include the build command in your start script.
The verifier tries to click buttons by role and text. Div-based buttons without role="button" may not be found. Use real <button> elements or add data-testid attributes.
FAQ
Ready to run?
Pick a challenge, build fast, and get verified. Any AI stack. Permanent record.
View Challenges