Skip to content
πŸπŸ› οΈ Backend and auth starter for SaaS startups
TypeScript TSQL JavaScript HTML Dockerfile
Branch: master
Clone or download
AnandChowdhary Merge pull request #336 from o15y/dependabot/npm_and_yarn/snyk-1.227.0
⬆️ Bump snyk from 1.226.2 to 1.227.0
Latest commit d87c557 Sep 17, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
.circleci πŸ’š Change Node to v10.16.3 Sep 4, 2019
.github/workflows πŸ‘· Add GitHub Actions Sep 13, 2019
assets πŸ“ Update brand info Jun 13, 2019
setup ✨ Add basic update script Aug 31, 2019
src πŸ”§ Update brute-free times Sep 13, 2019
static 🍱 Add favicon.ico Jul 9, 2019
.all-contributorsrc docs: update .all-contributorsrc Sep 14, 2019
.cirrus.yml πŸ‘· Add Cirrus CI Sep 5, 2019
.env.example ✨ Add ElasticSearch index prefix Aug 31, 2019
.gitignore πŸ™ˆ Add redis dump to .gitignore Sep 10, 2019
.snyk fix: .snyk & package.json to reduce vulnerabilities Jul 5, 2019
.travis.yml πŸ”§ Add NPM deploy to Travis CI Sep 13, 2019 πŸ“ Add Gitmoji to contributing guidelines Aug 30, 2019
Dockerfile 🐳 Add build to Dockerfile Aug 24, 2019
LICENSE πŸ“„ Add email to LICENSE Apr 22, 2019 docs: update Sep 14, 2019
azure-pipelines.yml πŸ‘· Add Azure Pipelines Sep 4, 2019
captain-definition 🐳 Use Dockerfile in Caprover Jul 11, 2019
netlify.toml πŸ› Fix incorrect build command Apr 30, 2019
package.json Merge pull request #336 from o15y/dependabot/npm_and_yarn/snyk-1.227.0 Sep 17, 2019
schema.sql Update for fine grained SQL permissions Aug 30, 2019
tsconfig.json βœ… Add first test Jul 15, 2019
yarn.lock Merge pull request #336 from o15y/dependabot/npm_and_yarn/snyk-1.227.0 Sep 17, 2019


Staart is a Node.js backend starter for SaaS startups written in TypeScript. It has built-in user management and authentication, billing, organizations, GDPR tools, and more.

Build GitHub Actions Travis CI Circle CI Azure Pipelines Cirrus CI
Dependencies Dependencies Dev dependencies Vulnerabilities
Community Contributors GitHub Type definitions

Staart is build to work with Staart UI, the frontend starter for SaaS.

⭐ Features

πŸ” Security

  • Authentication and user management with JWT
  • Two-factor authentication with TOTP
  • Setup multiple emails for each account
  • OAuth2 login with third-party accounts
  • Location-based login verification
  • Security event logging and history

πŸ’³ SaaS

  • Subscriptions management with Stripe
  • Organizations, teams, and user permissions
  • Invoices, billing, credit cards, payments
  • Rich HTML transactional emails with SES
  • GDPR-proof data export and delete
  • Affiliates and commission management
  • API gateway with API keys and rate limits
  • Auto-join members with domain verification

πŸ‘©β€πŸ’» Developer utilities

  • Decorators and class syntax with OvernightJS
  • Injection-proof helpers for querying databases
  • Data pagination and CRUD utilities for all tables
  • Authorization helpers (can a user do this?)
  • TypeScript interfaces for tables (ORM)
  • Caching and invalidation for common queries
  • User impersonation for super-admin
  • Easy redirect rules in YAML
  • Store server logs in ElasticSearch every minute

πŸ›  Usage

  1. Use this template or fork this repository
  2. Install dependencies with yarn or npm i
  3. Add a .env file based on config.ts.
  4. Create MariaDB/MySQL tables based on schema.sql
  5. Add your controllers in the ./src/controllers directory
  6. Generate your app.ts file using yarn generate-routes
  7. Build with yarn build and deploy with yarn start

