Home

Awesome

<p align="center"> <img src="https://raw.githubusercontent.com/electric-eloquence/fepper-npm/master/excludes/fepper-branding.png" alt="Fepper" > </p> <h2 align="center">A frontend prototyper tool for rapid prototyping of websites</h2>

Known Vulnerabilities Linux Build Status Mac Build Status Windows Build Status Node Version License

Downstream projects

Table of contents

<a id="install"></a>Install

System requirements

Simplest way to get started

Mac install

CLI install

Windows install

Base install

Post-install

<a id="configure"></a>Configure

Fepper will run perfectly well out-of-the-box with default configurations. For further customization, power-users can edit these files:

Edit conf.yml to suit the needs of your development environment. If using Git, conf.yml will not be version controlled by default.

Edit pref.yml to customize Fepper preferences. If you wish to use the fp syncback, fp frontend-copy, or fp template tasks, you must supply values for the backend.synced_dirs preferences in order for those directories to get processed and copied to the backend.

Edit patternlab-config.json to configure Pattern Lab, the design system behind the Fepper UI.

<a id="run"></a>Run

<a id="update"></a>Update

Run fp update to download and install the latest updates.

<a id="global-data"></a>Global Data

Edit source/_data/_data.json to globally populate <a href="https://www.npmjs.com/package/feplet" target="_blank">Feplet</a> (.mustache) templates with data. Never edit source/_data/data.json as it will get overwritten on each build.

<a id="partial-data"></a>Partial Data

Underscore-prefixed .json files within source/_patterns will be concatenated to the output of _data.json, the whole in turn getting built into data.json, the final source of globally scoped data.

Partial data is distinct from pattern data. For example, 01-blog.json is pattern data and specific to the 01-blog pattern. No other pattern will pick up 01-blog.json, even if 01-blog.mustache is included in another pattern. However, _01-blog.json is partial data and will get concatenated to the global data outputted to data.json. _01-blog.json will be picked up by all patterns.

<a id="markdown-content"></a>Markdown Content

Fepper provides the convenience of managing content in <a href="https://daringfireball.net/projects/markdown/syntax" target="_blank"> Markdown</a>. To do so, create a .md file of the same name as the pattern. Edit this file in Front Matter syntax like so:

example.md:
---
content_key: content
---
# Heading

Sample body content

Front Matter comprises YAML between the --- lines and Markdown below them. It doesn't appear to have a unified spec, so searches for documentation will probably just list various implementations. In any case, content_key can be any valid whitespace-free string. Use it to identify its corresponding tag in the .mustache file like so:

example.mustache:
<main id="content">
  {{{ content }}}
</main>

Once properly set up, the Markdown can be edited in the Code Viewer.

When creating .md files for pseudo-patterns, replace the .json extension while leaving the rest of the filename intact.

<a id="code-viewer"></a>Code Viewer

<a href="https://www.npmjs.com/package/feplet" target="_blank">Feplet</a> (.mustache) code can be viewed in the Fepper UI by clicking the eyeball icon in the upper right and then clicking Code. The Code Viewer will then be opened, displaying the Feplet code of the pattern, and the partials tags within will be hot-linked to open their respective patterns in the main panel of the Fepper UI.

If the pattern has an associated .md file, its Markdown code can be viewed by clicking the "Markdown" tab. In order for the Code Viewer to allow edits to the Markdown, Fepper must be LiveReloading correctly. In most cases, LiveReload will just work out-of-the-box.

If the project was set up with Git, the Markdown edits can be version controlled with the Code Viewer's Git Interface as well.

Most Developers should be familiar with setting up projects with Git. It is beyond the scope of this document to provide much further instruction on Git. However, Editors are encouraged to version-control their edits with Git if collaborating with others.

In order to get Editors set up with Git, first make sure Git is installed. Then, install <a href="https://github.com/cli/cli#readme" target="_blank">GitHub CLI </a> (macOS and Windows only). A CLI requires a Terminal app, but Editors will generally only need this for setup and background operations. In fact, much of the setup can be automated within clickable scripts.

To proceed, an account must be registered at GitHub.com, and GitHub CLI installed as per the instructions in the previous link. Then, run the following in the Terminal:

