Create a theme
The scaffold switches your own machine to the new theme and tells nobody else. Two things make it real for the project, a tagged version that holds your work and a line in grim.json, and they are the two steps people forget.
Before you start
The project is installed, so it has an .env, and the stack runs. The scaffold patches .env and refuses to when the file is missing. pnpm is on your machine, because the Vite dev server runs there and not in a container.
$ grim up
$ pnpm --version
$ git status --shortThe theme gets a repository of its own, grimoiry/grim-theme-<slug>, created with the token grim stored. Your GitHub account has to be allowed to create repositories in that organisation, and git needs a user.name and user.email. Without either, the theme is still created on disk and only the publishing is skipped.
A project has two theme slots. frontend is what visitors see, and admin is the back office. This recipe makes a frontend theme. For the other slot add --type=admin in step one and read THEME_ADMIN, themes.admin and --admin wherever the text says frontend.
The ritual, in order
Six steps. The first two change your machine only. The fifth and sixth are what reach your colleagues and the production build.
Scaffold the theme
grim make:themewritesresources/themes/frontend/shop-front/, points.envat it, makes the directory a git repository, creates the GitHub repository, and pushesmainand a first version tag.$ grim make:theme shop-front --activate Theme shop-front created Path resources/themes/frontend/shop-front/ Type frontend Activated yes (.env patched) Remote repo https://github.com/grimoiry/grim-theme-shop-front Reused existing no Published yesRead the
Publishedrow.no — 2 step(s) skippeddoes not fail the command, and it means the repository or the tag is missing. See When it does not work before you go on.What landed:
theme.json,app.blade.php,functions.php, the entry pointsts/frontend.tsandcss/frontend.css, a standard layout, an index page, an email layout and six error pages. An admin theme is smaller: the manifest,app.blade.php,functions.php,ts/app.tsandcss/app.css.Switch the project to it
--activatewrote two lines into.env. The first tells the app which theme to render, and the second makes Vite build the same one. Containers read.envwhen they are created, so take the stack down withgrim downand bring it up again.$ grep THEME_FRONTEND .env THEME_FRONTEND=shop-front VITE_THEME_FRONTEND=${THEME_FRONTEND} $ grim down $ grim upThe second line is a reference to the first, not a copy, so switching themes later is an edit of one value. To go back to the previous theme, put its slug into
THEME_FRONTENDand restart the same way. Both themes stay installed side by side.Work on it with Vite running
grim upstarted the Vite dev server on your machine and left it in the background. Whilepublic/hotexists, the app loads assets from the dev server, and a saved file shows in the browser without a reload.$ grim logs -f viteOpen
https://shop.testand editlayouts/standard.blade.phpandcss/frontend.cssin the theme directory. When a style does not arrive, the log is where Vite says why. ADevelopment readytable without aVite HMRrow meanspnpmwas not found;grim upsays so in one yellow line.Give it packages of its own
Optional. A package only this theme imports goes into a
package.jsonnext totheme.json, not into the root one, so only projects that carry the theme install it. It must be"private": trueand carry no install scripts; the rules and an example are with the validator, which checks the file with the manifest. Runpnpm installin the project afterwards and commit the changedpnpm-lock.yamlwith the project, not with the theme.Validate the manifest
theme.jsonis short:name,description,version,type, andrequires-modules, which the scaffold set to thefrontendmodule.grim manifest:validatechecks it against the rules the tag workflow enforces.$ grim manifest:validate resources/themes/frontend/shop-frontRun it after every edit of the manifest.
typehas to stayfrontendoradmin, andversionhas to be a fullX.Y.Z.Publish a version that holds your work
The tag from step one,
v2.5.0, points at the empty scaffold. A project installs themes by tag, so your work needs a tag of its own. Raiseversionintheme.jsonto2.5.1. The theme directory has no.gitof its own, so the release is cut from a clone outside the project: copy your work into it, commit, tag and push.$ git clone https://github.com/grimoiry/grim-theme-shop-front /tmp/grim-theme-shop-front $ cp -R resources/themes/frontend/shop-front/. /tmp/grim-theme-shop-front/ $ git -C /tmp/grim-theme-shop-front add -A $ git -C /tmp/grim-theme-shop-front commit -m "feat: first layout and styles" $ git -C /tmp/grim-theme-shop-front tag v2.5.1 $ git -C /tmp/grim-theme-shop-front push origin main v2.5.1Stay on the project's train:
2.5.xfor a project on train 2.5. The tag starts theValidateworkflow in the theme's repository, which fails when the tag andtheme.jsondisagree. The scaffold ships no.gitignore. Add one before the first line if the directory holds anything you do not want published.Add it to the project
make:themenever writes togrim.json. Until this step a colleague who clones the project gets the old theme.grim requirefinds the newest tag on the train, sees that the theme is already in the project, and puts it at the front of its slot.$ grim require shop-front --frontend $ git add -A $ git commit -m "feat: add shop-front theme"The first theme of a slot is the active one for a fresh install. The theme that was there before stays installed behind it.
What you have now
"themes": {
"frontend": ["shop-front:~2.5", "blank:~2.5"]
}On disk, resources/themes/frontend/shop-front/ is a plain directory at v2.5.1, committed in the project, and grimoiry/grim-theme-shop-front holds main and two tags. .env on your machine names the theme. A colleague's .env still names the old one after git pull and grim install, and they change THEME_FRONTEND by hand.
The production image is built with the theme .env names, so grim build on your machine already bundles shop-front. Later changes go back to the theme's repository with grim push --theme frontend/shop-front, or the way step five did, and reach every project that uses the theme with grim update.
⚠ .env THEME_FRONTEND=shop-front is not declared in grim.json themes.frontend … during a build is step six waiting to be done. The build goes on with the .env value, and the image is correct.
When it does not work
The Published row says no
no — 2 step(s) skipped means the theme is complete on disk and nothing reached GitHub. The warning above the table says which step failed, usually a missing git identity or a token that may not create repositories. Fix that, then finish by hand. grim prints the first two lines itself, and the tag is on you. When the first commit is missing as well, make it before the gh line.
$ cd resources/themes/frontend/shop-front
$ gh repo create grimoiry/grim-theme-shop-front --private --source=. --push
$ git tag v2.5.0
$ git push origin v2.5.0The printed hint names grimoiry even when you passed --org. Do not pass --org for a theme a project should install. grim resolves every theme under grimoiry.
“.env not found at …”
run `grim install` / `grim up` first to generate it is the rest of the message. The theme was scaffolded before the step failed, and a second run refuses because the directory exists. Generate the .env, then add the two lines of step two by hand.
“Theme directory already exists: resources/themes/frontend/shop-front/”
An earlier run got as far as the scaffold. Work with what is there, or delete the directory and run the command again.
require leaves the theme out
A Skipped row with the theme's name in the Packages added table means no tag on the project's train was found. Check that step five pushed the tag and that its version starts with the train, 2.5. shop-front is not available means the repository does not exist under grimoiry.
The page renders without styles
The dev server is not running or builds another theme. Check that both lines of step two are in .env, read grim logs vite, and run grim down and grim up again.
Questions
What is grim install --allow-unpublished-theme for?
It makes install take one theme from its directory on disk and record the version from its theme.json, without looking for a tag. The named theme is also left out of the package check, so it works when the repository does not exist yet. grim create-project --new-theme passes it for you when the publish failed. It is a stopgap for one machine: a colleague who clones the project cannot install until the theme is published.
Can a theme be sent with grim push?
Only a theme that is released from the monorepo. One you created here has a repository of its own, and you push to it with git.
Next recipe
Work on a client's dev box
Send your public key to the operator, paste the SSH block they send back, attach your editor to the project on the box, reload the stack after a change to .env, and open the database from there.
Read itSpells used here
grim make:theme
Weave a new theme
Scaffold a frontend or admin theme in the project, with its layouts and entry points, and publish it to a GitHub repository of its own.
grim up
Raise the stack
Start the project's containers and its Vite dev server, with a trusted certificate and a working address, and say where to open it.
grim down
Lower the stack
Stop the project's containers and its Vite server. Volumes stay unless you say otherwise.
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 require
Summon a module or theme
Add a module or theme to grim.json, install it with everything it depends on, and rewrite grim.lock, all inside the train the project is on.
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.