Templates

Directory Structure

The anatomy of a Lawn template.
The catalog is community-driven. Want to add an app? Open a PR on GitHub. Support for custom catalogs from other sources is coming soon.

Every template is a directory. The directory name is the app's unique identifier (e.g., paperless-ngx, jellyfin).

my-app/
├── manifest.yaml
├── icon.svg
├── locales/
│   └── en.json
├── lawn-compose/
│   ├── v1.0.0.yaml
│   └── v1.2.0.yaml
└── init-files/
    └── nginx.conf
FilePurpose
manifest.yamlApp metadata (name, category, icon, web port)
icon.svgApp icon shown in the catalog
locales/en.jsonUser-facing strings (display names, descriptions, labels)
lawn-compose/*.yamlVersioned compose files (Lawn picks the latest)
init-files/Files copied into the container before start (optional)

manifest.yaml — App metadata

The manifest controls how the app appears in the catalog — its name, description, category, and web UI link.

manifest.yaml
id: my-app
name: My App
tagline: A short one-liner about what this app does.
description: |
  A longer **markdown** description shown on the app detail page.
icon: server.rack         # SF Symbol fallback (used when no icon file exists)
category: Utilities
webPort: 8080

All fields:

FieldTypeRequiredDescription
idstringYesUnique identifier (must match the directory name)
namestringYesDisplay name
taglinestringNoShort one-line description
descriptionstringYesFull markdown description
iconstringYesSF Symbol name used as fallback when no icon file exists
categorystringYesOne of: Documents, Media, Development, Networking, Utilities, Databases, Monitoring
tagsstringNoSearch tags
featuresstringNoFeature bullet points
screenshotsstringNoScreenshot identifiers
linksLinkNoExternal links (github, docs, website)
webPortintNoThe container port for the web UI
webSchemestringNoURL scheme: http (default) or https
webPathstringNoPath appended to the web URL (e.g., /admin/)
compatibility.minLawnVersionstringNoMinimum Lawn version required to use this template (e.g., 0.2.0)

icon.svg — App icon

The app icon shown in the catalog and instance detail views. The file must be named icon with one of the supported extensions:

FormatExtensionNotes
SVG.svgPreferred. Scales to any size
PNG.pngUse at least 256×256 pixels
HEIF.heifmacOS native format
PDF.pdfVector format
No icon file? Lawn falls back to the SF Symbol name from the manifest's icon field.

lawn-compose/ — Container configuration

This directory holds versioned compose files. Each file defines how the app runs — container images, environment variables, volumes, ports, health checks, and Lawn extensions.

Versioning — the filename determines the version. Lawn uses semantic versioning (semver) , where version numbers follow the pattern major.minor.patch. The major number changes for big updates, minor for new features, and patch for bug fixes.

FormatExampleUse case
v32.yamlNextcloud 32Major-only
v10.10.yamlJellyfin 10.10Major.minor
v2.20.7.yamlPaperless-ngx 2.20.7Full semver

Lawn picks the latest version by default. When you release a new version of the app, add a new compose file — don't overwrite the old one. Existing instances track which version they were installed with.

See Format for compose file structure and Extensions for x-lawn features.


init-files/ — Startup files (optional)

Files in this directory are copied into the container's volume mounts before each start. This is useful for configuration files that need to exist on disk when the app boots — for example, a custom nginx config or a default settings file.

Each file is referenced by name in the compose file's x-lawn.initFiles array, which maps it to a path inside the container. Files are overwritten on every start, so the template always provides the latest version.


locales/ — User-facing strings

All display names, descriptions, option labels, notice titles, and element content live in a JSON localization file rather than in the YAML template. The YAML defines structure and behavior; the JSON provides presentation.

Every template must include a locales/en.json file. See Localization for the full JSON structure and field reference.