macOS and Windows:
git config --global user.email name@email.address
git config --global user.name 'User Name'
gh auth login

After issuing the gh auth login command, press Enter to accept each default. After accepting to login with a web browser, press Enter to open the GitHub.com authentication webpage. Sign in to GitHub if necessary. Then, enter the 8-character code from the Terminal. Click to Authorize github. If the webpage shows success, return to the Terminal. It should say, "Authentication complete. Press Enter to continue..."

After pressing Enter to exit the prompt, Editors should be able to use the Git Interface with no more prompts for authentication.

Linux and other Unix-like OSs:

It is not recommended to use Fepper's graphical Git Interface in Linux and other, more obscure Unix-like OSs. It is not straightforward to authenticate with GitHub CLI in such OSs. The technical knowledge required to authenticate would be better applied using Git as intended for Developers.

<a id="requerio-inspector"></a>Requerio Inspector

The Code Viewer also has a Requerio Inspector. <a href="https://github.com/electric-eloquence/requerio#readme" target="_blank"> Requerio</a> is a tool you can use to manage the state of your web application. HTML elements given state are referred to as "organisms". In order to view their states, Requerio and its organisms need to be initialized as per the <a href="https://github.com/electric-eloquence/requerio#readme" target="_blank"> Requerio docs</a>. It is necessary to define window.requerio in order for the Requerio Inspector to work, as per the following code example:

const requerio = window.requerio = new Requerio($, Redux, $organisms);

A properly working Requerio app will then have its organisms and their states show up in the Requerio Inspector like an expandable menu, the state tree. Hovering over the state tree should highlight the organism being inspected. (It may be necessary to give the organisms a CSS background-color in order for the highlighting to work.) The display of the states will update in real-time, should there be any changes to the organisms. You can even dispatch changes ("actions") to the organisms via your browser's Developer Tools:

<a id="static-site-generator"></a>Static Site Generator

Running fp static will generate a complete static site based on the files in source/_patterns/04-pages. The site will be viewable at http://localhost:3000/static/. An index.html will be generated based on whatever is declared as the defaultPattern in patternlab-config.json. If links to other pages in the 04-pages directory work correctly in the Fepper UI, they will work correctly in the static site, even if the public/static directory is copied and renamed.

For example, assume an article is at source/_patterns/04-pages/articles-/00-top-story.mustache. Create the link as follows:

<a href="{{ link.pages-top-story }}">Article Headline</a>

This would built to the public directory as:

<a href="../04-pages-articles--00-top-story/04-pages-articles--00-top-story.html">Article Headline</a>

The Static Site Generator would output this as:

<a href="articles--top-story.html">Article Headline</a>

Numeric prefixes to filenames and sub-directories will be dropped. Nested source directories will be flattened and all static HTML files would become siblings. The pathing of nested folders would be retained in the filenames, so the organizational benefits of nesting folders will be retained.

Appending a hyphen (-) to the "articles" directory is just a recommended convention for static sites. While the Static Site Generator flattens nested source directories, the double-hyphen suggests that "articles" categorizes the more specific parts that follow.

Additional files can be put in source/_static so long as they do not get overwritten by the Static Site Generator.

<a id="the-backend"></a>The Backend

Fepper can very easily work with a CMS backend such as Drupal or WordPress, while not requiring Apache, MySQL, or PHP. Put the actual backend codebase or even just a symbolic link to the codebase into the backend directory. Then, enter the relative paths to the appropriate backend directories in pref.yml. (Do not include "backend" or a leading slash.) You will then be able to run fp syncback or fp frontend-copy to export your frontend data into your backend web application.

<a id="templater"></a>Templater

Fepper's <a href="https://www.npmjs.com/package/feplet" target="_blank">Feplet</a> (.mustache) templates can be translated into templates compatible with your backend. Feplet tags just need to be replaced with tags the backend can use. Put these translations into YAML (.yml) files named similarly to the .mustache files in source/_patterns/03-templates. Follow <a href="https://github.com/electric-eloquence/fepper-drupal/blob/dev/source/_patterns/03-templates/page.yml" target="_blank"> this example</a> for the correct YAML syntax.

Follow these rules for setting up keys and values:

Run fp syncback or fp template.

