🐶 🐶 🐶 a popular-choice grab-bag framework for teams working on production web apps
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
commands
lib
test
.gitignore
README.md
Root.js
browser.js
cli.js
config.js
createApiServer.js
createAssetServer.js
createClient.js
createDb.js
createLog.js
createRoot.js
createStore.js
createStyle.js
index.js
intl.js
package-lock.json
package.json
transform.js

README.md

dogstack on a post-it note
dogstack

🐶 🐶 🐶 a popular-choice grab-bag framework for teams working on production web apps

🐱 see also catstack, dogstack's smarter, slimmer, more cunning partner in crime

features

  • abstracts away the app plumbing that you don't want to write again, and let's you focus on features
  • prescribes enough opinion to reduce friction for your team
  • is omakase, modules are hand-picked by expert chefs to deliver a consistent taste throughout
  • gives prescriptive opinions for how to structure production-scale apps

examples

documentation

dogstack.js.org

cli usage

api server

starts api server

dog api

asset server

starts asset server

dog asset

db

Runs knex command, with any arguments.

dog db

api usage

server.js

export configuration for the feathers server

example:

// server.js
export default {
  services: [
    require('./agents/service')
    require('./accounts/service'),
    require('./authentication/service'),
    require('./profiles/service'),
    require('./relationships/service')
  ]
}
// agents/service.js
import feathersKnex from 'feathers-knex'

export default function () {
  const app = this
  const db = app.get('db')

  const name = 'dogs'
  const options = { Model: db, name }

  app.use(name, feathersKnex(options))
  app.service(name).hooks(hooks)
}

const hooks = {
  before: {},
  after: {},
  error: {}
}

browser.js

dogstack exports a function createBrowserEntry out of browser.js with which to generate your dogstack client app. a dogstack app should have a file which calls this function with the required arguments, and which has it's name passed to entry as part of the asset config.

example:

const createBrowserEntry = require('dogstack/browser')
const Config = require('dogstack/config')
const config = Config()()
window.config = config

// other imports of files needed for browser entry argument, as outlined in sections below

createBrowserEntry({
  config,
  store,
  style,
  client,
  root,
  intl,
  routes,
  Layout
})

explanations and examples of the parts that must be passed to createBrowserEntry:

config

a feathers-configuration compatible config object. Dogstack provides dogstack/config as a wrapper around feathers-configuration to make this easy

example:

// config/default.js
module.exports = {
  favicon: 'app/favicon.ico',
  app: {
    name: 'Dogstack Example'
  },
  api: {
    port: 3001,
    url: 'http://localhost:3001/',
  },
  asset: {
    port: 3000,
    entry: 'browser.js',
    root: 'app/assets',
    url: 'http://localhost:3000/'
}

store

an object with updater and epic properties:

  • updater: a function of shape action => state => nextState, combined from each topic using redux-fp.concat
  • epic: a function of shape (action$, store, { feathers }) => nextAction$, combined from each topic using combineEpics

example:

// store.js
import updater from './updater'
import epic from './epic'

export default {
  updater,
  epic
}

style

an object with theme and setup properties:

  • theme: object passsed to <FelaThemeProvider theme={theme} />
  • setup: function of shape (renderer) => {}

example:

// style.js
export default {
  theme: {
    colorPrimary: 'green',
    colorSecondary: 'blue'
  },
  setup: (renderer) => {
    renderer.renderStatic(
      { fontFamily: 'Lato' },
      'html,body,#app'
    )
    renderer.renderFont('Lato', [
      'https://fonts.gstatic.com/s/lato/v11/qIIYRU-oROkIk8vfvxw6QvesZW2xOQ-xsNqO47m55DA.woff'
    ])
  }
}

client

configuration for feathers client, as an object with services and config properties:

  • services: an array of functions that will be run with client.configure(plugin)
  • apiUrl: the url of the api server for the client to connect to (normally this can be extracted from your config)

example:

// client.js
export default {
  services: [
    authentication
  ],
  config
}

root

a configuration object for the root React component with appNode and styleNode properties:

  • appNode: query selector string or dom node to render app content
  • styleNode: query selector string or dom node to render app styles

example:

// root.js
export default {
  appNode: '#app',
  styleNode: '#app-styles',
}

routes

an array of React routes to be rendered as props into your top-level Layout component

example:

// routes.js
export default [
  {
    name: 'home',
    path: '/',
    exact: true,
    Component: Home,
    selector: getIsNotAuthenticated,
    navigation: {
      title: 'app.home',
      icon: 'fa fa-home'
    }
  },
  {
    name: 'dogs',
    path: '/',
    exact: true,
    Component: UserIsAuthenticated(DogsContainer),
    selector: getIsAuthenticated,
    navigation: {
      title: 'dogs.dogs',
      selector: getIsAuthenticated,
      icon: 'fa fa-paw'
    }
  },
  {
    name: 'dog',
    path: '/d/:dogId',
    Component: UserIsAuthenticated(DogContainer)
  }
]

Layout

your top-level rendered React component, which accepts routes as props

example:

transform.js

exported browserify transform to be plugged in to your app's package.json

  • can be configured to whitelist particular config key / values to be available to the browser

example:

// package.json
...
"browserify": {
  "transform": [
    // other transforms
    [
      "dogstack/transform",
      {
        "config": {
          "keys": [
            "api",
            "asset",
            "authentication"
          ]
        }
      }
    ]
  ]
}
...