Turn Browser Clicks Into Resilient Playwright Tests

Record real browser interactions and DOM mutations. Let AI synthesize production-grade specs with zero fragile CSS selectors and automated assertions.

View Generated Code
No CSS `div:nth-child` slop Auto-assert toasts & URLs
Filling checkout payment form...
Click "Sign in" & check modal
Captured
Selecting dropdown option...
AI
Synthesis
Zero Fragile Selectors Role & Label
5x Faster Authoring
Playwright
100% Automated Assertions
Inspects DOM state mutations for alerts, toasts & URLs
85% Context Reduction Debounced
0ms
Config Setup Required
100%
User-Facing Locators
TypeScript
Clean Typed `.spec.ts`

Stop Debugging Broken Selectors

Traditional codegen generates brittle DOM trees with zero assertions. clickspec synthesizes maintainable, user-centric code.

Standard Codegen Output
Fragile & Flaky
// ❌ Fragile CSS paths that break on layout changes
await page.locator('div > div:nth-child(3) > input').fill('user@test.com');
await page.locator('.auth-input-v2__field_39x').fill('secret123');
await page.locator('xpath=//button[3]').click();

// ⚠️ ZERO assertions generated:
// Test silently passes even if login completely failed!
Result: 43% maintenance overhead
clickspec AI Synthesis
Resilient & Tested
import { test, expect } from '@playwright/test';

test('User authenticates & verifies dashboard', async ({ page }) => {
  // ✅ Accessible locators matching real user intent
  await page.getByLabel('Email Address').fill('user@test.com');
  await page.getByPlaceholder('Enter password').fill('secret123');
  await page.getByRole('button', { name: 'Sign In' }).click();

  // 🎯 Auto-synthesized smart assertions
  await expect(page).toHaveURL(/.*dashboard/);
  await expect(page.getByRole('heading', { name: 'Welcome back' })).toBeVisible();
  await expect(page.getByRole('alert')).toContainText('Login successful');
});
Result: Zero test flakes on refactors

Engineered for Clean Code Quality

No boilerplate fluff. Built with strict principles from the ground up.

Accessibility-First Locators

Prioritizes user-facing semantic queries like getByRole, getByLabel, and getByPlaceholder. Strictly forbids fragile hierarchy chains.

Smart Mutation Hooks

When you submit forms or trigger state changes, our client-side observer watches for toasts, dialogs, error banners, and URL transitions to generate automatic assertions.

Event Normalizer & Debouncer

Filters typing noise and accidental double-clicks. Compresses 40 individual keystroke events into a single, clean page.fill() command, minimizing LLM token cost.

Dual Model AI Backend

Powered by the new official @google/genai SDK using Gemini 3.8 Flash for fast, low-cost code synthesis, with seamless fallback to OpenAI gpt-4o-mini.

How clickspec Works

A four-stage pipeline designed for simplicity and rock-solid determinism.

Stage 01

Launch & Intercept

Launches Chromium with an exposed bridge and injects in-page DOM listeners for clicks, inputs, and SPA route changes.

core/browser.ts
Stage 02

Smart Assertion Hook

Detects newly rendered toast notifications, alerts, modals, and route changes after button clicks.

core/recorder.ts
Stage 03

Normalize & Compress

Debounces rapid key inputs into atomic fill operations and pairs assertion candidates with their actions.

core/normalizer.ts
Stage 04

AI Spec Synthesis

Gemini model generates clean TypeScript Playwright code, sanitized, verified, and saved straight to disk.

ai/synthesizer.ts
Quickstart Guide

Run clickspec in seconds

Node.js 18+ (ESM)
1. Run interactive generator (Zero install required):
npx clickspec http://localhost:3000
2. Or specify output file and test title:
npx clickspec https://app.com -o ./tests/checkout.spec.ts --title "Checkout Flow"
3. Execute your synthesized Playwright test:
npx playwright test ./tests/checkout.spec.ts --headed
AI Key Configuration: Add GEMINI_API_KEY (get one free at aistudio.google.com) to your .env, or pass OPENAI_API_KEY as fallback.