| name | app-commands |
| description | GROWI main application (apps/app) specific commands and scripts. Auto-invoked when working in apps/app. |
| user-invocable | false |
App Commands (apps/app)
Commands specific to the main GROWI application. For global commands (turbo, pnpm), see the global tech-stack skill.
Quality Check Commands
IMPORTANT: Distinguish between Turborepo tasks and package-specific scripts.
Turbo Tasks vs Package Scripts
| Task | Turborepo (turbo.json) | Package Script (package.json) |
|---|
lint | ✅ Yes | ✅ Yes (runs all lint:*) |
test | ✅ Yes | ✅ Yes |
build | ✅ Yes | ✅ Yes |
lint:typecheck | ❌ No | ✅ Yes |
lint:biome | ❌ No | ✅ Yes |
lint:styles | ❌ No | ✅ Yes |
Recommended Commands
turbo run lint --filter @growi/app
turbo run test --filter @growi/app
turbo run build --filter @growi/app
pnpm run lint:typecheck
pnpm run lint:biome
pnpm run lint:styles
Running individual test files: See the testing rule (.claude/rules/testing.md).
Quick Reference
| Task | Command |
|---|
| Migration | pnpm run dev:migrate |
| OpenAPI generate | pnpm run openapi:generate-spec:apiv3 |
| REPL console | pnpm run console |
| Visual regression | pnpm run reg:run |
| Version bump | pnpm run version:patch |
Database Migration
pnpm run dev:migrate
pnpm run dev:migrate:status
pnpm run dev:migrate:up
pnpm run dev:migrate:down
pnpm run migrate
Note: Migrations use migrate-mongo. Files are in config/migrate-mongo/.
Creating a New Migration
pnpm run dev:migrate:up
pnpm run dev:migrate:down
pnpm run dev:migrate:up
OpenAPI Commands
pnpm run openapi:generate-spec:apiv3
pnpm run lint:openapi:apiv3
pnpm run openapi:build:generate-operation-ids
Generated specs output to tmp/openapi-spec-apiv3.json.
Style Pre-build (Vite)
pnpm run dev:pre:styles-commons
pnpm run dev:pre:styles-components
pnpm run pre:styles-commons
pnpm run pre:styles-commons-components
Pre-builds SCSS styles into CSS bundles using Vite.
Debug & Utility
REPL Console
pnpm run console
pnpm run repl
Interactive Node.js REPL with Mongoose models loaded. Useful for debugging database queries.
Visual Regression Testing
pnpm run reg:run
Version Commands
pnpm run version:patch
pnpm run version:prerelease
pnpm run version:preminor
Build Measurement
./bin/measure-chunk-stats.sh
./bin/measure-chunk-stats.sh 3001
Output: [ChunkModuleStats] initial: N, async-only: N, total: N
For details on module optimization and baselines, see the build-optimization skill.
Production
pnpm run server
pnpm run server:ci
Note: preserver hook automatically runs migrations before starting.
CI/CD
pnpm run launch-dev:ci
pnpm run server:ci
Environment Variables
Development uses dotenv-flow:
.env - Default values
.env.local - Local overrides (not committed)
.env.development - Development-specific
.env.production - Production-specific
See .env.example for available variables.
Smoke Testing
The devcontainer always has MongoDB and other services running (see .claude/rules/devcontainer.md). The dev server can and should be started for smoke verification — never claim the runtime environment is unavailable.
Workflow
Step 1 — Override env vars without touching committed files
Create apps/app/.env.development.local (highest dotenv-flow priority; gitignored):
cat > apps/app/.env.development.local << 'EOF'
VAULT_ENABLED=false
EOF
dotenv-flow load order (first definition wins):
.env.development.local ← your override
.env.local
.env.development ← committed defaults
.env
Note: nodemon watches *.* but does not reliably pick up dotfile changes (files starting with .). After editing .env.development.local, kill the ts-node process manually so nodemon restarts it with the new env:
kill $(ss -tlnp | grep ':3000' | grep -o 'pid=[0-9]*' | cut -d= -f2)
Step 2 — Start the dev server in background
turbo run dev --filter @growi/app &
Wait for the ready message:
until curl -s http://localhost:3000/ > /dev/null 2>&1; do sleep 1; done
echo "Server ready"
Or watch the log for Express server is listening on port 3000.
Step 3 — Curl the endpoints
curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/_vault/repo.git/info/refs?service=git-upload-pack
curl -s -o /dev/null -w "%{http_code}" -X POST http://localhost:3000/_vault/repo.git/git-receive-pack
curl -s http://localhost:3000/_vault/repo.git/info/refs?service=git-upload-pack
curl -sI http://localhost:3000/_vault/repo.git/info/refs?service=git-upload-pack | grep -i retry-after
Step 4 — Switch env and retest
Edit .env.development.local, then kill and wait for nodemon to restart:
echo "VAULT_ENABLED=true" > apps/app/.env.development.local
kill $(ss -tlnp | grep ':3000' | grep -o 'pid=[0-9]*' | cut -d= -f2)
until curl -s http://localhost:3000/ > /dev/null 2>&1; do sleep 1; done
Step 5 — Manipulate MongoDB state if needed
node -e "
const { MongoClient } = require('/workspace/growi-vault/node_modules/.pnpm/mongodb@6.8.0_@aws-sdk+credential-providers@3.600.0_@aws-sdk+client-sso-oidc@3.600.0__socks@2.8.3/node_modules/mongodb');
async function main() {
const client = new MongoClient('mongodb://mongo:27017/growi?replicaSet=rs0');
await client.connect();
// e.g. reset bootstrap state
await client.db('growi').collection('vault_sync_state').updateOne(
{ _id: 'singleton' },
{ \$set: { bootstrapState: 'pending' } },
{ upsert: true }
);
await client.close();
}
main().catch(console.error);
"
Step 6 — Stop the server
kill $(pgrep -f "nodemon|src/server/app.ts") 2>/dev/null
What counts as a passing smoke test
- The Express server starts without throwing on import (
Express server is listening on port 3000 in logs)
- Feature-flag–gated endpoints return the correct status code for each flag state (404 when disabled, 503 with the right message when bootstrap incomplete, 403 for read-only enforcement)
- No unhandled exception in server startup logs
Troubleshooting
Migration Issues
pnpm run dev:migrate:status
pnpm run dev:migrate:down
pnpm run dev:migrate:up
Build Issues
pnpm run clean
pnpm run build