{"id":10861,"library":"expo-server","title":"Expo Router Server API","description":"expo-server is a foundational server-side API and runtime library specifically designed for projects leveraging Expo Router. It provides essential utilities and adapters for implementing server-side logic, including API routes, server-side rendering (SSR), and React Server Components (RSC) within a universal Expo application. Functioning primarily in a WinterCG-compliant environment, it allows developers to define API endpoints using a file-based convention (e.g., `+api.ts`), handle HTTP requests, and manage sensitive data securely on the server. The package facilitates full-stack development within the Expo ecosystem, enabling consistent codebases across native, web, and server environments. Expo SDK, which this package is part of or closely aligned with, typically releases new major versions three to four times a year. The current stable version of the broader Expo SDK is 55.x.x, with `expo-server` itself having independent, though generally aligned, releases (e.g., 0.7.5 as seen on npm for `@expo/server`). A key differentiator is its tight integration with Expo Router's opinionated file-system routing and universal development paradigm.","status":"active","version":"55.0.7","language":"javascript","source_language":"en","source_url":"https://github.com/expo/expo","tags":["javascript","expo","typescript"],"install":[{"cmd":"npm install expo-server","lang":"bash","label":"npm"},{"cmd":"yarn add expo-server","lang":"bash","label":"yarn"},{"cmd":"pnpm add expo-server","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Expo Router API routes and server modules are primarily ESM. CommonJS 'require' should be avoided.","wrong":"const { origin } = require('expo-server');","symbol":"origin","correct":"import { origin } from 'expo-server';"},{"note":"Ensure correct named import; casing matters.","wrong":"import { ENVIRONMENT } from 'expo-server';","symbol":"environment","correct":"import { environment } from 'expo-server';"},{"note":"Specific adapters are imported from sub-paths, not directly from the root package.","wrong":"import { createRequestHandler } from 'expo-server';","symbol":"createRequestHandler","correct":"import { createRequestHandler } from 'expo-server/adapter/http';"}],"quickstart":{"code":"/* app.json */\n{\n  \"expo\": {\n    \"web\": {\n      \"output\": \"server\"\n    }\n  }\n}\n\n/* src/app/hello+api.ts */\n// Ensure your project has 'web.output': 'server' in app.json for API routes to be bundled.\nimport { environment, origin } from 'expo-server';\n\nexport async function GET(request: Request) {\n  const url = new URL(request.url);\n  const name = url.searchParams.get('name') || 'world';\n  \n  console.log(`API Call received from origin: ${origin()}`);\n  console.log(`Running in environment: ${environment()}`);\n\n  return Response.json({\n    message: `Hello, ${name}! This is a server-side API route.`,\n    isProduction: environment() === 'production',\n    currentOrigin: origin()\n  });\n}\n\n// To test, run `npx expo start` and then navigate to `http://localhost:8081/hello` or `http://localhost:8081/hello?name=Alice` in your browser or a tool like curl.\n// In a native app, you would fetch from `/hello` and Expo Router would correctly proxy it to the server.","lang":"typescript","description":"Demonstrates creating a basic server-side API route using `expo-server` within an Expo Router project, including environment checks."},"warnings":[{"fix":"Add `\"web\": { \"output\": \"server\" }` under the `\"expo\"` key in your `app.json`.","message":"For Expo Router API routes and server-side features to function correctly, you must configure `\"web\": { \"output\": \"server\" }` in your `app.json` or `app.config.js` file. Omitting this will prevent server bundles from being generated.","severity":"breaking","affected_versions":">=1.0.0"},{"fix":"Ensure these imports and calls are isolated to files designated as server-side (e.g., `+api.ts` files or React Server Components).","message":"The runtime APIs exposed by `expo-server` (e.g., `origin`, `environment`, `runTask`, `deferTask`) are strictly for server-side code. Attempting to use them in client-side bundles will result in runtime errors.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"For production, set `\"expo\": { \"extra\": { \"router\": { \"origin\": \"https://your-server.com\" } } }`. Remember to remove or conditionally set `origin` for local development if it causes issues.","message":"When deploying Expo Router API routes to production or native builds, especially to third-party services, you often need to explicitly set the `origin` property in your `app.json` or `app.config.js` to the deployed server's URL. In development, it automatically points to the dev server.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Use server-side API routes to securely handle sensitive environment variables (e.g., API keys) and avoid exposing them to the client bundle. Always prefix client-facing environment variables with `EXPO_PUBLIC_`.","message":"Environment variables behave differently on the server vs. client. Server routes (e.g., `+api.ts`) have access to all environment variables, while client-side code only has access to those prefixed with `EXPO_PUBLIC_`.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Exercise caution when using RSCs. Test thoroughly, be aware of their limitations, and refer to the latest Expo documentation for best practices and stability notes. Use the 'use client' directive for components requiring client-side interactivity.","message":"React Server Components (RSC) support in Expo Router, while powerful, is still considered experimental or in beta. APIs may be subject to breaking changes without major SDK version bumps, and some traditional React features (hooks, state, browser APIs) are not available in RSCs.","severity":"deprecated","affected_versions":">=52.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Refactor imports to use ES module `import` syntax (e.g., `import { someFunction } from 'some-package';`).","cause":"Attempting to use CommonJS `require()` syntax in an Expo Router API route or other server module, which are typically ESM.","error":"Error: require is not defined in ES module scope"},{"fix":"Ensure that the corresponding HTTP method (e.g., `export function POST(request: Request) { ... }`) is defined and exported in your `+api.ts` file for the method you are using.","cause":"An API route was called with an HTTP method that is not explicitly exported by the `+api.ts` file (e.g., calling a `POST` route when only `GET` is exported).","error":"405 Method Not Allowed"},{"fix":"Verify `web.output: \"server\"` is set in `app.json`. For production native builds, set `\"expo\": { \"extra\": { \"router\": { \"origin\": \"https://your-deployed-server.com\" } } }` in your `app.json`.","cause":"The native application cannot resolve the API route URL, typically because the `origin` is not correctly configured for production deployments, or `web.output: \"server\"` is missing.","error":"Failed to fetch /your-api-route (or similar network error in native builds)"},{"fix":"Run `npx expo customize tsconfig.json` and ensure you start the development server (`npx expo start`) to generate typed routes. Make sure your `tsconfig.json` includes `expo-router/tsconfig.json`.","cause":"You are using `expo-router`'s navigation functions (like `router.push`) but haven't enabled or correctly configured typed routes, or are trying to access server-only types in a client context.","error":"Property 'push' does not exist on type 'Omit<Router, \"navigate\">' (or similar TypeScript error with router methods)"}],"ecosystem":"npm"}