An opossum assembling blue webpage panels at a desk beside a snowy mountain window

A useful first project is small enough to finish: one published page, a recognizable design, and a deployment you can explain. This walkthrough builds Trail Notes, a simple project site, using a prebuilt oCMS binary and the Tiny Sample HTML theme.

The theme example comes from oCMS v0.30.0. Use the Download page for the current release archives, checksums, and platform commands. You will edit HTML and CSS; running a prebuilt binary does not require Go or Node.js.

Download and start a local site

Choose your platform on Download and follow its quick start. The commands verify the archive, run ocms init my-site, and start the server. Open localhost:8080/admin/.

For a fresh seeded local site, the release README lists admin@example.com and changeme1234 as the bootstrap login. Change the administrator email and password in the account settings. Then stop the foreground server with Ctrl+C, set OCMS_DO_SEED=false in the generated my-site/.env, and start it again.

Open that generated my-site directory in your editor and terminal. The Download commands run in a subshell, so stopping them returns the parent terminal to its original directory. In the following steps, commands run from my-site, with the extracted ocms binary one directory above:

../ocms serve

Keep the generated OCMS_SESSION_SECRET and OCMS_MFA_KEY values. They belong to this site; replacing them with new values is not part of customizing its design.

Publish the first page

Set the site name to Trail Notes in Settings. In Pages, create a new item with the title Welcome to Trail Notes, slug welcome, and type Page. Add a short introduction, set its status to Published, and save it.

Trail Notes collects route notes, packing lists, and small discoveries from time outside. This is the starting page for the project.

Open http://localhost:8080/welcome in another tab. Check the title, paragraph, and public URL. A Page does not become a blog post just because it is published; use the Post type for entries you want in the blog listing.

Install the Tiny Sample theme

Download the Tiny Sample archive. It includes a complete set of eight page templates and a small stylesheet, so you can start with a working theme.

  1. Open Themes in the admin panel and choose the archive in the import form.
  2. Enter your current administrator password and import it. Importing installs the theme without activating it.
  3. Activate Tiny Sample, then reopen the homepage and /welcome.

The files are installed under custom/themes/tiny-sample/. Review themes before importing them: their templates and scripts run with the site's privileges. The sample deliberately omits custom menus, widgets, and theme settings; it is a useful starting point for a small site.

If you have explicitly set OCMS_ACTIVE_THEME in .env, it takes precedence over the admin selection at startup. Comment out that setting and restart when you want the admin panel to control the active theme.

Make the theme your own

Append a small palette change to custom/themes/tiny-sample/static/theme.css:

:root { color: #243447; background: #f3f6fa; }
a { color: #1a6fb5; }
a:hover { color: #124d7f; }
.site-header, footer { border-color: #dbe3ed; }
pre { background: #e9eff6; }
:focus-visible { outline-color: #1a6fb5; }

In templates/layouts/base.html, add a Welcome link inside the existing navigation. The language prefix keeps the link consistent with the theme's other links:

<a href="{{.LangPrefix}}/welcome">Welcome</a>

Edit theme.json: change its display name to Trail Notes and its version to 1.0.1. Keep the directory named tiny-sample; the sample's asset paths use that identifier. Restart oCMS to reload the templates and theme configuration. Its CSS URL includes the theme version, so changing the version also lets browsers fetch the revised stylesheet.

Reopen the homepage and Welcome page. You now have your own content, palette, and navigation without rebuilding the CMS.

Check the site before deployment

  • Open the homepage, /welcome, the blog listing, and a nonexistent URL.
  • Check a narrow phone-sized viewport and follow the navigation using Tab and Enter.
  • Confirm that the administrator account no longer uses the bootstrap email or password and that seeding is disabled.
  • Check that uploaded images and custom theme files are inside the site's directories.
  • In Modules, disable developer before switching to production. It is intended for development and prevents production startup while enabled. This project also leaves embed and migrator disabled. In production, an active embed module needs its proxy token, and an active migrator needs its source-database host allowlist. Configure those features separately when you need them.

Keep the custom theme in version control. Preserve the configuration and content through backups rather than committing database files or secret keys to a public repository.

Deploy the same site on a Linux host

Prepare an unprivileged account, a writable site directory, and an HTTPS reverse proxy on your server. Download and verify the Linux archive matching that server's architecture; a macOS binary is not a Linux deployment binary.

Stop the local application before copying its data, or take a consistent SQLite backup. Copy the database, uploads, custom theme, and .env to the server. Put the Linux binary in the server's site directory:

/srv/trail-notes/
  ocms
  .env
  data/ocms.db
  uploads/
  custom/themes/tiny-sample/

Edit the server's .env while keeping its existing secret and MFA keys. For a same-host reverse proxy that connects over IPv4, the relevant settings are:

OCMS_ENV=production
OCMS_SERVER_HOST=127.0.0.1
OCMS_SERVER_PORT=8080
OCMS_SITE_URL=https://notes.example.com
OCMS_DO_SEED=false
OCMS_ACTIVE_THEME=tiny-sample
OCMS_TRUSTED_PROXIES=127.0.0.1/32
OCMS_API_ALLOWED_CIDRS=127.0.0.1/32
OCMS_REQUIRE_FORM_CAPTCHA=false

This example does not publish public forms, so it explicitly sets OCMS_REQUIRE_FORM_CAPTCHA=false. For a site with public forms, configure the hCaptcha site and secret keys and keep that requirement enabled instead; an unconfigured verifier prevents production startup when the requirement is enabled.

Replace the example domain with your own. The API allowlist above admits only local callers; add the specific client CIDRs you need if you intend to use API keys remotely. Production requires the stable MFA key and rejects the default seeded account. It also checks the trusted-proxy and API source configuration.

From /srv/trail-notes, start the application with ./ocms serve. Configure your process manager to use that same working directory and command, then use the reverse-proxy guide to route HTTPS to the local listener. Check the local health endpoint:

curl -f http://127.0.0.1:8080/health

Check the public HTTPS homepage, Welcome page, and admin sign-in before considering the deployment ready. Enroll the required second factor when prompted. The deployment documentation covers server-specific setup.

Back up the project and plan updates

Keep the database, uploads, custom theme, and .env together in your backup plan. A SQLite backup command gives you a consistent database snapshot while the application is running:

sqlite3 data/ocms.db ".backup '/path/to/backups/trail-notes.db'"

Use a real backup directory, protect the configuration containing the keys, and check that you can restore the files. For an application update, read the release notes, take a backup, install the verified matching binary, and restart. Pending migrations run at startup. A theme-only change updates the theme files; it does not require rebuilding the binary.

Take the next small step

Add a Post for a route report, upload a real project image, or add a second language. Keep one change small enough to check before moving on. The theme documentation explains the rest of the template system, and the About page sets out where oCMS fits and what you operate yourself.

Written by OIV