How a Common site fits together
Every page on this site starts with the same three lines. This page explains what they do, how the files share their work, and the handful of patterns that keep a site of twenty pages as easy to change as a site of one.
<cl> set title to "Blog" include "header.html" </cl>
That is the whole trick. The rest of this page is what happens when it runs.
1. include: one file, used by many pages
include "file.html" puts another file into the page at that spot, and runs its <cl> blocks as if you had typed them there. Two things make it powerful:
- Included files share the page's names. A name set before the
includecan be read inside the file, and a name the file sets can be read by the page afterwards. - So do verbs. A verb defined in an included file can be used by the page that included it, so a file of verbs works like a small library.
# parts/kit.html <cl> set site to "My site" to badge label show "<span class='badge'>[label]</span>" end </cl> # any page <cl> include "parts/kit.html" show "<h1>[site]</h1>" badge "new" </cl>
The file name is always written by you, relative to the page's own folder: "header.html" or "parts/menu.html". Common refuses .., a leading /, and any name that came from a visitor, so nobody can make your page include a file you did not choose.
2. The include chain on this site
Open any page here and this is what runs, top to bottom. Each box is a file; each arrow is an include.
- blog.htmlsets
title, then includes the header - header.htmlthe
<head>, the theme, the navigation. Needstitle, so the page must set it first - settings.htmlnames the whole site shares: its name, tagline, this year
- database.htmlwhere the data lives: one switch for SQLite or Postgres
Then the page does its own work, and finishes with include "footer.html". Because the names flow down the chain, every page can use the settings without including them itself. Right now they say:
full_name | Common (CL) |
tagline | Code that reads like English |
this_year | 2026 |
database_kind | SQLite |
Change the site's name in settings.html and it changes in the title bar, the navigation and the footer of every page at once.
3. The folder
A Common site is a folder of files. This one, grouped by what each file is for:
index.html is /, blog.html is /blog and /blog/any-post, learn.html, quest.html, contact.html, …header.html, footer.html, settings.html, database.htmllessons.html (16 lessons, used by Learn and Practice), quests.html (10 levels, used by the Quest)logout.html, theme.html404.html, shown for any address with no pagetheme.css, and any images or fontssite.db, site.sql, cookies.db, cl.secret, and the outbox/ folder and mail.log that send email makes. Any file ending in .db, .sqlite, .sql, .secret, .eml or .log is refused, whatever its case.4. Seven patterns worth copying
The settings file
Anything you might want to change later, and anything more than one page uses, gets a name in one file. Pages read the name, never the value.
<cl> # settings.html: included by header.html, so every page has these set full_name to "Common (CL)" set tagline to "Code that reads like English" set this_year to year of today include "database.html" </cl>
The layout: header and footer
Each page sets what makes it different (its title, maybe a description), includes the header, writes its own content, and includes the footer. The order matters: the header shows title, so set title must come before include "header.html". Swap them and Common stops with I do not know what 'title' is.
A shared file that needs names set before it should say so in its first lines, so nobody has to read the whole file to find out. Keep that list short: one or two names. This site's header starts:
<cl> # Needs: title (set it before including this file), like # set title to "Blog" # include "header.html" include "settings.html" </cl>
<!DOCTYPE html> <html lang="en"> <cl> set title to "Contact" include "header.html" </cl> <section class="container"> <h1>Contact us</h1> </section> <cl> include "footer.html" </cl>
The data file
When two pages show the same things, keep the list in a file of its own. The Learn page shows the lessons and the Practice page opens them in an editor; both include lessons.html, so a new lesson appears in both.
<cl> # lessons.html: lists only, no HTML set lesson_titles to "Say hello", "Remember a value", "Math" set lesson_codes to "show \"Hello\"", "set x to 1", "show 2 + 2" </cl>
The action page
Some addresses are not pages to look at but things to do: sign out, switch the theme, save a form. They do their work and send the visitor somewhere with go to, so a refresh never does it twice. They need no HTML at all.
<cl> # logout.html: the whole file forget everything go to "/" </cl>
One page, many addresses
/blog/hello-world has no file of its own: the server finds blog.html and the page reads the rest of the address from path. One file then serves the list and every post.
set slug to last of split path by "/" if slug is "blog" set posts to ask database "select * from posts order by posted desc" otherwise set posts to ask database "select * from posts where slug = ?" with slug end
One switch for the database
Pages never write a database file name. They write open database site_database, and database.html says what that is. Moving from SQLite to Postgres is a one-line change in one file.
<cl> # database.html set site_database to "site.db" # set site_database to "postgres://user:password@host/dbname" </cl>
A verb for repeated markup
When the same piece of HTML appears for every item, name it. The blog's list draws each post with its own verb, so the loop stays one line.
to show_post post show <article> <h2><a href="/blog/[slug of post]">[title of post]</a></h2> <p>[date of posted of post]</p> </article> end end for each post in posts show_post post end
5. A starter site you can copy
Four files are a complete site with a shared layout. Make a folder, add these, and run cl serve 8000 my-site.
<cl> set site_name to "My site" </cl>
<cl> include "settings.html" </cl> <head> <meta charset="utf-8"> <title><cl>show "[title] - [site_name]"</cl></title> </head> <body> <nav><a href="/">Home</a> <a href="/about">About</a></nav>
<!DOCTYPE html> <html> <cl> set title to "Home" include "header.html" show "<h1>Welcome to [site_name]</h1>" include "footer.html" </cl>
<footer> <cl>show "[site_name], [year of today]"</cl> </footer> </body> </html>
Add about.html the same way as index.html and the About link works at /about.
6. When it does not work
| Common says | What happened |
|---|---|
I do not know what 'title' is | The header was included before the page set title. Move set title above the include. |
cannot find the file "…" | The name is relative to the page's folder. A page in shop/ includes "header.html" from shop/, not from the top. |
not a path with .. or a leading / | Includes stay inside the site folder. Keep shared parts beside the pages, or in a folder under them. |
cannot take a name that came from a visitor | The file name was built from query, form or path. Choose between fixed names with if instead. |
files include each other in a loop | a.html includes b.html, which includes a.html. Common stops after ten levels. |
Raw <cl> text in the browser | The page was opened as a file, not through Common. Use cl serve, or set up CGI as in the deploy guide. |
Next: build a guestbook using these pieces, or look any word up in the glossary.