Frontend prototyping framework.

dev-develop 2022-01-26 00:20 UTC

README

Genuine Norm (GNorm) is an all-encompassing starting point for Genuine UI projects that provides architectural direction, fast scaffolding, code familiarity and promotes developer scalability.

Dependencies

OR

If you are using a Mac or Linux environment, this project is setup to use Docksal for local development. If you are on a Windows machine, a Mac with the new M1 processor, or do not wish to use the Docker-based containerized environments, you will need to install Node.JS locally.

Installation

Docksal

  • In the theme root, run fin init from the command line. This installs the required dependencies, and runs an initial build of the asset files.

Local

  1. In the theme root (where this file lives), run npm ci to install the required Node dependencies.
  2. Then, run npm run build for an initial build of the asset files.

Development

Local

  • npm run dev - runs a Gulp task that builds the front-end assets in a development mode, and initiates a watch task using BrowserSync, and automatically opens your browser the prototype index at http://localhost:8080/.

Docksal

From the root of the project, several commands can be issued from terminal:

  • fin up - ensures the necessary Docker containers are running. The prototype index can be found at http://lw.docksal/
  • fin fe [command] - is a Docksal command with several possible arguments:
    • watch - runs the same Gulp dev tasks as local, but does not automatically open your browser.
    • build - runs the Gulp build task.
  • fin ps - displays project stats. If state is anything other than Up (healthy), you will need to restart the containers using fin up

Additional Gulp tasks

  • [fin/npx] gulp [task] - manually run an individual Gulp task. A complete list of tasks are available with [fin/npx] gulp --tasks

Dependencies

Project dependencies are added via npm and listed in the package.json file. To install a new dependency, run [fin] npm i -S [package name].

Project Architecture

Folder Structure

  • app/: All work should be done in the app folder. This is where your website's source code lives.
  • build/: When running Gulp, files from app are compiled into build. If you work out of the build folder, your work will be overwritten and you will be sad. Don't work out of the build folder.
  • gnorm/: This contains all of the Gulp tasks that the project relies on. There is also a config.js file that most of the tasks reference to make file paths and preferences more manageable.
  • node_modules/: The folder where the projects Node dependencies are installed.
  • .eslintrc.js: The configuration file that dictates syntactical rules for Javascript linting. Editor extensions will alert you to potential errors or style warnings.
  • gulpfile.babel.js: This references all of the tasks in gulp/tasks/. Tasks are broken apart for organizational purposes and referenced from this root file when you run gulp.
  • package.json: Defines the project's dependencies, preferences, and scripts.
  • package-lock.json: this file is automatically generated and modified whenever any npm dependencies change. You should not manually edit this file.
  • README.md: You're reading it.

Usage

Atomic Organization

To encourage organization, scalability, and code-reuse, we generally take an Atomic Design approach when structuring our HTML and Sass. Our Sass partials and HTML includes are broken apart in folders denoted by Atomic-style building blocks (atoms/pieces, molecules/components, organisms/regions, etc.).

HTML / Twig

GNorm uses the Twig template engine for creating HTML templates using reusable components. Twig provides the ability to:

  • Write a piece of code once and reuse it in multiple places.
  • Use conditional code to allow for variation in the template or component.
  • Use json data to populate content of each template, which allows the use of the same component partial within one or multiple templates with different content for each instance.

Your markup lives in the app folder, and can contain references to reusable includes (which live in app/includes/). For example:

{% include '@includes/2_pieces/icon.twig' %}

Each twig template in the root of the app folder also requires a json file that includes any data utilized in the template. These data files live in the app/json folder and must use the same name as the template file. This data is meant to simulate any data that might come from a CMS.

When Gulp runs, it takes the includes and data, and compiles the full HTML into the build folder.

More documentation can be found here.

SCSS

The styles are written using SCSS. Partials are organized using Atomic Design principles, with class names written with the BEM methodology.

Structure

Your styles live in the app/styles/ folder. This folder is organized atomically:

  • screen.scss: This contains globbing patterns that @include tools and partials contained in the following folders
  • 0_utility/: This contains font, helper, mixin, and variable declarations.
  • 1_core/: bare (classless) HTML
  • 2_pieces/: This is where your "Atoms" live.
  • 3_components/: This is where your "Molecules" live.
  • 4_regions/: This is where your "Organisms" live.
  • 5_pages/: This is where your "Layouts" live.

JS

Structure

GNorm uses Webpack along with a JS module loading system. The Javascript source files are in app/scripts/, organized:

  • app.js: This is your application bootstrap. All JS kicks off from here.
  • libs/: This is where vendor libraries and plugins live. Most 3rd party code will be installed via npm, but use this directory for things that aren't available through a package manager.
  • modules/: This is where your custom JS modules live.
    • modules/index.js: This is the "module registry". It lists each module in the project.

Creating A New Module

You can quickly generate a new module right from the command line. Run [fin\npx] gulp create-module. You will be prompted for the name of your new module. The name should be in PascalCase, with no spaces or numbers.

A new folder is generated in app/scripts/modules/, and adds a reference to the module registry.

The new module folder contains a *.main.js file of the same name. This exports an ES6 class:

class SampleModule {
  constructor(el) {
    this.$el = el
    this.method(this.$el)
  }

  method($element) {
    console.log($element)
  }
}
export default SampleModule

(If you're unfamiliar with the ES6 class syntax, you can read more about it here.)

To use this new module, call it with the data-module attribute in your HTML:

<div data-module="SampleModule">
  <p>My Module</p>
</div>

When the page loads the main assets/scripts/app.built.js file, it initializes the module registry. This searches the DOM for any node with a data-module attribute and instantiates a new version of that module via the reference in the module registry.

Note: The module loader passes the element that contains data-module. This allows for easy scoping if you need to load more than one instance of the module on a page.

Troubleshooting

Be sure that you run the [fin] npm ci command every once in a while, and especially after importing any commits from the repository that may include additions or updates to the Node dependencies found in package.json.