Recording of the visual regression run on odak.space · Odak — app walkthrough.

In this video· click a step to jump to it

O
Passed ✓

Test recording

Odak — app walkthrough

108,731 ms · 92,162 pixels changed

We built this regression test for odak.space — it's yours to keep, free.

Take this test with you

This is a real Playwright test, recorded against odak.space. Claim it into your own workspace and re-run it on every deploy — free.

export async function test(page, baseUrl, screenshotPath, stepLogger) {
  const shot = (n, slug) => screenshotPath.replace('.png', `-${n}-${slug}.png`);
  const SCROLL_THROUGH = "(async () => { const ease = t => 1 - Math.pow(1 - t, 3); const max = Math.max(0, document.body.scrollHeight - window.innerHeight); if (max < 40) return; const anim = (a, b, ms) => new Promise(res => { const t0 = performance.now(); const step = now => { const p = Math.min(1, (now - t0) / ms); window.scrollTo(0, a + (b - a) * ease(p)); p < 1 ? requestAnimationFrame(step) : res(); }; requestAnimationFrame(step); }); await anim(0, max, 1300); await new Promise(r => setTimeout(r, 300)); await anim(max, 0, 700); })()";

  await page.context().setExtraHTTPHeaders({ 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36' });
  await page.route('**/cdn-cgi/scripts/**', function (r) { r.abort(); }).catch(function () {});
  await page.route('**/*googletagmanager*/**', function (r) { r.abort(); }).catch(function () {});

  stepLogger.log('Public: marketing home');
  await page.goto(baseUrl + '/', { waitUntil: 'domcontentloaded' });
  await page.waitForLoadState('networkidle', { timeout: 4000 }).catch(function () {});
  await page.locator('h1, main').first().waitFor({ state: 'visible', timeout: 8000 }).catch(function () {});
+107 more lines — claim the test to get the full code.

Checks run

Run
✓
Visual
25.36%
Text
—
DOM
✓
Network
+45 −0
Console
✓
A11y
B
Perf
555 over
URL
✓
Variables
—
Full report
Log in →
92,162
Diff px
1m 49s
Duration
B
Accessible
WCAG 2.2 · 83
C
Fast
Web Vitals · 70

Notes from the demo run

AI-generated

We registered on Odak, verified with the 6-digit code, seeded three real tasks and a habit, then recorded the signed-in product end to end: the task board with search and status filters, the full task composer, the kanban board, the habit tracker, the calendar and the statistics page. For a solo-built productivity app the surface is unusually complete - five distinct views that all share one task model, and the dark theme holds together across every one of them.

Highlights
  • One task model, five honest views
    The same three tasks appear correctly on the board, the kanban columns, the calendar cell for Sep 25 and the statistics counters. Nothing drifted between views, which is the hard part and the part most solo task apps get wrong.
  • The composer is the whole product on one screen
    Title, rich-text description, due date, category, priority, status, tags, recurring toggle and file upload are all inline - no modal, no second step. Adding a task took one screen and one click.
  • Premium is marked, not hidden
    Related email and Assigned-to are visible with a lock icon rather than removed. A free user can see what upgrading buys without reading a pricing page.
  • Kanban states its own counts
    0 COMPLETED / 3 PENDING sits above the columns, and each column carries its own badge. The board answers 'where am I' before you read a single card.
Friction points
  • The interface mixes English and Turkish after switching to EN
    With EN selected, the board still shows PENDING as 'PENDİNG', category headings as 'CATEGORİES', and due dates as '25 Eyl'. The Turkish dotted-I is leaking through a locale-aware uppercase, and the date formatter is still pinned to tr-TR. Using toLocaleUpperCase('en') and passing the active locale into the date formatter would fix both.
  • Statistics reads as all zeros on a populated account
    With three open tasks and one habit, Statistics shows 0 completed, %0 success rate, '-' for most productive day. Technically correct, but a new user's first visit to the page looks broken. An empty-state line - 'complete a task to start your first streak' - would carry the same information without looking like a bug.
Couldn't reach
  • Add Task (final submit)·We composed a fourth task on camera but did not submit it, so the recording stays idempotent across re-runs.

10 visual changes

Step 1215 px changed
Before
Before
After
After
Diff
Diff
Step 3204 px changed
Before
Before
After
After
Diff
Diff
Step 419,348 px changed
Before
Before
After
After
Diff
Diff
Step 527,499 px changed
Before
Before
After
After
Diff
Diff
Step 627,464 px changed
Before
Before
After
After
Diff
Diff
Step 78,533 px changed
Before
Before
After
After
Diff
Diff
Step 88,547 px changed
Before
Before
After
After
Diff
Diff
Step 9204 px changed
Before
Before
After
After
Diff
Diff
Step 1470 px changed
Before
Before
After
After
Diff
Diff
Step 1578 px changed
Before
Before
After
After
Diff
Diff

Share this run

Earned · Lastest awards

Proof your app is not AI slop

LASTEST
starter
regressions
0
Badges stay live, ratchet upward, only downgrade on confirmed regression.
57,226 test runs recorded · 1,151 products tested with Lastest

This test was built for odak.space — claim it free

One click copies the test and baseline screenshots into your own Lastest workspace. Re-run on every deploy and catch regressions before your users do — free, no card required.