Weave a new theme
$ grim make:theme shop-front --activate
A new site needs its own face, and a theme is where that lives: the layouts, the pages, the stylesheet and the TypeScript entry point Vite builds from. grim make:theme lays down a theme with a layout, an index page and error pages already in place, so you start by changing a page instead of wiring an empty directory.
Reach for it at the start of a project's frontend, or when the admin should look different for one client. Editing a theme that already exists needs no command at all.
Usage
$ grim make:theme shop-front --activate # frontend theme, switched on in .env
$ grim make:theme shop-admin --type=admin # a theme for the admin
$ grim make:theme shop-front --no-repo # local only, nothing on GitHubRun it from the project directory. The slug is lowercase kebab-case and starts with a letter; anything else is refused with Theme slug must be lowercase kebab-case (e.g. boulder24, my-theme).
Arguments and options
Scaffold a new theme under resources/themes/{type}/{slug}/ (with validate.yml + GitHub repo)
Usage
grim make:theme [-t|--type TYPE] [-d|--description DESCRIPTION] [-a|--activate] [--no-repo] [--private] [--public] [--org ORG] [--use-existing] [--skip-push] [--] <slug>Arguments
| Argument | Description |
|---|---|
slug |
Theme slug in kebab-case (e.g. boulder24) (required) |
Options
| Option | Description |
|---|---|
-t, --type=TYPE |
Theme type: frontend or admin (default: frontend) |
-d, --description=DESCRIPTION |
Short description for theme.json |
-a, --activate |
Patch .env to activate this theme |
--no-repo |
Skip GitHub repository creation + git init |
--private |
Create the GitHub repo as private (default) |
--public |
Create the GitHub repo as public |
--org=ORG |
GitHub org (or user) to create the repo under (default: grimoiry) |
--use-existing |
If the remote repo already exists, reuse it instead of failing |
--skip-push |
Init local git + attach remote but do not push |
What it actually does
Each step is printed with a number and its duration.
- Scaffolds
resources/themes/<type>/<slug>/. What lands there depends on the type, see below. Theversionintheme.jsonis the version of the core the project is on. - Copies the validation workflow to
.github/workflows/validate.ymlinside the theme. - Patches
.env, only with--activate:THEME_FRONTEND=<slug>andVITE_THEME_FRONTEND=${THEME_FRONTEND}, or theADMINpair for an admin theme. Existing lines are replaced, missing ones appended. - Makes it a git repository with one commit on
main. - Creates the GitHub repository under
--org, private unless--public, attaches it asoriginand pushesmain. - Pushes a first version tag matching the
versionintheme.json. A theme with no release cannot be resolved by a constraint in any project'sgrim.json, so this is what makes it installable elsewhere.--skip-pushleaves out both pushes. - Prints a summary. Path, type, whether it was activated, the repository URL and a
Publishedrow.
Steps 4 to 6 are allowed to fail. A missing git identity or a token that cannot create repositories produces a warning, the run continues, and the theme is complete on disk.
What each type contains
frontend |
admin |
|
|---|---|---|
| Always | theme.json, app.blade.php, functions.php |
theme.json, app.blade.php, functions.php |
| Entry points | ts/frontend.ts, ts/bootstrap.ts, css/frontend.css |
ts/app.ts, css/app.css |
| Views | layouts/standard.blade.php, pages/index.blade.php, a Container component, an email layout |
None |
| Error pages | 403, 404, 419, 429, 500, 503 | None |
| Repository | grim-theme-<slug> |
grim-theme-admin-<slug> |
Pitfalls
--activate needs an .env
.env not found at <project>/.env — run `grim install` / `grim up` first to generate it. stops the run after the theme was scaffolded. Generate the .env, then set the two variables by hand; a second make:theme would refuse because the directory exists.
Published: no is easy to miss
When a publish step fails the command still ends in success, with no — 2 step(s) skipped in the Published row of the summary. Below it grim prints the commands to finish by hand: change into the theme directory and run gh repo create with --source=. --push.
The theme is not written into grim.json
make:theme touches .env at most. A colleague who clones the project gets the theme only if grim.json names it. Once the theme is published, grim require shop-front --frontend writes it into the slot and the lock. By hand, the entry in themes.frontend or themes.admin reads <slug>:<constraint>, for example shop-front:~2.5. When the slot declares some other theme, grim build warns that .env names one grim.json does not, and builds with the .env value.
After it finishes
Without --activate the command ends by naming the variable to set: THEME_FRONTEND=shop-front. Add VITE_THEME_FRONTEND=${THEME_FRONTEND} next to it, so that Vite builds the same theme the app renders. Containers read .env when they are created, so bring the stack up again.
$ grim down
$ grim upCheck the manifest with grim manifest:validate whenever you edit theme.json.
Related spells
grim make:module
Forge a new module
Scaffold a module under src/ with a provider, routes, a working admin CRUD and its own GitHub repository.
grim manifest:validate
Check a manifest
Validate module.json, theme.json and core.json against the manifest schema on your machine, before CI does it for you.
grim push
Send a change upstream
Turn the edits you made to one installed module or theme into a pull request against the monorepo it is released from.
grim build
Forge the production image
Build the project's production Docker image, tag it with the next version, and push it to GHCR when asked.
grim theme:info
Read a theme's entry
Show a frontend or admin theme's description, latest release, last push and archived status straight from GitHub, with its README on request.
Curses it can raise
Tailwind classes from modules are missing in the built CSS
The theme build does not see the templates of installed modules.