THIS REPO IS NO LONGER MAINTAINED, PLEASE SEE THE BUILDING-BLOX/BLOX-THEME-DEMO FOR REFERENCE INSTEAD
Building Blox lets developers curate sets of custom website components and facilitates the rapid development of static websites. It works seamlessly with the Appyay headless content management system.
✅ Static website generator
✅ Reuse website components across projects (add them as git submodules!)
✅ Content management system integration
This project is the starting point for creating Building Blox projects. Add git submodules "Blocks" into this project to build your site or remix existing Building Blox sites.
The Quiz site is a good example of how Building Blox makes it possible to create a library of website components.
Building Blox features include:
- Page templating (using Nunjucks)
- Sass preprocessing
- CSS concatenation and minification
- Javascript concatenation and uglification
- Multi-browser live browser reload
- Master-detail pattern
- Pagination
- Remote data fetching
- Optional content management system (using Appyay Headless CMS)
- Netlify configuration file
- A modular, reusable design
A block is just a directory representing one of the following:
A web page.
Part of a web page, like a section, header, etc.
Similar to a partial, but uses Nunjucks macros instead of includes to offer extended flexibility. Useful for things like a pagination component that need values passed to it.
A collection of related pages.
A collection or "library" of related partials (that may or may not be used in the generated website).
A collection or "library" of related components (that may or may not be used in the generated website).
A lambda is used to communicate with web services to implement functionality. It is actually just a Javascript file but if it is stored in version control it will be kept in a directory with a README.md file.
git clone https://github.com/Building-Blox/building-blox.git
cd building-blox
npm install
NOTE: building-blox.js library is not an NPM package yet so to run the project, you'll need to run:
cd building-blox.js
npm link
cd ..
npm link building-blox
npm run dev
The website will be viewable at http://localhost:3000. On save of the project, output will be compiled and built to the "public" directory and the website will be reloaded.
Building Blox assumes the following minimal directory structure:
|--src
|--assets
|--images
|--js
|--main.js
|--scss
|--_main.scss
|--data
|--db.json
|--templates
|--layout
|--layout.njk
|--pages
|--blox.page.home.<site_name>
|--home.njk
Page, partial and component blocks can be added to this project as directories. All blocks must contain:
<block-name>.njk
template file
All blocks may contain:
_<block-name>.scss
Sass file<blockname>.js
Javascript fileimages
directory
Page blocks may also contain:
partials
directorycomponents
directory<blockname>.yaml
config file (used by pages for connecting global partials/components)detail
directory (to implement master-detail pattern - see below)
Page package blocks (src/templates/pages/packages/<page_package_name>
) contain:
- page blocks
Global partial package blocks (src/templates/packages/partials/<partial_package_name>
) may contain:
- partial blocks
Global component package blocks (src/templates/packages/components/<component_package_name>
) may contain:
- component blocks
For reference, the blocks that this project contains are:
Located in src/templates/pages
- blox.page.home.site-name (change site-name to your site's name)
- blox.page.admin (no site-name suffix for admin page only)
Located in src/templates/layout/partials
- blox.partial.header.site-name
- blox.partial.footer.site-name
Blocks follow a strict naming convention to make exporting blocks as git repositories easy.
Blocks have the following naming convention:
blox.<block_type>.<block_name>
👉 Example
blox.page.home
It can optionally be suffixed with the site name:
blox.<block_type>.<block_name>.<site_name>
You can save any block in your project using git version control for reuse in other projects. To do this, run this command in your block's directory:
git init
And then go through the normal procedures to push your block's code to the remote repository. See blox.site.quiz site as an example of how blocks are managed in Github.
Page, partial and component blocks can be added to this project as git submodules.
Commands should be run in the project directory.
To add a page block, run:
git submodule add <git_clone_url> ./src/templates/pages/<block_full_name>
👉 Example
To add a new home page from the blox.site.quiz site:
git submodule add https://github.com/richjava/blox.page.home.quiz.git ./src/templates/pages/blox.page.home.quiz
Commands should be run in the page block directory.
To add a partial, run:
git submodule add <git_clone_url> ./partials/<partial_block_full_name>
And for a component, run:
git submodule add <git_clone_url> ./components/<component_block_full_name>
Commands should be run in the project directory.
To add a page to a page package:
git submodule add <git_clone_url> ./src/templates/pages/packages/<page_package_block_full_name>/<page_block_full_name>
Commands should be run in the page package block directory.
To add a page, run:
git submodule add <git_clone_url> ./<page_block_full_name>
Commands should be run in the project directory.
Global blocks need to be specified in the pages
<page_name>.yaml
file.
To add a global partial package, run:
git submodule add <git_clone_url> ./src/templates/packages/partials/<partial_package_block_full_name>
And for a global component package, run:
git submodule add <git_clone_url> ./src/templates/packages/components/<component_package_block_full_name>
Commands should be run in the global partial or component package block directory (i.e. src/templates/packages/<partials_or_components>/<partial_or_component_package_block>).
Global blocks need to be specified in the pages
<page_name>.yaml
file.
TO add a global partial, run:
git submodule add <git_clone_url> ./<partial_block_full_name>
And for a global component, run:
git submodule add <git_clone_url> ./<component_block_full_name>
To add a Lambda block, just place the block's Javascript file this project's functions
directory.
The README.md file of each block provides additional infomation about installation and dependencies.
Global packages allow you to reuse blocks across pages and use "libraries" of blocks.
To create a global package, add a directory to the src/templates/packages/partials
or src/templates/packages/components
directory with the following naming convention for a partial package:
blox.partial-package.<partial_package_name>
And this convention for a component package:
blox.component-package.<component_package_name>
Building Blox will connect styles and Javascript for the global blocks that you specify. You can configure which blocks to be connect in a page's <page_name>.yaml
file:
---
### Uncomment below to connect global blocks
# partialPackages:
# - name: <partial_package_name, i.e. blox.partial-package.navigation>
# blocks:
# - name: <partial_block_name, i.e. blox.partial.nav.quiz>
# componentPackages:
# - name: <component_package_name, i.e. blox.package.bootstrap>
# blocks:
# - name: <component_block_name, i.e. blox.component.pagination>
Page packages are used for keeping sets of related pages together.
To create a page package add a directory to the src/templates/pages/packages
directory with the following naming convention:
blox.page-package.<page_package_name>
Add pages to this directory and they will be processed in the same manner as those in the pages
parent directory.
Data is kept in JSON format and can be added in three ways:
- Manually add a
db.json
file with your JSON data to thedata
folder. - Uncomment the lines below in
webpack.config.js
and replace the placeholders with your Appyay credentials:
const Blox = require('building-blox');
const blox = new Blox({
mode: argv.mode,
// apiEndpoint: 'http://api.appyay.com/cd/v1/environments/<appyay_environment_id>/export',
// apiKey: '<appyay_api_key>'
});
Then run npm run build
to load the remote data.
The database data for the application is located at data/db.json. This data can be repopulated every time the project builds, so you can have dynamic data if used in combination with static hosting services, webhooks and a headless CMS.
Data in this file should be in the following format (using "features" as an example):
{
"features": {
"items": [
{
"id": "abc123",
...
}
]
}
}
The global blox
object should be set at the top of every page template and it will be available to all templates in the page:
{% set blox = htmlWebpackPlugin.options.blox %}
The blox
object has the following properties:
Property name | Description |
---|---|
app | Application related data from src/templates/app.yaml file |
db | Database data from src/data/db.json |
page | Page related metadata |
The blox.page
object provides metadata about the page and can be accessed in any template.
The blox.page
object has the following properties:
Property name | Description |
---|---|
name | Page name (slug) |
rootPage | Root page name for detail pages |
title | Page title (if available) |
path | Used to prefix paths for images, etc. |
Nunjucks is used for compiling template files to HTML.
Template files end with the ".njk" file extension and share the name of the block.
👉 Example
home.njk
The exception to this is detail pages (see "Master-detail pattern" below);
Page blocks are added as sub-directories of the "pages" directory and include a .njk file with the same name as the page.
You can include a global partial in a template like so:
{% include "packages/partials/blox.partial-package.<package>/blox.partial.<partial>/<partial>.njk" %}
👉 Example
{% include "packages/partials/blox.partial-package.navigation/blox.partial.nav.quiz/nav.njk" %}
And to add a global component:
{% include "packages/components/blox.component-package.<package>/blox.component.<component>/<component>.njk" %}
Each page extends the layout template, so needs to include this:
{% extends "layout/layout.html" %}
And the content of every page should be wrapped with a content block:
{% block content %}
<p>My page content</p>
{% endblock %}
Building Blox facilitates the master-detail pattern (i.e. list page and accompanying detail pages for each list item). This is achieved by:
- Adding a
detail
directory to your page block - Adding a Nunjucks file to the
detail
directory that follows the following name convention:<page-name>-detail.njk
.
👉 Example
...
|--pages
...
|--features // page folder
|--detail
|-- features-detail.njk // this is your detail page
|-- ..
|--features.njk //this is your list (master) page
|-- ..
...
So, if a feature item from your database has an slug of "my-feature", the detail page would now be accessible at:
http://localhost:3000/features/my-feature
The item for display on the detail page can be accessed through the blox.db.item
variable.
The list template will be the <page-name>.njk
file in the root of the page folder. The items to needed to form the list can be accessed through the global blox.db
global variable. For example, in your list template:
{% for feature in blox.db.features.items %}
<h2>{{feature.fields.title}}</h2>
{% endfor %}
The following variables will be available in list templates for facilitating pagination of list items:
- blox.page.pagination.offset
- blox.page.pagination.currentPage
- blox.page.pagination.total
- blox.page.pagination.itemsPerPage
The default number of items per page is 50. To specify another value, pass it into BuildingBlox in webpack.config.js
:
const itemsPerPage = 20;
const blox = new BuildingBlox({
...
itemsPerPage: itemsPerPage,
...
});
In your list template, you can loop through items in a range like so:
{% for i in range(blox.pagination.offset, blox.pagination.offset + blox.page.pagination.itemsPerPage ) %}
<h2>{{blox.db.features.items[i].fields.title}}</h2>
{% endfor %}
Sass files are stored in the src/assets/scss/
directory and in the root of page directories. The root Sass file for custom styles is src/assets/scss/_main.scss
.
Sass files kept at a page/partial/component level (in the templates directory) are automatically compiled and bundled.
Javascript files can be imported into the src/assets/js/main.js
file and will be bundled into public/js/<page-name>.js
.
Javascript files can also be included at page/component level (for example home.js
)and will be included in the bundled Javascript.
Images can be added to the src/assets/images
folder. This is an example of how to display an image in a template:
<img src="{{ blox.page.path }}images/my-image.png" alt="My image"/>
Check your template files, you may have specified the wrong path for an include or import.
Configure the partial/component in your pages .yaml file.
Try restarting the server :)
Open your terminal on any empty submodule and run:
git submodule init
git submodule update --remote
If you want to commit changes to the submodule, also run:
git checkout <branch-name>
Run:
git checkout <branch-name>