Create a module
The scaffold takes a minute. The rest of the half hour goes into the two things it cannot do for you, a migration and a test, and into the last step, which is the only one your colleagues ever see.
Before you start
The stack is up and the working tree of the project is clean. The last step changes grim.json and grim.lock, and you want that commit to hold nothing else.
$ grim up
$ git status --short
$ grim auth:whoamiThe module gets a repository of its own, grimoiry/grim-<name>, created with the token grim stored. Your GitHub account has to be allowed to create repositories in that organisation. Ask before you start. A refusal arrives after the module is already on disk.
Decide the names first. The module name is PascalCase and plural, such as Admissions. The model inside it is singular, such as Entry. Renaming later means touching every generated file.
The ritual, in order
Seven steps. The first creates the module and its repository. The last two publish it, and until they are done the module exists on your machine only.
Scaffold the module
grim make:modulewritessrc/Admissions/, enables the module, makes the directory a git repository, creates the GitHub repository and pushes the first commit.$ grim make:module Admissions --with-crud=Entry -d "Course admissions" Module Admissions created Path src/Admissions/ Namespace Modules\Admissions Provider AdmissionsProvider Kebab name admissions CRUD yes Model Entry Plural Entries CRUD slug admissions/entries Table admissions_entries Remote repo https://github.com/grimoiry/grim-admissionsRead
Plural,CRUD slugandTablebefore you build on them. The pluralizer knows regular English endings and little else. If a row reads wrong, deletesrc/Admissions/and the new repository and run it again with--plural. The slug carries a slash, not the dash the option's help text shows. The slash is correct. It is what lets the admin find the pages underPages/Entries/.What landed:
module.json,AdmissionsProvider.php,routes.php, a model, a repository class, four Vue pages, language files, an emptyDatabase/Migrations/and a workflow that validates the manifest on everyv*tag. There is no migration and no test. Those are the next two steps.Give it a table
The module is enabled and its table does not exist, so the admin page fails until you migrate. Create the migration inside the module, not in the project's
database/directory. Only what lives undersrc/Admissions/travels with the module.$ grim artisan -- make:migration create_admissions_entries_table --path=src/Admissions/Database/Migrations $ grim artisan migrateThe double dash matters. Without it
grim artisandrops--pathwithout a word and the file lands in the project. Write the columns into the new file before you run the second line, then fill infields()andgrid()onsrc/Admissions/Models/Entry.phpto match.See it in the admin
The provider registers the pages, the permissions and a menu entry. Check that the module is enabled, then log in to the admin at
https://shop.testand look for the new entry in the menu.$ grep Admissions storage/config/modules-enabled.php Modules\Admissions\AdmissionsProvider::class,The menu entry sits in a group with a fixed label that the scaffold wrote into
registerMenu()inAdmissionsProvider.php. Change thegroupvalue there by hand. The--menu-groupoption ofmake:moduleis accepted and has no effect, so do not rely on it.Write the first test
The scaffold ships no tests. Put them where the project's PHPUnit configuration looks for module tests,
src/Admissions/Tests/Unitandsrc/Admissions/Tests/Feature, and run that directory alone withgrim test.$ mkdir -p src/Admissions/Tests/Feature $ grim test src/Admissions/Tests $ grim testThe test run migrates
shop_testfirst, so your new migration is applied there as well. Run the whole suite once at the end. A new provider can break something far away.Validate the manifest
grim manifest:validatechecksmodule.jsonagainst the rules the tag workflow enforces. Run it now, and again whenever you add arequiresentry.$ grim manifest:validate src/AdmissionsThe
versioninmodule.jsonwas set to the first version of the train the project is on,2.5.0. Leave it. The tag you push next has to say the same.Publish a first version
A project resolves modules by tag, and the scaffold pushed a branch and no tag. Commit your work inside the module and tag it with the version from
module.json.$ git -C src/Admissions add -A $ git -C src/Admissions commit -m "feat: entries table, model fields and first test" $ git -C src/Admissions tag v2.5.0 $ git -C src/Admissions push origin main v2.5.0The tag starts the
Validateworkflow in the new repository. It fails when the tag and the manifest disagree. For the next release, raiseversioninmodule.json, commit, and tag again.Add it to the project
The project's repository ignores
src/, so nothing above has reached your colleagues.grim requirefinds the tag you pushed, sees that the checkout already sits on it, and writes the module intogrim.jsonandgrim.lock.$ grim require admissions $ git add grim.json grim.lock $ git commit -m "feat: add admissions module"grim.jsonnow holds"admissions": "~2.5". That commit is what makes the module part of the project.
What you have now
src/Admissions/ its own git repository, on tag v2.5.0
module.json name, namespace, version, provider
AdmissionsProvider.php CRUD, permissions, menu entry
Database/Migrations/ your migration
Tests/ your tests
grimoiry/grim-admissions branch main and tag v2.5.0
grim.json, grim.lock name the module, committedA colleague gets the module with git pull and grim install. On a project they had installed before, install does not enable it for them, because storage/config/modules-enabled.php is local to each machine. They add the provider line from step three by hand.
This module is yours, not the monorepo's, so grim push does not apply to it. Changes go out with git from src/Admissions/ and a new tag.
When it does not work
“Module directory already exists: src/Admissions/”
An earlier run failed after the scaffold, usually at the GitHub step. The module on disk is complete and enabled. Fix the cause, delete src/Admissions/ and run the command again, or create the repository yourself and attach it as origin.
“Repository grimoiry/grim-admissions already exists.”
The name is taken. The message goes on to offer --use-existing, which attaches that repository as origin. Use it only for an empty repository. The push that follows fails when main there already has history.
“Heads up: 'Users' is a core module name.”
A warning, not a refusal. A local module with the name of a core one may shadow it. Pick another name unless that is what you want.
require says the package is not available
admissions is not available — grimoiry/grim-admissions does not exist, or your token cannot see it. means the repository was created somewhere else, typically with --org. grim resolves every module under grimoiry, so a module created under another organisation cannot be required. Create it without --org.
The admin page answers with an SQL error
The table is missing. Step two was skipped, or the migration landed in the project's database/migrations because the double dash was left out. Move the file into src/Admissions/Database/Migrations/ and run grim artisan migrate.
Next recipe
Create a theme
Scaffold a theme with its own repository, switch the project to it, work on it with the Vite dev server running, validate the manifest, publish a version that holds your work and add the theme to grim.json.
Read itSpells used here
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 artisan
Run artisan in the container
Run an artisan command inside the app container, where the app's PHP, extensions and environment are.
grim test
Run the test suite
Run the project's tests in the app container against a separate test database that grim creates and migrates for you.
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.
Related recipes
Change a module and send it back
Check what kind of module you are in, make and test the change without committing it, read the dry run, open the pull request, and take the release when it arrives.
Create a theme
Scaffold a theme with its own repository, switch the project to it, work on it with the Vite dev server running, validate the manifest, publish a version that holds your work and add the theme to grim.json.