c15t
/
Select a framework
Nitro Quickstart
Writing Runners
Configuration
Deployment
Orchestration
Advanced Topics
OSS
Contributing
License
C15T Logo
DocsChangelog
xbskydiscordgithub0
c15t
/
Select a framework
Nitro Quickstart
Writing Runners
Configuration
Deployment
Orchestration
Advanced Topics
OSS
Contributing
License
home-2Docs
chevron-rightFrameworks
chevron-rightNitro
chevron-rightAdvanced

Advanced Topics

Advanced patterns and best practices for Nitro

Custom Schema Validators

Runners support Standard Schema-compatible validators, not just Zod:

import { StandardSchemaV1 } from "@standard-schema/spec";
import type { Runner } from "runners";

// Using a custom validator
const CustomInputSchema: StandardSchemaV1<string, string> = {
  "~standard": {
    validate: (value) => {
      if (typeof value !== "string") {
        return { issues: [{ message: "Must be string" }] };
      }
      return { value };
    },
  },
};

export const customRunner: Runner<typeof CustomInputSchema> = async (
  ctx,
  input
) => {
  "use runner";
  // input is typed as string
  return { name: "custom", status: "pass" };
};

Performance Optimization

1. Schema Pre-extraction

Schemas are extracted at build time for performance:

# Build extracts schemas automatically
npm run build

2. Parallel Execution

Use orchestrator for parallel execution:

const runRequest = {
  runners: [/* ... */],
  mode: "remote",
  concurrency: 10, // Run 10 jobs in parallel
};

3. Browser Reuse

Playwright contexts are reused when possible:

// Multiple runners can share browser context
const { page } = await withPlaywright(ctx, url);
// Browser is reused for subsequent runners

4. Lazy Loading

Runners are loaded only when needed:

// Runners loaded on-demand
const runner = await import(`./runners/${runnerName}`);

Error Recovery

Implement retry logic:

async function runWithRetry(
  runner: Runner,
  context: RunnerContext,
  input: unknown,
  maxRetries = 3
) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await runner(context, input);
    } catch (error) {
      if (attempt === maxRetries) {
        throw error;
      }
      
      // Exponential backoff
      await new Promise(resolve =>
        setTimeout(resolve, Math.pow(2, attempt) * 1000)
      );
    }
  }
}

Testing Runners

Unit Testing

import { describe, it, expect } from "vitest";
import { cookieBannerTest } from "./runners";

describe("cookieBannerTest", () => {
  it("should pass when banner is visible", async () => {
    const context = {
      log: () => {},
      region: "us-east-1",
    };
    
    const result = await cookieBannerTest(context, {
      url: "https://example.com",
    });
    
    expect(result.status).toBe("pass");
  });
});

Integration Testing

import { runRunners } from "runners";
import { cookieBannerTest } from "./runners";

describe("Runner Integration", () => {
  it("should execute runners", async () => {
    const result = await runRunners({
      runners: [cookieBannerTest],
      region: "us-east-1",
    });
    
    expect(result.results).toHaveLength(1);
    expect(result.results[0].status).toBe("pass");
  });
});

Advanced Playwright Usage

Custom Browser Options

import { withPlaywright } from "runners/playwright";

export const customBrowserRunner: Runner = async (ctx, input) => {
  "use runner";
  
  const { browser } = await withPlaywright(ctx, input.url);
  
  // Access browser directly
  const context = await browser.newContext({
    viewport: { width: 1920, height: 1080 },
    userAgent: "Custom User Agent",
  });
  
  const page = await context.newPage();
  // ... use custom page
};

Multiple Pages

export const multiPageRunner: Runner = async (ctx, input) => {
  "use runner";
  
  const { browser } = await withPlaywright(ctx, input.url);
  
  const pages = await Promise.all([
    browser.newPage(),
    browser.newPage(),
    browser.newPage(),
  ]);
  
  // Use multiple pages
  await Promise.all(pages.map(page => page.goto(input.url)));
  
  // ... rest of logic
};

See Also

  • Writing Runners - Runner authoring guide
  • API Reference - Complete API documentation
  • Deployment - Production deployment guide

Available in other SDKs

honoHonocode-3HTTP API
Runners brings execution, reliability, and distribution to async TypeScript. Build tests and checks that can run locally, in CI, or distributed across regions with ease.
Product
  • Documentation
  • Components
Company
  • GitHub
  • Contact
Legal
  • Privacy Policy
  • Cookie Policy
runners