summaryrefslogtreecommitdiffhomepage
path: root/docs/phase-0-setup.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/phase-0-setup.md')
-rw-r--r--docs/phase-0-setup.md338
1 files changed, 338 insertions, 0 deletions
diff --git a/docs/phase-0-setup.md b/docs/phase-0-setup.md
new file mode 100644
index 0000000..09ed772
--- /dev/null
+++ b/docs/phase-0-setup.md
@@ -0,0 +1,338 @@
+# 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=<actual token>
+ CLIENT_ID=<actual client id>
+ GUILD_ID=<actual 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