PocoCMS Technical Overview

PocoCMS is a single executable file that reads a directory tree of files, converts Markdown files to HTML, and passes the rest through to the webroot directory unchanged. The webroot is where HTML, stylesheets, and other file assets are sent to be published on the Web.

You can theme your website on a global or per-page basis. Themes are simple directories with CSS declarations and templates for page layout features: header, nav, aside, and footer.

Stylesheets are inlined, which means that they get absorbed right into the generated HTML file. It makes web pages render faster, sometimes much faster.

PocoCMS is meant above all to be unobtrusive, easy to learn, and extremely easy to get started with. You don't have to create weird special files get started, or download a theme from some obscure location on the web. Just type some Markdown and you can get started immediately.

A PocoCMS site is in a single directory

A PocoCMS site must occupy its own directory. All files are expected to be in that directory, including theme files, graphic assets, style sheets, and so on.

The root of the directory requires a file named either index.md or README.md. That file will be converted to HTML and upon conversion will be named index.html; such a file is required at the root of any website. If you have both README.md and index.md, in the root directory, README.md takes priority and index.md will be sadly ignored. You will also get confused when trying to remember which file to update, so just don't do that.

You create your site at the command line this way:

poco -new mysite
Site published to /Users/tom/pococms/poco/mysite/WWW/index.html

The directory in mysite looks like this:

.
โ”œโ”€โ”€ index.md
โ”œโ”€โ”€ WWW
โ”‚   โ””โ”€โ”€ index.html
โ””โ”€โ”€โ”€ .poco

The WWW directory is called the webroot and it is where all output goes. To publish your site, you just need to copy the webroot directory tree onto a public web server.

The .poco directory contains all assets needed to build your site: themes, graphic assets, and so forth. It's shown in most of its glorious detail .poco directory structure, although minor details (such as theme names or particular CSS files) will be different from that illustration.

Markdown extensions

The heart of PocoCMS' code that generates HTML from Markdown is an incredibly well-written Go Package named Goldmark, by a super-intelligent being from the future named Yuin who pretends to be human so the rest of us feel better. PocoCMS employs many extensions to Markdown including:

The PocoCMS theme framework

Most PocoCMS themes use the PocoCMS theme framework, which lets you publish complete-looking sites within a few seconds of choosing your theme. It's touched on here, but the theme framework page goes into more detail.

Each theme is in its own directory under .poco/themes. So if you want to edit the Electro theme, you'd go to your site's root directory by loading .poco/themes/electro/README.md. Because these directories are completely self-contained they can be copied from other sources or deleted at will.

PocoCMS themes are built up stylesheets and from files for the header, nav, aside, and footer. They're listed in a required file in the theme README.md file. That README.md lists what stylesheets and Markdown files are required to assemble the finished page.

If a theme specifies, for example, that the header is generated using header.md, then that file gets rendered in to HTML and placed between <header> tags. Same idea goes for the nav, aside, and footer.

The PocoCMS theme framework expects stylesheets to scope styles specifically to each layout element, for example:

File: .poco/css/layout.css
header ol li,header ul li, nav ol li, nav ul li {margin-left:0;}
header>ul>li,nav>ul>li{padding-right:.5em;}
article{width:var(--article-width);height:auto;}  
aside{width:var(--aside-width);padding:0 2em 0 2em;}  

