# Phase 0 — Project Setup & Installation > **Goal:** Initialize the project, install every dependency, configure all tooling, and create every non-code file. After this phase completes, the project is fully scaffolded and ready for Phase 1 (code). **No packages may be installed after this phase.** --- ## 0.1 — Initialize the Project ```bash cd /home/tradam/projects/music-bot git init npm init -y ``` Edit `package.json` to set these fields: ```jsonc { "name": "music-bot", "version": "1.0.0", "description": "Personal Discord music bot — streams YouTube audio to voice channels", "main": "dist/index.js", "type": "commonjs", "engines": { "node": ">=20.0.0" }, "scripts": { "build": "tsup", "start": "node dist/index.js", "dev": "ts-node src/index.ts", "test": "vitest run", "test:watch": "vitest", "test:coverage": "vitest run --coverage", "lint": "tsc --noEmit", "deploy-commands": "ts-node src/deploy-commands.ts" } } ``` --- ## 0.2 — Install Production Dependencies ```bash npm install discord.js @discordjs/voice discord-player @discord-player/extractor discord-player-youtubei mediaplex sodium-native dotenv ``` | Package | Purpose | |---|---| | `discord.js` v14 | Discord API client — gateway, REST, slash commands, intents | | `@discordjs/voice` | Low-level voice connections, audio players, audio resources | | `discord-player` v6+ | High-level music framework — queue, events, search, filters | | `@discord-player/extractor` | Default extractors bundled with discord-player | | `discord-player-youtubei` | YouTube extraction backend via youtubei.js (InnerTube API) | | `mediaplex` | Opus codec binding — recommended by discord-player over `@discordjs/opus` | | `sodium-native` | Voice data encryption — required by `@discordjs/voice` | | `dotenv` | Loads `.env` file into `process.env` for local development | --- ## 0.3 — Install Dev Dependencies ```bash npm install -D typescript @types/node ts-node tsup vitest @vitest/coverage-v8 ``` | Package | Purpose | |---|---| | `typescript` | TypeScript compiler | | `@types/node` | Node.js type declarations | | `ts-node` | Execute `.ts` files directly during development | | `tsup` | Fast zero-config TypeScript bundler for production builds | | `vitest` | Test runner (fast, native TypeScript, Vite-powered) | | `@vitest/coverage-v8` | Code coverage reporting via V8 engine | --- ## 0.4 — Create TypeScript Configuration Create `tsconfig.json`: ```json { "compilerOptions": { "target": "ES2022", "module": "commonjs", "lib": ["ES2022"], "outDir": "./dist", "rootDir": "./src", "strict": true, "noUncheckedIndexedAccess": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "forceConsistentCasingInFileNames": true, "esModuleInterop": true, "skipLibCheck": true, "resolveJsonModule": true, "declaration": true, "declarationMap": true, "sourceMap": true, "isolatedModules": true }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] } ``` --- ## 0.5 — Create Build Configuration Create `tsup.config.ts`: ```typescript import { defineConfig } from 'tsup'; export default defineConfig({ entry: ['src/index.ts'], format: ['cjs'], target: 'es2022', outDir: 'dist', clean: true, sourcemap: true, splitting: false, }); ``` --- ## 0.6 — Create Test Configuration Create `vitest.config.ts`: ```typescript import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { globals: true, environment: 'node', include: ['src/**/*.test.ts', 'tests/**/*.test.ts'], coverage: { provider: 'v8', include: ['src/**/*.ts'], exclude: [ 'src/**/*.test.ts', 'src/index.ts', 'src/deploy-commands.ts', ], }, }, }); ``` --- ## 0.7 — Create Environment File Templates ### `.env.example` (committed — documents required variables) ```env DISCORD_TOKEN=your_bot_token_here CLIENT_ID=your_application_id_here GUILD_ID=optional_test_guild_id_for_dev PREFIX=! ``` ### `.env` (never committed — actual secrets, fill in manually) ```env DISCORD_TOKEN= CLIENT_ID= GUILD_ID= PREFIX=! ``` --- ## 0.8 — Create `.gitignore` ```gitignore node_modules/ dist/ .env *.log coverage/ ``` --- ## 0.9 — Create `.dockerignore` ```dockerignore node_modules/ dist/ .env .git/ coverage/ docs/ *.md .gitignore ``` --- ## 0.10 — Create Dockerfile (Multi-Stage) The multi-stage build lets Dokploy build everything from the GitHub repo with no external CI step. ```dockerfile # ── Stage 1: Build ── FROM node:20-alpine AS builder WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci COPY tsup.config.ts tsconfig.json ./ COPY src/ ./src/ RUN npm run build # ── Stage 2: Production ── FROM node:20-alpine WORKDIR /app RUN apk add --no-cache ffmpeg COPY package.json package-lock.json ./ RUN npm ci --omit=dev COPY --from=builder /app/dist ./dist ENV NODE_ENV=production CMD ["node", "dist/index.js"] ``` > **Note:** The bot connects outbound to Discord's WebSocket gateway. It does not listen on any HTTP port. No domain or port mapping is needed in Dokploy. --- ## 0.11 — Create Directory Structure ```bash mkdir -p src/commands src/events src/player src/utils tests ``` --- ## 0.12 — Dokploy Deployment Notes When deploying on Dokploy: 1. **Create a Project** → **Create an Application** (not Compose — single container, no database) 2. **Provider:** GitHub → select the repo → branch `main` 3. **Build Type:** Dockerfile (at repo root, named `Dockerfile`) 4. **Environment Variables** (set in Dokploy's Environment tab): ``` DISCORD_TOKEN= CLIENT_ID= GUILD_ID= PREFIX=! ``` 5. **Domains:** Leave empty — the bot is not a web server 6. **Auto-Deploy:** Enabled by default — push to `main` triggers rebuild --- ## 0.13 — Verify Setup ```bash # TypeScript type-checks (will fail until src/index.ts exists — expected) npx tsc --noEmit # Vitest runs (0 tests found — expected) npm test # tsup builds (will fail until src/index.ts exists — expected) npm run build ``` --- ## 0.14 — Initial Commit ```bash git add -A git commit -m "chore: project scaffold — deps, tooling, dockerfile" ``` --- ## Final Directory Tree After Phase 0 ``` music-bot/ ├── docs/ │ ├── phase-0-setup.md │ └── phase-1-implementation.md ├── src/ │ ├── commands/ │ ├── events/ │ ├── player/ │ └── utils/ ├── tests/ ├── .dockerignore ├── .env ├── .env.example ├── .gitignore ├── Dockerfile ├── package.json ├── package-lock.json ├── tsconfig.json ├── tsup.config.ts └── vitest.config.ts ``` --- ## Phase 0 Checklist - [ ] `git init` - [ ] `npm init -y` → edit `package.json` (scripts, engines, type) - [ ] `npm install` production dependencies (8 packages) - [ ] `npm install -D` dev dependencies (6 packages) - [ ] Create `tsconfig.json` - [ ] Create `tsup.config.ts` - [ ] Create `vitest.config.ts` - [ ] Create `.env.example` and `.env` - [ ] Create `.gitignore` - [ ] Create `.dockerignore` - [ ] Create `Dockerfile` (multi-stage) - [ ] Create directories: `src/commands`, `src/events`, `src/player`, `src/utils`, `tests` - [ ] Verify commands run - [ ] Initial git commit