Skip to content

Instantly share code, notes, and snippets.

@nicodevs
Last active March 6, 2025 14:27
Show Gist options
  • Save nicodevs/0cfd8780d5bc952243fb31b07aae665c to your computer and use it in GitHub Desktop.
Save nicodevs/0cfd8780d5bc952243fb31b07aae665c to your computer and use it in GitHub Desktop.
Mise Brainstorming

Those Mildly Annoying Manual Tasks

One of the things that mildly annoys me after installing Laravel is dealing with migrations I'll never use—or worse, accidentally running them.

What do I mean? Well, when you create a new Laravel project using the installer, you get three migrations by default:

  • The users migration
  • The cache migration
  • The jobs migration

The first one is great—your app will almost certainly have users. But the other two? You only need them if you're planning to use database-driven caching or queues.

So before running my migrations for the first time, I have to remember to remove those files. I usually forget, and those tables end up sitting empty in the database forever. Not the end of the world, but still... (though maybe there's a way to avoid creating them that I just don't know about).

Speaking of files I'll never use: the front-end files. I love using Laravel to build REST APIs. You could say headless Laravel is my favorite Laravel flavor. So, do I need the resources folder or the Vite configuration file? Not really. I just remove them to keep the repo clean.

There are plenty of other common tasks after setting up Laravel—installing packages, configuring them, running a few commands... Wouldn't it be great to have all those steps predefined somewhere?

I know there are starter kits (and some really good ones!), but they're general solutions that might not offer the level of fine-tuning you need in certain situations. Good meals, definitely—but you can't hand-pick the ingredients.

Starting kit... builder?

Now, imagine having access to a thing that helps you run common post-Laravel installation tasks. Not a starter kit, but something closer to a starter kit builder.

I could tell it "Hey! I just installed Laravel. Now, I want to...":

  • Remove the cache table migration
  • Replace CACHE_STORE=database with CACHE_STORE=file in my .env file
  • Run the install:api artisan command
  • Remove all the frontend files: resources, package.json, vite.config.js. Heck, even routes/web.php! I'll never use it! So also remove the line web: __DIR__.'/../routes/web.php', from bootstrap/app.php

Interesting… this looks like a recipe with hand-picked ingredients. Let's take it further:

  • Install Blueprint
  • Grab this Gist and save it as draft.yaml
  • Then, run blueprint:build!

Oh, wait! Now I remember—Blueprint generates PHPUnit tests, but this time I wanted to use Pest. So before building, I needed to publish the configuration and swap out the test generator.

If only I had some kind of recipe to remind me of that step! (FORESHADOWING)

Again, I'm not looking for a generic setup. Sure, I could create a Laravel project, push it to a repo, and clone it whenever I need it. But different scenarios call for different setups.

Bash it!

I think that over the years, a dev collects many tiny bash and PHP snippets to run here and there. Let me share one with you that I put together to illustrate the case I mentioned above.

#!/bin/bash

# Exit on any error
set -e

echo "Starting..."

# ---

echo "Laravel: Create SQLite database"
touch database/database.sqlite

# ---

echo "Laravel: Remove cache table migration"
rm -f database/migrations/0001_01_01_000001_create_cache_table.php

# ---

echo "Laravel: Use file cache store"
php -r "require 'vendor/autoload.php'; (new \Illuminate\Filesystem\Filesystem)->replaceInFile('CACHE_STORE=database', 'CACHE_STORE=file', '.env');"

# ---

echo "Laravel: API setup"
php artisan install:api

# ---

echo "Laravel: Remove front-end files"
WEB_ROUTES_LINE="        web: __DIR__.'/../routes/web.php',\n"
php -r "require 'vendor/autoload.php'; (new \Illuminate\Filesystem\Filesystem)->replaceInFile(\"$WEB_ROUTES_LINE\", '', 'bootstrap/app.php');"
rm -rf resources
rm -f package.json
rm -f vite.config.js
rm -f routes/web.php

# ---

echo "Laravel: Remove default feature test"
rm -f tests/Feature/ExampleTest.php

# ---

echo "Duster: Install"
composer require tightenco/duster --dev

