node package manager
Easy collaboration. Discover, share, and reuse code in your team. Create a free org »

pristine-app

pristine

usage

developing a styleguide app with pristine

pristine ships with a React component and a server. The server sets up a cutting-edge Webpack hot-reloaded development environment and serves up your app for you. The React component wraps up your components and renders the pristine UI.

There's a bit of trickery involved to make all this work.

In the end, all you should have to do is provide a few things and you're good to go. We'll get to that in a moment, but let's start from the top:

npm i --save-dev pristine-app

We're saving pristine as a development dependency so that it won't be pulled in as a sub-dependency for apps which will consume the styleguide we create with it. In other words, if I'm developing the cats-and-buttons styleguide, and I want my cat-app to consume its components, I don't want cat-app to also have to install pristine when it does that—pristine is only used and installed by cats-and-buttons.

Set up your package.json start script to look something like this:

{
  "scripts": {
    "start": "pristine start"
  },
  "..."
}

... this will run the provided pristine server for you. Configuration is available over command line:

--pristineConfig # location of config file (see app config section)
--mongoUri # mongodb connection url (overridden by MONGODB_URI env variable)
--webpackConfig # custom webpack config file (read the whole readme AND the default webpack file before attempting)
--port # an alternate port to run on (defaults 3000)

The server is set up, but there's still a few more things you need to provide.

NEW: run bootstrapper

To skip the following, run ./node_modules/.bin/pristine bootstrap to bootstrap the initial files into your working directory.

Initial development files

Create a pristine.js file, which will be referred to as the 'main file'. pristine expects this to be present (you could override that using the entry value in the config as described later).

Your pristine.js should look something like this:

import FirstComponent from './components/FirstComponent';
import SecondComponent from './components/SecondComponent';
 
import themeOne from './themes/themeOne';
import themeTwo from './themes/themeTwo';
 
export const components = [
  FirstComponent,
  SecondComponent,
];
 
export const themes = [
  themeOne,
  themeTwo,
];
 
export const header = null;

Note that we are exporting three things here:

  • A list of our components. This can also be an object, where keys are category names, and values are lists of components in that category.

  • A list of themes. These are styled-components themes. Supply at least one if you utilize themes in your components.

  • A header. It's completely optional. Use this to change what renders in the header of the app. Can be a string or a React node.

pristine will require this file and use its exports to populate the styleguide editor. If something goes wrong, this is probably the first place to look.

A few last things

Oh, you'll need to have MongoDb installed and running. Yeah, I know. As far as databases go, though, it's one of the easiest to kickstart a hobby project with.

Now try npm start. Wait a few seconds for webpack to build the bundle, then visit http://localhost:3000. I hope you see the pristine UI. If not, double check the instructions, then submit an issue if you're sure it's my fault.

styleguide app config

The server can and should be configured with a JSON file (by the --config flag) which contains some information about your usage

{
  "appName": "my app",
  "packageName": "my-app",
  "mongoUri": "mongodb://mongourl.com/database",
  "entry": "myStyleguideModule.js",
}

appName: the name of the app/styleguide you're using pristine for

packageName: the name of the npm package you're publishing from pristine (used for code samples in the app)

mongoUri: a MongoDb connection string, same as --mongoUri parameter (overridden by all others, including CLI parameter and environment variable MONGODB_URI).

entry: a relative location from your root directory (wherever you run pristine start from) to your main file. Default is pristine.js.

wrappers

You can use wrapper components provided with Pristine to control how your components are rendered in the inspect page. By default, all components are wrapped in a center wrapper, which uses a flexbox layout to center the component horizontally and vertically. This works well for components which don't much care about their surroundings. However, it can contort components which attempt to grow to fit their containers. There are a few other wrappers you can use:

  • full: Adds no extra layout styling; simply renders the component within the render area, allowing use of the full area. Probably most analogous to how the component will be rendered 'in the wild'.
  • children: A special wrapper which allows you to pass JSX child content as the second parameter to the wrapper function. This child content will always be rendered inside the component, unless the component is passed a property _pristine_empty with a true value. The _pristine_empty property will not be shown in the usage code.
  • padded: Like full, but adds some padding using a wrapper div. Padding defaults to 12px, but you can override that by passing any valid padding value as the second parameter.

Use wrappers like so (in our app.js):

import { full, center, children, padded } from 'pristine-app';
 
export const renderedComponents = [
  full(SomeComponent),
  center(SomeComponent),
  children(SomeComponent, (<h1>rendered as a child!</h1>)),
  padded(SomeComponent, '1em 1em 0 1.5em'),
];

custom wrappers

You can create your own wrappers using the wrapper thunk which is exported from the library as createWrapper. createWrapper takes one parameter, a function in which you should define and return your Wrapper class.

const wrapper = createWrapper(function (WrappedComponent, extraArgs...) { /* returns Wrapper class */ });
const wrappedComponent = wrapper(SomeComponent);

Your wrapper class must inherit from Wrapper, which is exposed by the library. To do that, just replace the normal extends React.Component with extends Wrapper in your class definition.

distributing your styleguide

pristine is designed to enable you to distribute your styleguide look + feel as a hard dependency for your applications.

for react

To distribute your React components, you'll want to include your shared component library which you developed using Pristine as a Git submodule in your project (NOT as an NPM/Yarn dependency). Including it as a Git submodule makes your components act like 'first-class' code, allowing dead-simple integration into your existing React app (just import your components from the submodule directory). Of course, your Webpack configuration for your parent app should be able to load anything in your component files, so depending on how you wrote your components, you may need to tweak that.

for vanilla js / other frameworks

WARNING: currently broken, I believe.

In production mode, pristine includes a download link in the header for the CSS file it generates. Add this stylesheet to your project and apply the classnames as specified in the HTML usage examples.

generators

pristine ships with a generator for your components. To use it, run pristine generate.

deploying

Your pristine app should be ready for deployment to environments like heroku, but using the default hot-reloading webpack config will eat up a lot of memory. You'll probably want to build a webpack bundle and run the server in produciton mode. To do so, run webpack pointed to the included production webpack config file:

{
  "scripts": {
    "postinstall": "pristine build"
  }
}

Make sure your NODE_ENV environment variable is production, so that your server will serve up the bundle. I think this is default behavior on heroku.

developing pristine

I recommend using npm link to link up the pristine-components, pristine, and pristine-example repos locally to test. Run pristine-example to test your changes. Wow, I really need automated testing, I'm so sorry.

disclaimer

pristine is an experimental and volatile young project. I wouldn't count on it staying consistent in pattern, interface or even purpose in the short-term. Don't build your business on this, please.

I don't have many tests and half of them are broken. I'm on a 2-week sprint to get something worth showing off so I'm afraid I've gone a bit lax. I'm generally a big proponent of testing so I do hope to circle back on that once the dust settles.

acknowledgements

I kickstarted pristine as a sabbatical project at my company Bandwidth. They're really cool to let me dive into a passion project like that. If it ends up being any good, we'll be using it internally.