Skip to content
Get started

Project structure

A site is one folder: your configuration, content and plugins, with Lettern's code beside them. Updates never touch your content.

On this page

A site is one folder, and it is a Composer project however it got there.

#The folder

PathWhat it holdsCommit to git?
index.php, cms, .htaccessFront controller, command line and Apache rules. Lettern keeps them current.With Composer: no. They come back on composer install
setup.php, bundle.jsonWhat a fresh upload uses to fetch the release. Unused once it has run.No
composer.json, composer.lockWhat this site uses: letterncms/cms and its plugins.Yes
vendor/Lettern and the libraries it runs on, on a site managed with Composer.No
runtime/The same vendor/, one folder per release, on a site that updates itself.No
plugins/The plugins of this site: plugins/<name>, and a third party's in plugins/<vendor>-<name>. Your own go here too.Only what you wrote
config/site.yaml (name, URL, languages), plugins.yaml (enabled plugins, disabled modules), roles.yaml, admin.yaml (the default sidebar and home arrangement) and one YAML file per settings namespace.Yes
config/license.keyThe key of a paid plugin, when this site has one.Yes
content/design/The design system (tokens.json), fonts, custom.css and custom.js.Yes
content/collections/Collection definitions, and entries of file-based collections โ€” including templates/ and components/.Yes
content/ (the rest)Fieldsets, globals, forms, menus, redirects.Yes
public/What visitors get: built pages, uploaded media in media/, and in _cms/ generated images, compiled CSS, fonts and plugin assets.Media only
storage/Logs, caches, drafts of file-based entries (unpublished template and component changes too), encrypted secrets, the SQLite database.No
.envDatabase credentials, app key, environment flags.No

#Where the code is

Lettern itself is the Composer package letterncms/cms, at vendor/letterncms/cms. You don't edit it, and an update replaces it. It holds:

FolderWhat it holds
src/The kernel: content, users, abilities, the package system, HTTP and CLI.
modules/The admin's modules: the admin itself, content, collections, globals, users, account, audit, home, settings and the Modules screen.
brand/brand.json (the product's name and links), wordmark.svg and mark.svg; see Configuration.

A site that updates itself keeps that vendor/ in runtime/<version>/vendor/, and the one-line file runtime/current names the release in use. That is how an update goes live and goes back. On a site managed with Composer there is no runtime/, and vendor/ sits in the site folder.

#What to put in git

Commit composer.json, composer.lock, config/, content/ and the plugins you wrote โ€” the design system, templates, components, collections, global sets, menus, forms and file-based entries are plain JSON, YAML and Markdown that diff nicely. Ignore vendor/, runtime/, storage/, .env, the plugins Composer installs and the generated parts of public/. New projects come with a .gitignore that does this.