# ---

echo "Pest: Install Faker plugin"
composer require pestphp/pest-plugin-faker --dev

# ---

echo "Blueprint: Install"
composer require -W --dev laravel-shift/blueprint

# ---

echo "Blueprint: Install Additional Assertions"
composer require --dev jasonmccreary/laravel-test-assertions

# ---

echo "Blueprint: Publish config"
php artisan vendor:publish --tag=blueprint-config

# ---

echo "Blueprint: Generate Pest tests instead of PhpUnit tests"
php -r "require 'vendor/autoload.php'; (new \Illuminate\Filesystem\Filesystem)->replaceInFile('PhpUnitTestGenerator', 'PestTestGenerator', 'config/blueprint.php');"

# ---

echo "Blueprint: Ignore .blueprint file"
echo '/.blueprint' >> .gitignore

# ---

echo "Blueprint: Save Gist as draft.yaml"
curl https://gist.githubusercontent.com/nicodevs/0e889f237161010f478af66e164c79df/raw -o draft.yaml

# ---

echo "Blueprint: Build"
php artisan blueprint:build

# ---

echo "Laravel: Migrate fresh and seed"
php artisan migrate:fresh --seed

# ---

echo "Duster: Fix"
./vendor/bin/duster fix

# ---

echo "Done!"

A couple of notes:

  • Most of the commands are quite simple, like removing a file or directory with rm, or running commands with php artisan.
  • I use cURL to grab a snippet from a Gist and save it as draft.yaml.
  • I use Laravel to replace strings in certain files, like replacing CACHE_STORE=database with CACHE_STORE=file in my .env file. Why use PHP and Laravel instead of sed? Well, sed behaves differently between macOS and Linux, so I prefer not to risk it. Plus, being able to run small Laravel snippets from the command line is kind of cool.

For convenience, I've stored this bash file online on my site. Here:

https://nicodevs.com/recipe.txt

So, if I run this bash file in the root of my newly installed Laravel project, I'll have a fully scaffolded custom API. Thanks to Blueprint, I'll even get some basic CRUD tests! I just need to:

laravel new demo-api && cd demo-api
curl -L https://nicodevs.com/recipe.txt -o recipe.sh
chmod +x recipe.sh
./recipe.sh

Try it—it's super fun! In the installer prompts, choose: no starter kit, Pest as the testing framework, SQLite as the database, and say no to running migrations (the recipe takes care of that later).

Did it work? Great! Now, run:

php artisan test

Lego it!

My recipe.sh is great (at least, I think it is!), but it's still a fixed set of steps. I copy and paste it, editing as needed—removing what I don't need and adding what I do. But when you need to fight with bash, the magic fades away.

Let's go back to the idea of this thing that helps you put together your starter kit.

What if it had a user interface to search for and select common ingredients for my recipe? Searching "Duster" could return:

  • Duster: Install
  • Duster: Publish GitHub Action
  • Duster: Publish Husky Hooks
  • Duster: Fix

...and I could check the ones I want—in this case, "Install" and "Fix."

Searching for Blueprint might return:

  • Blueprint: Install
  • Blueprint: Install Additional Assertions
  • Blueprint: Publish config file
  • Blueprint: Ignore .blueprint file
  • Blueprint: Build

...and more. I could even pull in an ingredient that lets me download a file or compressed folder:

After selecting the ingredients I want, I could sort them. For example, the "File: Download" step that downloads a Gist and saves it as draft.yaml needs to go before "Blueprint: Install."

Nothing matches exactly what I'm looking for? I can add my own ingredients and have them ready for my recipes. Maybe my custom ingredient "Show inspirational quote" runs php artisan inspire.

Once I'm happy with the order of the ingredients, my recipe is ready! The starter kit creator shows me the final bash script. In essense will be pretty similar to the bash script I've included above.

The user can copy it, download it, or perhaps give it a cool name (money-maker-api!) and publish it publicly to share with others.

Then, to run it locally, I can grab it from this thing and run:

laravel new demo-api && cd demo-api
curl -L https://mise.com/nicodevs/money-maker-api.txt -o recipe.sh
chmod +x recipe.sh
./recipe.sh

