Screenshots are from the Sample Website demo of Code Modules.
Code Modules (CM) is an include-based architecture for static websites where the pages are created at build time. Code Modules doesn’t dictate a certain style of website. Code Modules organizes the way in which your pages get built, but what you build is entirely up to you. You can build anything you like using any markup you choose.
Code Modules provides a method of splitting a single web page into a series of includes, arranged as modules which can also call other modules, that are then pieced back together into web pages. It uses BBEdit — a venerable text editor. BBEdit has a robust includes feature and allows for the definition of variables. Most everything else about Code Modules are conventions. There’s nothing to install; source code for sample and blank modules are available on GitHub; these serve as a useful starting point. A Sample Website demonstrates Code Modules in action. Source code for the Sample Website allows you to see Code Modules in action. Code Modules is free and open source under the MIT license.
If you don’t use BBEdit, Code Modules isn’t for you. Move along. Nothing to see.
While I use BBEdit, it’s possible that other text editors or static HTML generators have an include feature with variables that could be used to create something similar. However, I don't know of any that do. Let me know if you know of something else that would work.
Pipsqueak Productions has been creating hand coded websites for our clients since 1994. Code Modules was developed organically over that time to support our workflow; it’s released here for the first time. The modules themselves encapsulate much of the complexity of those websites, making them flexible and easy to maintain. We think it’s a terrific way to build static websites that don’t need a database in the back end. We build dynamic sites too — sometimes, they are absolutely the right choice. But we have a special fondness for static websites. See the article Dynamic vs. Static Web Pages on Pipsqueak’s website.
I like static HTML websites. They're performant, secure, and don’t require much maintenance on a server. Databases have their place, of course, but they add complexity to any project. If the user needs to be able to do something that changes the data for everyone — perhaps adding a comment or a “like” — then a database will be required. However, many of the websites I work on don't require a database. All websites have data, but data can often be represented within the markup at build time rather than being dynamically pulled from a database on each page load.
Coding data directly into the HTML markup is poor practice, however. One issue that arises with this approach is the DRY principle — “don't repeat yourself.” Errors are reduced if a piece of data is just found in one place. But generally, without a database, a website that displays data in several places needs to duplicate that data in each page of markup that uses it. That’s a big disadvantage making maintenance particularly difficult.
Another issue is encapsulation. Anyone who has had to wrestle with the markup for, say, a carousel, can attest that HTML markup can get messy and complex. Manually adding a new picture to the slideshow can involve dozens of changes to next and previous arrow links, thumbnail lists, navigation dots, classes on elements, and head-based preload links. A system that hides that complexity from the maintainer provides a significant advantage, even when that maintainer is still you, six months after first developing the site.
A related problem is contending with messy markup. When using a grid framework like Bootstrap, it can be difficult to see the markup that defines the layout amidst the rest of the markup. Separating the layout markup from the rest of the content can help here. For example, if that extensive carousel markup can be represented in the parent file by just a single calling line, then the function of the parent’s surrounding markup, perhaps placing that carousel at a particular location on the page, is much clearer.
Code Modules addresses these problems by using includes. An include is a piece of markup in a separate file that can be pulled into the main page when needed. A classic use case for an include is a footer. Rather than duplicating identical markup at the bottom of each page, there’s one file containing footer markup that is added to each page either upon load or at build time. Code Modules builds pages in advance locally using BBEdit’s tools; the pages are fully built when they are uploaded to production and served to users.
A traditional include — like the markup for a footer that is the same on every page — is just a static bit of canned markup. At its simplest, a CM module can just return that canned markup in the same manner as a traditional include. But a CM module can do much more.
Code Modules allow for data to be placed into variables where they can be reused across the site without replication. There are several types of variables depending on where they are defined: global variables, variables defined in the calls to modules, and variables within modules dedicated to a specific bit of content — like a blog post or a social media link. Capturing the data in reusable variables helps address the DRY problem.
Building a full Code Module for some content type isn’t always necessary. If, say, a set of social media links appears in just one place on a single page, then it’s easiest just to mark it up on that page. If those links are on every page, then a traditional include — or a simple include contained in the Element module — would work. But if those links need to be a little different on the home page than they are on secondary pages, or they appear both in the header and the footer with different markup, then a Markup module is the right answer.
Finally, a module can be tested. A module generates known and inspectable markup. The module can be refactored in isolation and then the new markup can be compared against the old markup to verify that the functionality hasn’t changed. BBEdit’s compare tool works very well for this purpose.
Begin at Conventions Overview