eas-hosting – Agents & Automation skill for AI agents
Curated upstream guidance for Eas Hosting; use when the workflow matches the user goal.
Install the eas-hosting skill with one command
Pick the tool you use, copy the command and paste it in your terminal. The skill lands in that tool's skills folder and is ready in your next session.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/eas-hosting-2e192.tgz | tar xz -C ~/.claude/skills
Call it in Claude Code: /eas-hosting – then describe the task you want done.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/eas-hosting-2e192.tgz | tar xz -C ~/.codex/skills
Call it in Codex: $eas-hosting – then describe the task you want done.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/eas-hosting-2e192.tgz | tar xz -C ~/.hermes/skills
Call it in Hermes Agent: /eas-hosting – then describe the task you want done.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/eas-hosting-2e192.tgz | tar xz -C ~/.deepcode/skills
Call it in DeepSeek: /eas-hosting – then describe the task you want done.
SKILL.md content
EAS Hosting
> EAS service - costs apply. EAS Hosting is a paid Expo Application Services product with free-tier limits; production deploys use your plan's request and bandwidth allowance. See https://expo.dev/pricing. Authoring API routes and exporting the web bundle are free and open source, and you can self-host the exported server output instead of EAS Hosting.
EAS Hosting deploys your Expo web app and API routes to Expo's managed edge (Cloudflare Workers). Export the web bundle with npx expo export -p web and ship it with eas deploy - the same command deploys any Expo Router API routes bundled alongside it. This skill covers deploying a website, authoring API routes, and the hosting runtime; see the Deployment section below for the deploy workflow.
These are partial route examples, not production authentication or data-access implementations. Presence of an Authorization header is not verification: validate issuer, audience, signature and expiry with the chosen provider, derive tenant identity server-side and enforce object ownership. Return 401 until a real verifier is implemented. Bound request bodies, upstream timeouts and paid AI calls; rate-limit and redact upstream errors. Public CORS is only for intentionally public endpoints, not access control. Native clients need a configured absolute HTTPS API origin; browser-relative fetch examples are not universally valid in React Native. Verify Expo runtime limits against current EAS docs; Workers capabilities are not all exposed by EAS Hosting.
When to Use API Routes
Use API routes when you need:
- Server-side secrets — API keys, database credentials, or tokens that must never reach the client
- Database operations — Direct database queries that shouldn't be exposed
- Third-party API proxies — Hide API keys when calling external services (OpenAI, Stripe, etc.)
- Server-side validation — Validate data before database writes
- Webhook endpoints — Receive callbacks from services like Stripe or GitHub
- Rate limiting — Control access at the server level
- Heavy computation — Offload processing that would be slow on mobile
When NOT to Use API Routes
Avoid API routes when:
- Data is already public — Use direct fetch to public APIs instead
- No secrets required — Static data or client-safe operations
- Real-time updates needed — Use WebSockets or services like Supabase Realtime
- Simple CRUD — Consider Firebase, Supabase, or Convex for managed backends
- File uploads — Use direct-to-storage uploads (S3 presigned URLs, Cloudflare R2)
- Authentication only — Use Clerk, Auth0, or Firebase Auth instead
File Structure
API routes live in the app directory with +api.ts suffix:
app/
api/
hello+api.ts → GET /api/hello
users+api.ts → /api/users
users/[id]+api.ts → /api/users/:id
(tabs)/
index.tsxBasic API Route
// app/api/hello+api.ts
export function GET(request: Request) {
return Response.json({ message: "Hello from Expo!" });
}HTTP Methods
Export named functions for each HTTP method:
// app/api/items+api.ts
export function GET(request: Request) {
return Response.json({ items: [] });
}
export async function POST(request: Request) {
const body = await request.json();
return Response.json({ created: body }, { status: 201 });
}
export async function PUT(request: Request) {
const body = await request.json();
return Response.json({ updated: body });
}
export async function DELETE(request: Request) {
return new Response(null, { status: 204 });
}Dynamic Routes
// app/api/users/[id]+api.ts
export function GET(request: Request, { id }: { id: string }) {
return Response.json({ userId: id });
}Request Handling
Query Parameters
export function GET(request: Request) {
const url = new URL(request.url);
const page = url.searchParams.get("page") ?? "1";
const limit = url.searchParams.get("limit") ?? "10";
return Response.json({ page, limit });
}Headers
export function GET(request: Request) {
const auth = request.headers.get("Authorization");
if (!auth) {
return Response.json({ error: "Unauthorized" }, { status: 401 });
}
return Response.json({ error: "Token verification not implemented" }, { status: 401 });
}JSON Body
export async function POST(request: Request) {
const { email, password } = await request.json();
if (!email || !password) {
return Response.json({ error: "Missing fields" }, { status: 400 });
}
return Response.json({ success: true });
}Environment Variables
Use process.env for server-side secrets:
// app/api/ai+api.ts
export async function POST(request: Request) {
const { prompt } = await request.json();
const response = await fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
},
body: JSON.stringify({
model: "gpt-4",
messages: [{ role: "user", content: prompt }],
}),
});
const data = await response.json();
return Response.json(data);
}Set environment variables:
- Local: Create
.envfile (never commit) - EAS Hosting: Use
eas env:createor Expo dashboard
CORS Headers
Add CORS for web clients:
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
};
export function OPTIONS() {
return new Response(null, { headers: corsHeaders });
}
export function GET() {
return Response.json({ data: "value" }, { headers: corsHeaders });
}Error Handling
export async function POST(request: Request) {
try {
const body = await request.json();
// Process...
return Response.json({ success: true });
} catch (error) {
console.error("API error:", error);
return Response.json({ error: "Internal server error" }, { status: 500 });
}
}Testing Locally
Start the development server with API routes:
npx expo startThis starts a local server at http://localhost:8081 with full API route support.
Test with curl:
curl http://localhost:8081/api/hello
curl -X POST http://localhost:8081/api/users -H "Content-Type: application/json" -d '{"name":"Test"}'Deployment to EAS Hosting
Prerequisites
npm install -g eas-cli
eas loginDeploy
Deploying ships your web bundle and any Expo Router API routes together - eas deploy handles both. The export runs whether you have a full website, an API-routes-only backend, or both.
# Export the web bundle (includes any API routes)
npx expo export -p web
# Deploy a preview (PR-style URL)
npx eas-cli@latest deploy
# Deploy to production
npx eas-cli@latest deploy --prodEverything lands on EAS Hosting (Cloudflare Workers).
Environment Variables for Production
# Create a secret
eas env:create --name OPENAI_API_KEY --environment production
# Enter the value through the CLI secure prompt; do not put it in shell history.
# Or use the Expo dashboardCustom Domain
Configure in eas.json or Expo dashboard.
Automate with EAS Workflows
Deploy the website (and API routes) on every push to main with a type: deploy workflow:
.eas/workflows/deploy.yml
name: Deploy
on:
push:
branches:
- main
# https://docs.expo.dev/eas/workflows/syntax/#deploy
jobs:
deploy_web:
type: deploy
params:
prod: truePreview deploys for pull requests use the same job type with prod: false:
name: Web PR Preview
on:
pull_request:
types: [opened, synchronize]
jobs:
preview:
type: deploy
params:
prod: falseTo author or validate workflow YAML beyond these examples, use the eas-workflows skill.
EAS Hosting Runtime (Cloudflare Workers)
API routes run on Cloudflare Workers. Key limitations:
Missing/Limited APIs
- No Node.js filesystem —
fsmodule unavailable - No native Node modules — Use Web APIs or polyfills
- Limited execution time — provider/plan-specific CPU and wall-clock limits; verify current EAS documentation
- No assumed persistent connections — verify EAS-specific streaming/WebSocket support
- fetch is available — Use standard fetch for HTTP requests
Use Web APIs Instead
// Use Web Crypto instead of Node crypto
const hash = await crypto.subtle.digest(
"SHA-256",
new TextEncoder().encode("data")
);
// Use fetch instead of node-fetch
const response = await fetch("https://api.example.com");
// Use Response/Request (already available)
return new Response(JSON.stringify(data), {
headers: { "Content-Type": "application/json" },
});Database Options
Since filesystem is unavailable, us
… (full content is in the download package)
Related skills
- eas-observe – Curated upstream guidance for Eas Observe; use when the workflow matches the user goal.
- eas-simulator – Curated upstream guidance for Eas Simulator; use when the workflow matches the user goal.
- prompt-governance – Use when managing prompts in production at scale: versioning prompts, running A/B tests…
- ecl-harness-engineer – Create or audit ECL Agent Harness infrastructure: AGENTS.md, change tracking, repository…
- effective-agent-skills – Author and review high-quality agent skills with triggers, progressive disclosure, and…
- subagent-driven-development – Execute plans via delegate_task subagents (2-stage review).
- ejentum-reasoning-harness – MCP server exposing four cognitive harness modes (reasoning, code, anti-deception…
- etsy-search-listings – Fetch live Etsy search listing rows for a keyword, market phrase, or category via Apify…