Key advantages:

  • A user interface makes this thing very user friendly. No need to battle with YAML or JSON files, no need to learn a new set of package methods, just interacting with the UI.
  • I don't need to know bash. The starter kit creator has a big collection of bash instructions. And all the instructions are somewhat simple: rm, curl, echo, php artisan something, etc. One liners more than long scripts. For crazy loops or super complex stuff, leverage on a Laravel command.
  • But even if I know just the basic commands to install Laravel and packages, I'll most likely understand the resulting recipe. I'll know what I'm about to run—no mysteries, no sneaky crypto miners (unless you install one on purpose!).
  • It's shareable and extendable. I can share a link to the recipe or a link to the script.

Key disadvantage?

  • This thing is actually a directory. It contains many, many ingredients. Keeping a clean directory is rewarding, but not an easy task. AI can help but, at the end of the day, a human should review additions and changes to the directory. Perhaps in the form of pull requests? Maybe!
  • Now, I'm not sure if this is just a disadvantage. For the end user, it's nice to know there's someone checking the ingredients and making sure there is no rm -rf / in there.

So...?

I would love for this thing to exist. Am I describing Mise, the new project from Matt Stauffer? (Hi, Matt! 👋). I'm not sure!

Perhaps this is not even close to what Matt is looking for, but I wanted to share how I would do it and answer his questions!

Should it be YAML (cleaner) or PHP (easier to do custom stuff, easier to parse and write)?

The end result is bash. Thanks to the UI, the user doesn't need to worry about YAML, config files, or PHP setup scripts. But they can always use the UI to add custom steps, in bash, with the ability to use PHP—for example:

  • Run this command: php artisan app:setup-something
  • Ping this webhook: curl https://example.com/webhook
  • Print a fake name: php -r "require 'vendor/autoload.php'; echo fake()->name();"

Does "recipes" or "steps" make sense?

Absolutely! I called steps ingredients in this post.

How best to distribute "official" steps?

The project's repo will have a directory of checked ingredients. If someone wants to add an ingredient, they can create a pull request. The team will analyze the proposal and decide whether to accept it. If accepted, the ingredient will appear in the public directory.

The checked ingredients are part of the project’s codebase, not just stored in a private database. This means that anyone can pull the repo and run the app locally or self-host it, instead of using the website (mise.com).

How best to distribute steps and recipes that aren't "official"? How do we let people share their own?

Users can log in and create their own ingredients. By default, these are private, so "My wacky step" won't show up when other users search for "wacky."

However, users can share recipes, as explained earlier. A recipe will clearly show if a given step is official (checked by the team) or custom (created by the user).

Does namespacing steps make the most sense? For example, step('duster/install') runs the Steps/Duster/Install PHP class?

Makes sense to have some kind of namespace, box, container or category to group ingredients ("Duster", "Blueprint", "File", etc).

It's also worth mentioning that recipes will have the username as the "namespace." It would be great to have "Login with GitHub" and make the username match GitHub's username for more recognition (https://mise.com/nicodevs).

Should it allow for user input?

If this means user input in the sense of terminal prompts, then yes! Running the bash command will allow it.

If this means accepting step parameters, also yes: some ingredients will require them (e.g., the URL of the file to download). Custom ingredients will need the entire command to execute.

Is there a better way, other than building this as a Laravel app, to make it as useful as possible for other tools (e.g., a modified Laravel installer or something else)?

Assuming these steps run after a Laravel installation and from the root of the project is a great advantage, because you can use the power of Laravel for steps.

But… if you think about it, nothing stops you from creating or consuming commands that assume other scenarios. For example, a recipe could have steps like npm create nuxt my-app, npx nuxi module add icon, and node my-setup.js for a Nuxt project.

In Closing

This was super fun. Thinking of recipes and ingredients made me think of miso, the Japanese dish (close to mise!). I hope all of this makes at least some sense. It feels like a spiritual successor to Lambo, but in app form. I'm not sure if this is the direction Mise will take, but happy to ping pong ideas any day!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment