npm i biti -g
️ this repo is deprecated in favor of @rola/static and the rola project.
biti watch pages/ static/
biti
is pretty simple. It operates on a single directory of pages, which each
define and export properties and methods that biti
uses to render the page.
For the examples here, we'll use /pages
as our pages directory, but you could
call it anything.
Each page requires the following exports:
pathname
- string - the path where you'd like the page to appearview
- function - a function that returns a React componentThe pathname property will be passed to the view
component.
An simple page might look like this:
import React from 'react'
export const pathname = '/about'
export function view ({ pathname }) {
return (
<>
<h1>About Us</h1>
<p>...</p>
</>
)
}
Pages can also export a state
object, which will also be passed to the view
function when rendering.
import React from 'react'
export const pathname = '/about'
export const state = {
title: 'About Us',
description: '...'
}
export function view ({ state, pathname }) {
return (
<>
<h1>{state.title}</h1>
<p>{state.description}</p>
</>
)
}
Routes that require data or those that need dynamic properties can define a
config
function that returns a page config containing the same properties
listed above.
These values will be deeply merged with whatever static exports were provided.
import React from 'react'
import { getAboutPage } from './lib/api.js'
export const pathname = '/about'
export const state = {
title: 'About Us',
team: [
'Eric'
]
}
export function config () {
return getAboutPage()
.then(res => {
return {
state: {
team: res.team
}
}
})
}
export function view ({ state, pathname }) {
return (
<>
<h1>{state.title}</h1>
<h2>Team</h2>
{state.team.map(name => (
<p key={name}>{name}</p>
))}
</>
)
}
For generative pages and pagination, the config
function can also return an
array of page configs. Each of these configs should define its own pathname
,
so that each page is rendered separately.
The following example will generate a page for each post returned from
getBlogPosts
:
import React from 'react'
import { getBlogPosts } from './lib/api.js'
export function config () {
return getBlogPosts()
.then(posts => {
return posts.map(post => ({
pathname: `/posts/${post.slug}`,
state: {
title: post.title,
content: post.content
}
}))
})
}
export function view ({ state, pathname }) {
return (
<>
<h1>{state.title}</h1>
<article>
{state.content}
</article>
</>
)
}
biti
supports minimal configuration, and otherwise falls back to smart
defaults. To define a config for all rendering tasks, you can create a
biti.config.js
file.
biti
supports the following properties on the config file:
env
- object - properties on this object will be attached to process.env
,
as well as defined globally within the compilation.alias
- object - module import aliasesExample:
module.exports = {
env: {
API_KEY: 'abcdefg'
},
alias: {
components: './src/components'
}
}
By default, biti
defines a single alias @
that points to process.cwd()
.
You can use it throughout your templates like this:
import Component from '@/src/components/Component.js'
biti
only has two commands: render
and watch
.
Both follow the same pattern:
biti <command> <src> <dest>
For example:
biti render /pages /static
These commands also accept globs as the src
property, allowing you to specify
individual pages or directories.
biti render /pages/about-us.js /static
biti render /pages/*.js /static
biti render /pages/marketing-site/*.js /static
biti render /pages/**/*.js /static
Using biti
programmatically is virtually the same as using the CLI, only
you'll need to pass your configuration object manually.
const biti = require('biti')
const config = {
env: { ... },
alias: { ... }
}
const app = biti(config)
Both render
and watch
have the following signature:
app.render(src, dest)
Renders all pages from src
dest
.
app.render('/src', '/static')
Watches all pages in src
and renders to dest
on file change.
app.watch('/src', '/static')
A biti
instance emits a few helpful events as well.
After rendering a single page.
app.on('render', page => {})
After rendering all pages. On watch this is called after every change has been compiled and rendered.
app.on('rendered', pages => {})
app.on('error', error => {})
MIT License © Eric Bailey