Add README, CLAUDE.md, INSTRUCTIONS.md, and CI workflow
- README.md: feature list, stack, project structure, deferred items - CLAUDE.md: architecture, conventions, route map, CSS variable system, EventSub subscription table, data model, custom event names - INSTRUCTIONS.md: step-by-step initial deploy guide (Twitch app registration through OBS setup and custom CSS/JS), plus git workflow, first push, GitHub Actions, branching, and update procedure - .github/workflows/ci.yml: syntax check and import check on every push Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6ad661c220
commit
c46f2f2fc3
4 changed files with 532 additions and 0 deletions
50
.github/workflows/ci.yml
vendored
Normal file
50
.github/workflows/ci.yml
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
|
||||
- name: Syntax check
|
||||
run: |
|
||||
python3 -c "
|
||||
import ast, sys, pathlib
|
||||
errors = []
|
||||
for f in pathlib.Path('app').rglob('*.py'):
|
||||
try:
|
||||
ast.parse(f.read_text())
|
||||
except SyntaxError as e:
|
||||
errors.append(f'{f}: {e}')
|
||||
if errors:
|
||||
for e in errors: print('SYNTAX ERROR:', e)
|
||||
sys.exit(1)
|
||||
files = list(pathlib.Path('app').rglob('*.py'))
|
||||
print(f'All {len(files)} Python files OK')
|
||||
"
|
||||
|
||||
- name: Import check
|
||||
run: python -c "from app.main import app; print('App import OK')"
|
||||
env:
|
||||
DATABASE_URL: sqlite:///./test.db
|
||||
SECRET_KEY: ci-test-secret-not-real
|
||||
TWITCH_CLIENT_ID: ci-placeholder
|
||||
TWITCH_CLIENT_SECRET: ci-placeholder
|
||||
TWITCH_REDIRECT_URI: http://localhost:8000/auth/callback
|
||||
APP_BASE_URL: http://localhost:8000
|
||||
130
CLAUDE.md
Normal file
130
CLAUDE.md
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
# CLAUDE.md
|
||||
|
||||
## Running the app
|
||||
|
||||
```bash
|
||||
source .venv/bin/activate
|
||||
uvicorn app.main:app --reload
|
||||
```
|
||||
|
||||
Requires `.env` — copy from `.env.example`. Database is created automatically on startup (`SQLModel.metadata.create_all`).
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
Twitch ──EventSub WebSocket──► app/eventsub.py ──► dispatch.py ──► ws.py ──► OBS overlay
|
||||
Twitch ──IRC (tmi.js)────────────────────────────────────────────────────► OBS overlay
|
||||
```
|
||||
|
||||
- `eventsub.py` runs as an asyncio background task started in `main.py` lifespan
|
||||
- When it receives a notification, it calls `dispatch.dispatch_event()`
|
||||
- `dispatch_event()` opens its own DB session (not request-scoped), resolves matching `EventAction` rows, checks cooldowns, logs to `ActivityLog`, and calls `ws.manager.broadcast()`
|
||||
- `ws.manager` holds a list of active WebSocket connections from `/ws/overlay`
|
||||
- The overlay JS receives the broadcast and plays the action
|
||||
|
||||
## Key conventions
|
||||
|
||||
**No passwords anywhere.** Auth is Twitch OAuth only. Session is a signed cookie via `SessionMiddleware`. `request.session["user_id"]` stores the DB user ID after login.
|
||||
|
||||
**Singleton tables.** `Settings` and `OverlayLayout` each have one row. `database.get_settings()` and `database.get_layout()` create the row on first call. Both return detached objects (safe to use after session close — no lazy relationships).
|
||||
|
||||
**Background DB sessions.** `eventsub.py` and `dispatch.py` use `with Session(engine) as session` directly — not FastAPI's `Depends(get_session)` which is request-scoped. Never pass a request-scoped session to a background task.
|
||||
|
||||
**Cooldowns are in-memory.** `app/cooldowns.py` tracks `{action_id: (triggered_at, duration)}`. Restarting the server resets all cooldowns. This is intentional — keeping them in the DB is not worth the complexity for this use case.
|
||||
|
||||
**Multiple actions per event.** `dispatch_event()` loops through ALL matching `EventAction` rows for the event type and fires each one (subject to its own cooldown). There is no "first match wins" logic.
|
||||
|
||||
**Event matching rules:**
|
||||
- `event_type="command"`: `event_detail` must match the command name (case-insensitive, required)
|
||||
- `event_type="bits"`: if `event_detail` is set, it's treated as a minimum bits threshold (`bits_amount >= int(event_detail)`)
|
||||
- `event_type="channel_points"`: `event_detail` is the reward ID; None matches any reward
|
||||
- `event_type="sub"/"gift_sub"`: `event_detail` is the tier ("1000", "2000", "3000"); None matches any tier
|
||||
- `event_type="follow"/"raid"`: `event_detail` not used for matching
|
||||
|
||||
## Route map
|
||||
|
||||
| Method | Path | File | Notes |
|
||||
|---|---|---|---|
|
||||
| GET | `/` | routers/dashboard.py | Activity log, EventSub status |
|
||||
| GET | `/auth/login` | routers/auth.py | Login page |
|
||||
| GET | `/auth/twitch` | routers/auth.py | Redirect to Twitch OAuth |
|
||||
| GET | `/auth/callback` | routers/auth.py | Exchange code, save user, start EventSub |
|
||||
| GET | `/auth/logout` | routers/auth.py | Clear session |
|
||||
| GET | `/overlay` | routers/overlay.py | Live OBS browser source |
|
||||
| GET | `/overlay/preview` | routers/overlay.py | Mock preview for layout editor |
|
||||
| WS | `/ws/overlay` | routers/overlay.py | Bidirectional: commands up, actions down |
|
||||
| GET/POST | `/actions` | routers/actions.py | List and create actions (HTMX) |
|
||||
| POST | `/actions/{id}/test` | routers/actions.py | Fire action immediately, skip cooldown |
|
||||
| POST | `/actions/{id}/toggle` | routers/actions.py | Enable/disable (HTMX) |
|
||||
| DELETE | `/actions/{id}` | routers/actions.py | Delete (HTMX) |
|
||||
| GET/POST | `/media` | routers/media.py | Upload list (HTMX) |
|
||||
| DELETE | `/media/{id}` | routers/media.py | Delete file from disk and DB |
|
||||
| GET/POST | `/layout` | routers/layout.py | Style form |
|
||||
| POST | `/layout/positions` | routers/layout.py | JSON endpoint called by drag JS |
|
||||
| GET/POST | `/settings` | routers/settings.py | Channel, gap audio, custom CSS/JS |
|
||||
| POST | `/settings/reconnect` | routers/settings.py | Restart EventSub task |
|
||||
|
||||
## Overlay CSS variable system
|
||||
|
||||
All overlay positioning and styling is driven by CSS custom properties injected into `overlay.html` and `overlay_preview.html` from `OverlayLayout`:
|
||||
|
||||
| Variable | Controls |
|
||||
|---|---|
|
||||
| `--chat-left`, `--chat-top` | Chat box position (%) |
|
||||
| `--chat-width`, `--chat-height` | Chat box size (%) |
|
||||
| `--chat-font-size` | Chat font size (px) |
|
||||
| `--chat-bg-opacity` | Chat message background opacity |
|
||||
| `--chat-text-color` | Chat message text color |
|
||||
| `--alert-left`, `--alert-top` | Alert position (%, centered via transform) |
|
||||
| `--alert-font-size` | Alert font size (px) |
|
||||
| `--alert-bg-opacity` | Alert background opacity |
|
||||
| `--alert-text-color` | Alert text color |
|
||||
|
||||
The layout editor (`/layout`) has drag handles in the parent document overlaid on an iframe pointing to `/overlay/preview`. Since both are same-origin, the editor updates the iframe's CSS variables directly via `iframe.contentDocument.documentElement.style.setProperty(...)` for live preview. Positions are persisted via `POST /layout/positions` (JSON) on drag end.
|
||||
|
||||
## Custom events dispatched to overlay JS
|
||||
|
||||
When the overlay WebSocket receives an `execute` message, it dispatches a `CustomEvent` on `document` before playing the alert:
|
||||
|
||||
```javascript
|
||||
document.dispatchEvent(new CustomEvent(`bashyoverlay:${msg.event_type}`, { detail: msg }));
|
||||
```
|
||||
|
||||
Available event types: `sub`, `gift_sub`, `bits`, `channel_points`, `command`, `follow`, `raid`.
|
||||
|
||||
`msg.detail` contains `{ event_type, action_type, media_url, alert_text }`.
|
||||
|
||||
## Data model
|
||||
|
||||
```
|
||||
User ──────────────────────────────── Twitch OAuth user (one per login)
|
||||
Settings ──────────────────────────── Singleton: channel, gap audio, custom CSS/JS
|
||||
OverlayLayout ─────────────────────── Singleton: widget positions and styles
|
||||
MediaFile ──────────────────────────── Uploaded sound or video file
|
||||
EventAction ──── media_file (FK) ───── Event → action mapping
|
||||
ActivityLog ────────────────────────── Append-only event log
|
||||
```
|
||||
|
||||
`Claim` unique constraint on `(item_id, attendee_id)` prevents double-claiming — wait, that's IllBring. BashyOverlay has no Claim model. `EventAction` has no unique constraints; multiple rows with the same `event_type` are allowed and all fire.
|
||||
|
||||
## EventSub subscriptions
|
||||
|
||||
| Twitch event | Condition | Scope required |
|
||||
|---|---|---|
|
||||
| `channel.subscribe` v1 | `broadcaster_user_id` | `channel:read:subscriptions` |
|
||||
| `channel.subscription.message` v1 | `broadcaster_user_id` | `channel:read:subscriptions` |
|
||||
| `channel.subscription.gift` v1 | `broadcaster_user_id` | `channel:read:subscriptions` |
|
||||
| `channel.cheer` v1 | `broadcaster_user_id` | `bits:read` |
|
||||
| `channel.channel_points_custom_reward_redemption.add` v1 | `broadcaster_user_id` | `channel:read:redemptions` |
|
||||
| `channel.follow` v2 | `broadcaster_user_id` + `moderator_user_id` | `moderator:read:followers` |
|
||||
| `channel.raid` v1 | `to_broadcaster_user_id` | none |
|
||||
|
||||
Token refresh is handled in `eventsub._refresh_token()` — triggered on 401 during subscription.
|
||||
|
||||
## Not yet implemented
|
||||
|
||||
- Alert variable interpolation (`{username}` in alert text)
|
||||
- Mod access (currently streamer-only login)
|
||||
- Blerp / HudFX integrations
|
||||
- Crypto payment notifications
|
||||
- Morning-of reminder emails (IllBring feature, not applicable here)
|
||||
274
INSTRUCTIONS.md
Normal file
274
INSTRUCTIONS.md
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
# Deployment & Git Instructions
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Python 3.10 or higher
|
||||
- A Twitch account (the channel you stream on)
|
||||
- Git
|
||||
|
||||
---
|
||||
|
||||
## Initial Deploy
|
||||
|
||||
### 1. Register a Twitch application
|
||||
|
||||
1. Go to [dev.twitch.tv/console/apps](https://dev.twitch.tv/console/apps)
|
||||
2. Click **Register Your Application**
|
||||
3. Fill in:
|
||||
- **Name:** anything (e.g. `BashyOverlay`)
|
||||
- **OAuth Redirect URLs:** `http://localhost:8000/auth/callback`
|
||||
- **Category:** Application Integration
|
||||
4. Click **Create**
|
||||
5. On the next screen, click **Manage** to see your app
|
||||
6. Copy the **Client ID**
|
||||
7. Click **New Secret** and copy the **Client Secret**
|
||||
|
||||
Keep both — you will need them in the next step.
|
||||
|
||||
---
|
||||
|
||||
### 2. Clone the repository
|
||||
|
||||
```bash
|
||||
git clone https://github.com/yourusername/BashyOverlay.git
|
||||
cd BashyOverlay
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. Configure environment variables
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Open `.env` and fill in:
|
||||
|
||||
```env
|
||||
TWITCH_CLIENT_ID=paste_your_client_id_here
|
||||
TWITCH_CLIENT_SECRET=paste_your_client_secret_here
|
||||
TWITCH_REDIRECT_URI=http://localhost:8000/auth/callback
|
||||
|
||||
SECRET_KEY=paste_a_random_string_here
|
||||
APP_BASE_URL=http://localhost:8000
|
||||
DATABASE_URL=sqlite:///./bashyoverlay.db
|
||||
```
|
||||
|
||||
Generate a `SECRET_KEY` with:
|
||||
|
||||
```bash
|
||||
python3 -c "import secrets; print(secrets.token_hex(32))"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. Run the deploy script
|
||||
|
||||
```bash
|
||||
chmod +x deploy.sh
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
The script will:
|
||||
- Check that Python 3.10+ is installed
|
||||
- Create a `.venv` virtual environment
|
||||
- Install all Python dependencies
|
||||
- Verify `.env` is filled in
|
||||
- Create the `static/media/` directory
|
||||
- Start the server at `http://localhost:8000`
|
||||
|
||||
To stop the server: `Ctrl+C`
|
||||
|
||||
To start again without the setup steps:
|
||||
|
||||
```bash
|
||||
source .venv/bin/activate
|
||||
uvicorn app.main:app --reload
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5. Log in with Twitch
|
||||
|
||||
1. Open `http://localhost:8000` in your browser
|
||||
2. Click **Login with Twitch**
|
||||
3. Authorise the app — you will be asked to grant permissions for subscriptions, bits, channel points, and follower data
|
||||
4. You are redirected to the dashboard; EventSub connects automatically
|
||||
|
||||
**Bookmark the dashboard URL.** There are no accounts or passwords — the session cookie keeps you logged in.
|
||||
|
||||
---
|
||||
|
||||
### 6. Configure OBS browser source
|
||||
|
||||
1. In OBS, go to **Sources → + → Browser**
|
||||
2. Set the URL to the value shown on the Settings page (default: `http://localhost:8000/overlay`)
|
||||
3. Set **Width** and **Height** to match your stream resolution (typically `1920` × `1080`)
|
||||
4. Check **Shutdown source when not visible**
|
||||
5. In the **Custom CSS** box paste:
|
||||
```css
|
||||
body { background: transparent !important; }
|
||||
```
|
||||
6. Click OK
|
||||
|
||||
The overlay will appear transparent in OBS. Chat messages and alerts show on top of your game/content.
|
||||
|
||||
---
|
||||
|
||||
### 7. Upload media
|
||||
|
||||
1. Go to **Media** in the management UI
|
||||
2. Click **Choose File** and upload sounds (MP3, OGG, WAV) and/or videos (MP4, WebM)
|
||||
3. Preview them in the browser before assigning them to actions
|
||||
|
||||
---
|
||||
|
||||
### 8. Configure actions
|
||||
|
||||
1. Go to **Actions**
|
||||
2. For each event you want to react to, fill in the **Add action** form:
|
||||
- **Event type:** `sub`, `gift_sub`, `bits`, `channel_points`, `command`, `follow`, or `raid`
|
||||
- **Event detail:** command name (for commands), minimum bits (for bits), reward ID (for channel points), tier (for subs) — leave blank to match any
|
||||
- **Action type:** `sound`, `video`, or `alert`
|
||||
- **Media file:** pick an uploaded file (for sound/video)
|
||||
- **Alert text:** message shown on screen (for alert type)
|
||||
- **Cooldown:** seconds before this action can fire again
|
||||
3. Click **Test** on each action to verify it fires before going live
|
||||
|
||||
To find a channel point reward ID: open your Twitch dashboard, go to Channel Points → Manage Rewards, then click a reward. The ID is in the page URL.
|
||||
|
||||
---
|
||||
|
||||
### 9. Configure the layout
|
||||
|
||||
1. Go to **Layout**
|
||||
2. Drag the **Chat** handle to where you want chat to appear on screen
|
||||
3. Drag the bottom-right corner of the Chat handle to resize it
|
||||
4. Drag the **Alert** handle to where you want alerts to appear
|
||||
5. Adjust font size, opacity, and text color in the form below the canvas
|
||||
6. Click **▶ Preview alert** to see the animation with your current settings
|
||||
7. Click **Save styles** when done
|
||||
8. **Refresh the OBS browser source** (`Right-click source → Refresh`) to apply layout changes
|
||||
|
||||
---
|
||||
|
||||
### 10. Optional: Custom CSS and JS
|
||||
|
||||
Go to **Settings** and scroll to the bottom.
|
||||
|
||||
**Custom CSS example** — glow effect on alerts:
|
||||
```css
|
||||
#alert {
|
||||
box-shadow: 0 0 30px #9146ff;
|
||||
border: 2px solid #9146ff;
|
||||
}
|
||||
.chat-msg {
|
||||
border-left: 3px solid;
|
||||
}
|
||||
```
|
||||
|
||||
**Custom JS example** — react to a raid:
|
||||
```javascript
|
||||
document.addEventListener('bashyoverlay:raid', (e) => {
|
||||
console.log('Raided!', e.detail.alert_text);
|
||||
});
|
||||
```
|
||||
|
||||
Available events: `bashyoverlay:sub`, `bashyoverlay:gift_sub`, `bashyoverlay:bits`, `bashyoverlay:channel_points`, `bashyoverlay:command`, `bashyoverlay:follow`, `bashyoverlay:raid`.
|
||||
|
||||
Click **Save settings** then refresh the OBS browser source.
|
||||
|
||||
---
|
||||
|
||||
## Git Actions
|
||||
|
||||
### First push to GitHub
|
||||
|
||||
After creating a new empty repository on GitHub:
|
||||
|
||||
```bash
|
||||
git remote add origin https://github.com/yourusername/BashyOverlay.git
|
||||
git branch -M main
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Day-to-day workflow
|
||||
|
||||
```bash
|
||||
# Check what has changed
|
||||
git status
|
||||
git diff
|
||||
|
||||
# Stage and commit changes
|
||||
git add app/routers/actions.py templates/actions.html
|
||||
git commit -m "add sub tier filtering to action matching"
|
||||
|
||||
# Push to remote
|
||||
git push
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### GitHub Actions CI
|
||||
|
||||
The repository includes `.github/workflows/ci.yml`. It runs automatically on every push and pull request and does the following:
|
||||
|
||||
1. Installs Python 3.11
|
||||
2. Installs all dependencies from `requirements.txt`
|
||||
3. Syntax-checks every Python file under `app/`
|
||||
4. Verifies the FastAPI app imports without error
|
||||
|
||||
No secrets are required for CI — it uses placeholder values for Twitch credentials.
|
||||
|
||||
To view CI results: go to your repository on GitHub → **Actions** tab.
|
||||
|
||||
---
|
||||
|
||||
### Adding GitHub repository secrets (for future CD)
|
||||
|
||||
If you later want to deploy automatically, add secrets in GitHub:
|
||||
|
||||
1. Go to your repository → **Settings → Secrets and variables → Actions**
|
||||
2. Click **New repository secret**
|
||||
3. Add:
|
||||
- `TWITCH_CLIENT_ID`
|
||||
- `TWITCH_CLIENT_SECRET`
|
||||
- `SECRET_KEY`
|
||||
|
||||
Reference them in a workflow step with `${{ secrets.TWITCH_CLIENT_ID }}`.
|
||||
|
||||
---
|
||||
|
||||
### Branches
|
||||
|
||||
```bash
|
||||
# Create a feature branch
|
||||
git checkout -b feature/alert-interpolation
|
||||
|
||||
# Work, commit, push
|
||||
git push -u origin feature/alert-interpolation
|
||||
|
||||
# Merge back to main when done (on GitHub via pull request, or locally)
|
||||
git checkout main
|
||||
git merge feature/alert-interpolation
|
||||
git push
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Updating a deployment
|
||||
|
||||
If BashyOverlay is running on another machine or you pull in new changes:
|
||||
|
||||
```bash
|
||||
git pull
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt # in case dependencies changed
|
||||
uvicorn app.main:app --reload
|
||||
```
|
||||
|
||||
The SQLite database is updated automatically on startup — new tables and columns are created by `SQLModel.metadata.create_all`. Existing data is preserved.
|
||||
|
||||
> **Note:** `create_all` only adds new tables and columns — it does not handle column renames or deletions. If a migration requires dropping a column, do it manually with `sqlite3 bashyoverlay.db "ALTER TABLE ..."` before restarting.
|
||||
78
README.md
Normal file
78
README.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
# BashyOverlay
|
||||
|
||||
Self-hosted Twitch stream alert and overlay platform. Subs, bits, channel points, follows, raids, and chat commands trigger configurable sound and video reactions — all running locally on your machine, no third-party alert service required.
|
||||
|
||||
## Features
|
||||
|
||||
- **OBS browser source overlay** — transparent chat display with gap audio (tone plays when chat goes quiet, volume and pitch scale with silence duration)
|
||||
- **Twitch EventSub** — real-time events for subs, gift subs, bits, channel points, follows, and raids
|
||||
- **Chat commands** — `!command` triggers via tmi.js, no bot account needed for public channels
|
||||
- **Action system** — map any event to a sound, video clip, or on-screen alert; multiple actions per event; per-action cooldowns and enable/disable toggle
|
||||
- **Test button** — fire any action instantly from the management UI without waiting for a real event
|
||||
- **Self-hosted media library** — upload your own MP3s and MP4s
|
||||
- **Layout editor** — WYSIWYG iframe editor; drag chat and alert widgets, resize chat, live style preview
|
||||
- **Custom CSS / JS** — inject code directly into the overlay; hook into `bashyoverlay:sub`, `bashyoverlay:raid`, etc.
|
||||
- **Management UI** — dashboard with activity log, EventSub status, action config, media library
|
||||
- **Twitch OAuth** — login with your Twitch account; no passwords anywhere
|
||||
|
||||
## Stack
|
||||
|
||||
- Python 3.10+ · FastAPI · SQLModel · SQLite
|
||||
- Jinja2 · HTMX · Pico CSS (dark theme)
|
||||
- tmi.js · Twitch EventSub WebSocket
|
||||
- interact.js (layout editor drag and resize)
|
||||
|
||||
## Quick start
|
||||
|
||||
See **[INSTRUCTIONS.md](INSTRUCTIONS.md)** for the full setup guide including Twitch app registration and OBS configuration.
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# fill in your Twitch credentials and a SECRET_KEY
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
## Project structure
|
||||
|
||||
```
|
||||
app/
|
||||
main.py — FastAPI app, lifespan, EventSub startup
|
||||
models.py — SQLModel table definitions
|
||||
database.py — engine, session dependency, singleton helpers
|
||||
auth.py — Twitch OAuth helpers, session dependency
|
||||
eventsub.py — EventSub WebSocket background task, token refresh
|
||||
dispatch.py — event → action resolution, cooldowns, DB log, broadcast
|
||||
ws.py — WebSocket connection manager for overlay clients
|
||||
cooldowns.py — in-memory cooldown tracking per action
|
||||
routers/
|
||||
auth.py — /auth/login, /auth/callback, /auth/logout
|
||||
dashboard.py — / dashboard with activity log
|
||||
overlay.py — /overlay (live), /overlay/preview, /ws/overlay
|
||||
actions.py — /actions CRUD, test, toggle
|
||||
media.py — /media upload and delete
|
||||
layout.py — /layout editor, /layout/positions (drag save)
|
||||
settings.py — /settings
|
||||
templates/
|
||||
overlay.html — OBS browser source (live tmi.js + WebSocket)
|
||||
overlay_preview.html — layout editor preview (mock data, no live connections)
|
||||
layout.html — iframe-based drag-and-drop layout editor
|
||||
base.html — management UI shell
|
||||
dashboard.html — activity log
|
||||
actions.html — action configuration
|
||||
media.html — media library
|
||||
settings.html — settings including custom CSS/JS
|
||||
login.html — Twitch OAuth login page
|
||||
partials/ — HTMX response fragments
|
||||
static/
|
||||
overlay.css — overlay styles using CSS custom properties
|
||||
style.css — management UI styles
|
||||
media/ — uploaded sounds and videos (gitignored)
|
||||
```
|
||||
|
||||
## Deferred / upcoming
|
||||
|
||||
- Blerp sound library integration
|
||||
- HudFX video library integration
|
||||
- Crypto payment notifications (Base/ETH wallet watching)
|
||||
- Alert variable interpolation (`{username}` in alert text)
|
||||
- Mod access (currently streamer-only login)
|
||||
Loading…
Add table
Add a link
Reference in a new issue