Modern Discord music bot with typed architecture, polished music panels, playlist persistence, and production-ready Lavalink flow.
Nexa Music v3 is a TypeScript Discord music bot built on discord.js v14, riffy, and Lavalink v4. It focuses on clean interaction design, stronger runtime safety, and a scalable codebase.
v3 introduces four new commands (/search, /bassboost, /speed, /grab), full environment variable configuration, bug fixes for prefix adapter user resolution and duplicate handlers, improved queue display, and zero TypeScript type errors.
| Area | Changes |
|---|---|
| New Commands | /search, /bassboost, /speed, /grab |
| Configuration | All settings configurable via .env environment variables |
| Bug Fixes | Fixed duplicate nodeError handler, prefix adapter getUser() returning null, removed as never casts |
| Queue Display | Shows track durations, total queue duration, requester names, handles large queues |
| Reliability | Uses stable client.riffy.nodes API instead of undocumented internals |
| Type Safety | Zero tsc errors across the entire codebase |
| Cleanup | Removed unused pretty-ms dependency, pinned discord.js@14.21.0 |
| Area | Highlights |
|---|---|
| UI | Full Components V2 panel-based replies and richer playback messaging |
| Type Safety | Full JS to TS migration with typed client, commands, events, and storage |
| Playback | Track control buttons, improved autoplay logic, pause/resume sync, and queue flow cleanup |
| Persistence | SQLite storage for playlists and guild 24/7 settings |
| Commands | Recursive command loading and hybrid prefix/slash support |
| Diagnostics | Improved node stats, health views, and collector timeout handling |
| Reliability | Better reconnect handling and safer player state checks |
| Layer | Tools |
|---|---|
| Bot Framework | discord.js v14 |
| Audio Layer | riffy + Lavalink v4 |
| Language | TypeScript |
| Storage | better-sqlite3 + Drizzle ORM |
| UI System | Discord Components V2 |
| Config | dotenv with full .env support |
| Integrations | Top.gg SDK, Genius Lyrics API |
| Architecture | Typed commands, events, handlers, storage, and utils |
Supported platforms depend on your Lavalink configuration and plugins.
/play- Search and queue tracks or playlists/search- Interactive search with button selectors (NEW in v3)/skip,/stop,/pause,/resume/queue- Improved display with durations and totals (Updated in v3)/seek,/shuffle,/loop,/volume/nowplaying- Now playing panels with interactive control buttons/autoplay- Autoplay with stronger current-track checks/247- 24/7 mode with persisted guild settings/join,/leave,/clear,/remove,/previous/bassboost- Bass boost presets (NEW in v3)/speed- Playback speed control (NEW in v3)/grab- Save current track to DMs (NEW in v3)/lyrics- Auto-scrolling lyric pages
/playlist-create/playlist-add/playlist-load/playlist-view/playlist-remove/playlist-delete
/help/node/ping/about/avatar/serverinfo/uptime
/eval/shards
src/
commands/
hybrid/
interaction/
developer/
information/
music/
playlist/
utility/
events/
bot/client/
riffy/node/
riffy/player/
handlers/
settings/
storage/
types/
utils/git clone https://github.com/koddyvx/Nexa-Music.git
cd Nexa-MusicRecommended:
bun installNode fallback:
npm installcp .env.example .envEdit your .env file with the following values:
# Required
TOKEN=your_discord_bot_token
CLIENT_ID=your_bot_client_id
# Optional
TOPGG_TOKEN=your_topgg_token
GENIUS_TOKEN=your_genius_api_token
DEVELOPER_IDS=875402851986325504
# Bot Settings
PREFIX=-
EMBED_COLOR=ff0000
SEARCH_ENGINE=ytsearch
# Lavalink Node
NODE_NAME=nexa-1
NODE_HOST=lava-v4.ajieblogs.eu.org
NODE_PORT=443
NODE_PASSWORD=your_lavalink_password
NODE_SECURE=trueAll values have sensible defaults if omitted. See .env.example for the full list.
bun run typecheck
bun run build
bun run startDirect bot process:
bun run start:botNode fallback:
npm run typecheck
npm run build
npm run start:node| Requirement | Version |
|---|---|
| Bun | 1.2+ recommended |
| Node.js | 18+ |
| Java | 17+ recommended for Lavalink |
| Lavalink | v4 |
| Discord Bot | Valid token and application setup |
| Item | Path |
|---|---|
| DB Init | src/storage/db.ts |
| Schema | src/storage/schema.ts |
| Playlists | src/storage/playlists.ts |
| Guild Settings | src/storage/guildSettings.ts |
| Config | drizzle.config.ts |
| SQLite File | storage/nexa.sqlite |
Drizzle commands:
npm run db:generate
npm run db:push
npm run db:studio- Shared panel helpers live in
src/utils/discord.ts - Help and node commands use collectors with timeout lock behavior
- Playback responses are standardized around the same panel system
/247 mode:onenables persistent 24/7 mode per guild- Queue end will not disconnect when 24/7 is enabled
- Voice disconnects trigger reconnect handling
- Node disconnects retry automatically with logged status
- Four new commands:
/search,/bassboost,/speed,/grab - Full environment variable configuration for all settings
- Fixed duplicate nodeError handler causing double log entries
- Fixed prefix adapter
getUser()now resolves mentions and usernames - Removed
as nevertype casts, replaced with proper type assertions - Improved queue display with durations and total time
- Uses stable
client.riffy.nodesAPI instead of undocumented internals - Removed unused
pretty-msdependency - Pinned
discord.js@14.21.0for stable type compatibility - Zero TypeScript type errors across the entire codebase
- Full TypeScript migration
- Advanced Components V2 UI flow
- SQLite + Drizzle playlist persistence
- Hybrid prefix/slash command structure
- Stronger node diagnostics and player state handling
- Better permission and interaction guards
- Discord: https://discord.gg/fbu64BmPFD
- Open an issue on GitHub
- Submit a PR with clear change notes
- Discord bot setup: https://discordjs.guide/preparations/setting-up-a-bot-application.html
- Lavalink docs: https://lavalink.dev/
- Riffy package: https://www.npmjs.com/package/riffy
This project is licensed under MIT. Please follow Discord and streaming platform terms when deploying publicly.
Built by KoDdy and Razi under Infinity.