Beyond Moon's Defaults: Adding Explicit Multi-App Commands
MoonRepo is exceptional at managing multiple applications. Running moon run :dev starts all your dev servers with colored output and intelligent parallelization. It just works. But as a monorepo grows, you might want more control over which apps start, clearer log prefixes, or structured production workflows. This article explores what Moon already provides and what convenience layers can add value.
What Moon Already Provides
Before adding anything, understand what MoonRepo gives you out of the box:
The Command:
moon run :dev
What It Does:
- Starts all projects with a
devtask defined - Executes them in parallel automatically
- Provides colored output to differentiate apps
- Handles process management and cleanup
- Respects task dependencies
This is excellent. For many monorepos, moon run :dev is all you need. It's fast, reliable, and requires zero configuration beyond your existing moon.yml files.
Why Add More Commands?
As our monorepo grew, we identified three scenarios where additional control was valuable:
1. Explicit App Selection
The Problem: moon run :dev runs every project with a dev task. If you add a docs site, admin panel, or internal tools to your monorepo, they all start too.
The Solution: Explicit commands targeting specific apps:
pnpm dev:all # Only api, astro-app, web
This prevents accidentally starting unwanted services and makes intentions clear.
2. Named Prefixes
Moon's Output: Colored logs (great!)
What We Added: Named prefixes like [api], [astro], [next]
Using concurrently, we added explicit labels:
[api] Server listening on port 3001
[astro] Ready at http://localhost:4321
[next] Compiled successfully
Is this necessary? No. Moon's colors work fine. Is it clearer? Marginally. Some developers prefer explicit labels when debugging multi-app issues.
3. Production Orchestration
The Gap: Moon excels at development workflows, but production server orchestration needed structure.
What We Added:
pnpm start:all # Builds first, then starts production servers
This command:
- Ensures builds complete before starting servers
- Uses moon task dependencies (
deps: ['~:build']) - Provides consistent production workflow
- Prevents "forgot to rebuild" errors
This is the biggest genuine improvement.
The Implementation
Here's what we added to package.json:
{
"scripts": {
"dev:all": "moon run api:dev astro-app:dev web:dev",
"dev:all:parallel": "concurrently -n \"api,astro,next\" -c \"blue,magenta,cyan\" \"moon run api:dev\" \"moon run astro-app:dev\" \"moon run web:dev\"",
"start:all": "moon run api:start astro-app:preview web:start",
"build:all": "moon run :build"
}
}
Plus moon task additions for production modes:
# apps/astro-app/moon.yml
tasks:
preview:
command: 'astro preview'
local: true
deps:
- '~:build'
# apps/web/moon.yml
tasks:
start:
command: 'next start'
local: true
deps:
- '~:build'
The deps: ['~:build'] configuration is key—it ensures apps are built before production servers start.
Honest Assessment: Was It Worth It?
Time invested: ~30 minutes
Dependency added: concurrently (if using parallel mode)
Value delivered:
⭐⭐⭐ Production orchestration - The start:all command is genuinely useful for structured deployments.
⭐⭐ Explicit selection - Prevents accidentally starting all projects as your monorepo grows.
⭐⭐ Discoverability - New developers see commands in pnpm run listing, familiar Node.js pattern.
⭐ Named prefixes - Marginally clearer than Moon's colors alone.
Bottom line: If moon run :dev works for you, stick with it. Add these conveniences when your workflow outgrows Moon's defaults—particularly for production deployments.
When to Use Each Approach
Use Moon's native commands when:
- You want all projects with dev tasks to start
- Moon's colored output is sufficient
- You prefer Moon's simplicity and zero configuration
- You're comfortable with
moon run :dev
Add convenience scripts when:
- Your monorepo has 5+ projects and you only need specific apps
- You want explicit named prefixes for debugging
- You need structured production workflows
- New developers find
pnpm runmore familiar than moon commands
The Bigger Picture
This article isn't about solving fundamental problems—Moon already handles multi-app development elegantly. It's about recognizing when a convenience layer adds value:
For small monorepos (2-4 apps): moon run :dev is perfect. Don't overcomplicate.
For growing monorepos (5+ projects): Explicit selection and production workflows become valuable.
For open-source projects: Documentation and familiar commands (pnpm run) lower the barrier to contribution.
Lessons Learned
The real insight here isn't technical—it's about honest assessment. We initially thought we were solving major problems. In reality, we added polish on top of already-excellent tooling.
Moon's defaults are strong. If you're adding layers, make sure they deliver genuine value. In our case:
- Production orchestration: Yes
- Explicit app selection: Yes, as we scale
- Named prefixes: Nice-to-have, not need-to-have
Small improvements matter, but so does recognizing when the default is already excellent. Build on Moon's strengths rather than working around imagined weaknesses.