<p><a href="https://github.com/electric-eloquence/fepper-drupal" target="_blank"> Fepper for Drupal</a> and <a href="https://github.com/electric-eloquence/fepper-wordpress" target="_blank"> Fepper for WordPress</a> have working examples of templates compatible with the Templater.</p>

<a id="webserved-directories"></a>Webserved Directories

When using a backend, assets generally need to be shared with the Fepper frontend. The syncback and frontend-copy tasks copy files from Fepper to the backend, but not the other way. Instead of providing a task to copy in the reverse direction, Fepper serves backend files if their directories are entered into the webserved_dirs block in pref.yml. Be sure these values are formatted as YAML array elements.

WEBSERVED DIRECTORIES ARE FOR STATIC ASSETS ONLY! DO NOT WEBSERVE DIRECTORIES WITH BACKEND SOURCE CODE! NO BACKEND PROGRAMMING LANGUAGE WILL GET PREPROCESSED! IF A STATIC SITE IS GENERATED, OR THE EXPRESS APP PUBLICLY SERVED, SOURCE CODE WILL BE RENDERED AS PLAIN TEXT! THIS WILL MAKE PUBLIC ANY SENSITIVE INFORMATION CONTAINED WITHIN!

<a id="html-scraper"></a>HTML Scraper

Fepper can scrape and import the HTML of any valid web page into a reusable pattern. A common use-case is to scrape pages from a backend populated with CMS content in order to auto-generate data files, and to replicate the CMS's HTML structure. To open the Scraper, click Scrape in the Fepper UI, and then click HTML Scraper. Enter the URL of the page you wish to scrape. Then, enter the CSS selector you wish to target (prepended with "#" for IDs and "." for classes). Classnames and tagnames may be appended with array index notation ([n]). Otherwise, the Scraper will scrape all elements of that class or tag sequentially. Such a loosely targeted scrape will save many of the targeted fields to a JSON file, but will only save the first instance of the target to a Feplet (.mustache) file.

Upon submission, you should be able to review the scraped output on the subsequent page. If the output looks correct, enter a filename and submit again. The Scraper will save .mustache and .json files by that name in the 98-scrape directory, also viewable under the Scrape menu of the toolbar. The Scraper will also correctly indent the Feplet code.

<a id="variables.styl"></a>variables.styl

source/_scripts/src/variables.styl is a file containing variables that can be shared across the Stylus CSS preprocessor, browser JavaScripts, and PHP backends (and possibly other language backends as well). It ships with these values:

bp_lg_max = -1
bp_md_max = 1024
bp_sm_max = 767
bp_xs_max = 480
bp_xx_max = 320
bp_xx_min = 0

It cannot contain comments, semi-colons, curly braces, etc. It is straightforward to import and use these variables in Stylus and JavaScript. PHP must import them with parse_ini_file(). Fepper tries to be agnostic about CSS processors and tries to keep the amount of npms to download to a minimum. However, since Stylus allows for this easy sharing of variables, most Fepper distros ship with the <a href="https://www.npmjs.com/package/fp-stylus" target="_blank">fp-stylus</a> extension and a fully-populated source/_styles/src/stylus directory. The Stylus files are written in the terse, YAML-like, indentation-based syntax. However, the more verbose, CSS-like syntax (with curly braces and semi-colons) is perfectly valid as well.

The UI's viewport resizer buttons are dependent on the values in variables.styl. The default values will configure the XX, XS, SM, and MD buttons to resize the viewport to each breakpoint's assigned maximum width. The LG button will resize the viewport to a width that is greater than bp_md_max by the distance between bp_sm_max and bp_md_max.

Users have the ability to add, modify, or delete values in variables.styl. The UI will respect these changes; but keep in mind that additions must be prefixed by bp_ and suffixed by _max in order for them to appear as viewport resizer buttons. A -1 value translates to Number.MAX_SAFE_INTEGER, and effectively means infinity.

<a id="ui-customization"></a>UI Customization

