# devcodes-website

> Instantly generate a beautiful, modern website for any Discord bot.

[![npm](https://img.shields.io/npm/v/devcodes-website)](https://www.npmjs.com/package/devcodes-website)
[![Discord](https://img.shields.io/badge/support-discord-5865f2)](https://discord.gg/ESh2Dp2xX9)

Give your Discord bot a professional landing page in under 10 lines of code. `devcodes-website` generates a fully self-contained, mobile-responsive, dark-themed website served by an Express server — no static files to host, no templates to manage.

---

## Features

- 🎨 **Fully customisable** — change accent colour, background, cards
- 📊 **Live stats** — server count & user count update dynamically via `setStats()`
- 🔗 **Invite + Support links** — "Add to Discord" & "Support Server" CTAs built in
- ⚡ **Commands showcase** — list your commands grouped by category
- 📦 **Zero config HTML** — completely self-contained, no external assets required (except Google Fonts)
- 🟦 **TypeScript first** — full type definitions included

---

## Install

```bash
npm install devcodes-website
```

---

## Quick Start

```js
const { BotWebsite } = require('devcodes-website');

const site = new BotWebsite({
  name: 'My Bot',
  tagline: 'The bot your server deserves',
  description: 'A powerful, easy-to-use Discord bot with moderation, music, games and more.',
  avatar: 'https://cdn.discordapp.com/avatars/YOUR_BOT_ID/YOUR_AVATAR.png',
  prefix: '!',

  serverCount: 150,
  userCount: 12000,

  inviteUrl: 'https://discord.com/oauth2/authorize?client_id=YOUR_ID&scope=bot',
  supportUrl: 'https://discord.gg/your-server',
  githubUrl: 'https://github.com/you/your-bot',

  port: 3000,
});

site.listen(() => console.log('Website running on http://localhost:3000'));
```

---

## Configuration

### `BotWebsiteConfig`

| Property | Type | Required | Description |
|---|---|---|---|
| `name` | `string` | ✅ | Bot display name |
| `description` | `string` | ✅ | Description paragraph shown in the hero |
| `tagline` | `string` | | Short one-line tagline shown as gradient text |
| `avatar` | `string` | | URL to the bot's avatar image |
| `prefix` | `string` | | Command prefix shown as a hero stat pill |
| `serverCount` | `number` | | Number of servers the bot is in |
| `userCount` | `number` | | Number of users the bot can see |
| `inviteUrl` | `string` | | OAuth2 invite link — renders "Add to Discord" button |
| `supportUrl` | `string` | | Discord support server invite — renders "Support Server" button |
| `githubUrl` | `string` | | GitHub repository URL shown in footer |
| `features` | `BotWebsiteFeature[]` | | Feature highlight cards (4 defaults if omitted) |
| `commands` | `BotWebsiteCommand[]` | | Commands to showcase — grouped by category |
| `theme` | `BotWebsiteTheme` | | Color scheme overrides |
| `port` | `number` | | Port to serve on (default: `3000`) |

### `BotWebsiteFeature`

```ts
{ icon: '🛡️', title: 'Moderation', description: 'Powerful moderation tools.' }
```

### `BotWebsiteCommand`

```ts
{ name: 'ban', description: 'Ban a member from the server.', category: 'Moderation' }
```

### `BotWebsiteTheme`

```ts
theme: {
  accent: '#5865f2',           // primary color (default: Discord blurple)
  accentSecondary: '#7289da',  // hover color
  background: '#0a0a0f',       // page background
  backgroundCard: '#12121e',   // card background
}
```

---

## Updating Live Stats

Call `setStats()` at any time to update the displayed counts without restarting:

```js
// With discord.js
client.on('guildCreate', () => {
  site.setStats({ serverCount: client.guilds.cache.size });
});
client.on('guildDelete', () => {
  site.setStats({ serverCount: client.guilds.cache.size });
});
```

The frontend polls `/devcodes-website/stats` and updates the hero stat pills automatically.

---

## Adding Custom Routes

The underlying Express app is exposed as `site.app`:

```js
site.app.get('/api/custom', (req, res) => {
  res.json({ hello: 'world' });
});

site.listen(3000);
```

---

## Full discord.js Example

```js
const { Client, GatewayIntentBits } = require('discord.js');
const { BotWebsite } = require('devcodes-website');

const client = new Client({ intents: [GatewayIntentBits.Guilds] });

const site = new BotWebsite({
  name: 'Dev Codes Bot',
  tagline: 'The ultimate utility bot',
  description: 'Showcase, moderation, fun commands and more — everything your server needs.',
  prefix: '!',
  inviteUrl: 'https://discord.com/oauth2/authorize?client_id=YOUR_ID&scope=bot',
  supportUrl: 'https://discord.gg/ESh2Dp2xX9',
  theme: { accent: '#5865f2' },
  features: [
    { icon: '🛡️', title: 'Moderation', description: 'Ban, kick, mute and more.' },
    { icon: '🎵', title: 'Music',       description: 'High-quality music playback.' },
    { icon: '🎮', title: 'Fun',         description: 'Games and fun commands.' },
    { icon: '📊', title: 'Stats',       description: 'Detailed server statistics.' },
  ],
  commands: [
    { name: 'ping',  description: 'Check bot latency.',   category: 'Utility' },
    { name: 'help',  description: 'List all commands.',    category: 'Utility' },
    { name: 'ban',   description: 'Ban a member.',         category: 'Moderation' },
    { name: 'kick',  description: 'Kick a member.',        category: 'Moderation' },
    { name: 'play',  description: 'Play a song.',          category: 'Music' },
    { name: 'skip',  description: 'Skip the current song.',category: 'Music' },
  ],
  port: 3000,
});

client.once('ready', () => {
  site.setStats({
    serverCount: client.guilds.cache.size,
    userCount:   client.users.cache.size,
  });
  site.listen(() => {
    console.log(`Website: http://localhost:3000`);
    console.log(`Bot: ${client.user.tag}`);
  });
});

client.on('guildCreate', () => site.setStats({ serverCount: client.guilds.cache.size }));
client.on('guildDelete', () => site.setStats({ serverCount: client.guilds.cache.size }));

client.login(process.env.BOT_TOKEN);
```

---

## API

### `new BotWebsite(config)`
Creates the website instance. The Express server is set up but not started.

### `site.listen(port?, callback?)`
Starts the server. Returns the `http.Server` instance.

### `site.setStats({ serverCount?, userCount? })`
Updates live stats. The frontend polls automatically — no restart needed. Chainable.

### `site.updateConfig(patch)`
Patches the config and re-renders the page HTML. Useful for updating bot info at runtime. Chainable.

### `site.close(callback?)`
Gracefully stops the server.

### `site.app`
The raw Express `Application` — add custom middleware or routes.

---

## Support

Need help? Join our Discord: **[discord.gg/ESh2Dp2xX9](https://discord.gg/ESh2Dp2xX9)**
