How to Use Loki to Compare Mobile and Desktop Versions of an Indian Website
Loki compares Storybook stories, not arbitrary live URLs. See how to set up desktop and mobile visual checks, and when to use Playwright for a live Indian website.
Short answer: Loki’s documented workflow compares screenshots of components represented as Storybook stories. It is not documented as a tool for entering an arbitrary live website URL. If your Indian website has a Storybook, use Loki to compare its stories across configured desktop and mobile targets. If you need to compare a live URL, use browser automation such as Playwright to open the same page in explicitly configured desktop and mobile contexts. No URL was supplied here, so this guide makes no claims about a particular Indian website or its layout.
That distinction matters: a Loki comparison tells you whether the configured Storybook story changed in the configured render target. A Playwright screenshot tells you what a particular URL rendered under the browser and emulation settings you ran. Neither alone proves how every physical phone behaves.
1. Choose the workflow that matches the input
| Your input | Use | What the result means |
|---|---|---|
| Components represented in Storybook stories | Loki | Visual differences between current story renders and approved reference images for configured targets. |
| A live website URL without a Storybook | Playwright or another browser automation workflow | The page render and behavior for the URL, browser, viewport, and emulation settings actually run. |
| Confidence about a specific physical handset | Run a separate test on that physical device | Evidence for that handset and tested browser; emulation is not a physical-device test. |
Loki’s guide describes Storybook as its input and requires a running Storybook instance for the workflow. Its web initialization defaults to laptop and iPhone configurations using local Chrome, but those defaults do not cover every browser or phone. Review and name the targets you actually intend to compare. Loki Getting Started guide.
For a live URL, Playwright supports Chromium, WebKit, and Firefox, as well as selected emulated device profiles. Emulation can configure viewport, screen size, user agent, touch, locale, timezone, geolocation, permissions, and color scheme, depending on the context or profile you use. Playwright browser documentation and Playwright emulation documentation.
2. Set up Loki for Storybook stories
Prerequisites and compatibility
The Loki guide lists Node.js 16 or later. GraphicsMagick is optional for its gm diffing engine; Docker is needed for the chrome.docker target; and Chrome 59 or later is listed for chrome.app. The guide says recent Storybook versions generally need no extra integration, while older versions may need a React configuration import; React Native has a separate integration. These details can vary by installed Loki release, so check the guide and your package’s version before applying older setup instructions. See Loki’s current setup guide.
Initialize, capture, compare, review
- From the project root, run
npx loki initor the equivalent command for the Loki version and package manager already used by your project. Review the configuration Loki adds topackage.json. - Start Storybook and leave it running while Loki accesses the stories. For an iOS simulator or Android emulator workflow, the guide says the Storybook app must also be running in that simulator or emulator.
- Create the initial reference screenshots with
yarn loki update. - Run the visual comparison with
yarn loki test. To limit the run to a configured target, the guide givesyarn loki test laptopas an example; use the actual configuration name in your project. - Inspect the current screenshots under
loki/currentand the differences underloki/difference. Decide whether each changed pixel is an intended design update, an application defect, or capture noise. - For intentional changes, update the reference set with
yarn loki approveor Loki’s suggested selective update command, then commit reference images with the code so future runs compare against the reviewed state.
# Terminal 1: start the Storybook command configured by your project
# Example only; the exact script name depends on the project:
yarn storybook
# Terminal 2: create or refresh references, then compare
yarn loki update
yarn loki test
# Optional: run a named configuration only
yarn loki test laptop
# After reviewing and accepting intended visual changes
yarn loki approve
The Loki guide documents loki init, loki update, loki test, and approval as the core cycle. Use the scripts generated by your own project and the installed version’s guide where command names differ. A baseline is only a snapshot of the state you chose to approve; Loki cannot determine whether a design change is correct for your users.
3. Make the desktop and mobile comparison meaningful
For a useful comparison, keep the story, data, fonts, assets, and application state fixed while changing the target configuration. Configure an explicit desktop/laptop target and a mobile target that represent the widths and rendering conditions you intend to support. Confirm those names in Loki’s generated configuration rather than assuming the default iPhone target represents all mobile devices.
- Use the same Storybook story and deterministic fixture data for both targets.
- Record the configuration names and, where available, viewport or device settings in the project configuration and review notes.
- Wait for fonts, images, and asynchronous story content to settle before treating a difference as a layout regression.
- Review the full current image and difference image. A diff highlights change; it does not explain whether the change is desirable.
- Keep approved baseline updates in the same change review as the corresponding code and design update.
For an Indian audience, add the conditions the product actually needs to support, such as the relevant language, content length, currency formatting, or location-dependent state, as explicit story fixtures or browser context settings. The title does not identify a site, language, or defect, so those should be selected from the application’s requirements rather than inferred from the country reference.
4. Compare a live website URL with Playwright
When the target is an arbitrary live site, use a browser automation tool to open the URL in two controlled contexts. The following example uses Playwright Test with a desktop Chromium context and a mobile device profile. Install Playwright Test and its browser binaries according to the official Playwright installation guide; device profile names are versioned, so confirm the selected profile is available in the installed package.
// tests/site-responsive.spec.js
const { test, expect, devices } = require('@playwright/test');
const target = process.env.TARGET_URL || 'https://example.in';
test('capture desktop and mobile renders of the same page', async ({ browser }) => {
const desktop = await browser.newContext({
viewport: { width: 1440, height: 900 },
locale: 'en-IN',
timezoneId: 'Asia/Kolkata',
colorScheme: 'light',
});
const mobile = await browser.newContext({
...devices['iPhone 13'],
locale: 'en-IN',
timezoneId: 'Asia/Kolkata',
colorScheme: 'light',
});
try {
const desktopPage = await desktop.newPage();
const mobilePage = await mobile.newPage();
await Promise.all([
desktopPage.goto(target, { waitUntil: 'networkidle', timeout: 60000 }),
mobilePage.goto(target, { waitUntil: 'networkidle', timeout: 60000 }),
]);
// Use the same stable state for both captures. This assertion confirms
// the page loaded; replace it with a site-specific readiness condition.
await expect(desktopPage.locator('body')).toBeVisible();
await expect(mobilePage.locator('body')).toBeVisible();
await Promise.all([
desktopPage.screenshot({ path: 'desktop.png', fullPage: true }),
mobilePage.screenshot({ path: 'mobile.png', fullPage: true }),
]);
} finally {
await Promise.all([desktop.close(), mobile.close()]);
}
});
Run it with a URL of your choice, for example:
TARGET_URL=https://example.in npx playwright test tests/site-responsive.spec.js --project=chromium
This produces separate desktop and mobile screenshots for inspection; it does not automatically calculate a cross-viewport diff, since the dimensions and responsive layout are expected to differ. For a pixel comparison, compare each run against a baseline made with the same viewport, browser, device settings, page state, and capture method. Do not compare a mobile image directly to a desktop baseline and interpret all responsive layout changes as defects.
Pick comparable browser state
- URL and route: use the same canonical URL, query parameters, and route in both contexts.
- Viewport and device: record dimensions and device profile. A mobile profile can include touch and user-agent settings, not just a narrow viewport.
- Locale and time: set these explicitly if localized strings, dates, or regional content affect the render. Playwright documents locale and timezone emulation.
- Authentication and consent: establish equivalent login, cookie, and consent states in both contexts if the site requires them.
- Readiness: prefer a site-specific selector or application-ready condition when network idle is unreliable due to analytics or long polling.
- Browser engine: if browser differences matter, run the required Playwright projects separately and label each result with its engine.
Playwright’s device emulation is useful for repeatable browser checks, but describe it accurately as emulation. For a claim about a real handset, perform and report a separate physical-device check.
5. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. One GET request can return a PNG, JPEG, WebP, or PDF screenshot. For a quick capture of the same URL, use the API call below; see the ScreenshotNeo API documentation for request options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.in -o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.in"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://example.in',
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const bytes = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', bytes));
To compare mobile and desktop, request each target URL with the appropriate viewport/device options documented by the API. A single default capture does not itself establish a responsive comparison; preserve the two configuration values with the resulting files.
- Cookie and consent banners are accepted like a visitor and more than 60 known consent platforms, newsletter popups, and chat widgets are removed before the shot; each step can be turned off.
- Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed. Responses identify the page verdict and billing status in headers.
- An MCP server provides
take_screenshot,get_page_info, andcapture_pdftools for Claude, Cursor, and other MCP clients. - 1,000 screenshots per month are free without a card; paid plans start at $5 for 3,000. Every feature is available on every plan.
Sign up for 1,000 free screenshots a month, with no card required.
6. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Loki cannot connect to Storybook | Storybook is not running, is on an unexpected address, or is inaccessible from the selected target. | Start Storybook first, verify the configured URL/port, and ensure a simulator or emulator target can reach the Storybook app when required. |
| No mobile configuration appears | The project is relying on defaults or a configuration name that differs from the command filter. | Inspect generated Loki configuration, define/select the intended target, and pass its exact name to loki test. |
| Every run has noisy differences | Fonts, animation, timestamps, remote data, image loading, or browser/environment changes make captures nondeterministic. | Use stable story fixtures, wait for app readiness, disable or freeze motion where appropriate, and keep the capture environment consistent. |
Playwright times out at networkidle |
The page keeps network connections active or makes analytics/streaming requests. | Navigate using a suitable load state, then wait for a specific page element or application-ready signal before capture. |
| Live page differs between desktop and mobile beyond layout | Different authentication, consent, locale, cache, or page data is active in each context. | Set equivalent state explicitly and compare captures with their context settings recorded. |
| Screenshot does not look like a physical phone | Emulation models selected browser parameters and is not a test of every handset, browser version, or hardware behavior. | Use emulation for repeatable checks and test on the named physical devices when handset-specific confidence is required. |
| Baseline approval hides a regression | A visual difference was approved without review. | Inspect current and difference images before approval; tie baseline changes to reviewed design intent. |
7. Performance, reliability, and cost
Loki’s runtime depends on the number of stories and configurations, browser startup, and screenshot/diff processing. Reduce turnaround by running only the affected named configuration during development, then run the project’s intended full target set before merging. The official guide’s optional diff engine and Docker target have their own prerequisites; choosing a target has environment and maintenance implications.
For live-site checks, desktop and mobile captures require separate browser contexts. Parallelizing them can reduce elapsed time, but it also increases concurrent browser and network use. Public sites may rate limit automated traffic or return bot checks; use a controlled test environment or permissioned access where possible. Keep retries bounded: a persistent application failure should remain visible rather than be converted into a misleading successful screenshot.
Loki is an open-source visual testing workflow, not a per-screenshot hosted API price in the cited setup guide. Budget for the browser and CI resources your workflow consumes. Playwright likewise runs in your chosen environment; costs depend on that environment and any separate infrastructure. ScreenshotNeo’s supplied pricing is 1,000 free shots per month, Starter $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000; yearly billing gives two months free. The supplied product facts state that only clean shots are billed and that all features are on every plan. Check current plan details on its site before adopting them.
8. FAQ
Can Loki compare any public Indian website by URL?
The cited Loki guide documents Storybook story testing, not arbitrary URL capture. Use a browser automation workflow for a live URL.
Does the default Loki iPhone target represent all mobile devices?
No. It is a default configuration, not evidence of coverage for every handset, browser, or viewport.
Should I approve every difference after a design release?
Approve only after reviewing the changed images and confirming the differences are intended.
Does Playwright emulation prove how the site works on a real phone?
No. It establishes results under the emulated settings and browser you ran; test a physical device for handset-specific evidence.
Can a screenshot comparison find every responsive issue?
No. It can reveal visual differences in captured states, but interaction, accessibility, performance, and device-specific behavior need their own checks.


