diff --git a/cli.js b/cli.js
index 1e7ef10..ba29988 100755
--- a/cli.js
+++ b/cli.js
@@ -41,7 +41,8 @@ const cli = meow(`
-d --out-dir Output directory (default dist)
-s --static Output static HTML without JS bundle
-t --template Path to custom HTML template
-
+ --basename Basename for URL paths
+ --title Page title
`, {
flags: {
// dev
diff --git a/docs/JSX.md b/docs/JSX.md
new file mode 100644
index 0000000..b1f5e63
--- /dev/null
+++ b/docs/JSX.md
@@ -0,0 +1,19 @@
+---
+---
+
+# Using JSX
+
+x0 supports Compositor JSX format, which allows writing files as pure JSX without any JavaScript syntax.
+
+```jsx
+---
+title: JSX Example
+---
+import { Box, Heading } from 'rebass'
+
+
+
+ Hello
+
+
+```
diff --git a/docs/MDX.md b/docs/MDX.md
new file mode 100644
index 0000000..aa4b7f6
--- /dev/null
+++ b/docs/MDX.md
@@ -0,0 +1,20 @@
+
+# Using MDX
+
+x0 also supports [MDX][mdx] format out of the box.
+MDX allows you to mix markdown syntax with JSX to render React components.
+
+```mdx
+---
+title: MDX Example
+---
+import { Box } from 'rebass'
+
+# Hello
+
+
+ Beep
+
+```
+
+[mdx]: https://github.com/mdx-js/mdx
diff --git a/docs/_app.js b/docs/_app.js
index 478845d..839a66d 100644
--- a/docs/_app.js
+++ b/docs/_app.js
@@ -8,9 +8,47 @@ import {
Box,
Container,
} from 'rebass'
+import sortBy from 'lodash.sortby'
import LandingLayout from './_layout'
import theme from './_theme'
+import X0 from './_logo'
+
+const navOrder = [
+ 'index',
+ 'getting-started',
+ 'markdown',
+ 'react',
+ 'MDX',
+ 'JSX',
+ 'routing',
+ 'custom-app',
+ 'components',
+ 'ScopeProvider',
+ 'SidebarLayout',
+ 'LivePreview',
+ 'LiveEditor',
+ 'cli-options',
+ 'exporting',
+ 'examples',
+]
+const pageNames = {
+ index: 'Home',
+ 'cli-options': 'CLI Options'
+}
+
+const sortRoutes = routes => [
+ ...sortBy([...routes], a => {
+ const i = navOrder.indexOf(a.name)
+ return i < 0 ? Infinity : i
+ })
+].map(route => {
+ if (!pageNames[route.name]) return route
+ return {
+ ...route,
+ name: pageNames[route.name]
+ }
+})
export default class App extends React.Component {
static defaultProps = {
@@ -29,10 +67,16 @@ export default class App extends React.Component {
? LandingLayout
: SidebarLayout
+ const nav = sortRoutes(routes)
+
return (
-
+ }
+ />
)
diff --git a/docs/_logo-rect.js b/docs/_logo-rect.js
new file mode 100644
index 0000000..8adbfd9
--- /dev/null
+++ b/docs/_logo-rect.js
@@ -0,0 +1,27 @@
+import React from 'react'
+import X0 from './_logo'
+
+export default ({
+ size = 1024
+}) =>
+
diff --git a/docs/_logo.js b/docs/_logo.js
new file mode 100644
index 0000000..cde8154
--- /dev/null
+++ b/docs/_logo.js
@@ -0,0 +1,29 @@
+import React from 'react'
+
+export default ({
+ size = 128,
+ color = 'currentcolor'
+}) =>
+
diff --git a/docs/cli-options.md b/docs/cli-options.md
new file mode 100644
index 0000000..ccfa293
--- /dev/null
+++ b/docs/cli-options.md
@@ -0,0 +1,39 @@
+---
+name: CLI Options
+---
+
+# CLI Options
+
+```
+--webpack Path to webpack config file
+--match String to match routes against using minimatch
+```
+
+The following options are used for the development server.
+
+```
+-o --open Open dev server in default browser
+-p --port Port for dev server
+--analyze Runs with webpack-bundle-analyzer plugin
+```
+
+The following options are used for static export.
+
+```
+-d --out-dir Output directory (default dist)
+-s --static Output static HTML without JS bundle
+-t --template Path to custom HTML template
+--basename Basename for URL paths
+--title Page title
+```
+
+## package.json
+
+CLI options can also be specified in a `package.json` field named `x0`.
+
+```json
+"x0": {
+ "title": "Hello",
+ "basename": "/my-site"
+}
+```
diff --git a/docs/components/LiveEditor.md b/docs/components/LiveEditor.md
new file mode 100644
index 0000000..cd89867
--- /dev/null
+++ b/docs/components/LiveEditor.md
@@ -0,0 +1,17 @@
+
+# LiveEditor
+
+The LiveEditor component can be used in React components outside of markdown code fences.
+When used within a [ScopeProvider](ScopeProvider) component, there's no need to pass a custom `scope` object.
+
+```jsx
+import React from 'react'
+import { LiveEditor } from '@compositor/x0/components'
+
+const code = ``
+
+export default props =>
+
+```
diff --git a/docs/components/LivePreview.md b/docs/components/LivePreview.md
new file mode 100644
index 0000000..3d5b87d
--- /dev/null
+++ b/docs/components/LivePreview.md
@@ -0,0 +1,17 @@
+
+# LivePreview
+
+The LivePreview component can be used in React components outside of markdown code fences.
+When used within a [ScopeProvider](ScopeProvider) component, there's no need to pass a custom `scope` object.
+
+```jsx
+import React from 'react'
+import { LivePreview } from '@compositor/x0/components'
+
+const code = ``
+
+export default props =>
+
+```
diff --git a/docs/components/ScopeProvider.md b/docs/components/ScopeProvider.md
new file mode 100644
index 0000000..09712bb
--- /dev/null
+++ b/docs/components/ScopeProvider.md
@@ -0,0 +1,17 @@
+
+# ScopeProvider
+
+The ScopeProvider component allows you to customize the components that are used to render markdown elements
+and to provide components in scope for rendering code fences as live previews.
+It's best to use this component in a [Custom App](/custom-app) component.
+
+```jsx
+import React from 'react'
+import ScopeProvider from '@compositor/x0/components'
+import * as scope from '../src'
+
+export default props =>
+
+ {props.children}
+
+```
diff --git a/docs/components/SidebarLayout.md b/docs/components/SidebarLayout.md
new file mode 100644
index 0000000..7ffcc1d
--- /dev/null
+++ b/docs/components/SidebarLayout.md
@@ -0,0 +1,134 @@
+
+# SidebarLayout
+
+The SidebarLayout component can be used to quickly create a documentation site with navigation.
+This site uses the SidebarLayout component for navigation and pagination in the documentation section.
+
+To use the component, import it in a [custom App](/custom-app).
+
+```jsx
+import React from 'react'
+import { SidebarLayout } from '@compositor/x0/components'
+
+export default props =>
+
+```
+
+## Customizing navigation
+
+The `props.routes` array can be altered to customize the order, names, and other aspects of the navigation.
+
+### Sorting the routes
+
+By default the `routes` array is in alphabetical order, with index pages occuring first.
+To sort the array for display in navigation, pass a new `routes` prop to the SidebarLayout component.
+
+```jsx
+import React from 'react'
+import { SidebarLayout } from '@compositor/x0/components'
+import sortBy from 'lodash.sortby'
+
+const navOrder = [
+ 'index',
+ 'getting-started',
+ 'api'
+]
+
+export default props => {
+ const sortedRoutes = sortBy(props.routes, route => {
+ const i = navOrder.indexOf(route.name)
+ return i
+ })
+
+ return (
+
+ )
+}
+```
+
+### Customizing Route Names
+
+By default the layout will format the filename by capitalizing each word and removing hyphens.
+To customize the name of the routes for navigation, pass a new `routes` prop to the SidebarLayout component.
+
+```jsx
+import React from 'react'
+import { SidebarLayout } from '@compositor/x0/components'
+import sortBy from 'lodash.sortby'
+
+const routeNames = {
+ index: 'Home',
+ api: 'API'
+}
+
+export default props => {
+ const renamedRoutes = props.routes.map(route => {
+ if (!routeNames[route.name]) return route
+ return {
+ ...route,
+ name: routeNames[route.name]
+ }
+ })
+
+ return (
+
+ )
+}
+```
+
+## Full Width Pages
+
+The SidebarLayout component will center the contents of the page by default.
+To make a page span the full width of the main column, set the `fullWidth` option in default props or front-matter.
+
+```md
+---
+fullWidth: true
+---
+
+# Full-width markdown page
+```
+
+```jsx
+import React from 'react'
+
+export default class extends React.Component {
+ static defaultProps = {
+ fullWidth: true
+ }
+
+ render () {
+ return (
+
Full-width component
+ )
+ }
+}
+```
+
+## Page-Specific Layouts
+
+Custom layouts can be specified as front-matter or default props, then handled in a custom App component to control the layout for specific pages.
+
+```jsx
+// example with custom layouts
+import React from 'react'
+import { SidebarLayout } from '@compositor/x0/components'
+import HomeLayout from './_home-layout.js'
+
+export default props => {
+ const { route } = this.props
+ const { layout } = route.props
+
+ const Layout = layout === 'home' ? HomeLayout : SidebarLayout
+
+ return
+}
+```
+
+
diff --git a/docs/components/index.md b/docs/components/index.md
new file mode 100644
index 0000000..cdbd4df
--- /dev/null
+++ b/docs/components/index.md
@@ -0,0 +1,9 @@
+
+# Built-in Components
+
+x0 includes several built-in components to make creating a custom site quicker.
+
+- [ScopeProvider](ScopeProvider)
+- [SidebarLayout](SidebarLayout)
+- [LivePreview](LivePreview)
+- [LiveEditor](LiveEditor)
diff --git a/docs/custom-app.md b/docs/custom-app.md
new file mode 100644
index 0000000..ed80d10
--- /dev/null
+++ b/docs/custom-app.md
@@ -0,0 +1,126 @@
+
+# Custom App Component
+
+Use a custom App component to completely customize the layout, add context providers, use global state, or set a custom scope.
+
+## Layouts
+
+Create a file named `_app.js` to provider a custom App component to x0.
+This file can be used for custom layouts, including headers, footers, and navigation.
+
+```jsx
+// _app.js
+import React from 'react'
+import { Link } from 'react-router-dom'
+import {
+ Container,
+ Toolbar,
+ NavLink
+} from 'rebass'
+
+export default class extends React.Component {
+ render () {
+ const { children } = this.props
+ return (
+
+
+
+ Home
+
+
+
+ {children}
+
+
+ )
+ }
+}
+```
+
+## Providers
+
+Context providers, such as styled-component's `ThemeProvider` can be included in a custom app.
+
+```jsx
+import React from 'react'
+import { ThemeProvider } from 'styled-components'
+import theme from '../src/theme'
+
+export default props =>
+
+
+ {props.children}
+
+
+```
+
+## Scope
+
+Use the x0 `ScopeProvider` to customize the components used when rendering markdown elements in `.md` or `.mdx` files.
+The `ScopeProvider` also provides scope to [live code examples](markdown/#code-fences) in code fences.
+
+```jsx
+import React from 'react'
+import { ScopeProvider } from '@compositor/x0/components'
+import * as scope from '../src'
+
+export default props =>
+
+ {props.children}
+
+```
+
+## App State
+
+Global application state can also be provided in a custom App.
+Use `props.Component` instead of `props.children` to pass props to the rendered route.
+
+```jsx
+import React from 'react'
+
+export default class extends React.Component {
+ state = {
+ count: 0
+ }
+
+ update = fn => this.setState(fn)
+
+ render () {
+ const { Component } = this.props
+
+ return (
+
+ )
+ }
+}
+```
+
+## Props
+
+Custom Apps receive the following props, which can expose greater control over the rendering.
+
+- `children`: rendered content of the page
+- `Component`: a component to pass props to the current route and render content
+- `routes`: an array of route objects for the entire site – can be used for rendering navigation
+- `route`: the current route object
+- The [React Router][react-router] state is also passed to the App
+
+### Route Object
+
+Routes include the following properties:
+
+- `key`: the filepath from webpack's `require.context`
+- `name`: the basename of the file
+- `path`: path used for routing
+- `extname`: file extension
+- `dirname`: file directory
+- `exact`: (boolean) added to index pages for React Router
+- `module`: the JS module for the file
+- `Component`: the default export from the file
+- `props`: default props or front-matter specified in the file
+
+[react-router]: https://github.com/ReactTraining/react-router
+
diff --git a/docs/examples.md b/docs/examples.md
new file mode 100644
index 0000000..b3d0793
--- /dev/null
+++ b/docs/examples.md
@@ -0,0 +1,5 @@
+---
+ignore: true
+---
+
+# Examples
diff --git a/docs/exporting.md b/docs/exporting.md
new file mode 100644
index 0000000..4aa9152
--- /dev/null
+++ b/docs/exporting.md
@@ -0,0 +1,49 @@
+
+# Exporting
+
+x0 sites can be exported as static sites using the `x0 build` command.
+
+```sh
+x0 build docs
+```
+
+## Options
+
+Options for static export can be passed as flags or specified in a `package.json` field named `x0`.
+
+```
+-d --out-dir Output directory (default dist)
+-s --static Output static HTML without JS bundle
+-t --template Path to custom HTML template
+--basename Basename for URL paths
+--title Page title
+```
+
+## Custom HTML Templates
+
+A custom HTML template function can be used for greater control over the HTML output.
+
+```js
+module.exports = ({
+ html = '',
+ css = '',
+ scripts,
+ title = 'x0',
+ meta = [],
+ links = [],
+}) =>
+`
+
+
+
+ ${title}
+ ${css}
+
+
${html}
+${scripts}
+`
+```
+
+See the [default template][template] for an example.
+
+[template]: https://github.com/c8r/x0/blob/master/lib/template.js
diff --git a/docs/getting-started.md b/docs/getting-started.md
new file mode 100644
index 0000000..356939e
--- /dev/null
+++ b/docs/getting-started.md
@@ -0,0 +1,92 @@
+---
+---
+
+# Getting Started
+
+Install x0 either globally or as a dev dependency in your project.
+
+```sh
+npm install --global @compositor/x0
+```
+
+```sh
+npm install --save-dev @compositor/x0
+```
+
+Create a directory for your documentation or other site.
+
+```sh
+mkdir docs
+```
+
+Start the development server.
+
+```sh
+x0 docs
+```
+
+*Note: if you installed x0 as a dev dependency, add the command above to a run script in your `package.json`*
+
+
+Create an `index.md` file in the `docs/` directory.
+
+```md
+# Hello World
+```
+
+Open your browser to to see the file you just created.
+
+To create another route, add another file to the `docs/` directory,
+for example `getting-started.md`
+
+````md
+# Getting Started
+
+```sh
+npm install @compositor/x0
+```
+````
+
+The `getting-started.md` file should now be available at .
+
+Add a link to the *Getting Started* page from `index.md`.
+
+```md
+# Hello World
+
+- [Getting Started](getting-started)
+```
+
+## Using React components
+
+In addition to markdown, x0 can render any React component as a page.
+Create a `demo.js` file.
+
+```jsx
+// demo.js
+import React from 'react'
+
+export default class extends React.Component {
+ render () {
+ return (
+
Demo
+ )
+ }
+}
+```
+
+## Using MDX
+
+x0 also supports [MDX][mdx] format, which allows you to mix JSX with markdown syntax.
+
+```md
+import { Box } from 'rebass'
+
+# Hello MDX
+
+
+ This will render as a React component
+
+```
+
+[mdx]: https://github.com/mdx-js/mdx
diff --git a/docs/index.js b/docs/index.js
index 0290f41..69c4155 100644
--- a/docs/index.js
+++ b/docs/index.js
@@ -20,8 +20,20 @@ const Video = styled.video([], {
borderRadius: '16px',
})
+const features = [
+ 'Zero-config',
+ 'No plugins',
+ 'Components over configuration',
+ 'Use markdown, MDX, or React components',
+ 'Automatic file-system based routing',
+ 'Completely customizable',
+ 'Static-site generator',
+ 'Isolated development environment',
+]
+
export default class extends React.Component {
static defaultProps = {
+ name: 'Home',
layout: 'landing'
}
@@ -29,15 +41,7 @@ export default class extends React.Component {
return (
-
- x0: Zero-config React development environment & static site generator
-
-
+
+
+ x0:
+ Document & develop React components without breaking a sweat
+