Skip to main content
Frameworks

Backend frameworks on Easel

Deploy Hono, Express, Fastify, H3, Koa, Elysia, and NestJS servers to Easel as a single function.

Easel deploys a Node.js server built with Hono, Express, Fastify, H3, Koa, Elysia, or NestJS as one Easel Function that handles every request. You keep your app's own routing. Easel finds the app's entry file, bundles it with its imports, and routes all paths to it.

At a glance

RenderingServer (every request runs your app)
Server runtimeNode.js
Adapter requiredNo. Export the app from its entry file
Automatic detectionYes, from the entry file's import
Entry fileapp, index, or server at the top level or in src/ (main for NestJS)

Deploy a backend app

Put the app in an entry file and export it. Easel looks for, in the root directory:

  • app, index, or server, with a .js, .cjs, .mjs, .ts, .cts, or .mts extension, at the top level or in src/
  • main with the same extensions, at the top level or in src/, for NestJS
src/index.ts
import { Hono } from "hono";

const app = new Hono();

app.get("/", (c) => c.text("Hello from Hono"));
app.get("/api/users/:id", (c) => c.json({ id: c.req.param("id") }));

export default app;

CommonJS apps export it with module.exports = app. Then create a project from your Git repository or deploy with the CLI:

easel deploy

Easel detects the framework from the entry file importing it, and sets the project's Framework preset. A project created without a preset gets one on its first build. See framework detection.

What Easel deploys

App outputEasel resource
Entry file and its importsOne function that serves every path
Files in public/CDN assets, served before the function

Routing

Your app's router handles every path, with two exceptions that take precedence over it:

  • A root api/ folder. Each file in api/ becomes its own function at /api/<name>. Those routes shadow your app's own /api/* routes. Keep the app's routes in src/ and don't add a root api/ folder unless you mean to.
  • public/index.html. Files in public/ are served from the CDN first, so public/index.html answers / instead of your app. Remove it, or serve the page from a route.

ES modules

With "type": "module" in package.json, Node.js resolves relative imports only with their file extension. Write .js even when the source file is TypeScript:

src/index.ts
import { users } from "./routes/users.js";

An import without the extension builds, then fails at runtime with ERR_MODULE_NOT_FOUND.

Troubleshooting

The build failed with "the build produced no functions"

Easel stopped the build because publishing it would have served your server code as static files. Either:

  • The Framework preset is Other while the source is a backend app. Set the preset to your framework in Project settings → Build and redeploy.
  • The preset names a backend framework but no entry file matched. Rename or move the app's entry file to one of the entry file names.

/api/* routes return the wrong response

A root api/ folder shadows them. See Routing.

/ shows a static page instead of the app

public/index.html answers /. See Routing.

Known limitations

The app runs as a function, so it doesn't keep in-memory state or open connections between requests. See Functions runtime for what persists, and Limits for durations and sizes.