Skip to content

Commit 2d352eb

Browse files
committed
Expand scdev skill with multi-stack templates, debugging, and setup guidance
1 parent 0eca28d commit 2d352eb

1 file changed

Lines changed: 128 additions & 7 deletions

File tree

skills/scdev/SKILL.md

Lines changed: 128 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -438,14 +438,27 @@ default:
438438

439439
### Step 1: Create the config
440440

441-
Create `.scdev/config.yaml` with the project's services. Use `${PROJECTPATH}:/app` for the
442-
source code mount.
441+
Analyze the project to build the right config:
443442

444-
### Step 2: Add to .gitignore (optional)
443+
1. **Check the tech stack** - look at `package.json`, `composer.json`, `requirements.txt`, `go.mod`
444+
2. **Pick the base image**:
445+
- Node.js: `node:22-alpine` (or `node:22` if native modules need glibc)
446+
- PHP: `webdevops/php-nginx:8.3` (with nginx) or `php:8.3-fpm` (FPM only)
447+
- Python: `python:3.12-slim`
448+
3. **Find the dev command** - check `package.json` scripts, `Makefile`, README
449+
4. **Find the port** - check dev server output or framework defaults (Nuxt: 3000, Vite: 5173, Laravel: 80, Django: 8000)
450+
5. **Add database services** if needed - check for connection strings in `.env` or config
451+
6. **Add mutagen ignores** for the detected stack (see table below)
452+
453+
Create `.scdev/config.yaml`. See "Config Templates by Stack" below for ready-to-use templates.
454+
455+
### Step 2: Add to .gitignore
445456

446457
```
447458
# scdev local state
448459
.scdev/local/
460+
# pnpm store (created inside container, platform-specific)
461+
.pnpm-store/
449462
```
450463

451464
### Step 3: Start
@@ -508,19 +521,25 @@ Run tests with `scdev exec app pnpm test` (or `scdev test` if a test.just exists
508521

509522
## Debugging
510523

511-
**Container won't start:**
524+
**Container won't start or keeps crashing:**
512525
```bash
513526
scdev logs -f <service> # check what's failing
514-
scdev down && scdev start # clean restart
527+
scdev restart # quick restart (fixes most transient issues)
528+
scdev down && scdev start # full clean restart if restart didn't help
515529
scdev config # verify resolved config looks right
516530
```
531+
Containers can crash for many reasons - Docker Desktop updates, resource limits, bad commands.
532+
Don't over-investigate. `scdev restart` fixes most cases.
517533

518-
**Can't reach the app in the browser:**
534+
**Can't reach the app in the browser (redirects to docs page):**
519535
```bash
520536
scdev info # check the URL and routing config
521537
scdev services status # ensure shared router is running
522538
scdev services recreate # rebuild router if config changed
523539
```
540+
If the app redirects to `docs.shared.scalecommerce.site`, the router can't reach your container.
541+
Check that the container is running (`scdev status`) and that `routing.port` matches the port
542+
your app actually listens on.
524543

525544
**File changes not reflected (macOS):**
526545
```bash
@@ -535,7 +554,11 @@ scdev mutagen flush # wait for sync to complete
535554

536555
**Email not showing up in Mailpit:**
537556
- Ensure `shared.mail: true` in config
538-
- Configure your app's SMTP to: host `scdev_mail`, port `1025`
557+
- Configure your app's SMTP to:
558+
- Host: `scdev_mail`, Port: `1025`, no auth, no TLS
559+
- Node.js (nodemailer): `{ host: 'scdev_mail', port: 1025, secure: false }`
560+
- PHP (Laravel): `MAIL_HOST=scdev_mail MAIL_PORT=1025 MAIL_ENCRYPTION=null`
561+
- Python (Django): `EMAIL_HOST='scdev_mail' EMAIL_PORT=1025`
539562

540563
## macOS / Mutagen Best Practices
541564

@@ -563,6 +586,104 @@ the wrong binaries get synced back into the new container, causing crashes like
563586
**Performance:** With proper ignores, a Nuxt app with ~1000 dependencies installs in ~7s cold,
564587
~2.5s warm. Without ignores, the same install takes 35s+ due to sync overhead.
565588

589+
### Mutagen Ignore by Stack
590+
591+
| Stack | Always ignore |
592+
|-------|--------------|
593+
| Node.js/pnpm | `node_modules`, `.pnpm-store`, `.nuxt`, `.next`, `.output` |
594+
| Node.js/npm | `node_modules` |
595+
| PHP/Composer | `vendor`, `var/cache`, `var/log` |
596+
| Python | `__pycache__`, `.venv`, `*.pyc` |
597+
| General | Build output dirs, cache dirs, log dirs |
598+
599+
## Config Templates by Stack
600+
601+
### Node.js (Nuxt/Next/Vite)
602+
603+
```yaml
604+
name: my-app
605+
606+
services:
607+
app:
608+
image: node:22-alpine
609+
command: corepack enable && pnpm install && pnpm dev --host 0.0.0.0
610+
working_dir: /app
611+
volumes:
612+
- ${PROJECTPATH}:/app
613+
routing:
614+
port: 3000
615+
616+
mutagen:
617+
ignore:
618+
- node_modules
619+
- .pnpm-store
620+
- .nuxt
621+
- .output
622+
```
623+
624+
### PHP + MySQL (Laravel/Symfony/Shopware)
625+
626+
```yaml
627+
name: my-shop
628+
629+
services:
630+
app:
631+
image: webdevops/php-nginx:8.3
632+
working_dir: /app
633+
volumes:
634+
- ${PROJECTPATH}:/app
635+
environment:
636+
WEB_DOCUMENT_ROOT: /app/public
637+
DATABASE_URL: mysql://root:root@db:3306/app
638+
routing:
639+
port: 80
640+
641+
db:
642+
image: mysql:8.0
643+
volumes:
644+
- db_data:/var/lib/mysql
645+
environment:
646+
MYSQL_ROOT_PASSWORD: root
647+
MYSQL_DATABASE: app
648+
649+
mutagen:
650+
ignore:
651+
- vendor
652+
- var/cache
653+
- var/log
654+
```
655+
656+
### Python + PostgreSQL (Django/FastAPI)
657+
658+
```yaml
659+
name: my-api
660+
661+
services:
662+
app:
663+
image: python:3.12-slim
664+
command: pip install -r requirements.txt && python manage.py runserver 0.0.0.0:8000
665+
working_dir: /app
666+
volumes:
667+
- ${PROJECTPATH}:/app
668+
environment:
669+
DATABASE_URL: postgres://postgres:postgres@db:5432/app
670+
routing:
671+
port: 8000
672+
673+
db:
674+
image: postgres:16-alpine
675+
volumes:
676+
- db_data:/var/lib/postgresql/data
677+
environment:
678+
POSTGRES_PASSWORD: postgres
679+
680+
mutagen:
681+
ignore:
682+
- __pycache__
683+
- .venv
684+
- "*.pyc"
685+
```
686+
566687
## Tips
567688

568689
- `version` and `domain` are optional - scdev defaults sensibly

0 commit comments

Comments
 (0)