• JavaScript 52.2%
  • CSS 27.2%
  • HTML 16.7%
  • Shell 2%
  • Dockerfile 1.9%
Find a file
2026-05-31 22:33:20 +02:00
.woodpecker rebranded the bot from SimplyEmbeds to SkyEmbeds 2026-05-31 16:22:53 +02:00
public Fix: /editembed no longer depends on the 30-minute in-memory session. 2026-05-31 22:33:20 +02:00
src Fix: /editembed no longer depends on the 30-minute in-memory session. 2026-05-31 22:33:20 +02:00
.gitignore added files 2026-05-31 14:22:16 +02:00
config.json rebranded the bot from SimplyEmbeds to SkyEmbeds 2026-05-31 16:22:53 +02:00
docker-compose.yml rebranded the bot from SimplyEmbeds to SkyEmbeds 2026-05-31 16:22:53 +02:00
Dockerfile changed org.opencontainers.image.licenses to GPL3-only 2026-05-31 21:35:04 +02:00
LICENSE added files 2026-05-31 14:22:16 +02:00
package.json rebranded the bot from SimplyEmbeds to SkyEmbeds 2026-05-31 16:22:53 +02:00
README.md Fix: /editembed no longer depends on the 30-minute in-memory session. 2026-05-31 22:33:20 +02:00
update-container.sh Added a update file to update the container 2026-05-31 21:41:48 +02:00

SkyEmbeds

A self-hostable Discord bot for creating rich embeds via a beautiful web editor.

By CrystalSky


Features

  • /createembed #channel — generates a private, one-time editor link
  • /editembed <message link or ID> — opens the editor prefilled from an existing SkyEmbeds message
  • Live Preview — side-by-side on desktop, tab-switching on mobile
  • Discord Markdown — bold, italic, underline, strikethrough, code, code blocks, blockquotes
  • Channel Linking — insert #channel-name mentions via dropdown
  • Accent Color — hex picker + quick-color palette
  • Large Image & Thumbnail URL support
  • Author name + icon
  • Custom Footer text (falls back to hoster info from config.json)
  • Create sessions expire after 30 minutes, edit links can be reopened later
  • Fully open source & self-hostable

Quick Start

Prerequisites

Installation

git clone https://github.com/yourname/skyembeds.git
cd skyembeds
npm install

Configuration

Edit config.json:

{
  "discord": {
    "token": "YOUR_BOT_TOKEN",
    "clientId": "YOUR_APPLICATION_CLIENT_ID"
  },
  "server": {
    "port": 3000,
    "baseUrl": "http://localhost:3000"
  },
  "hoster": {
    "name": "Your Name / Org",
    "email": "contact@example.com",
    "website": "https://example.com",
    "tosUrl": "https://example.com/tos",
    "privacyUrl": "https://example.com/privacy"
  },
  "branding": {
    "footerText": "Powered by SkyEmbeds"
  }
}

baseUrl must be the publicly accessible URL of your web server (e.g. https://embeds.yourdomain.com). Discord users will follow this link to open the editor.

Register Slash Commands

npm run deploy-commands

This registers /createembed and /editembed globally. Global commands can take up to 1 hour to propagate.

Start the Bot

npm start

Usage

  1. Invite the bot to your server with bot + applications.commands scopes and Send Messages, Embed Links permissions.
  2. In any channel, run /createembed #channel to create a new embed, or /editembed <message link or ID> to edit an existing one. Discord does not expose reply targets to slash commands, so the edit command needs a link or ID.
  3. The bot replies with an ephemeral message containing your personal editor link.
  4. Open the link, design your embed, and click Send Embed or Save Changes.
  5. The embed appears in the chosen channel instantly, or the original message is updated.
  6. Edit links remain valid for reopening later, until the source message is deleted or the bot can no longer access it.

Project Structure

skyembeds/
├── config.json          ← Configuration (token, hoster info, etc.)
├── package.json
├── src/
│   ├── index.js         ← Bot + Express server
│   └── deploy-commands.js
└── public/              ← Web editor assets
    ├── editor.html      ← Main editor page
    ├── expired.html     ← Session-expired page
    ├── css/
    │   └── editor.css
    └── js/
        ├── markdown.js  ← Discord Markdown renderer
        └── editor.js    ← Editor logic, preview, send

Docker

A pre-built image is published to the Forgejo registry on every push to main:

docker pull git.crystalsky.dev/crystalsky/skyembeds:latest

Run with a mounted config file:

docker run -d \
  --name skyembeds \
  -p 3000:3000 \
  -v /path/to/your/config.json:/app/config.json:ro \
  git.crystalsky.dev/crystalsky/skyembeds:latest

Docker Compose

services:
  skyembeds:
    image: git.crystalsky.dev/crystalsky/skyembeds:latest
    restart: unless-stopped
    ports:
      - "3000:3000"
    volumes:
      - ./config.json:/app/config.json:ro

CI/CD (Woodpecker CI)

The .woodpecker/ directory contains two workflow files:

File Triggers Purpose
lint.yaml push, pull_request Installs deps, validates config.json, checks all required files exist
docker.yaml push / manual on main Builds a multi-arch image (linux/amd64, linux/arm64) and pushes to the Forgejo registry

Required Secrets

Set these in your Woodpecker project settings (Settings → Secrets):

Secret Value
reg_url git.crystalsky.dev
reg_owner crystalsky
reg_token A Forgejo personal access token with package:write scope

The project must be marked Trusted in Woodpecker (required for privileged: true used by the buildx plugin).


Self-Hosting with a Domain

For production, place a reverse proxy (nginx, Caddy) in front of the Express server:

Caddy example:

embeds.yourdomain.com {
    reverse_proxy localhost:3000
}

Set baseUrl in config.json to https://embeds.yourdomain.com.


License

GPL v3 — see LICENSE