All aspects of the UI are available for customization. For example, the toolbar can accept additions, modifications, and deletions per the needs of end-users. The UI markup is compiled by recursive, functional React calls. The recursion tree is reflected by the directory structure containing the modules which compose the UI. To override any given module, copy the directory structure leading to the module from <a href="https://github.com/electric-eloquence/fepper-npm/tree/dev/ui/core/styleguide/index/html" target="_blank"> https://github.com/electric-eloquence/fepper-npm/tree/dev/ui/core/styleguide/index/html</a> to source/_ui/index/html, respective to your implementation. Modifications to modules in that directory will override the corresponding modules in core. Additions (so long as they are correctly nested) will also be recognized.

A working example of UI customization can be found at <a href="https://github.com/electric-eloquence/fepper-drupal/blob/dev/source/_ui/index/html/00-head/head.component.js" target="_blank"> https://github.com/electric-eloquence/fepper-drupal/blob/dev/source/_ui/index/html/00-head/head.component.js</a>. The Fepper for Drupal project overrides its HTML title to read "Fepper for Drupal" instead of "Fepper". In order to do so, it has the head.component.js module nested in directories that correspond to the tags that nest the head HTML element. Both head.component.js and its nesting directories must be named similarly to their corresponding elements. .component.js indicates that the file is a module to be rendered by React. <a href="https://reactjs.org/docs/dom-elements.html" target="_blank"> It must export properties that React.createElement() understands</a>. The numeric prefix to 00-head orders it to precede 01-foot, even though "foot" precedes "head" alphabetically.

In this example, by allowing customizations in the 00-head directory separate from the core components, core updates will be respected for all components except for the HTML head.

Browser JavaScript and CSS customizations can (and should) be componentized this way as well. While a head element is unlikely to have associated scripts or styles, the UI's main element does have its scripts and styles componentized as <a href="https://github.com/electric-eloquence/fepper-npm/tree/dev/ui/core/styleguide/index/html/01-body/40-main" target="_blank"> main.js and main.css in index/html/01-body/40-main</a>. A big advantage for this type of componentization comes when elements are renamed or deleted. When you rename or delete the element, are you absolutely sure you'll rename or delete accordingly in some far-flung, monolithic script or style file?

Alas, no one should be forced to componentize this way. Generic modifications to UI scripts can be added to source/_scripts/ui-extender.js.

Similarly, generic modifications to UI styles can be added to source/_styles/pattern-scaffolding.css. (The file is named this way to adhere to the Pattern Lab convention on defining pattern states. It should not be relied on for pattern scaffolding.)

View All markup can also be overridden by copying the .mustache files in <a href="https://github.com/electric-eloquence/fepper-npm/tree/dev/ui/core/styleguide/viewall" target="_blank"> https://github.com/electric-eloquence/fepper-npm/tree/dev/ui/core/styleguide/viewall</a> and pasting them to source/_ui/viewall (nested correctly). Modifications will then be recognized and displayed in the UI. (No additions are allowed.) Custom View All styles can be added to source/_styles/pattern-scaffolding.css.

You will need to compile the UI in order for the browser to pick up custom changes to the UI:

fp ui:compile

New UI customizations will not be picked up simply by restarting Fepper.

The UI exposes these additional tasks:

<a id="extensions"></a>Extensions

The extend directory is purposed for extending Fepper's functionality. Extensions can be contributed or custom. The extend directory will not be modified when updating Fepper.

Contributed extensions:
Custom extensions:

It may be helpful to write help text for a custom extension, especially when a person other than the author uses it. To do this, create a custom task appended by ":help". Declare and log the help text as follows, and it will be output by running fp extend:help.

'use strict';

const gulp = global.gulp;

gulp.task('custom-task:help', function (cb) {
  let helpText = `
Fepper Custom Task Extension

Usage:
    <task> [<additional args>...]

Task and description:
    fp custom-task:help    Print usage and description of custom task.
`;

  console.log(helpText);
  cb();
});
Confs and prefs:

You might need to access the values in the conf.yml and pref.yml files in order to write custom tasks. They are exposed through global.conf and global.pref (on the global Node object).

The values in patternlab-config.json are exposed through global.conf.ui. Please note that all paths in patternlab-config.json will be converted to absolute paths in global.conf.ui. Relative paths can be accessed through global.conf.ui.pathsRelative.

Utilities:

Common utilty functions for custom extensions are available from the <a href="https://www.npmjs.com/package/fepper-utils" target="_blank">Fepper Utils</a> npm.

