Skip to content
Flexible web framework.
Branch: master
Clone or download
Latest commit 86e11d0 Feb 10, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
helpers improve full stack examples Dec 20, 2018
plugins improve wording Feb 10, 2019
.gitignore add .npmignore May 12, 2018
.npmignore improve docs Dec 31, 2018
package.json misc Dec 22, 2018


Star if you like              Co-maintain Reframe
Follow on Twitter          Chat on Discord          


Intro   |   Starters   |   Usage Manual   |   Concepts   |   Plugins


Framework to create web apps.

Designed for high development speed with no sacrifice on flexibility.

Assembles a JavaScript stack that integrates with:
   •  Node.js server (Express, Koa, Hapi, ...)
   •  Modern frontend (React, Vue.js, React Native Web, ...)
   •  Node.js ORM (Objection.js, TypeORM, ...)
   •  Utils (TypeScript, React Router, PostCSS, ...)

All stacks are supported:
   •  frontend + backend + database/ORM (aka full-stack)
   •  frontend + backend (aka SSR)
   •  frontend-only (aka static site)
   •  backend-only (aka old-school app with plain old HTML)

We create an app simply by defining a React component and a so-called page config. No build configuration, no server configuration. (But, if you want, you can configure and take control over everything.)



Web frameworks have a bad reputation regarding flexibility. There is a general belief that there is a trade off between development speed and flexibility and that a web framework always comes with a lost in flexibility. We believe it doesn't have to be that way.

Reframe is designed from the ground up to be entirely flexible, based on three pillars:

  1. Eject - All Reframe parts are ejectable: You can eject and take control over the build code, the webpack config, the render code, the routing code, the server code, ...

  2. Slim - Most code we write are for do-one-thing-do-it-well libraries that can be used independently of Reframe. Reframe in itself is only a tiny ejectable wrapper on top of do-one-thing-do-it-well libraries.

  3. Flexible stack - You can easily and at any time change your app's stack. For example, you can start with a static site and add a Node.js server afterwards.

Benefits of that flexibility:

Take Over Control - Not only can you eject and take control over everything, but you can do so progressively, one Reframe part at a time. Reframe is slim and ejecting everything leaves you with only ~500 LOC.

Removable - Ejecting all Reframe parts effectively removes Reframe: Your code then doesn't depend on @reframe packages but only on do-one-thing-do-it-well libraries (such as React, Express, Webpack, ...).

Rapid Prototyping - When starting out, you most often don't know what stack is right for you. Reframe embraces that: You can change your app's stack at any time. You don't know whether or not you need SSR? Start with your best guest and add/remove SSR as you go.

⇧ TOP ⇧

Quick Start

  1. Install the Reframe CLI:

    $ npm install -g @reframe/cli
    With yarn
    $ yarn global add @reframe/cli
    With npx (local install)

    Instead of globally installing @reframe/cli, you can use npx:

    $ npx @reframe/cli create react-frontend

    Then prefix every $ reframe <command> with npx. For example:

    $ cd my-react-frontend/
    $ npx reframe dev

    npx uses the @reframe/cli locally installed at my-react-frontend/node_modules/@reframe/cli.

  2. Create a new app with the react-frontend starter:

    $ reframe create react-frontend
  3. Build and serve the app:

    $ cd my-react-frontend/
    $ reframe dev
  4. Open http://localhost:3000.

  5. Read Usage Manual - Basics.

The react-frontend starter scaffolds a static site. There are other starters to scaffold a SSR app, a backend-only app, a full-stack app, etc. See Starters.

⇧ TOP ⇧


Showcase of a database + server + frontend stack.

Let's create our app. First, we define our data models with Objection.js:

const {Model} = require('objection');

class Person extends Model {
  static tableName = 'persons';
  static jsonSchema = {
    properties: {
      id: {type: 'integer'},
      name: {type: 'string'}

module.exports = Person;
const {Model} = require('objection');
const Person = require('./Person');

class Animal extends Model {
  static tableName = 'animals';
  static jsonSchema = {
    properties: {
      id: {type: 'integer'},
      name: {type: 'string'},
      ownerId: {type: 'integer'}
  static relationMappings = {
    owner: {
      relation: Model.BelongsToOneRelation,
      modelClass: Person,
      join: {
        from: 'animals.ownerId',
        to: ''

module.exports = Animal;

Then, we create an endpoint using Wildcard API:

const {endpoints} = require('wildcard-api');
const Person = require('../db/models/Person');
const Animal = require('../db/models/Animal');

// We create an endpoint to retrieve all the data that our PetsPage need.

endpoints.getPetsPageData = async function(personId) {
  const person = await Person.query().findOne('id', personId);
  const pets = await Animal.query().where('ownerId', personId);
  return {person, pets};

Finally, we create PetsPage, a page to view a person's pets:

import React from 'react';
import {endpoints} from 'wildcard-api/client';

export default {
  route: '/pets/:personId',
  view: Pets,

function Pets({person, pets}) {
  return (
      {}'s pets:
      { =>
        <div key={}>{}</div>
      ) }

async function getInitialProps({personId}) {
  const {person, pets} = await endpoints.getPetsPageData(personId);
  return {person, pets};

That's it: We create a full-stack app with no build configuration, no server configuration, no API configuration.

The react-sql starter scaffolds such Reframe + Objection + Wildcard API stack.

⇧ TOP ⇧

You can’t perform that action at this time.