Skip to content
Switch branches/tags

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time


install size

Zero config typescript/es6 server with the filesystem as the router


Inspired by NextJS, iga exposes a lightweight server using your file system as a router.

  • One command
  • 0 config ES6 modules
  • Typescript out of the box
  • Use the file system as the router
  • Automatic code reloading


npm install iga


In your package.json:

  "scripts": {
    "dev": "iga",
    "start": "iga start"

Then create a routes folder with an index.js. Each route should export a function with the standard NodeJS request and response objects with some helpers.

// routes/index.js
export default () => 'Hello from iga!'

If you run npm start and you visit http://localhost:3000 you will see Hello from iga!.


Now let's create another endpoint. Create a file routes/random-fruit.js:

// routes/random-fruit.js
export default () => {
  const fruits = ['apple', 'orange', 'pear']
  const random = Math.floor(Math.random() * 3)

  return fruits[random]

Now if you run npm start again and visit http://localhost:3000/random-fruit you will get any of the fruits we declared in the file.

If you don't want to restart the server everytime you make changes, use npm run dev to disable cache and see the latest changes to your code.

Response / Request

iga catches the return value of your function and makes an http response with it, so you can do things like:

  • return 'some text': Response will be plain text
  • return { foo: bar }: Response will be JSON
  • return 403: Response will send a 403 status code

If you still want to do something manually, you can use both request and response objects, like:

export default (req, res) => {
  res.end(`Hello from ${req.url}`)

In this case the return value will be ignored, because http headers have already been sent with res.end.



Contains the result of require('url').parse(req.url, true).query, so you can code faster:

// routes/find-user.js
export default req => {
  if (!req.query.userId) {
    return 403 // bad request

  const user = getUserFromDatabase({ id: req.query.userId })
  if (!user) {
    return 404 // not found

  return { results: [user] }

Filesystem as the router

As you might have noticed by the previous examples, iga convers your file system into routes as follows:

  • routes/index.js: /
  • routes/foo.js: /foo
  • routes/foo/bar.js: /foo/bar
  • routes/also-typescript.ts: /also-typescript

ES6 / Typescript

By default, iga allows you to write your code in es5 module.exports, es6 export defaultor even typescript, with 0 configurations, thanks to sucrase. For .js files it will allow you to write es6 modules, but you can also directly write typescript in .ts files.

import { ServerResponse, IncomingMessage } from 'http'

export default function(req: IncomingMessage, res: ServerResponse) {
  res.end('hello from typescript.ts')


If you want to, your exported function can be an async function so you can use await inside it to manage promises.




Without any arguments, iga will build your project everytime there's a change in your routes folder, so you can focus on coding.

iga start

It will start the server without rebuilding. This should be used in production.


-p | --port XXXX

Optional. Start the server on port XXXX. Defaults to 3000.

Programmatic usage

iga exposes an API so it's easier to test and use as a library:

import iga from 'iga'
import http from 'http'

const server = new http.Server(iga)

If you want, there are some options you can customize:

import { getMiddleWare } from 'iga'
import http from 'http'

const server = new http.Server(
    routes: __dirname,
    useCache: false


routes?: string

Path to the folder that contains your routes

Default: path.join(process.cwd(), 'routes')

useCache?: boolean

If false everytime you change your code you will be able to see the new version on the server This is what iga command uses with no arguments

Default: true


Any provider that can run NodeJS will work. If you want to use, I made a simple example that works. It uses deploy.js as the lambda in




Pablo Varela