Object-oriented Fepper:

Beneath the gulp tasking system lies object-oriented Fepper. Running any fp task instantiates the Fepper class. This instance is exposed through the global.fepper object. By directly accessing the Fepper instance, you can run any Fepper operation without gulp. Deeper within Fepper lies the Patternlab class. By directly accessing Patternlab, you can run any Pattern Lab operation without Fepper. The Patternlab instance is attached to Fepper as global.fepper.ui.patternlab. The global.fepper object can, of course, be easily inspected in a console.

If there is something you wish were different about the Fepper class, or any of its member classes, you can inherit from the class, and make whatever changes you wish, without worry that your changes will be overwritten by the next update.

Here is an example of overriding the fp help command:

  1. Create an instance_file. For this example, let's write it at extend/custom/hack-help.js.
'use strict';

const FepperSuper = require('fepper');
const HelperSuper = require('fepper/core/tasks/helper');
const TasksSuper = require('fepper/core/tasks/tasks');

class Helper extends HelperSuper {
  constructor(options) {
    super(options);
  }

  main() {
    console.log('ASYNC ALL THE THINGS!');
  }
}

class Tasks extends TasksSuper {
  constructor(options) {
    super(options);
    this.helper = new Helper(this.options);
  }
}

module.exports = class Fepper extends FepperSuper {
  constructor(cwd) {
    super(cwd);
    this.tasks = new Tasks(this.options);
  }
}
  1. Declare instance_file in pref.yml.
instance_file: extend/custom/hack-help.js
  1. Run fp help on the command line. It should log <a href="https://www.npmjs.com/package/gulp4-run-sequence#why-the-culinary-task-names" target="_blank"> "ASYNC ALL THE THINGS!"</a>

Hackers wishing to view the code for any of these classes will find that the ES6 syntax and object-orientation makes the code mostly self-documenting. The entry point to the Fepper class is in <a href="https://github.com/electric-eloquence/fepper-npm/blob/dev/core/fepper.js" target="_blank"> Fepper NPM at core/fepper.js</a>.

There is currently no public API for object-oriented Fepper. To express demand for one, <a href="https://github.com/electric-eloquence/fepper/issues" target="_blank"> please open an issue</a>.

<a id="express-app"></a>Express App

Fepper exposes its <a href="https://expressjs.com/" target="_blank">Express</a> application through the global.expressApp object. This object can be overridden with custom routes and middleware via the custom:tcp-ip (or contrib:tcp-ip) extension task. Initialization of global.expressApp occurs before this task, and listening occurs afterward.

global.expressApp is a direct reference to global.fepper.tcpIp.fpExpress.app.

<a id="mobile-devices"></a>Mobile Devices

The best way to browse the Fepper UI on a mobile device is through the wireless connection on your development machine. These are the instructions for doing this on a Mac:

If your Mac is connected to the Internet wirelessly:

If your Mac is connected to the Internet through a wire:

<a id="i18n"></a>I18N

The Elements, Compounds, and Components directories are optional and can be renamed to anything your charset and file system allow without further configuration, so long as there are no collisions with other names. The Templates, Pages, and Scrape directories allow for similar renaming but they must be configured in patternlab-config.json.

The text in the UI, as well as console messages, can be changed by editing source/_ui/i18n/en.json. Replace the blank values with alternate English values if you wish. If you want translation to another language, create a new file named by the abbreviation for the language. For example: source/_ui/i18n/es.json for Spanish. Then, assign that abbreviation to the lang key in pref.yml. In the .json file, assign the translated values to the English keys.

Fepper follows a popular convention of naming the translation function t. (See <a href="https://github.com/i18next/i18next" target="_blank">i18next</a> and <a href="https://github.com/i18next/react-i18next" target="_blank">react-i18next</a> as other examples.) Be sure never to redefine the global.t variable.

If a need arises for documentation in other languages, you are strongly encouraged to make the translations, and use the options that Open Source offers to distribute them to the rest of the world.

<a id="keyboard-shortcuts"></a>Keyboard Shortcuts

As a reminder, the viewport sizes can be customized in source/_scripts/src/variables.styl.

<a id="more-documentation"></a>More Documentation