Vibium Coding Standards & Conventions
Vibium coding standards and conventions: naming per language, structuring scripts, choosing sync vs async, clean teardown, and writing agent-friendly automation.
Vibium coding standards come down to four habits: follow each language's naming idiom, keep scripts small and linear, pick sync or async deliberately, and always tear the browser down cleanly. Vibium exposes an identical API across its Python and JavaScript/TypeScript clients — only the casing differs (snake_case in Python, camelCase in JS) — and both sync and async flavours offer the same capabilities, so your conventions transfer everywhere. Good Vibium code reads like a description of the user journey: launch, navigate, find by intent, act, assert, quit. Because Vibium auto-waits for actionability, idiomatic scripts avoid manual retry loops and sleeps, which keeps them short and readable. And because Vibium also powers AI agents through its CLI and MCP server, writing clear, semantically-selected automation makes your code legible to both humans and LLMs. This guide sets out conventions for naming, structure, sync vs async, and teardown.
How should I name things in Vibium?
Match the host language's convention — Vibium already does. The same method is vibe.getAttribute() in JavaScript and vibe.get_attribute() in Python; findAll() vs find_all(). Don't fight it. For your own variables, name the browser handle something readable like vibe (the community convention) and name elements by their role, not their selector.
from vibium import browser_sync as browser
vibe = browser.launch()
vibe.go("https://app.example.com")
# Good: variables describe the element's purpose
submit_button = vibe.find(role="button", text="Submit")
email_field = vibe.find(label="Email")
# Avoid: names that leak the selector
# btn = vibe.find("div.x > button:nth-child(2)")
vibe.quit()How should I structure a Vibium script?
Launch once, group steps into small functions, and keep one logical flow per file. A flat 200-line script is hard to read and harder to debug. Break the journey into named steps so failures point at a stage ("login", "add_to_cart") rather than a line number.
from vibium import browser_sync as browser
def login(vibe, email, password):
vibe.go("https://app.example.com/login")
vibe.find(label="Email").type(email)
vibe.find(label="Password").type(password)
vibe.find(role="button", text="Sign in").click()
def open_settings(vibe):
vibe.find(role="link", text="Settings").click()
def main():
vibe = browser.launch()
try:
login(vibe, "user@example.com", "secret")
open_settings(vibe)
png = vibe.screenshot()
with open("settings.png", "wb") as f:
f.write(png)
finally:
vibe.quit()
main()Notice the absence of sleeps and retry loops — auto-waiting covers timing. See find element and screenshot for the methods used here.
When should I choose sync vs async?
Choose sync for simple, linear scripts and async only when you need concurrency. Both are first-class in Vibium with the same method count and capabilities, so the decision is about ergonomics, not power.
- Sync (
from vibium import browser_sync): reads top-to-bottom, noawait, ideal for tutorials, one-off automations, and most test cases. - Async (
from vibium import browser): use when driving several pages in parallel, or inside an async framework (FastAPI, aiohttp) where blocking calls would stall the event loop.
# Sync — most scripts want this
from vibium import browser_sync as browser
vibe = browser.launch()
vibe.go("https://example.com")
vibe.quit()Don't mix the two in one script, and don't reach for async "to be safe" — it adds await noise for no benefit in a linear flow. The deeper trade-offs are covered in Vibium sync vs async.
How do I clean up reliably?
Always quit the browser in a finally block (or a context manager) so the Go binary tears down Chrome even when an assertion throws. Leaked browser processes are a common source of CI slowdowns. Vibium 26.2 specifically hardened shutdown — Ctrl+C and crashes now clean up child processes — but your code should still guarantee quit() runs.
vibe = browser.launch()
try:
vibe.go("https://example.com")
# ... steps that might raise ...
finally:
vibe.quit() # runs even on failure — no zombie ChromeWriting agent-friendly automation
Prefer semantic selectors and small, named steps because the same code is read by AI agents through Vibium's MCP server and CLI. Vibium's ref-based agent workflow (map → act by @ref) and semantic find mean intent-based selectors are not just cleaner for humans — they map directly onto how an LLM reasons about a page. Code that says find(role="button", text="Checkout") is self-documenting for both audiences. If you expose your flows to Claude Code, see Vibium MCP in Claude Code.
Conventions at a glance
- Use the language idiom:
snake_casein Python,camelCasein JS. - Name variables by role (
submit_button), not by selector. - Launch once; group steps into small, named functions.
- Default to sync; reach for async only for concurrency.
- Always
quit()infinallyor a context manager. - Let auto-waiting handle timing — no manual sleeps or retries.
Consistent conventions make Vibium scripts easy to read, debug, and hand to an agent. Next, apply them in your first Vibium script (Python) and tighten reliability with flake-free tests.
Frequently asked questions
What naming convention does Vibium use?
Vibium follows each language's idiom: camelCase methods in JavaScript and TypeScript (vibe.getAttribute), and snake_case in Python (vibe.get_attribute). The API surface is identical across both clients and across sync and async, so only the casing differs between languages.
Should I use Vibium's sync or async API?
Use the sync API for simple scripts, learning, and linear automations — it reads top to bottom with no await. Use async for concurrency, such as driving multiple pages at once or integrating with an async web framework. Both are first-class with identical capabilities.
How should I structure a Vibium script?
Launch the browser once, group related steps into small functions, use semantic selectors, and always quit the browser in a finally block or context manager so processes clean up even on failure. Keep one logical flow per script and let auto-waiting handle timing.
Vibium is created by Jason Huggins. This is an independent tutorial — see the official Vibium site and GitHub repo for canonical docs.
Related guides
Running Vibium in CI/CD with GitHub Actions
Run Vibium tests in CI/CD with GitHub Actions — install on a runner, run headless, and upload screenshots and traces as artifacts on failure.
4 min read→Best PracticesHow to Write Flake-Free Vibium Tests
Write flake-free Vibium tests by trusting auto-waiting, using semantic selectors, isolating state with browser contexts, and controlling the clock and network.
4 min read→Best PracticesThe Page Object Model with Vibium
Apply the Page Object Model in Vibium with Python — wrap pages in classes, centralize locators, and keep tests readable, DRY, and resilient to UI change.
4 min read→Best PracticesHow to Parallelize Vibium Tests
Parallelize Vibium tests with pytest-xdist — give each test its own browser or context, run workers in parallel, and cut suite time without flaky cross-talk.
4 min read→