Browser and edge runtimes
Purpose and Scope
This page explains how the repository validates the OpenAI TypeScript and JavaScript SDK outside the ordinary Node.js server process. The browser and edge fixtures are ecosystem tests: small applications that exercise the published package shape, runtime assumptions, and Web API compatibility in environments where Node-specific globals may be absent or constrained. The reader problem is not how to build a full production browser application, but how to understand which runtime patterns are intentionally tested and what safety boundaries apply when using the SDK in client-side or edge code.
Sources: ecosystem-tests/browser-direct-import/public/index.js, ecosystem-tests/browser-direct-import/src/test.ts, ecosystem-tests/cloudflare-worker/src/worker.ts, ecosystem-tests/vercel-edge/src/pages/index.tsx
The strongest browser signal is the direct-import fixture. It imports OpenAI and toFile from the built index.mjs file under node_modules/openai, creates a client in a real browser document, and runs a set of assertions through DOM-visible test results. That matters because browser compatibility is not only a type-checking concern: upload inputs, raw responses, audio transcription calls, module loading, timers, and error surfaces all need to survive execution in a page context.
The edge signal is represented by separate Cloudflare Worker and Vercel/Next fixtures. The Cloudflare Worker fixture uses the platform fetch handler shape, receives OPENAI_API_KEY from the worker environment binding, dynamically imports openai, constructs the client, and runs upload-oriented Web API cases. The Vercel fixture is intentionally minimal, but it establishes a Next.js page route as part of the edge ecosystem coverage rather than a Node-only example. Together, these files show that runtime coverage is assembled from small host-specific applications instead of a single universal test harness.
Relevant Source Files
ecosystem-tests/browser-direct-import/public/index.js- Browser-hosted test page that imports the ESM SDK build directly, creates anOpenAIclient withdangerouslyAllowBrowser: true, defines lightweightdescribe,it, andexpecthelpers, and records JSON test results into the DOM.ecosystem-tests/browser-direct-import/src/test.ts- Puppeteer runner that opens the browser fixture, passesOPENAI_API_KEYthrough the test URL, waits for the page test harness to finish, extracts#results, and fails the ecosystem test if any browser case reports failure.ecosystem-tests/cloudflare-worker/src/worker.ts- Cloudflare Worker fetch handler that exposes a/testendpoint, imports the SDK at runtime, constructs a client fromenv.OPENAI_API_KEY, registers Web API upload test cases, and returns eitherPassed!or diagnostic failure output.ecosystem-tests/vercel-edge/src/pages/index.tsx- Minimal Next.js page fixture used by the Vercel Edge ecosystem test setup to verify the host application surface builds and serves a page in that environment.
Runtime Model
The direct browser fixture deliberately opts into browser execution with dangerouslyAllowBrowser: true. That option name is important: the browser page reads an API key from location.search, then constructs new OpenAI({ apiKey: params.get('apiKey') ?? undefined, dangerouslyAllowBrowser: true }). In an application, exposing a secret key to the browser would normally be unsafe because every user can inspect client-side JavaScript, network requests, and URLs. In this repository, that pattern is confined to an ecosystem test whose only job is to prove browser mechanics such as ESM import, Web File-style uploads, and response handling.
Sources: ecosystem-tests/browser-direct-import/public/index.js
The browser harness is also intentionally self-contained. Instead of relying on Jest or Node assertions inside the page, it defines local describe, it, and expect functions, stores test cases in an array, and serializes results into a pre#results element. This keeps the browser test close to the runtime being validated: failures are produced by page code, surfaced through the DOM, and then consumed by the outer Puppeteer process. That split is useful when debugging incompatibilities because console messages, network responses, page errors, and request failures are all observed by the runner.
Sources: ecosystem-tests/browser-direct-import/public/index.js, ecosystem-tests/browser-direct-import/src/test.ts
Cloudflare Workers use a different security and runtime model. The worker does not receive the API key from a browser query string; it declares OPENAI_API_KEY on the Env interface and constructs the SDK client from env.OPENAI_API_KEY inside the request handler. The fixture also treats / as a readiness endpoint for server polling and reserves /test for actual SDK execution. That route split mirrors the needs of edge deployment tests: first prove the worker is up, then invoke the code path that imports the SDK and performs runtime-specific assertions.
Sources: ecosystem-tests/cloudflare-worker/src/worker.ts
Execution Flow
The direct-import browser flow begins in the TypeScript runner, not in the HTML page. Puppeteer launches Chromium with --no-sandbox, opens a new page, attaches diagnostic listeners for console output, page errors, HTTP responses, and failed requests, and then reads OPENAI_API_KEY from the local process environment. If the key is absent, the test fails before navigation. When the key exists, Puppeteer opens http://localhost:8081/index.html?apiKey=..., waits for an element with id running, and then polls until that marker disappears or the three-minute ceiling is reached.
Sources: ecosystem-tests/browser-direct-import/src/test.ts
Inside the browser page, the harness runs registered tests sequentially. For each test case it races the handler against a timeout, records either a passed result or an error stack, and updates the #results element after every case. The runner later parses that element as JSON and fails the outer process if any result has passed: false. This design gives developers two layers of information: the browser page records structured per-test outcomes, while Puppeteer records host-level failures such as navigation, request, or script errors.
Sources: ecosystem-tests/browser-direct-import/public/index.js, ecosystem-tests/browser-direct-import/src/test.ts
The Cloudflare Worker flow is request-driven. A GET to /test triggers dynamic imports, first for the SDK and then for local upload Web API test cases. The worker creates a local it registration function and expectation helpers, passes them to uploadWebApiTestCases, and executes the collected handlers one by one. It keeps an allPassed flag, logs progress to the worker console, and returns plain text. A successful run returns Passed!; a failed run returns concatenated descriptions and failure details, while top-level setup errors produce a 500 response.
Sources: ecosystem-tests/cloudflare-worker/src/worker.ts
API Components and Host-Specific Constraints
For browser usage, the fixture shows three concrete SDK-facing pieces: the default OpenAI client export, the toFile helper export, and resource calls made through the client such as client.audio.transcriptions.create and client.chat.completions.create. The included type-only checks demonstrate the intended Uploadable boundary by marking invalid file inputs with @ts-expect-error. The runtime tests then focus on whether browser-compatible file and response shapes work once the ESM build is loaded directly from node_modules/openai/index.mjs.
Sources: ecosystem-tests/browser-direct-import/public/index.js
For Cloudflare Workers, the important component is the platform fetch entrypoint. The SDK is imported inside that handler with await import('openai'), which exercises compatibility with the worker bundling and module-loading path. The client is created without dangerouslyAllowBrowser because this is server-side edge code: the secret comes from an environment binding, and requests run in the worker isolate rather than in a user-controlled page. The worker-specific test also leans on Web API upload cases, which is a useful signal because edge platforms often provide browser-like Request, Response, Blob, and File behavior rather than full Node streams.
Sources: ecosystem-tests/cloudflare-worker/src/worker.ts
The Vercel fixture shown here is intentionally small: a Next.js page component renders metadata and a simple Hello, world! body. Its value is not API coverage by itself, but as part of the ecosystem-test matrix it gives the repository a host application that can be built and served under Vercel-style constraints. When investigating a Vercel Edge issue, treat this file as the route fixture and look for adjacent test configuration in the same ecosystem test package before assuming it exercises a particular SDK resource method.
Sources: ecosystem-tests/vercel-edge/src/pages/index.tsx
Testing Signals and Debugging
A passing browser direct-import run ends with Puppeteer printing the number of passed tests after it verifies that #results contains an array and that no result is failed. If the page never writes results, the runner throws failed to get test results from page; if tests fail, it includes the failed result objects in the thrown error. On catch, the runner attempts to dump document.body.innerHTML, which is especially useful when the page harness stopped before removing #running or before rendering the results element.
Sources: ecosystem-tests/browser-direct-import/src/test.ts
A passing Cloudflare Worker run returns the literal response body Passed! from /test. Failures are designed to be readable both in worker logs and in HTTP output: each registered test description is paired with the stringified result or stack trace. If importing the SDK, importing the test cases, or constructing the client fails before individual cases run, the outer catch logs the stack and returns it with status 500. That makes the fixture useful for distinguishing package import problems from API behavior problems.
Sources: ecosystem-tests/cloudflare-worker/src/worker.ts
Practical Guidance
Use these fixtures as compatibility signals, not as production architecture templates. The browser direct-import page proves the SDK can load and perform selected operations in a page when explicit browser usage is enabled, but it also demonstrates why secrets in browsers are dangerous by passing the API key through a URL. For real applications, prefer moving authenticated OpenAI calls behind a server, worker, or other trusted backend unless you have a deliberate public-client design. Edge workers are a better match for keeping keys private while still staying close to users geographically.
When adding or debugging browser and edge support, start by matching the failing environment to the closest fixture. Browser ESM import and DOM-result failures belong with the direct-import pair; Cloudflare request handling, environment bindings, and Web API upload behavior belong with the worker fixture; Vercel/Next routing or build issues belong with the Vercel ecosystem package. Next, reproduce with the smallest route or page, preserve the diagnostic output style used here, and only then add broader API coverage. Related pages: platforms-runtimes, deployment-data-controls, files-uploads, and streaming-example.