diff --git a/packages/pubsweet-styleguide/package.json b/packages/pubsweet-styleguide/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..8f10e73f6e17a2fb7b618e88b156fede82a099ad
--- /dev/null
+++ b/packages/pubsweet-styleguide/package.json
@@ -0,0 +1,39 @@
+{
+  "name": "@pubweet/styleguide",
+  "version": "0.1.0",
+  "files": [
+    "src",
+    "dist"
+  ],
+  "main": "src",
+  "dependencies": {
+    "react": "^15.6.1",
+    "react-dom": "^15.6.1",
+    "react-redux": "^5.0.2",
+    "react-router-dom": "^4.2.2",
+    "recompose": "^0.26.0",
+    "redux": "^3.6.0",
+    "redux-form": "^7.0.3",
+    "xpub-journal": "^0.0.2",
+    "xpub-theme": "^0.0.2"
+  },
+  "devDependencies": {
+    "babel-core": "^6.26.0",
+    "babel-loader": "^7.1.2",
+    "babel-preset-env": "^1.6.0",
+    "babel-preset-react": "^6.24.1",
+    "babel-preset-stage-2": "^6.24.1",
+    "css-loader": "^0.28.4",
+    "node-sass": "^4.5.3",
+    "rimraf": "^2.6.1",
+    "sass-loader": "^6.0.6",
+    "style-loader": "^0.19.0",
+    "webpack": "^3.8.1",
+    "webpack-node-externals": "^1.6.0"
+  },
+  "scripts": {
+    "clean": "rimraf dist",
+    "prebuild": "npm run clean && npm run lint",
+    "build": "webpack --progress --profile"
+  }
+}
diff --git a/packages/pubsweet-styleguide/src/components/StyleGuideRenderer.js b/packages/pubsweet-styleguide/src/components/StyleGuideRenderer.js
new file mode 100644
index 0000000000000000000000000000000000000000..b1a65700dfd22533f14e9ac59fc07e47849c3114
--- /dev/null
+++ b/packages/pubsweet-styleguide/src/components/StyleGuideRenderer.js
@@ -0,0 +1,18 @@
+import React from 'react'
+import classes from './StyleGuideRenderer.local.scss'
+
+const StyleGuideRenderer = ({ title, children, toc }) => (
+  <div className={classes.root}>
+    <div className={classes.sidebar}>
+      <header className={classes.header}>
+        <h1 className={classes.title}>{title}</h1>
+      </header>
+
+      <nav className={classes.nav}>{toc}</nav>
+    </div>
+
+    <div className={classes.content}>{children}</div>
+  </div>
+)
+
+export default StyleGuideRenderer
diff --git a/packages/pubsweet-styleguide/src/components/StyleGuideRenderer.local.scss b/packages/pubsweet-styleguide/src/components/StyleGuideRenderer.local.scss
new file mode 100644
index 0000000000000000000000000000000000000000..bdd3e8097da381478d55ed6ac804cf701de0422d
--- /dev/null
+++ b/packages/pubsweet-styleguide/src/components/StyleGuideRenderer.local.scss
@@ -0,0 +1,37 @@
+.root {
+  display: grid;
+  grid-template-areas: "side content";
+  grid-template-columns: 1fr 3fr;
+  height: 100vh;
+  width: 100vw;
+}
+
+.sidebar {
+  display: flex;
+  flex-direction: column;
+  grid-area: side;
+  overflow-y: hidden;
+}
+
+.content {
+  grid-area: content;
+  overflow-y: auto;
+  padding: 1rem;
+}
+
+.header {
+  padding: 0.5rem;
+}
+
+.nav {
+  flex: 1;
+  overflow-y: auto;
+  padding: 0.5rem;
+}
+
+.title {
+  font-family: "Fira Sans", sans-serif;
+  font-size: 1rem;
+  margin-bottom: 0;
+  padding: 0 1rem;
+}
diff --git a/packages/pubsweet-styleguide/src/components/Wrapper.js b/packages/pubsweet-styleguide/src/components/Wrapper.js
new file mode 100644
index 0000000000000000000000000000000000000000..b0df3e215880398c8f3c948ea2d3cab36ac5b270
--- /dev/null
+++ b/packages/pubsweet-styleguide/src/components/Wrapper.js
@@ -0,0 +1,33 @@
+import React from 'react'
+import { Provider } from 'react-redux'
+import { BrowserRouter as Router } from 'react-router-dom'
+import { reducer as formReducer } from 'redux-form'
+import { createStore, combineReducers } from 'redux'
+import { JournalProvider } from 'xpub-journal'
+
+import 'xpub-theme'
+
+import * as journal from '../config/journal'
+
+import classes from './Wrapper.local.scss'
+
+const rootReducer = combineReducers({
+  form: formReducer,
+})
+
+const store = createStore(
+  rootReducer,
+  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
+)
+
+const Wrapper = ({ children }) => (
+  <Provider store={store}>
+    <Router>
+      <JournalProvider journal={journal}>
+        <div className={classes.root}>{children}</div>
+      </JournalProvider>
+    </Router>
+  </Provider>
+)
+
+export default Wrapper
diff --git a/packages/pubsweet-styleguide/src/components/Wrapper.local.scss b/packages/pubsweet-styleguide/src/components/Wrapper.local.scss
new file mode 100644
index 0000000000000000000000000000000000000000..7f3a1cd9c7537ff5770c04584c6c0372a5f0f062
--- /dev/null
+++ b/packages/pubsweet-styleguide/src/components/Wrapper.local.scss
@@ -0,0 +1,7 @@
+:global(body) {
+  overflow: hidden;
+}
+
+.root {
+  font-family: 'Fira Sans', sans-serif;
+}
diff --git a/packages/pubsweet-styleguide/src/components/index.js b/packages/pubsweet-styleguide/src/components/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..6c609447f503d184ae88fb2abd76b6cd9eba9690
--- /dev/null
+++ b/packages/pubsweet-styleguide/src/components/index.js
@@ -0,0 +1,4 @@
+module.exports = {
+  StyleGuideRenderer: require('./StyleGuideRenderer'),
+  Wrapper: require('./Wrapper'),
+}
diff --git a/packages/pubsweet-styleguide/src/config/journal/article-sections.js b/packages/pubsweet-styleguide/src/config/journal/article-sections.js
new file mode 100644
index 0000000000000000000000000000000000000000..f258a498836451ea9f6b30abf64b44a2bf4c6c47
--- /dev/null
+++ b/packages/pubsweet-styleguide/src/config/journal/article-sections.js
@@ -0,0 +1,30 @@
+export default [
+  {
+    value: 'cognitive-psychology',
+    label: 'Cognitive Psychology',
+  },
+  {
+    value: 'social-psychology',
+    label: 'Social Psychology',
+  },
+  {
+    value: 'personality-psychology',
+    label: 'Personality Psychology',
+  },
+  {
+    value: 'developmental-psychology',
+    label: 'Developmental Psychology',
+  },
+  {
+    value: 'clinical-psychology',
+    label: 'Clinical Psychology',
+  },
+  {
+    value: 'organizational-behavior',
+    label: 'Organizational Behavior',
+  },
+  {
+    value: 'methodology',
+    label: 'Methodology and Research Practice',
+  },
+]
diff --git a/packages/pubsweet-styleguide/src/config/journal/article-types.js b/packages/pubsweet-styleguide/src/config/journal/article-types.js
new file mode 100644
index 0000000000000000000000000000000000000000..bdaa9f9e39346a55815221a86b57050db13a97ac
--- /dev/null
+++ b/packages/pubsweet-styleguide/src/config/journal/article-types.js
@@ -0,0 +1,18 @@
+export default [
+  {
+    value: 'original-research',
+    label: 'Original Research Report',
+  },
+  {
+    value: 'review',
+    label: 'Review',
+  },
+  {
+    value: 'opinion',
+    label: 'Opinion/Commentary',
+  },
+  {
+    value: 'registered-report',
+    label: 'Registered Report',
+  },
+]
diff --git a/packages/pubsweet-styleguide/src/config/journal/decisions.js b/packages/pubsweet-styleguide/src/config/journal/decisions.js
new file mode 100644
index 0000000000000000000000000000000000000000..6a91c806aee2ea843eaa301739387e7522a103de
--- /dev/null
+++ b/packages/pubsweet-styleguide/src/config/journal/decisions.js
@@ -0,0 +1,23 @@
+export default {
+  accept: {
+    label: 'Accept',
+    color: 'green',
+    message: 'The submission has been accepted for publication',
+  },
+  minor: {
+    label: 'Minor revisions',
+    color: 'orange',
+    message:
+      'The submission will be accepted for publication after minor changes',
+  },
+  major: {
+    label: 'Major revisions',
+    color: 'yellow',
+    message: 'The requested changes must be made before submission for review',
+  },
+  reject: {
+    label: 'Reject',
+    color: 'red',
+    message: 'The submission is not acceptable for publication',
+  },
+}
diff --git a/packages/pubsweet-styleguide/src/config/journal/declarations.js b/packages/pubsweet-styleguide/src/config/journal/declarations.js
new file mode 100644
index 0000000000000000000000000000000000000000..012e4d46c2bfe3b20da969a9277a391d61c18094
--- /dev/null
+++ b/packages/pubsweet-styleguide/src/config/journal/declarations.js
@@ -0,0 +1,28 @@
+export default {
+  questions: [
+    {
+      id: 'openData',
+      legend: 'Data is open',
+    },
+    {
+      id: 'previouslySubmitted',
+      legend: 'Previously submitted',
+    },
+    {
+      id: 'openPeerReview',
+      legend: 'Open peer review',
+    },
+    {
+      id: 'streamlinedReview',
+      legend: 'Streamlined review',
+    },
+    {
+      id: 'researchNexus',
+      legend: 'Submitted as part of the research nexus?',
+    },
+    {
+      id: 'preregistered',
+      legend: 'Pre-registered?',
+    },
+  ],
+}
diff --git a/packages/pubsweet-styleguide/src/config/journal/editors.js b/packages/pubsweet-styleguide/src/config/journal/editors.js
new file mode 100644
index 0000000000000000000000000000000000000000..e19de06a9df69826e9e7667f9ff7d4d2ca44944f
--- /dev/null
+++ b/packages/pubsweet-styleguide/src/config/journal/editors.js
@@ -0,0 +1,32 @@
+export default {
+  managingEditor: [
+    {
+      user: 1,
+      name: 'Managing Editor One',
+    },
+    {
+      user: 2,
+      name: 'Managing Editor Two',
+    },
+  ],
+  seniorEditor: [
+    {
+      user: 3,
+      name: 'Senior Editor One',
+    },
+    {
+      user: 4,
+      name: 'Senior Editor Two',
+    },
+  ],
+  handlingEditor: [
+    {
+      user: 5,
+      name: 'Handling Editor One',
+    },
+    {
+      user: 6,
+      name: 'Handling Editor Two',
+    },
+  ],
+}
diff --git a/packages/pubsweet-styleguide/src/config/journal/index.js b/packages/pubsweet-styleguide/src/config/journal/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..30bc3a405632a2e2ff3972ac0c490a26666ce330
--- /dev/null
+++ b/packages/pubsweet-styleguide/src/config/journal/index.js
@@ -0,0 +1,9 @@
+export { default as metadata } from './metadata'
+export { default as declarations } from './declarations'
+export { default as decisions } from './decisions'
+export { default as recommendations } from './recommendations'
+export { default as sections } from './sections'
+export { default as articleSections } from './article-sections'
+export { default as articleTypes } from './article-types'
+export { default as editors } from './editors'
+export { default as roles } from './roles'
diff --git a/packages/pubsweet-styleguide/src/config/journal/metadata.js b/packages/pubsweet-styleguide/src/config/journal/metadata.js
new file mode 100644
index 0000000000000000000000000000000000000000..940970ae1d4d51ac0889b940344d453af3e48360
--- /dev/null
+++ b/packages/pubsweet-styleguide/src/config/journal/metadata.js
@@ -0,0 +1,4 @@
+export default {
+  name: 'Example Journal',
+  issn: '1234-1234',
+}
diff --git a/packages/pubsweet-styleguide/src/config/journal/recommendations.js b/packages/pubsweet-styleguide/src/config/journal/recommendations.js
new file mode 100644
index 0000000000000000000000000000000000000000..ad4a252206cd22d092ada66a38271ab86881f2c9
--- /dev/null
+++ b/packages/pubsweet-styleguide/src/config/journal/recommendations.js
@@ -0,0 +1,17 @@
+export default [
+  {
+    value: 'accept',
+    label: 'Accept',
+    color: 'green',
+  },
+  {
+    value: 'revise',
+    label: 'Revise',
+    color: 'orange',
+  },
+  {
+    value: 'reject',
+    label: 'Reject',
+    color: 'red',
+  },
+]
diff --git a/packages/pubsweet-styleguide/src/config/journal/roles.js b/packages/pubsweet-styleguide/src/config/journal/roles.js
new file mode 100644
index 0000000000000000000000000000000000000000..0f9334d4c66a69a75359e50150a8f7b40f153ee6
--- /dev/null
+++ b/packages/pubsweet-styleguide/src/config/journal/roles.js
@@ -0,0 +1,6 @@
+export default {
+  author: 'Author',
+  handlingEditor: 'Handling Editor',
+  managingEditor: 'Managing Editor',
+  seniorEditor: 'Senior Editor',
+}
diff --git a/packages/pubsweet-styleguide/src/config/journal/sections.js b/packages/pubsweet-styleguide/src/config/journal/sections.js
new file mode 100644
index 0000000000000000000000000000000000000000..72bbd760b76499147343cb51e9a73954f71eade3
--- /dev/null
+++ b/packages/pubsweet-styleguide/src/config/journal/sections.js
@@ -0,0 +1,6 @@
+export default [
+  {
+    id: 'submissions',
+    label: 'My Submissions',
+  },
+]
diff --git a/packages/pubsweet-styleguide/src/index.js b/packages/pubsweet-styleguide/src/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..88b6ebcddf409aced437479f935853774ae078b3
--- /dev/null
+++ b/packages/pubsweet-styleguide/src/index.js
@@ -0,0 +1 @@
+module.exports = require('./components')
diff --git a/packages/pubsweet-styleguide/src/webpack-config.js b/packages/pubsweet-styleguide/src/webpack-config.js
new file mode 100644
index 0000000000000000000000000000000000000000..71c81cef1c423f1a706dd4cc76ce5f07cc55a936
--- /dev/null
+++ b/packages/pubsweet-styleguide/src/webpack-config.js
@@ -0,0 +1,124 @@
+process.env.BABEL_ENV = 'development'
+process.env.NODE_ENV = 'development'
+
+const path = require('path')
+const webpack = require('webpack')
+// const nodeExternals = require('webpack-node-externals')
+
+module.exports = dir => {
+  const include = [
+    path.join(dir, 'src'),
+    /pubsweet-[^/]+\/src/,
+    /xpub-[^/]+\/src/,
+    /wax-[^/]+\/src/,
+    /@pubsweet\/[^/]+\/src/,
+  ]
+
+  return {
+    devtool: 'cheap-module-source-map',
+    entry: './src/index.js',
+    // externals: [nodeExternals({
+    //   whitelist: [/\.(?!js$).{1,5}$/i]
+    // })],
+    module: {
+      rules: [
+        {
+          oneOf: [
+            // ES6 modules
+            {
+              test: /\.js$/,
+              include,
+              loader: 'babel-loader',
+              options: {
+                presets: [
+                  [require('babel-preset-env'), { modules: false }],
+                  require('babel-preset-react'),
+                  require('babel-preset-stage-2'),
+                ],
+                cacheDirectory: true,
+              },
+            },
+
+            // CSS modules
+            {
+              test: /\.local\.css$/,
+              include,
+              use: [
+                'style-loader',
+                {
+                  loader: 'css-loader',
+                  options: {
+                    modules: true,
+                    // sourceMap: true,
+                    localIdentName: '[name]_[local]-[hash:base64:8]',
+                  },
+                },
+              ],
+            },
+
+            // SCSS modules
+            {
+              test: /\.local\.scss$/,
+              include,
+              use: [
+                'style-loader',
+                {
+                  loader: 'css-loader',
+                  options: {
+                    modules: true,
+                    importLoaders: 1,
+                    // sourceMap: true,
+                    localIdentName: '[name]_[local]-[hash:base64:8]',
+                  },
+                },
+                'sass-loader',
+              ],
+            },
+
+            // global CSS
+            {
+              test: /\.css$/,
+              use: ['style-loader', 'css-loader'],
+            },
+
+            // global SCSS
+            {
+              test: /\.scss$/,
+              use: [
+                'style-loader',
+                'css-loader',
+                // {
+                //   loader: 'css-loader',
+                //   options: {
+                //     importLoaders: 1,
+                //   }
+                // },
+                'sass-loader',
+              ],
+            },
+
+            // Files
+            {
+              exclude: [/\.js$/, /\.html$/, /\.json$/],
+              loader: 'file-loader',
+              options: {
+                name: 'static/media/[name].[hash:8].[ext]',
+              },
+            },
+          ],
+        },
+      ],
+    },
+    output: {
+      filename: 'index.js',
+      path: path.join(dir, 'dist'),
+    },
+    plugins: [
+      // mock constants
+      new webpack.DefinePlugin({
+        PUBSWEET_COMPONENTS: '[]',
+      }),
+    ],
+    watch: true,
+  }
+}
diff --git a/packages/pubsweet-styleguide/webpack.config.js b/packages/pubsweet-styleguide/webpack.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..f4cc52969a202b0eeeb0a2d67475312813a3b1dc
--- /dev/null
+++ b/packages/pubsweet-styleguide/webpack.config.js
@@ -0,0 +1,3 @@
+const webpackConfig = require('./src/webpack-config')
+
+module.exports = webpackConfig(__dirname)