This specificity is required because Markdown by definition produces pure HTML with no classes or Ids allowed (Markdown and CommonMark don't officially support these attributes at the moment).

The framework is optimized for quick development, and you can learn more at Creating themes.

Global vs. page themes

A theme declaration on the home page is also known as the global theme. It lets you propagate the theme through all pages in the site.

All pages inherit the home page theme, unless...

If you specify a theme in the front matter of the home page, all other pages in the site will inherit that theme by default:

file: index.md
---
theme: informer
---

an individual page overrides the theme using pagetheme

If you want to override the theme for one or more pages, you can do so on a per-page basis by using the pagetheme declaration:

file: not-the-home-page.md
---
pagetheme: electro
---

Expensive web designers hate this 1 weird trick

Suppose you want a separate theme for the home page than for the rest of the site? It's a common case because the home page is often used for sales purposes.

Remember that you declare a global theme on the home page using the theme declaration, but that you can override themes on a per-page basis using pagetheme? Yeah, you see where we're going.

This is how you create a site using the pocodocs theme for everything but the home page, but you use the hero theme for the home page itself. You put both declarations on the home page:

file: index.md
---
theme: pocodocs
pagetheme: hero
---

This only applies to the home page, because it's the only place PocoCMS respects the theme: rule.

Starting a site

โ”œโ”€โ”€ index.md
โ”œโ”€โ”€ WWW
โ”‚   โ””โ”€โ”€ index.html
โ””โ”€โ”€ .poco

This is a simplified view of the directory structure. For a more accurate one, see Complete tree listing of a new project.

Building a site

cd mysite
poco

Invoking poco by itself builds the site, which means it generates HTML for your directory tree of Markdown files. In more detail:

Directory: ./poco/themes/base theme
header: header.md
nav: nav.md
aside: aside.md
footer: footer.md
stylesheets:
- ../../css/root.css
- ../../css/reset.css
- ../../css/sizes.css
- ../../css/layout.css
- ../../css/type.css
- ../../css/colors.css
- ../../css/media.css
---

Theme structure

A theme's name is its directory name. The README.me file in that subdirectory has a special use. It determines what files are used to produce the theme. It's also known as the theme README file.

Stylesheets in the theme's README.md file

The list of one or more stylesheets in standard Markdown unordered list format are required for each page that uses the theme.

If a stylesheet is in the theme directory it will appear like this:

stylesheets:
- electro.css

Stylesheets that live on the web

They can also be specified by URL, as in:

stylesheets:
- https://cdn.jsdelivr.net/npm/water.css@2/out/water.css

If you don't use a theme or include a stylesheets declaration, no problem. PocoCMS will just crank out raw unstyled HTML.

Stylesheet paths and the ../ notation

Stylesheet paths begin at the root of the project. The ../ notation means to go down a directory. Here's how to interpret something like this:

stylesheets:
- ../../css/root.css

If somehow there were stylesheets in the themes directory, they'd be reached like this:

stylesheets:
- ../nope.css

Or in the .poco directory, also not gonna happen:

stylesheets:
- ../../hellno.css

Knowing that, here's a directory tree showing where themes appear:

.
โ”œโ”€โ”€ index.md
โ”‚   
โ”œโ”€โ”€ WWW
โ”‚   โ””โ”€โ”€ index.html
โ”‚   
โ””โ”€โ”€โ”€ .poco
    โ”‚
    โ”œโ”€โ”€ css
    โ”‚   โ”œโ”€โ”€ colors.css
    โ”‚   โ”œโ”€โ”€ .. etc
    โ”‚   โ””โ”€โ”€ type.css
    โ”‚
    โ””โ”€โ”€ themes
        โ”œโ”€โ”€ base
        โ”‚   โ”œโ”€โ”€ LICENSE
        โ”‚   โ”œโ”€โ”€ README.md
        โ””โ”€โ”€ .. etc


We need access to the css directory from a subdirectory under themes, for example, base in that illustration.

It's part of the file system so it ends up looking like this:

stylesheets:
- ../../css/root.css

And that's how all the theme framework themes get to share CSS files. It allows updates to the framework by changing only a single file, instead of having to propagate changes to multiple theme directories.

Files used for page layout elements

The contents of each of the page layout elements (header, nav, aside, and footer) are derived from the file listed after the element:

header: header.md
nav: nav.md
aside: aside.md
footer: footer.md

If you don't want a theme to support a particular layout element, just remove the line. None of the page layout elements is required.

The filenames can be anything you want, but here at the massive corporate Poco HQ we aren't very creative and follow this convention stricly.

For example, header.md could be as simple as:

File: header.md
Welcome to our incredible site

More likely, depending on your site's CSS, it will look something like this: a Markdown unordered list, and will be rendered as horizontal links on the header:

* [pocoCMS](https://pococms.com)
* [Download](https://github.com/pococms/downloads/tree/main/dist)
* [Documentation](/docs/index.html)
* [Report an issue](https://github.com/pococms/poco/issues)
* [GitHub](https://github.com/pococms/poco)

This is also likely for the nav and footer. In no case is it required for technical reasons. It's just how most site menus work these days.

Files can be Markdown or HTML

If a file ends in .md it's treated as Markdown. If it ends in .html it's an HTML file and is inserted directly into the output stream. If it's HTML, you must include the proper tags for each page layout element: <header> and </header>, <footer> and </footer>, and so on.

Page layout elements are included on every page, unless you hide them

When PocoCMS generates a site, every page uses that theme incorporates the CSS files required for that theme. The same is true with the header, nav, footer and aside. Assuming files for them exist in the README.md front matter, each generated page will have them all. But they can be suppressed on a page-by-page basis using hide. For example, if you don't wait a page to have a nav bar just do this:

---
hide: nav
---
# Missing!

What happened to the navbar on this page?

...OR replace a page layout element with a local file

You can also replace any single page layout element on a per-page basis by creating a file for it in the same directory. Suppose you want to remind users to check for an important update. You'd do this. Your article would include an nav declaration like this one in the front matter:

File: beta-users.md
nav: news-update.md
# New release!

Beta users should update immediately. See the news announcement above.

Then instead of whatever navbar was included in your theme, it's overridden by the file called news-update.md (use any filename you want).

File: news-update.md
If you used beta version 10.0.9, please **[upgrade now](beta-10-0-0.html)**

Installation

PocoCMS is distribued as a single executable file. It doesn't require an installation step.

When a new PocoCMS project is created via poco -new, the factory .poco directory is copied from within the PocoCMS executable.

Running PocoCMS

Suppose you plan to create a new site, also known as a project. You'd create a subdirectory, in this example mysite, and make it the current directory:

# Create a subdirectory named mysite. 
# Replace with your own directory name here.
mkdir ~/mysite
# Make it the current directory.
cd ~/mysite
poco

You're then informed:

Site published to /Users/tom/pococms/poco/ed/WWW/index.html

Here's what happens when you run poco with no command-line options as shown previously:

---
Stylesheets:
- "https://cdn.jsdelivr.net/gh/pococms/poco/pages/assets/css/poquito.css"
---
# Welcome to mysite

hello, world.

Learn more at [PocoCMS tutorials](https://pococms.com/docs/tutorials.html) 

When you load the web page you'll see it has minimal styling and that the first part of the file doesn't get displayed. That first part between the --- lines is called the front matter, and it provides a set of instructions to format and display the generated HTML, which starts with Welcome to mysite.

The front matter is considered a separate document. It is in YAML format. The only YAML in this document is stylesheets:, which is used to generate a <link> tag that pulls in a minimal spreadsheet from a CDN. It could just as easily be a local file but this makes for a quick demo.

.poco directory structure

Here's an accurate but abridged view of the contents of the .poco directory in a new site. Repetitive elements have been replaced by an .. etc note; if you've seen one theme directory, you've seen them all.

.
โ”œโ”€โ”€ index.md
โ”‚   
โ”œโ”€โ”€ WWW
โ”‚   โ””โ”€โ”€ index.html
โ”‚   
โ””โ”€โ”€โ”€ .poco
    โ”œโ”€โ”€ css
    โ”‚   โ”œโ”€โ”€ colors.css
    โ”‚   โ”œโ”€โ”€ .. etc
    โ”‚   โ””โ”€โ”€ type.css
    โ”‚
    โ”œโ”€โ”€ demo
    โ”‚   โ”œโ”€โ”€ img-sample-night-sky-1280x853.jpg
    โ”‚   โ”œโ”€โ”€ .. etc
    โ”‚   โ””โ”€โ”€ mdemo.md
    โ”‚
    โ”œโ”€โ”€ endjs
    โ”‚   โ”œโ”€โ”€ empty1.js
    โ”‚   โ””โ”€โ”€ empty2.js
    โ”‚
    โ”œโ”€โ”€ img
    โ”‚   โ”œโ”€โ”€ facebook-14px-clear.svg
    โ”‚   โ”œโ”€โ”€ facebook-24px-blue.svg
    โ”‚   โ”œโ”€โ”€ .. etc
    โ”‚   โ”œโ”€โ”€ twitter-14px-blue.svg
    โ”‚   โ”œโ”€โ”€ twitter-14px-clear.svg
    โ”‚   โ””โ”€โ”€ youtube-14px-red.svg
    โ”‚
    โ”œโ”€โ”€ js
    โ”‚   โ”œโ”€โ”€ docready.js
    โ”‚   โ”œโ”€โ”€ last
    โ”‚   โ”‚   โ””โ”€โ”€ aside.js
    โ”‚   โ””โ”€โ”€ userlast
    โ”‚       โ””โ”€โ”€ notes.txt
    โ”‚
    โ””โ”€โ”€ themes
        โ”œโ”€โ”€ base
        โ”‚   โ”œโ”€โ”€ LICENSE
        โ”‚   โ”œโ”€โ”€ README.md
        โ”‚   โ”œโ”€โ”€ aside.md
        โ”‚   โ”œโ”€โ”€ footer.md
        โ”‚   โ”œโ”€โ”€ header.md
        โ”‚   โ””โ”€โ”€ nav.md
        โ”‚
        โ”œโ”€โ”€ electro
        โ”‚   โ”œโ”€โ”€ LICENSE
        โ”‚   โ”œโ”€โ”€ README.md
        โ”‚   โ”œโ”€โ”€ aside.md
        โ”‚   โ”œโ”€โ”€ electro.css
        โ”‚   โ”œโ”€โ”€ footer.md
        โ”‚   โ”œโ”€โ”€ header.md
        โ”‚   โ””โ”€โ”€ nav.md
        โ””โ”€โ”€ .. etc

Complete tree listing of a new project

.
โ”œโ”€โ”€ index.md
โ”œโ”€โ”€ WWW
โ”‚   โ””โ”€โ”€ index.html
โ””โ”€โ”€ .poco
    โ”œโ”€โ”€ css
    โ”‚   โ”œโ”€โ”€ colors.css
    โ”‚   โ”œโ”€โ”€ featuretable.css
    โ”‚   โ”œโ”€โ”€ layout.css
    โ”‚   โ”œโ”€โ”€ media.css
    โ”‚   โ”œโ”€โ”€ medium-skinny.css
    โ”‚   โ”œโ”€โ”€ nav-menu.css
    โ”‚   โ”œโ”€โ”€ reset.css
    โ”‚   โ”œโ”€โ”€ root.css
    โ”‚   โ”œโ”€โ”€ sizes.css
    โ”‚   โ”œโ”€โ”€ skinny.css
    โ”‚   โ””โ”€โ”€ type.css
    โ”œโ”€โ”€ demo
    โ”‚   โ”œโ”€โ”€ img-sample-night-sky-1280x853.jpg
    โ”‚   โ”œโ”€โ”€ index.md
    โ”‚   โ”œโ”€โ”€ mdemo.md
    โ”‚   โ””โ”€โ”€ show-layout.md
    โ”œโ”€โ”€ endjs
    โ”‚   โ”œโ”€โ”€ empty1.js
    โ”‚   โ””โ”€โ”€ empty2.js
    โ”œโ”€โ”€ img
    โ”‚   โ”œโ”€โ”€ facebook-14px-clear.svg
    โ”‚   โ”œโ”€โ”€ facebook-24px-blue.svg
    โ”‚   โ”œโ”€โ”€ twitter-14px-blue.svg
    โ”‚   โ”œโ”€โ”€ twitter-14px-clear.svg
    โ”‚   โ””โ”€โ”€ youtube-14px-red.svg
    โ”œโ”€โ”€ js
    โ”‚   โ”œโ”€โ”€ docready.js
    โ”‚   โ”œโ”€โ”€ last
    โ”‚   โ”‚   โ””โ”€โ”€ aside.js
    โ”‚   โ””โ”€โ”€ userlast
    โ”‚       โ””โ”€โ”€ notes.txt
    โ””โ”€โ”€ themes
        โ”œโ”€โ”€ base
        โ”‚   โ”œโ”€โ”€ LICENSE
        โ”‚   โ”œโ”€โ”€ README.md
        โ”‚   โ”œโ”€โ”€ aside.md
        โ”‚   โ”œโ”€โ”€ footer.md
        โ”‚   โ”œโ”€โ”€ header.md
        โ”‚   โ””โ”€โ”€ nav.md
        โ”œโ”€โ”€ electro
        โ”‚   โ”œโ”€โ”€ LICENSE
        โ”‚   โ”œโ”€โ”€ README.md
        โ”‚   โ”œโ”€โ”€ aside.md
        โ”‚   โ”œโ”€โ”€ electro.css
        โ”‚   โ”œโ”€โ”€ footer.md
        โ”‚   โ”œโ”€โ”€ header.md
        โ”‚   โ””โ”€โ”€ nav.md
        โ”œโ”€โ”€ hack
        โ”‚   โ”œโ”€โ”€ LICENSE
        โ”‚   โ”œโ”€โ”€ README.md
        โ”‚   โ”œโ”€โ”€ aside.md
        โ”‚   โ”œโ”€โ”€ footer.md
        โ”‚   โ”œโ”€โ”€ hack.css
        โ”‚   โ”œโ”€โ”€ header.md
        โ”‚   โ””โ”€โ”€ nav.md
        โ”œโ”€โ”€ informer
        โ”‚   โ”œโ”€โ”€ LICENSE
        โ”‚   โ”œโ”€โ”€ README.md
        โ”‚   โ”œโ”€โ”€ aside.md
        โ”‚   โ”œโ”€โ”€ dark.css
        โ”‚   โ”œโ”€โ”€ footer.md
        โ”‚   โ”œโ”€โ”€ header.md
        โ”‚   โ”œโ”€โ”€ index.md
        โ”‚   โ”œโ”€โ”€ informer.css
        โ”‚   โ”œโ”€โ”€ nav.md
        โ”‚   โ””โ”€โ”€ reset.css
        โ”œโ”€โ”€ newman
        โ”‚   โ”œโ”€โ”€ LICENSE
        โ”‚   โ”œโ”€โ”€ README.md
        โ”‚   โ”œโ”€โ”€ footer.md
        โ”‚   โ”œโ”€โ”€ header.md
        โ”‚   โ””โ”€โ”€ nav.md
        โ”œโ”€โ”€ paper
        โ”‚   โ”œโ”€โ”€ LICENSE
        โ”‚   โ”œโ”€โ”€ README.md
        โ”‚   โ”œโ”€โ”€ aside.md
        โ”‚   โ”œโ”€โ”€ footer.md
        โ”‚   โ”œโ”€โ”€ header.md
        โ”‚   โ””โ”€โ”€ nav.md
        โ”œโ”€โ”€ pasteboard
        โ”‚   โ”œโ”€โ”€ LICENSE
        โ”‚   โ”œโ”€โ”€ README.md
        โ”‚   โ”œโ”€โ”€ aside.md
        โ”‚   โ”œโ”€โ”€ foo.css
        โ”‚   โ”œโ”€โ”€ footer.md
        โ”‚   โ”œโ”€โ”€ header.md
        โ”‚   โ”œโ”€โ”€ nav.md
        โ”‚   โ””โ”€โ”€ pasteboard.css
        โ”œโ”€โ”€ pocodocs
        โ”‚   โ”œโ”€โ”€ LICENSE
        โ”‚   โ”œโ”€โ”€ README.md
        โ”‚   โ”œโ”€โ”€ aside.md
        โ”‚   โ”œโ”€โ”€ big-circles.css
        โ”‚   โ”œโ”€โ”€ footer.md
        โ”‚   โ”œโ”€โ”€ header.md
        โ”‚   โ”œโ”€โ”€ nav.md
        โ”‚   โ””โ”€โ”€ pocodocs.css
        โ”œโ”€โ”€ rawdog
        โ”‚   โ”œโ”€โ”€ LICENSE
        โ”‚   โ”œโ”€โ”€ README.md
        โ”‚   โ””โ”€โ”€ rawdog.css
        โ”œโ”€โ”€ skyscraper
        โ”‚   โ”œโ”€โ”€ LICENSE
        โ”‚   โ”œโ”€โ”€ README.md
        โ”‚   โ”œโ”€โ”€ aside.md
        โ”‚   โ”œโ”€โ”€ footer.md
        โ”‚   โ”œโ”€โ”€ header.md
        โ”‚   โ”œโ”€โ”€ nav.md
        โ”‚   โ””โ”€โ”€ skyscraper.css
        โ””โ”€โ”€ tufte
            โ”œโ”€โ”€ LICENSE
            โ”œโ”€โ”€ README.md
            โ”œโ”€โ”€ aside.md
            โ”œโ”€โ”€ dark.css
            โ”œโ”€โ”€ footer.html
            โ”œโ”€โ”€ footer.md
            โ”œโ”€โ”€ header.md
            โ”œโ”€โ”€ index.md
            โ”œโ”€โ”€ layout-only.css
            โ”œโ”€โ”€ nav.md
            โ””โ”€โ”€ tufte.css