Updating Staart

To update your installation of Staart, run the following:

node setup/update.js

If you've used the "Use this template" option on GitHub, you might have to force pull from o15y/staart the first time since the histories wouldn't match. You can use the flag --allow-unrelated-histories in this case.

πŸ’» API

Staart comes with tens of helper and CRUD methods for users, organizations, and more.

View wiki docs β†’

View TypeDoc β†’

View API demo β†’

View frontend demo β†’

πŸ‘©β€πŸ’Ό Getting started

After forking this repository, you can get started by writing your first endpoint. We do this by creating a new file in the ./src/controllers folder. For example, create api.ts:

import { Request, Response } from "express";
import asyncHandler from "express-async-handler";
import { Get, Controller, ClassWrapper, Middleware } from "@overnightjs/core";
import { authHandler, validator } from "../helpers/middleware";
import Joi from "@hapi/joi";

export class ApiController {
      { name: Joi.string().min(3).required() },
  async sayHello(req: Request, res: Response) {
    const name =;
    if (name === "Anand")
      return res.json({ text: `Hello, ${name}!`; });
    throw new Error("404/user-not-found");

The above code 20 lines of code with create a new endpoint which can be accessed at, which will respond with a JSON object with the text "Hello, Anand!".

Staart code is easily understandable. You create a new controller, api, which means all routes in this class will have the prefix /api. Then, you create an HTTP GET method hello and use our built-in validator to say that the query parameter name must be a string of at least 3 characters.

With the asyncHandler, you can use async functions and Staart will handle errors for you. In this case, if the provided name is Anand, your function returns a JSON response "Hello, Anand!" and otherwise sends an error 404.


For common tasks such as finding users or authorizing API keys, Staart provides various helper functions.

Let's look at what you need to do if you want to let users be able to delete organizations. For this, you want to check where a user is actually allowed to delete that organization, if they're logged in, and make sure nobody can brute force this endpoint.

import { can } from "../helpers/authorization";
import { Authorizations, ErrorCode } from "../interfaces/enum";
import { authHandler, bruteForceHandler } from "../helpers/middleware";
import { deleteOrganization } from "../crud/organization";

// Your controller here
async deleteOrg(req: Request, res: Response) {
  const orgId =;
  const userId =;
  if (await can(userId, Authorizations.DELETE, "organization", orgId)) {
    await deleteOrganization(orgId);
    return res.status(204);
  throw new Error(ErrorCode.INSUFFICIENT_PERMISSION);

In the above example, the Staart helpers and middleware used are:

  • Authentication (authHandler): Checks if a user's token is valid and adds res.locals.token; and if it isn't, sends a 401 Unauthorized error.
  • Brute force prevention (bruteForceHandler): Prevents users from making too many requests in a short time, can be configured via ./src/config.ts
  • Authorization (can): Returns whether a user is allowed to perform an action based on their permissions

Of course, we actually prefer to write our logic in the rest folder and only the handler as a controller. For a deeper dive into Staart, look at our Wiki docs.

πŸ‘₯ Contributors

Thanks goes to these wonderful people (emoji key):

Anand Chowdhary
Anand Chowdhary

πŸ’» πŸ“– 🎨


πŸ› πŸ€”

πŸ› πŸ’»


This project follows the all-contributors specification. Contributions of any kind welcome!

πŸ—οΈ Built with Staart

🏁 Staart Ecosystem

The Staart ecosystem consists of open-source projects to build your SaaS startup, written in TypeScript.

πŸ› οΈ Staart Node.js backend with RESTful APIs Travis CI GitHub
🌐 Staart UI Frontend Vue.js Progressive Web App Travis CI GitHub
πŸ“± Staart Native React Native app for Android and iOS Travis CI GitHub
🎨 Staart.css Sass/CSS framework and utilities Travis CI GitHub

πŸ“„ License

You can’t perform that action at this time.