feat: add GitHub-themed animated landing page for Cloudflare Pages and rewrite README.md without emojis

swadhinbiswas committed 1 months ago
5ae967f
1 parent e173eca
commit 5ae967f
10 files changed
+2438 -100
β–ΌREADME.md
+203-98
1
-# 🐦 DevPulse (RavenDev)
1
+# DevPulse (RavenDev)
2
2
3
-> **The Developer Operating System for Discord.** A production-grade, multi-tenant developer platform providing GitHub intelligence, telemetry, 30+ deterministic offline developer tools, security audits, website uptime monitoring, tech news, and team workflows inside Discord.
3
+DevPulse is a production-grade GitHub power-user platform built specifically for Discord. It eliminates the need for developers to switch back and forth between Discord and browser tabs by providing repository intelligence, pull request reviews and merges, CI/CD monitoring, code investigation, and team turnaround telemetry directly within Discord slash commands and interactive components.
4
+
5
+Repository: [email protected]:husteno-o/git-discord-bot.git
6
+Website: Cloudflare Pages (apps/web)
7
+
8
+---
9
+
10
+## Architecture and Core Philosophy
11
+
12
+DevPulse is built with the principle of zero configuration for public data and zero friction for everyday tasks:
13
+
14
+1. Zero Connection Required for Public Repositories: Any developer on the server can run repository analysis, code searches, commit inspections, releases, and trending lookups without connecting an account.
15
+2. Encrypted Token Storage: Personal Access Tokens (PATs) used for write actions (approving pull requests, merging, triggering GitHub Actions workflows) are encrypted using AES-256-GCM with per-record initialization vectors and authentication tags. Plaintext credentials are never logged or stored.
16
+3. Native Discord Interface: Interactive buttons, select menus, and visual embed trees allow developers to navigate repository views, trigger merges, and review pull requests without typing lengthy commands.
17
+4. Single Synchronized Runtime: Operates as a pure Discord bot with zero required inbound open ports. An optional Fastify health check server can be toggled via configuration when deploying to platforms that require port binding.
18
+
19
+---
20
+
21
+## Technology Stack
22
+
23
+- Runtime: Bun 1.4+
24
+- Language: TypeScript 5.7+ (Strict Mode, ESNext)
25
+- Discord API: discord.js v14 with Gateway v10
26
+- Database: Turso (libSQL) with Drizzle ORM
27
+- Caching and Distributed Locks: Upstash Redis with automatic in-memory fallback
28
+- Optional HTTP Engine: Fastify 5
29
+- Code Quality and Formatting: Biome
30
+- Test Suite: Vitest
4
31
5
32
---
6
33
7
-## 🌟 Key Capabilities
8
-
9
-- **πŸ“¦ Deep GitHub Intelligence**: Interactive repository dashboards with observed activity logs (14 days), workload distribution, focus breakdown, cycle times, PR throughput, and button navigation (`/github repo`).
10
-- **πŸ‘¨β€πŸ’» Developer Productivity & Telemetry**: Personal dashboards tracking commits, PRs, review velocity, day-of-week workload balance, and turnaround times (`/dev dashboard`).
11
-- **πŸ› οΈ Deterministic Developer Toolbox**: 30+ tools operating 100% offline with zero AI dependencies:
12
- - JSON (prettify, minify, validate)
13
- - YAML (format, YAML ↔ JSON)
14
- - Cryptography (SHA-256, MD5, SHA-512, UUID v4/v7)
15
- - JWT inspector (headers, claims, expiration)
16
- - Regex evaluator & match tester
17
- - Crontab parser with future run times
18
- - Unix timestamp & timezone converter
19
- - Permissions (Chmod octal & symbolic calculator)
20
- - Semver comparator
21
- - Network (HTTP tester with strict SSRF blocker, DNS resolution, SSL cert inspector, HTTP status reference)
22
-- **πŸ“¦ Package & Dependency Intelligence**: Live registry lookup across npm, PyPI, crates.io, and Go modules (`/deps lookup`).
23
-- **πŸ›‘οΈ Security Center & Zero-Log Secret Scanner**:
24
- - Live CVE / GHSA advisory lookup powered by OSV (`/security cve`).
25
- - Automated message secret detection (scans for leaked GitHub tokens, AWS keys, private keys, database URLs, and Discord bot tokens; warns author immediately with rotation guide and deletion button; never logs or persists secrets).
26
-- **πŸ“‘ Website & Synthetic Health Monitoring**: HTTP status, response latency, and SSL certificate expiration checks running on an asynchronous scheduler (`/monitor add`).
27
-- **πŸ‘₯ Team Workflows & Project Memory**: Daily engineering standup generator with observed GitHub telemetry (`/team standup`), reminders (`/remind in`), and architectural context memory (`/project add`).
28
-- **πŸ”₯ Trending & Tech News**: Real-time trending GitHub repositories, fast-growing developer technologies, and curated RSS news feeds across 10+ categories (`/trending`, `/news`).
29
-- **πŸ€– Optional AI Provider**: Vendor-agnostic AI provider abstraction (OpenAI, Anthropic, Gemini). The core platform operates deterministically without any AI API key configured.
34
+## Core Feature Areas
35
+
36
+### 1. Repository Intelligence (/repo)
37
+Inspect any public or private repository:
38
+- Overview: Stars, forks, open issues, pull requests, watchers, license, and default branch.
39
+- Health Score: Automated calculation (0 to 100) assessing README existence, license, contributing guide, issue templates, description, topics, and maintenance activity.
40
+- Dependencies: Dependency manifests, package managers, and direct dependency breakdowns.
41
+- Growth: 30-day star velocity and repository expansion rate.
42
+- Interactive Navigation: Direct button controls for switching between Overview, Commits, PRs, Issues, and Releases.
43
+
44
+### 2. Pull Request Power Tools (/pr)
45
+Perform real pull request workflows directly inside Discord:
46
+- View Details: Full metadata, branch targets, author, line additions and deletions (+482 -193), review states, and cycle times.
47
+- Status Checks: Comprehensive CI check runs and commit status results.
48
+- Review Actions: Direct Discord interactive buttons to Approve, Request Changes, or Merge into the target branch.
49
+- Filters: Stale pull requests and pull requests awaiting review.
50
+
51
+### 3. Universal Search (/search)
52
+Search across GitHub using official search qualifiers:
53
+- Code Search: Search source code across files, organizations, and languages.
54
+- Issues and Pull Requests: Filter by status, label, author, assignee, and mentions.
55
+- Repositories: Search by topics, star counts, forks, and updated dates.
56
+- Commits: Find commits by message, hash, author, or committer date.
57
+
58
+### 4. Code Investigation (/code)
59
+Inspect remote codebases without cloning:
60
+- View File: Fetch and render syntax-highlighted code chunks with line numbers.
61
+- Git Blame: Line-by-line attribution showing author, commit hash, commit message, and relative timestamp.
62
+- Commit to PR Link: Resolve any commit SHA back to the associated pull request where it was merged.
63
+
64
+### 5. Lifecycle Timeline (/investigate)
65
+Trace an issue or feature request through its entire development lifecycle:
66
+- Chronological Timeline: Issue Creation -> Commit -> Pull Request -> Code Review -> Merge -> Release Tag.
67
+- Identifies who approved the change, what release it shipped in, and resolution time.
68
+
69
+### 6. Developer Activity and Histograms (/activity)
70
+Track engineering rhythm and repository momentum:
71
+- Activity Visualizer: ASCII daily commit histograms displaying work distribution across Monday through Sunday.
72
+- Churn Analysis: Additions versus deletions ratio to measure refactoring versus new feature volume.
73
+- Personal Telemetry: The /activity me command displays personal contribution velocity.
74
+
75
+### 7. GitHub Trending Radar (/trending)
76
+Discover rising projects and libraries across modern ecosystems:
77
+- Language Filters: TypeScript, Rust, AI and Machine Learning, Bun, Databases, Go, and Python.
78
+- Velocity Metrics: Stars gained in daily, weekly, or monthly periods.
79
+
80
+### 8. GitHub Watchtower (/watch)
81
+Automated event subscriptions delivered to dedicated Discord channels:
82
+- Channel Subscriptions: Listen for releases, new pull requests, opened issues, or security advisories.
83
+- Configurable Routing: Route different event types to specific channels (for example, alerts to #dev-alerts and releases to #announcements).
84
+
85
+### 9. CI/CD Workflow Intelligence (/actions)
86
+Monitor and manage GitHub Actions pipelines:
87
+- Visual Workflow Tree: Render branch and workflow statuses in structured ASCII trees.
88
+- Run History: View recent runs, conclusion status (success, failure, cancelled, in_progress), duration, and triggering actors.
89
+- Control Actions: Rerun failed jobs or cancel running workflows directly from Discord.
90
+
91
+### 10. Security Radar (/security)
92
+Security vulnerability tracking and alert management:
93
+- Dependabot Alerts: Open security vulnerability reports with affected packages, patched versions, and severity tiers.
94
+- Advisory Lookup: Search GitHub Security Advisories and CVE identifiers.
95
+- Real-Time Secret Scanner: Background message monitor that immediately detects leaked API keys, tokens, or database credentials, alerts the author privately with rotation instructions, and offers one-click deletion.
96
+
97
+### 11. Release Management (/release)
98
+Track and draft releases:
99
+- Latest Release: View published tags, assets, download counts, and release notes.
100
+- Tag Comparison: Compare differences and commit counts between tags (for example, v1.2.0...v1.3.0).
101
+- Release Notes Generator: Automatically compiles changelogs from merged pull requests between git tags.
102
+
103
+### 12. Team Intelligence (/team)
104
+Engineering team metrics designed for healthy collaboration:
105
+- Throughput and Velocity: Merged PR volume and average turnaround time.
106
+- Workload Balance: Review distribution across team members to prevent individual burnout.
107
+- Zero Toxicity: Focuses on process improvement, cycle times, and review turnaround rather than arbitrary commit count rankings.
30
108
31
109
---
32
110
33
-## πŸ—οΈ Architecture & Technology Stack
111
+## Utilities and Convenience Commands
34
112
35
-- **Runtime**: [Bun 1.4](https://bun.sh)
36
-- **Language**: TypeScript 5.7+ (Strict mode, ESNext)
37
-- **Discord Library**: [discord.js v14](https://discord.js.org)
38
-- **Database**: [Turso (libSQL / SQLite)](https://turso.tech) with [Drizzle ORM](https://orm.drizzle.team)
39
-- **Caching & Locks**: [Upstash Redis](https://upstash.com) with resilient in-memory fallback
40
-- **HTTP Server**: [Fastify 5](https://fastify.dev)
41
-- **Validation**: [Zod](https://zod.dev)
42
-- **Structured Logging**: [Pino](https://getpino.io) with automatic credential redaction
43
-- **Code Quality**: [Biome](https://biomejs.dev)
44
-- **Test Suite**: [Vitest](https://vitest.dev)
113
+- /home: Morning developer command center showing your active PRs, pending reviews, repository watch alerts, and trending highlights.
114
+- /connect: Securely store your GitHub Personal Access Token encrypted with AES-256-GCM.
115
+- /why: Trace a specific file and line change back through Commit -> PR -> Originating Issue.
116
+- /ask: Deterministic query helper for questions like pull requests waiting for review over 24 hours or frequently modified files.
117
+- /tools: GitHub developer essentials including .gitignore generator, SPDX license viewer, and GitHub platform status.
118
+- /settings: Server defaults, preferred repositories, alert routing, and quiet hours.
119
+- /help: Interactive directory of all available commands grouped by category.
45
120
46
121
---
47
122
48
-## πŸš€ Quick Start
123
+## Quick Start Guide
124
+
125
+### Prerequisites
126
+- Bun runtime (version 1.4 or higher)
127
+- Discord Application Bot Token with Send Messages, Embed Links, and Use Slash Commands permissions
128
+- (Optional) GitHub Personal Access Token for write operations and private repository access
129
+- (Optional) Turso Database URL and Upstash Redis credentials
49
130
50
-### 1. Clone & Install Dependencies
131
+### 1. Clone Repository
51
132
```bash
52
-git clone https://github.com/swadhin/discordbot.git
53
-cd discordbot
133
+git clone [email protected]:husteno-o/git-discord-bot.git
134
+cd git-discord-bot
54
135
bun install
55
136
```
56
137
57
138
### 2. Configure Environment
58
-Copy `.env.example` to `.env` and configure your credentials:
139
+Create your local environment file:
59
140
```bash
60
141
cp .env.example .env
61
142
```
62
143
63
-### 3. Verify System Health
64
-Run quality checks:
144
+Configure your credentials in `.env`:
145
+```env
146
+NODE_ENV=development
147
+LOG_LEVEL=info
148
+
149
+# Discord Configuration
150
+DISCORD_TOKEN=your_discord_bot_token_here
151
+DISCORD_CLIENT_ID=your_discord_application_id_here
152
+DISCORD_PUBLIC_KEY=your_discord_public_key_here
153
+
154
+# Database Configuration (Defaults to local file:devpulse.db)
155
+TURSO_DATABASE_URL=file:devpulse.db
156
+TURSO_AUTH_TOKEN=
157
+
158
+# Redis Cache (Optional, defaults to in-memory cache)
159
+UPSTASH_REDIS_REST_URL=
160
+UPSTASH_REDIS_REST_TOKEN=
161
+
162
+# GitHub Configuration (Optional for public repositories)
163
+GITHUB_TOKEN=
164
+```
165
+
166
+### 3. Verify Code Quality and Run Tests
65
167
```bash
66
-# Typecheck all 16 workspaces
168
+# Typecheck all packages
67
169
bun run typecheck
68
170
69
-# Run linter
171
+# Run Biome linter
70
172
bun run lint
71
173
72
-# Execute automated tests
174
+# Run Vitest test suite
73
175
bun run test
74
176
75
-# Compile production bundles
177
+# Compile all workspaces
76
178
bun run build
77
179
```
78
180
79
-### 4. Start Services
181
+### 4. Start the Application
182
+```bash
183
+# Start the Discord Bot
184
+bun run start
185
+```
186
+
187
+---
188
+
189
+## Deploying the Landing Page to Cloudflare Pages
190
+
191
+The marketing and documentation landing page is located in the apps/web directory. It is built as an optimized static site ready for deployment on Cloudflare Pages.
192
+
193
+### Method A: Cloudflare Dashboard Deployment
194
+1. Log in to the Cloudflare dashboard and navigate to Workers & Pages -> Create Application -> Pages -> Connect to Git.
195
+2. Select your repository: husteno-o/git-discord-bot.
196
+3. Set the following build settings:
197
+ - Framework preset: None
198
+ - Build command: bun run build:web
199
+ - Build output directory: apps/web/dist
200
+4. Deploy the site.
201
+
202
+### Method B: Wrangler CLI Deployment
203
+```bash
204
+# Build the static site bundle
205
+bun run build:web
206
+
207
+# Deploy directly via Wrangler
208
+bun x wrangler pages deploy apps/web/dist --project-name=devpulse
209
+```
210
+
211
+---
212
+
213
+## Docker Deployment
214
+
215
+To run DevPulse in a containerized environment:
216
+
80
217
```bash
81
-# Run the Discord Bot
82
-bun run start:bot
218
+# Build Docker image
219
+docker build -t devpulse:latest .
220
+
221
+# Run with environment variables
222
+docker run -d \
223
+ --name devpulse \
224
+ --env-file .env \
225
+ devpulse:latest
226
+```
83
227
84
-# Run the Fastify API (Health checks & Webhooks)
85
-bun run start:api
228
+Alternatively, use Docker Compose:
229
+```bash
230
+docker compose up -d
86
231
```
87
232
88
233
---
89
234
90
-## πŸ“‹ Slash Command Reference
91
-
92
-| Command | Subcommand | Description |
93
-| :--- | :--- | :--- |
94
-| `/github` | `repo <owner/repo>` | Comprehensive repository dashboard with interactive buttons |
95
-| `/github` | `commits <owner/repo>` | View recent commit log and authors |
96
-| `/github` | `prs <owner/repo>` | View active and merged pull requests |
97
-| `/github` | `issues <owner/repo>` | View open issue reports and comments |
98
-| `/github` | `releases <owner/repo>` | View published version releases |
99
-| `/dev` | `dashboard` | Personal developer productivity and focus telemetry |
100
-| `/dev` | `profile [user]` | Inspect public developer statistics |
101
-| `/dev` | `link-github <user>` | Bind GitHub account for automated telemetry |
102
-| `/tools` | `json <action> <input>` | JSON formatting, minification, and validation |
103
-| `/tools` | `yaml <action> <input>` | YAML formatting and YAML ↔ JSON conversion |
104
-| `/tools` | `jwt <token>` | Decodes token header, payload, algorithm, and expiration |
105
-| `/tools` | `hash <algo> <input>` | Generate SHA-256, MD5, SHA-1, or SHA-512 hash |
106
-| `/tools` | `uuid [v4\|v7]` | Generate random or time-ordered UUID |
107
-| `/tools` | `regex <pattern> <text>` | Test regex patterns with match groups |
108
-| `/tools` | `cron <expression>` | Human-readable schedule explanation + next 5 runs |
109
-| `/tools` | `timestamp <value>` | Convert Unix epoch <-> ISO <-> relative Discord time |
110
-| `/tools` | `timezone <time> <from> <to>` | Convert between international timezones |
111
-| `/tools` | `chmod <value>` | Octal <-> symbolic permissions calculator |
112
-| `/tools` | `semver <v1> <v2>` | Compare two semantic version strings |
113
-| `/tools` | `http <url> [method]` | Safe HTTP tester with strict SSRF blocker |
114
-| `/tools` | `dns <domain> [type]` | Resolve A, AAAA, MX, TXT, NS records |
115
-| `/tools` | `ssl <domain>` | Inspect SSL certificate issuer and days remaining |
116
-| `/tools` | `status <code>` | HTTP status code catalog and explanations |
117
-| `/deps` | `lookup <eco> <pkg>` | Dependency inspector for npm, PyPI, crates.io, Go |
118
-| `/security` | `cve <id>` | OSV / CVE vulnerability advisory lookup |
119
-| `/security` | `package <eco> <pkg>` | Check open vulnerability advisories |
120
-| `/security` | `status` | View security policies and secret scanner state |
121
-| `/monitor` | `add <url> [name]` | Add website or API endpoint to synthetic monitor |
122
-| `/monitor` | `list` | View configured monitors with real-time status |
123
-| `/monitor` | `status <id>` | View latency sparkline and check history |
124
-| `/monitor` | `remove <id>` | Remove monitor |
125
-| `/trending` | `github [lang] [period]`| Trending repositories with high star velocity |
126
-| `/trending` | `technologies` | Fastest-growing developer tools and runtimes |
127
-| `/news` | `latest [category]` | Curated tech news headlines from verified feeds |
128
-| `/team` | `standup <today> [blockers]` | Post standup with observed GitHub activity |
129
-| `/team` | `activity` | Aggregated team velocity and commit throughput |
130
-| `/remind` | `in <duration> <note>` | Timezone-aware reminders (`30m`, `2h`, `1d`) |
131
-| `/project` | `add <name> <stack>` | Register architectural project memory |
132
-| `/project` | `view <name>` | View project context and tech stack |
133
-| `/settings` | `view` | View server policies, channel routing, and toggles |
134
-| `/setup` | *(None)* | Interactive guided server onboarding wizard |
135
-| `/help` | `[module]` | Interactive command browser with category select menu |
235
+## Security and Compliance
236
+
237
+- AES-256-GCM Encryption: Used for all sensitive user credentials stored in the database.
238
+- Zero Secret Logging: Structured logger automatically masks and redacts access tokens, webhooks, and private keys.
239
+- SSRF Guard: Outbound network checks strictly reject loopback, RFC 1918 private IPv4 addresses, and link-local ranges.
240
+- Rate Limiting: Built-in sliding window rate limiter protects against abusive command execution.
136
241
β–Όapps/web/build.ts
+41-0
1
+import { existsSync } from "node:fs";
2
+import { cp, mkdir, rm } from "node:fs/promises";
3
+import path from "node:path";
4
+
5
+const projectRoot = import.meta.dir;
6
+const distDir = path.join(projectRoot, "dist");
7
+const srcDir = path.join(projectRoot, "src");
8
+const publicDir = path.join(projectRoot, "public");
9
+
10
+console.log("Building DevPulse Landing Page for Cloudflare Pages...");
11
+
12
+// Clean dist directory
13
+if (existsSync(distDir)) {
14
+ await rm(distDir, { recursive: true, force: true });
15
+}
16
+await mkdir(distDir, { recursive: true });
17
+
18
+// Bundle TypeScript app
19
+const buildResult = await Bun.build({
20
+ entrypoints: [path.join(srcDir, "app.ts")],
21
+ outdir: distDir,
22
+ target: "browser",
23
+ minify: true,
24
+ naming: "app.js",
25
+});
26
+
27
+if (!buildResult.success) {
28
+ console.error("Build failed:", buildResult.logs);
29
+ process.exit(1);
30
+}
31
+
32
+// Copy HTML and CSS
33
+await cp(path.join(srcDir, "index.html"), path.join(distDir, "index.html"));
34
+await cp(path.join(srcDir, "styles.css"), path.join(distDir, "styles.css"));
35
+
36
+// Copy public assets & Cloudflare Pages files (_headers, etc.)
37
+if (existsSync(publicDir)) {
38
+ await cp(publicDir, distDir, { recursive: true });
39
+}
40
+
41
+console.log("Landing page build completed successfully in apps/web/dist!");
0
42
β–Όapps/web/package.json
+17-0
1
+{
2
+ "name": "@devpulse/web",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "build": "bun run build.ts",
8
+ "typecheck": "tsc --noEmit",
9
+ "dev": "bun run --watch build.ts",
10
+ "preview": "bun run serve.ts"
11
+ },
12
+ "devDependencies": {
13
+ "@types/node": "^22.13.0",
14
+ "bun-types": "^1.4.2",
15
+ "typescript": "^5.7.3"
16
+ }
17
+}
0
18
β–Όapps/web/public/_headers
+11-0
1
+/*
2
+ X-Frame-Options: DENY
3
+ X-Content-Type-Options: nosniff
4
+ Referrer-Policy: strict-origin-when-cross-origin
5
+ Permissions-Policy: camera=(), microphone=(), geolocation=()
6
+
7
+/assets/*
8
+ Cache-Control: public, max-age=31536000, immutable
9
+
10
+/*.html
11
+ Cache-Control: public, max-age=0, must-revalidate
0
12
β–Όapps/web/serve.ts
+29-0
1
+import { existsSync } from "node:fs";
2
+import path from "node:path";
3
+
4
+const distDir = path.join(import.meta.dir, "dist");
5
+const port = 4173;
6
+
7
+if (!existsSync(distDir)) {
8
+ console.log("dist folder not found, running build first...");
9
+ const proc = Bun.spawnSync(["bun", "run", "build.ts"], { cwd: import.meta.dir });
10
+ console.log(proc.stdout.toString());
11
+}
12
+
13
+const server = Bun.serve({
14
+ port,
15
+ fetch(req) {
16
+ const url = new URL(req.url);
17
+ const filePath = path.join(distDir, url.pathname === "/" ? "index.html" : url.pathname);
18
+
19
+ const file = Bun.file(filePath);
20
+ if (file.size > 0) {
21
+ return new Response(file);
22
+ }
23
+
24
+ // Fallback to index.html for SPA/static routing
25
+ return new Response(Bun.file(path.join(distDir, "index.html")));
26
+ },
27
+});
28
+
29
+console.log(`DevPulse landing page preview running at http://localhost:${server.port}`);
0
30
β–Όapps/web/src/app.ts
+404-0
1
+// DevPulse Interactive Landing Page Controller
2
+
3
+export interface SimState {
4
+ activeTab: string;
5
+ prStatus: "open" | "approved" | "changes_requested" | "merged";
6
+ repoTab: "overview" | "commits" | "prs" | "issues" | "releases";
7
+}
8
+
9
+const state: SimState = {
10
+ activeTab: "pr",
11
+ prStatus: "open",
12
+ repoTab: "overview",
13
+};
14
+
15
+// Clipboard copy helper
16
+export function copyText(text: string, triggerBtn?: HTMLElement) {
17
+ navigator.clipboard.writeText(text).then(() => {
18
+ if (triggerBtn) {
19
+ const originalHtml = triggerBtn.innerHTML;
20
+ triggerBtn.innerHTML = `
21
+ <svg width="14" height="14" viewBox="0 0 16 16" fill="#3fb950">
22
+ <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/>
23
+ </svg>
24
+ <span style="color: #3fb950; font-weight: 600;">Copied!</span>
25
+ `;
26
+ setTimeout(() => {
27
+ triggerBtn.innerHTML = originalHtml;
28
+ }, 2200);
29
+ }
30
+ });
31
+}
32
+
33
+// Simulator views
34
+const tabTemplates: Record<string, () => string> = {
35
+ pr: () => {
36
+ let statusBadge = `<span class="status-tag status-tag-green">🟒 Ready to merge</span>`;
37
+ let mergeButtonHtml = `<button class="discord-btn discord-btn-primary" id="sim-btn-merge">Merge into main</button>`;
38
+
39
+ if (state.prStatus === "approved") {
40
+ statusBadge = `<span class="status-tag status-tag-green">βœ… Approved by you</span>`;
41
+ } else if (state.prStatus === "changes_requested") {
42
+ statusBadge = `<span class="status-tag" style="background: rgba(248,81,73,0.15); color: #f85149; border: 1px solid rgba(248,81,73,0.3)">⚠️ Changes Requested</span>`;
43
+ } else if (state.prStatus === "merged") {
44
+ statusBadge = `<span class="status-tag status-tag-purple">🟣 Merged into main (commit #9a8f2c)</span>`;
45
+ mergeButtonHtml = `<button class="discord-btn discord-btn-disabled" disabled>Merged</button>`;
46
+ }
47
+
48
+ return `
49
+ <div class="discord-message">
50
+ <div class="discord-avatar">
51
+ <svg viewBox="0 0 16 16"><path d="M5 3.254V3.25v.004a.75.75 0 1 1 0-.004Zm1.5 0a2.25 2.25 0 1 0-3 2.122V8.75a2.25 2.25 0 0 0 1.5 2.122v.378a2.25 2.25 0 1 0 1.5 0v-.378a2.25 2.25 0 0 0 1.5-2.122V5.376A2.25 2.25 0 0 0 6.5 3.254Z"/></svg>
52
+ </div>
53
+ <div class="discord-content">
54
+ <div class="discord-header">
55
+ <span class="bot-name">DevPulse</span>
56
+ <span class="bot-tag">BOT</span>
57
+ <span class="message-time">Today at 10:42 AM</span>
58
+ </div>
59
+ <div class="command-echo">/pr 142 repo:vercel/next.js</div>
60
+ <div class="discord-embed" style="border-left-color: ${state.prStatus === "merged" ? "#a371f7" : "#2ea043"}">
61
+ <div class="embed-author">
62
+ <span>vercel/next.js</span>
63
+ <span>β€’</span>
64
+ <span>Pull Request #142</span>
65
+ </div>
66
+ <div class="embed-title">
67
+ feat(router): optimize parallel route cache hydration
68
+ </div>
69
+ <div class="embed-desc">
70
+ ${statusBadge}
71
+ Author: <strong>@timneutkens</strong> β€’ Target: <code>canary β¬… feature/route-cache</code>
72
+ Files Changed: <strong>14</strong> β€’ <span style="color: #3fb950">+482</span> <span style="color: #f85149">βˆ’193</span>
73
+ </div>
74
+ <div class="embed-grid">
75
+ <div>
76
+ <div class="embed-field-name">CI Status</div>
77
+ <div class="embed-field-value">βœ… 12/12 Checks Passing</div>
78
+ </div>
79
+ <div>
80
+ <div class="embed-field-name">Reviews</div>
81
+ <div class="embed-field-value">${state.prStatus === "approved" ? "3/2 (Required met)" : "2/2 (Required met)"}</div>
82
+ </div>
83
+ <div>
84
+ <div class="embed-field-name">Merge Conflicts</div>
85
+ <div class="embed-field-value">None (Clean merge)</div>
86
+ </div>
87
+ <div>
88
+ <div class="embed-field-name">Cycle Time</div>
89
+ <div class="embed-field-value">1d 4h 12m</div>
90
+ </div>
91
+ </div>
92
+ <div class="discord-action-row">
93
+ <button class="discord-btn discord-btn-success" id="sim-btn-approve">Approve</button>
94
+ <button class="discord-btn discord-btn-danger" id="sim-btn-changes">Request Changes</button>
95
+ ${mergeButtonHtml}
96
+ <button class="discord-btn" onclick="window.open('https://github.com', '_blank')">Open GitHub β†—</button>
97
+ </div>
98
+ </div>
99
+ </div>
100
+ </div>
101
+ `;
102
+ },
103
+
104
+ repo: () => {
105
+ return `
106
+ <div class="discord-message">
107
+ <div class="discord-avatar">
108
+ <svg viewBox="0 0 16 16"><path d="M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5Zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8ZM5 12.25a.25.25 0 0 1 .25-.25H12v1.5H5.25a.25.25 0 0 1-.25-.25Z"/></svg>
109
+ </div>
110
+ <div class="discord-content">
111
+ <div class="discord-header">
112
+ <span class="bot-name">DevPulse</span>
113
+ <span class="bot-tag">BOT</span>
114
+ <span class="message-time">Today at 10:45 AM</span>
115
+ </div>
116
+ <div class="command-echo">/repo name:vercel/next.js</div>
117
+ <div class="discord-embed" style="border-left-color: #58a6ff">
118
+ <div class="embed-author">Repository Intelligence</div>
119
+ <div class="embed-title">vercel/next.js</div>
120
+ <div class="embed-desc">
121
+ The React Framework for the Web. Used by top engineering teams worldwide.
122
+ <strong>Health Score: 96 / 100</strong> [β– β– β– β– β– β– β– β– β– β–‘]
123
+ </div>
124
+ <div class="embed-grid">
125
+ <div>
126
+ <div class="embed-field-name">Stars / Forks</div>
127
+ <div class="embed-field-value">β˜… 124,510 β€’ β‘‚ 26,840</div>
128
+ </div>
129
+ <div>
130
+ <div class="embed-field-name">Open Issues / PRs</div>
131
+ <div class="embed-field-value">Issue: 412 β€’ PR: 89</div>
132
+ </div>
133
+ <div>
134
+ <div class="embed-field-name">License / Branch</div>
135
+ <div class="embed-field-value">MIT β€’ canary</div>
136
+ </div>
137
+ <div>
138
+ <div class="embed-field-name">30d Star Velocity</div>
139
+ <div class="embed-field-value"><span style="color:#3fb950">+1,840 stars</span> (+1.5%)</div>
140
+ </div>
141
+ </div>
142
+ <div class="discord-action-row">
143
+ <button class="discord-btn ${state.repoTab === "overview" ? "discord-btn-primary" : ""}" id="sim-repo-overview">Overview</button>
144
+ <button class="discord-btn ${state.repoTab === "commits" ? "discord-btn-primary" : ""}" id="sim-repo-commits">Commits</button>
145
+ <button class="discord-btn ${state.repoTab === "prs" ? "discord-btn-primary" : ""}" id="sim-repo-prs">PRs (89)</button>
146
+ <button class="discord-btn ${state.repoTab === "issues" ? "discord-btn-primary" : ""}" id="sim-repo-issues">Issues (412)</button>
147
+ <button class="discord-btn ${state.repoTab === "releases" ? "discord-btn-primary" : ""}" id="sim-repo-releases">Releases (v15.2.0)</button>
148
+ </div>
149
+ </div>
150
+ </div>
151
+ </div>
152
+ `;
153
+ },
154
+
155
+ actions: () => {
156
+ return `
157
+ <div class="discord-message">
158
+ <div class="discord-avatar">
159
+ <svg viewBox="0 0 16 16"><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"/></svg>
160
+ </div>
161
+ <div class="discord-content">
162
+ <div class="discord-header">
163
+ <span class="bot-name">DevPulse</span>
164
+ <span class="bot-tag">BOT</span>
165
+ <span class="message-time">Today at 10:48 AM</span>
166
+ </div>
167
+ <div class="command-echo">/actions repo:vercel/next.js branch:canary</div>
168
+ <div class="discord-embed" style="border-left-color: #2ea043">
169
+ <div class="embed-author">GitHub Actions CI/CD Pipeline</div>
170
+ <div class="embed-title">canary β€’ Run #4,892 Passed</div>
171
+ <div class="embed-desc">Triggered by <strong>@leerob</strong> via push on commit <code>3a91e4f</code></div>
172
+ <div class="embed-code-block">canary (commit 3a91e4f)
173
+β”œβ”€β”€ Unit Tests (Node 20 & 22) βœ… Passing (1m 42s)
174
+β”œβ”€β”€ Turbopack Integration E2E βœ… Passing (4m 15s)
175
+β”œβ”€β”€ Edge Runtime Compatibility βœ… Passing (52s)
176
+β”œβ”€β”€ Security Scanning & Audit βœ… Passing (38s)
177
+└── Production Bundle Analyzer βœ… Passing (1m 04s)</div>
178
+ <div class="discord-action-row">
179
+ <button class="discord-btn" id="sim-btn-rerun">Rerun All Jobs</button>
180
+ <button class="discord-btn discord-btn-danger" id="sim-btn-cancel" disabled>Cancel</button>
181
+ <button class="discord-btn" onclick="window.open('https://github.com', '_blank')">View Workflow Run β†—</button>
182
+ </div>
183
+ </div>
184
+ </div>
185
+ </div>
186
+ `;
187
+ },
188
+
189
+ investigate: () => {
190
+ return `
191
+ <div class="discord-message">
192
+ <div class="discord-avatar">
193
+ <svg viewBox="0 0 16 16"><path d="M11.5 7a4.499 4.499 0 1 1-8.998 0A4.499 4.499 0 0 1 11.5 7Zm-.82 4.74a6 6 0 1 0-1.06 1.06l3.04 3.04a.75.75 0 1 0 1.06-1.06l-3.04-3.04Z"/></svg>
194
+ </div>
195
+ <div class="discord-content">
196
+ <div class="discord-header">
197
+ <span class="bot-name">DevPulse</span>
198
+ <span class="bot-tag">BOT</span>
199
+ <span class="message-time">Today at 10:50 AM</span>
200
+ </div>
201
+ <div class="command-echo">/investigate pr:142 repo:vercel/next.js</div>
202
+ <div class="discord-embed" style="border-left-color: #a371f7">
203
+ <div class="embed-author">Lifecycle Investigation Engine</div>
204
+ <div class="embed-title">Full End-to-End Development Trace</div>
205
+ <div class="embed-desc">Chronological lifecycle trace from original bug report to published version:</div>
206
+ <div class="embed-code-block">1. Issue Created: #892 "Hydration mismatch in nested parallel routes" by @alex (Sep 1)
207
+2. Branch Created: feature/route-cache (Sep 2)
208
+3. Commit Added: 8f3b12a "fix: reconcile router slot metadata" by @timneutkens
209
+4. PR Opened: #142 (Sep 2)
210
+5. CI Verification: 12 checks passed (Sep 2)
211
+6. Code Reviews: Approved by @sokra & @kdy1 (Sep 3)
212
+7. Merged: Merged into canary by @timneutkens (Sep 3)
213
+8. Shipped In: v15.2.0-canary.18 (Sep 4)</div>
214
+ <div class="discord-action-row">
215
+ <button class="discord-btn" onclick="copyText('Issue #892 -> PR #142 -> v15.2.0-canary.18', this)">Copy Investigation Summary</button>
216
+ </div>
217
+ </div>
218
+ </div>
219
+ </div>
220
+ `;
221
+ },
222
+
223
+ code: () => {
224
+ return `
225
+ <div class="discord-message">
226
+ <div class="discord-avatar">
227
+ <svg viewBox="0 0 16 16"><path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .215-.734.749.749 0 0 1 1.06-.026Zm-6.56 0a.75.75 0 0 1 1.06 0 .749.749 0 0 1 .215.734.749.749 0 0 1-.215.734L2.06 8l3.72 3.72a.749.749 0 0 1-.215.734.749.749 0 0 1-1.06.026L.22 8.53a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0Z"/></svg>
228
+ </div>
229
+ <div class="discord-content">
230
+ <div class="discord-header">
231
+ <span class="bot-name">DevPulse</span>
232
+ <span class="bot-tag">BOT</span>
233
+ <span class="message-time">Today at 10:52 AM</span>
234
+ </div>
235
+ <div class="command-echo">/code blame file:packages/next/src/server/route-matcher.ts lines:40-46</div>
236
+ <div class="discord-embed" style="border-left-color: #58a6ff">
237
+ <div class="embed-author">Code Blame & Attribution</div>
238
+ <div class="embed-title">route-matcher.ts (Lines 40-46)</div>
239
+ <div class="embed-code-block">40 | export function matchRoute(url: string, routes: Route[]): Route | null {
240
+41 | // [e71ab82 @timneutkens 3d ago] Fast-path lookup for exact match
241
+42 | const exact = exactMap.get(url);
242
+43 | if (exact) return exact;
243
+44 | // [8f3b12a @sokra 1w ago] Fallback dynamic param evaluator
244
+45 | return evaluateRegexRoutes(url, routes);
245
+46 | }</div>
246
+ <div class="embed-desc">Commit <code>8f3b12a</code> originated from <strong>PR #138</strong> merged into canary on Aug 28.</div>
247
+ </div>
248
+ </div>
249
+ </div>
250
+ `;
251
+ },
252
+
253
+ activity: () => {
254
+ return `
255
+ <div class="discord-message">
256
+ <div class="discord-avatar">
257
+ <svg viewBox="0 0 16 16"><path d="M1.5 1.75V13.5h13.75a.75.75 0 0 1 0 1.5H.75a.75.75 0 0 1-.75-.75V1.75a.75.75 0 0 1 1.5 0Zm14.28 2.53-5.25 5.25a.75.75 0 0 1-1.06 0L7 7.06 2.53 11.53a.75.75 0 0 1-1.06-1.06l5-5a.75.75 0 0 1 1.06 0L10 7.94l4.72-4.72a.75.75 0 0 1 1.06 1.06Z"/></svg>
258
+ </div>
259
+ <div class="discord-content">
260
+ <div class="discord-header">
261
+ <span class="bot-name">DevPulse</span>
262
+ <span class="bot-tag">BOT</span>
263
+ <span class="message-time">Today at 10:55 AM</span>
264
+ </div>
265
+ <div class="command-echo">/activity me days:7</div>
266
+ <div class="discord-embed" style="border-left-color: #3fb950">
267
+ <div class="embed-author">Developer Engineering Rhythm</div>
268
+ <div class="embed-title">Personal Activity Profile (@swadhin)</div>
269
+ <div class="embed-desc">
270
+ Total Commits: <strong>48</strong> β€’ PRs Authored: <strong>6</strong> β€’ PRs Reviewed: <strong>14</strong>
271
+ Weekly Rhythm Histogram:
272
+ </div>
273
+ <div class="embed-code-block">Mon β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 14
274
+Tue β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 10
275
+Wed β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 6
276
+Thu β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 12
277
+Fri β–ˆβ–ˆβ–ˆβ–ˆ 4
278
+Sat β–ˆ 1
279
+Sun β–ˆ 1</div>
280
+ <div class="embed-grid">
281
+ <div>
282
+ <div class="embed-field-name">Churn Ratio</div>
283
+ <div class="embed-field-value">+2,140 / βˆ’840 (2.5x)</div>
284
+ </div>
285
+ <div>
286
+ <div class="embed-field-name">Average Cycle Time</div>
287
+ <div class="embed-field-value">18h 40m</div>
288
+ </div>
289
+ </div>
290
+ </div>
291
+ </div>
292
+ </div>
293
+ `;
294
+ },
295
+};
296
+
297
+export function renderSimulator() {
298
+ const container = document.getElementById("simulator-render-area");
299
+ if (!container) return;
300
+
301
+ const renderer = tabTemplates[state.activeTab];
302
+ if (renderer) {
303
+ container.innerHTML = renderer();
304
+ attachSimulatorEvents();
305
+ }
306
+}
307
+
308
+function attachSimulatorEvents() {
309
+ const approveBtn = document.getElementById("sim-btn-approve");
310
+ const changesBtn = document.getElementById("sim-btn-changes");
311
+ const mergeBtn = document.getElementById("sim-btn-merge");
312
+ const rerunBtn = document.getElementById("sim-btn-rerun");
313
+
314
+ if (approveBtn) {
315
+ approveBtn.addEventListener("click", () => {
316
+ state.prStatus = "approved";
317
+ renderSimulator();
318
+ });
319
+ }
320
+
321
+ if (changesBtn) {
322
+ changesBtn.addEventListener("click", () => {
323
+ state.prStatus = "changes_requested";
324
+ renderSimulator();
325
+ });
326
+ }
327
+
328
+ if (mergeBtn) {
329
+ mergeBtn.addEventListener("click", () => {
330
+ mergeBtn.textContent = "Merging...";
331
+ setTimeout(() => {
332
+ state.prStatus = "merged";
333
+ renderSimulator();
334
+ }, 500);
335
+ });
336
+ }
337
+
338
+ if (rerunBtn) {
339
+ rerunBtn.addEventListener("click", () => {
340
+ rerunBtn.textContent = "Dispatching GitHub Actions...";
341
+ setTimeout(() => {
342
+ rerunBtn.textContent = "Workflows Triggered βœ…";
343
+ }, 700);
344
+ });
345
+ }
346
+
347
+ // Repo sub-tabs
348
+ for (const sub of ["overview", "commits", "prs", "issues", "releases"]) {
349
+ const btn = document.getElementById(`sim-repo-${sub}`);
350
+ if (btn) {
351
+ btn.addEventListener("click", () => {
352
+ state.repoTab = sub as any;
353
+ renderSimulator();
354
+ });
355
+ }
356
+ }
357
+}
358
+
359
+// Initialize on DOM load
360
+document.addEventListener("DOMContentLoaded", () => {
361
+ // Tab switching
362
+ const tabs = document.querySelectorAll<HTMLButtonElement>(".sim-tab-btn");
363
+ for (const tab of tabs) {
364
+ tab.addEventListener("click", () => {
365
+ for (const t of tabs) {
366
+ t.classList.remove("active");
367
+ }
368
+ tab.classList.add("active");
369
+ const target = tab.getAttribute("data-tab");
370
+ if (target) {
371
+ state.activeTab = target;
372
+ renderSimulator();
373
+ }
374
+ });
375
+ }
376
+
377
+ // Initial render
378
+ renderSimulator();
379
+
380
+ // Filter feature cards
381
+ const filterInput = document.getElementById("feature-search-input") as HTMLInputElement | null;
382
+ if (filterInput) {
383
+ filterInput.addEventListener("input", (e) => {
384
+ const q = (e.target as HTMLInputElement).value.toLowerCase().trim();
385
+ const cards = document.querySelectorAll<HTMLElement>(".feature-card");
386
+ for (const card of cards) {
387
+ const text = card.innerText.toLowerCase();
388
+ if (q === "" || text.includes(q)) {
389
+ card.style.display = "flex";
390
+ } else {
391
+ card.style.display = "none";
392
+ }
393
+ }
394
+ });
395
+ }
396
+
397
+ // Copy Clone command button
398
+ const clonePill = document.getElementById("clone-repo-pill");
399
+ if (clonePill) {
400
+ clonePill.addEventListener("click", () => {
401
+ copyText("git clone [email protected]:husteno-o/git-discord-bot.git", clonePill);
402
+ });
403
+ }
404
+});
0
405
β–Όapps/web/src/index.html
+571-0
1
+<!DOCTYPE html>
2
+<html lang="en">
3
+<head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>DevPulse β€” The GitHub Power-User Operating System for Discord</title>
7
+ <meta name="description" content="Stop switching between Discord and your browser. Inspect repositories, review and merge pull requests, trigger CI/CD pipelines, and trace lifecycles right from Discord." />
8
+
9
+ <!-- OpenGraph / Social Meta Tags -->
10
+ <meta property="og:type" content="website" />
11
+ <meta property="og:title" content="DevPulse β€” The GitHub Power-User Operating System for Discord" />
12
+ <meta property="og:description" content="Deep GitHub intelligence, pull request reviews, Actions monitoring, and team telemetry inside Discord." />
13
+ <meta property="og:url" content="https://github.com/husteno-o/git-discord-bot" />
14
+ <meta name="twitter:card" content="summary_large_image" />
15
+ <meta name="twitter:title" content="DevPulse β€” GitHub Power Tools in Discord" />
16
+ <meta name="twitter:description" content="Never leave Discord for your daily GitHub workflow." />
17
+
18
+ <link rel="stylesheet" href="./styles.css" />
19
+ <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%232ea043'><path d='M5 3.254V3.25v.004a.75.75 0 1 1 0-.004Zm1.5 0a2.25 2.25 0 1 0-3 2.122V8.75a2.25 2.25 0 0 0 1.5 2.122v.378a2.25 2.25 0 1 0 1.5 0v-.378a2.25 2.25 0 0 0 1.5-2.122V5.376A2.25 2.25 0 0 0 6.5 3.254Z'/></svg>" />
20
+</head>
21
+<body>
22
+ <div class="bg-grid"></div>
23
+ <div class="ambient-glow-1"></div>
24
+ <div class="ambient-glow-2"></div>
25
+
26
+ <!-- Navigation -->
27
+ <header class="navbar">
28
+ <div class="container nav-container">
29
+ <a href="#" class="brand-logo">
30
+ <div class="brand-icon-wrapper">
31
+ <svg viewBox="0 0 16 16">
32
+ <path d="M5 3.254V3.25v.004a.75.75 0 1 1 0-.004Zm1.5 0a2.25 2.25 0 1 0-3 2.122V8.75a2.25 2.25 0 0 0 1.5 2.122v.378a2.25 2.25 0 1 0 1.5 0v-.378a2.25 2.25 0 0 0 1.5-2.122V5.376A2.25 2.25 0 0 0 6.5 3.254Z"/>
33
+ </svg>
34
+ </div>
35
+ <span class="brand-text">DevPulse</span>
36
+ <span class="brand-tag">GitHub OS</span>
37
+ </a>
38
+
39
+ <nav>
40
+ <ul class="nav-links">
41
+ <li><a href="#simulator">Live Simulator</a></li>
42
+ <li><a href="#features">12 Core Areas</a></li>
43
+ <li><a href="#killer-tools">Power Utilities</a></li>
44
+ <li><a href="#architecture">Architecture</a></li>
45
+ <li><a href="#quickstart">Quick Start</a></li>
46
+ </ul>
47
+ </nav>
48
+
49
+ <div class="nav-actions">
50
+ <a href="https://github.com/husteno-o/git-discord-bot" target="_blank" rel="noopener noreferrer" class="btn btn-github btn-sm">
51
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
52
+ <path d="M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 0 1-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 0 1 0 8c0-4.42 3.58-8 8-8Z"/>
53
+ </svg>
54
+ GitHub
55
+ </a>
56
+ <a href="#quickstart" class="btn btn-primary btn-sm">Get Started</a>
57
+ </div>
58
+ </div>
59
+ </header>
60
+
61
+ <!-- Hero Section -->
62
+ <section class="hero-section">
63
+ <div class="container">
64
+ <div class="hero-pill">
65
+ <span class="pill-dot"></span>
66
+ <span>Dedicated GitHub Power-User Operating System for Discord</span>
67
+ </div>
68
+
69
+ <h1 class="hero-title">
70
+ The GitHub Command Center.<br />
71
+ <span class="hero-title-gradient">Built Inside Discord.</span>
72
+ </h1>
73
+
74
+ <p class="hero-subtitle">
75
+ Eliminate context-switching forever. Review and merge pull requests, inspect repository health, monitor CI/CD Actions runs, trace commit lifecycles, and audit vulnerabilities directly from Discord.
76
+ </p>
77
+
78
+ <div class="hero-actions">
79
+ <a href="#quickstart" class="btn btn-discord btn-lg">
80
+ <svg width="20" height="20" viewBox="0 0 16 16" fill="currentColor">
81
+ <path d="M13.54 2.67A13.06 13.06 0 0 0 10.27 1.5a.05.05 0 0 0-.05.02c-.14.26-.3.6-.41.87a12.06 12.06 0 0 0-3.62 0c-.11-.27-.28-.61-.42-.87a.05.05 0 0 0-.05-.02 13.06 13.06 0 0 0-3.27 1.17.05.05 0 0 0-.02.04C.34 5.76-.23 8.78.08 11.75a.06.06 0 0 0 .02.04 13.13 13.13 0 0 0 3.97 2.01.05.05 0 0 0 .06-.02c.3-.42.57-.86.8-1.33a.05.05 0 0 0-.03-.07 8.65 8.65 0 0 1-1.24-.6.05.05 0 0 1-.01-.08c.08-.06.17-.13.25-.19a.05.05 0 0 1 .05-.01c2.61 1.2 5.44 1.2 8.02 0a.05.05 0 0 1 .05.01c.08.06.17.13.25.19a.05.05 0 0 1-.01.08 8.44 8.44 0 0 1-1.24.6.05.05 0 0 0-.03.07c.24.47.51.91.8 1.33a.05.05 0 0 0 .06.02 13.1 13.1 0 0 0 3.98-2.01.06.06 0 0 0 .02-.04c.38-3.52-.64-6.52-2.48-9.04a.05.05 0 0 0-.02-.04Z"/>
82
+ </svg>
83
+ Deploy Bot to Server
84
+ </a>
85
+
86
+ <div class="clone-pill" id="clone-repo-pill" title="Click to copy clone command">
87
+ <svg width="14" height="14" viewBox="0 0 16 16">
88
+ <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"/>
89
+ <path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"/>
90
+ </svg>
91
+ <span>git clone [email protected]:husteno-o/git-discord-bot.git</span>
92
+ <span class="clone-btn-icon">πŸ“‹</span>
93
+ </div>
94
+ </div>
95
+
96
+ <div class="hero-badges">
97
+ <div class="hero-badge-item">
98
+ <svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg>
99
+ <span>Zero Auth for Public Repos</span>
100
+ </div>
101
+ <div class="hero-badge-item">
102
+ <svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg>
103
+ <span>AES-256-GCM Encrypted PATs</span>
104
+ </div>
105
+ <div class="hero-badge-item">
106
+ <svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg>
107
+ <span>Zero Open Inbound Ports</span>
108
+ </div>
109
+ <div class="hero-badge-item">
110
+ <svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg>
111
+ <span>Sub-15ms Response Times</span>
112
+ </div>
113
+ </div>
114
+ </div>
115
+ </section>
116
+
117
+ <!-- Interactive Live Discord / GitHub Simulator -->
118
+ <section class="simulator-section" id="simulator">
119
+ <div class="container">
120
+ <div class="simulator-wrapper">
121
+ <div class="simulator-header">
122
+ <div class="window-dots">
123
+ <span class="window-dot dot-red"></span>
124
+ <span class="window-dot dot-yellow"></span>
125
+ <span class="window-dot dot-green"></span>
126
+ </div>
127
+ <div class="simulator-title">
128
+ <svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor">
129
+ <path d="M0 2.75C0 1.784.784 1 1.75 1h12.5c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 14.25 15H1.75A1.75 1.75 0 0 1 0 13.25Zm1.75-.25a.25.25 0 0 0-.25.25v10.5c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25V2.75a.25.25 0 0 0-.25-.25Z"/>
130
+ </svg>
131
+ <span>#engineering-ops β€’ DevPulse Interactive Terminal</span>
132
+ </div>
133
+ <div style="width: 50px;"></div>
134
+ </div>
135
+
136
+ <div class="simulator-tabs">
137
+ <button class="sim-tab-btn active" data-tab="pr">πŸ”€ /pr 142</button>
138
+ <button class="sim-tab-btn" data-tab="repo">πŸ“Š /repo vercel/next.js</button>
139
+ <button class="sim-tab-btn" data-tab="actions">βš™οΈ /actions main</button>
140
+ <button class="sim-tab-btn" data-tab="investigate">πŸ•΅οΈ /investigate #892</button>
141
+ <button class="sim-tab-btn" data-tab="code">🧠 /code route-matcher.ts</button>
142
+ <button class="sim-tab-btn" data-tab="activity">πŸ“ˆ /activity me</button>
143
+ </div>
144
+
145
+ <div class="simulator-body" id="simulator-render-area">
146
+ <!-- Dynamic rendering via app.ts -->
147
+ </div>
148
+ </div>
149
+ </div>
150
+ </section>
151
+
152
+ <!-- The 12 Core GitHub Areas -->
153
+ <section class="features-section" id="features">
154
+ <div class="container">
155
+ <div class="section-header">
156
+ <div class="section-tag">Feature Matrix</div>
157
+ <h2 class="section-title">The 12 Core GitHub Power Areas</h2>
158
+ <p class="section-desc">
159
+ Engineered for developers who want complete control over their GitHub workflow without ever having to leave their team's chat.
160
+ </p>
161
+ <div style="margin-top: 20px;">
162
+ <input type="text" id="feature-search-input" placeholder="Search commands, topics (e.g. pr, actions, security)..." style="width: 100%; max-width: 440px; padding: 10px 16px; background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: 8px; color: var(--text-primary); font-family: inherit; font-size: 0.9rem;" />
163
+ </div>
164
+ </div>
165
+
166
+ <div class="features-grid">
167
+ <!-- 1. /repo -->
168
+ <div class="feature-card">
169
+ <div class="feature-top">
170
+ <div class="feature-icon-box">
171
+ <svg viewBox="0 0 16 16"><path d="M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5Zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8ZM5 12.25a.25.25 0 0 1 .25-.25H12v1.5H5.25a.25.25 0 0 1-.25-.25Z"/></svg>
172
+ </div>
173
+ <span class="feature-command-badge">/repo</span>
174
+ </div>
175
+ <h3 class="feature-name">Repository Intelligence</h3>
176
+ <p class="feature-text">Deep repository diagnostics including stars, forks, open issues/PRs, automated Health Score (0-100), dependencies graph, and 30-day growth rate.</p>
177
+ <ul class="feature-bullets">
178
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Health Score based on community standards</li>
179
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Interactive button navigation tabs</li>
180
+ </ul>
181
+ </div>
182
+
183
+ <!-- 2. /pr -->
184
+ <div class="feature-card">
185
+ <div class="feature-top">
186
+ <div class="feature-icon-box">
187
+ <svg viewBox="0 0 16 16"><path d="M5 3.254V3.25v.004a.75.75 0 1 1 0-.004Zm1.5 0a2.25 2.25 0 1 0-3 2.122V8.75a2.25 2.25 0 0 0 1.5 2.122v.378a2.25 2.25 0 1 0 1.5 0v-.378a2.25 2.25 0 0 0 1.5-2.122V5.376A2.25 2.25 0 0 0 6.5 3.254Z"/></svg>
188
+ </div>
189
+ <span class="feature-command-badge">/pr</span>
190
+ </div>
191
+ <h3 class="feature-name">Pull Request Power Tools</h3>
192
+ <p class="feature-text">Execute real pull request workflows directly in Discord. Inspect line diffs (+482 -193), check runs, review statuses, and execute Approve or Merge actions.</p>
193
+ <ul class="feature-bullets">
194
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Real-time CI check pipeline aggregation</li>
195
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Action buttons: Approve, Changes, Merge</li>
196
+ </ul>
197
+ </div>
198
+
199
+ <!-- 3. /search -->
200
+ <div class="feature-card">
201
+ <div class="feature-top">
202
+ <div class="feature-icon-box">
203
+ <svg viewBox="0 0 16 16"><path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"/></svg>
204
+ </div>
205
+ <span class="feature-command-badge">/search</span>
206
+ </div>
207
+ <h3 class="feature-name">Universal GitHub Search</h3>
208
+ <p class="feature-text">Search across GitHub code, issues, PRs, repos, and commits using official qualifiers like `repo:`, `language:`, `is:open`, and `author:`.</p>
209
+ <ul class="feature-bullets">
210
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Fast multi-type discovery</li>
211
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Sub-100ms response formatting</li>
212
+ </ul>
213
+ </div>
214
+
215
+ <!-- 4. /code -->
216
+ <div class="feature-card">
217
+ <div class="feature-top">
218
+ <div class="feature-icon-box">
219
+ <svg viewBox="0 0 16 16"><path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .215-.734.749.749 0 0 1 1.06-.026Zm-6.56 0a.75.75 0 0 1 1.06 0 .749.749 0 0 1 .215.734.749.749 0 0 1-.215.734L2.06 8l3.72 3.72a.749.749 0 0 1-.215.734.749.749 0 0 1-1.06.026L.22 8.53a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0Z"/></svg>
220
+ </div>
221
+ <span class="feature-command-badge">/code</span>
222
+ </div>
223
+ <h3 class="feature-name">Code Viewer & Blame</h3>
224
+ <p class="feature-text">Read remote source code with syntax highlighting, perform git blame on specific line intervals, and resolve which PR introduced a given commit.</p>
225
+ <ul class="feature-bullets">
226
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Line-by-line commit authorship</li>
227
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Direct origin pull request resolution</li>
228
+ </ul>
229
+ </div>
230
+
231
+ <!-- 5. /investigate -->
232
+ <div class="feature-card">
233
+ <div class="feature-top">
234
+ <div class="feature-icon-box">
235
+ <svg viewBox="0 0 16 16"><path d="M11.5 7a4.499 4.499 0 1 1-8.998 0A4.499 4.499 0 0 1 11.5 7Zm-.82 4.74a6 6 0 1 0-1.06 1.06l3.04 3.04a.75.75 0 1 0 1.06-1.06l-3.04-3.04Z"/></svg>
236
+ </div>
237
+ <span class="feature-command-badge">/investigate</span>
238
+ </div>
239
+ <h3 class="feature-name">Lifecycle Investigation</h3>
240
+ <p class="feature-text">Reconstruct the entire lifecycle of a bug or feature: Originating Issue -> Commits -> Pull Request -> Reviewers -> Merge -> Release Tag.</p>
241
+ <ul class="feature-bullets">
242
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Complete chronological timeline</li>
243
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Identifies approvals and release tags</li>
244
+ </ul>
245
+ </div>
246
+
247
+ <!-- 6. /activity -->
248
+ <div class="feature-card">
249
+ <div class="feature-top">
250
+ <div class="feature-icon-box">
251
+ <svg viewBox="0 0 16 16"><path d="M1.5 1.75V13.5h13.75a.75.75 0 0 1 0 1.5H.75a.75.75 0 0 1-.75-.75V1.75a.75.75 0 0 1 1.5 0Zm14.28 2.53-5.25 5.25a.75.75 0 0 1-1.06 0L7 7.06 2.53 11.53a.75.75 0 0 1-1.06-1.06l5-5a.75.75 0 0 1 1.06 0L10 7.94l4.72-4.72a.75.75 0 0 1 1.06 1.06Z"/></svg>
252
+ </div>
253
+ <span class="feature-command-badge">/activity</span>
254
+ </div>
255
+ <h3 class="feature-name">Developer Histograms</h3>
256
+ <p class="feature-text">Visualize commit rhythms with ASCII weekly bar charts (`Mon β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ`), addition/deletion churn rates, and team turnaround velocity.</p>
257
+ <ul class="feature-bullets">
258
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Terminal-friendly ASCII histograms</li>
259
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> /activity me personal stats</li>
260
+ </ul>
261
+ </div>
262
+
263
+ <!-- 7. /trending -->
264
+ <div class="feature-card">
265
+ <div class="feature-top">
266
+ <div class="feature-icon-box">
267
+ <svg viewBox="0 0 16 16"><path d="M9.504.43a1.5 1.5 0 0 1 2.456.963l.006.127.034 1.834a3.5 3.5 0 0 0 1.802 3.03l.158.087 1.488.744a1.5 1.5 0 0 1 .74 1.848l-.053.138-.68 1.487a3.5 3.5 0 0 0-.25 2.186l.06.311.383 1.533a1.5 1.5 0 0 1-1.332 1.848l-.16.009-.434.004a4.5 4.5 0 0 1-4.496-4.32l-.004-.18V8.75a.75.75 0 0 0-1.5 0v3.491a6 6 0 0 0 5.86 5.999l.24.005.434-.004a3 3 0 0 0 2.91-3.693l-.383-1.533a2 2 0 0 1 .143-1.25l.68-1.487a3 3 0 0 0-1.374-3.97l-1.488-.745a2 2 0 0 1-1.03-1.731l-.034-1.835a3 3 0 0 0-4.912-2.18L7.43 2.857a.75.75 0 1 0 1.06 1.06l1.014-.987Z"/></svg>
268
+ </div>
269
+ <span class="feature-command-badge">/trending</span>
270
+ </div>
271
+ <h3 class="feature-name">Ecosystem Radar</h3>
272
+ <p class="feature-text">Curated trending repos across modern stacks: TypeScript, Rust, AI/ML, Bun, Databases, Go, and Python with daily and weekly star velocity metrics.</p>
273
+ <ul class="feature-bullets">
274
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> 7 modern ecosystem filters</li>
275
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> High-signal growth filtering</li>
276
+ </ul>
277
+ </div>
278
+
279
+ <!-- 8. /watch -->
280
+ <div class="feature-card">
281
+ <div class="feature-top">
282
+ <div class="feature-icon-box">
283
+ <svg viewBox="0 0 16 16"><path d="M8 2a6 6 0 0 0-6 6c0 1.77.78 3.36 2 4.47v.78c0 .41.34.75.75.75h6.5c.41 0 .75-.34.75-.75v-.78A5.996 5.996 0 0 0 14 8a6 6 0 0 0-6-6Zm0 1.5a4.5 4.5 0 0 1 4.5 4.5c0 1.4-.64 2.65-1.65 3.48a.75.75 0 0 0-.35.64v.38H5.5v-.38a.75.75 0 0 0-.35-.64A4.485 4.485 0 0 1 3.5 8 4.5 4.5 0 0 1 8 3.5Z"/></svg>
284
+ </div>
285
+ <span class="feature-command-badge">/watch</span>
286
+ </div>
287
+ <h3 class="feature-name">GitHub Watchtower</h3>
288
+ <p class="feature-text">Subscribe specific Discord channels to releases, pull requests, issues, or security advisories. Configure granular event routing per repository.</p>
289
+ <ul class="feature-bullets">
290
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Automated webhook delivery</li>
291
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Multi-channel event distribution</li>
292
+ </ul>
293
+ </div>
294
+
295
+ <!-- 9. /actions -->
296
+ <div class="feature-card">
297
+ <div class="feature-top">
298
+ <div class="feature-icon-box">
299
+ <svg viewBox="0 0 16 16"><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"/></svg>
300
+ </div>
301
+ <span class="feature-command-badge">/actions</span>
302
+ </div>
303
+ <h3 class="feature-name">CI/CD Workflow Tree</h3>
304
+ <p class="feature-text">Visual representation of GitHub Actions pipelines in structured ASCII trees. Track run conclusions, durations, and trigger job reruns directly in Discord.</p>
305
+ <ul class="feature-bullets">
306
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Visual branch & job hierarchy</li>
307
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Rerun and cancel workflows</li>
308
+ </ul>
309
+ </div>
310
+
311
+ <!-- 10. /security -->
312
+ <div class="feature-card">
313
+ <div class="feature-top">
314
+ <div class="feature-icon-box">
315
+ <svg viewBox="0 0 16 16"><path d="M7.467.133a1.748 1.748 0 0 1 1.066 0l5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667l5.25-1.68Z"/></svg>
316
+ </div>
317
+ <span class="feature-command-badge">/security</span>
318
+ </div>
319
+ <h3 class="feature-name">Security & Leak Guard</h3>
320
+ <p class="feature-text">Dependabot vulnerability alerts, GHSA / CVE breakdowns, and background message scanner that detects leaked tokens with one-click revocation guides.</p>
321
+ <ul class="feature-bullets">
322
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Dependabot & GHSA vulnerability feeds</li>
323
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Zero-log message secret scanner</li>
324
+ </ul>
325
+ </div>
326
+
327
+ <!-- 11. /release -->
328
+ <div class="feature-card">
329
+ <div class="feature-top">
330
+ <div class="feature-icon-box">
331
+ <svg viewBox="0 0 16 16"><path d="M1 7.775V2.75C1 1.784 1.784 1 2.75 1h5.025c.464 0 .91.184 1.238.513l6.25 6.25a1.75 1.75 0 0 1 0 2.474l-5.026 5.026a1.75 1.75 0 0 1-2.474 0l-6.25-6.25A1.752 1.752 0 0 1 1 7.775Zm1.5 0c0 .066.026.13.073.177l6.25 6.25a.25.25 0 0 0 .354 0l5.025-5.025a.25.25 0 0 0 0-.354l-6.25-6.25a.25.25 0 0 0-.177-.073H2.75a.25.25 0 0 0-.25.25ZM6 4.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0Z"/></svg>
332
+ </div>
333
+ <span class="feature-command-badge">/release</span>
334
+ </div>
335
+ <h3 class="feature-name">Release Management</h3>
336
+ <p class="feature-text">Inspect published tags, compare commit deltas between releases (`v1.2.0...v1.3.0`), and automatically generate markdown release notes from merged PRs.</p>
337
+ <ul class="feature-bullets">
338
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Tag comparison and asset counts</li>
339
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Automated changelog generator</li>
340
+ </ul>
341
+ </div>
342
+
343
+ <!-- 12. /team -->
344
+ <div class="feature-card">
345
+ <div class="feature-top">
346
+ <div class="feature-icon-box">
347
+ <svg viewBox="0 0 16 16"><path d="M2 5.5a3.5 3.5 0 1 1 5.898 2.549 5.508 5.508 0 0 1 3.034 4.084.75.75 0 1 1-1.482.235 4.002 4.002 0 0 0-6.898-2.618.75.75 0 0 1-1.052-.008A3.491 3.491 0 0 1 2 5.5Zm3.5-2a2 2 0 1 0 0 4 2 2 0 0 0 0-4Zm8.5 4.5a3 3 0 1 1-5.07 2.217.75.75 0 1 1 1.06-.063 1.5 1.5 0 1 0 2.51-1.154.75.75 0 0 1 1.5 0Z"/></svg>
348
+ </div>
349
+ <span class="feature-command-badge">/team</span>
350
+ </div>
351
+ <h3 class="feature-name">Team Velocity & Balance</h3>
352
+ <p class="feature-text">Team turnaround metrics without toxic vanity rankings. Review velocity, cycle times, and review load balancing to prevent engineering burnout.</p>
353
+ <ul class="feature-bullets">
354
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Review turnaround cycle times</li>
355
+ <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Workload distribution balance</li>
356
+ </ul>
357
+ </div>
358
+ </div>
359
+ </div>
360
+ </section>
361
+
362
+ <!-- Killer Features Section -->
363
+ <section class="killer-section" id="killer-tools">
364
+ <div class="container">
365
+ <div class="section-header">
366
+ <div class="section-tag">High-Impact Utilities</div>
367
+ <h2 class="section-title">Workflow Accelerators</h2>
368
+ <p class="section-desc">Designed to solve everyday engineering bottlenecks in seconds.</p>
369
+ </div>
370
+
371
+ <div class="killer-grid">
372
+ <div class="killer-card">
373
+ <h4 class="killer-card-title">
374
+ <svg width="18" height="18" viewBox="0 0 16 16" fill="var(--gh-blue)"><path d="M6.906.664a1.749 1.749 0 0 1 2.187 0l5.25 4.2c.415.332.657.835.657 1.367v7.019A1.75 1.75 0 0 1 13.25 15h-3.5a.75.75 0 0 1-.75-.75V9H7v5.25a.75.75 0 0 1-.75.75h-3.5A1.75 1.75 0 0 1 1 13.25V6.231c0-.531.242-1.034.657-1.366l5.25-4.2Zm1.25 1.171a.25.25 0 0 0-.312 0l-5.25 4.2a.25.25 0 0 0-.094.196v7.019c0 .138.112.25.25.25H5.5V8.25a.75.75 0 0 1 .75-.75h3.5a.75.75 0 0 1 .75.75v5.25h2.75a.25.25 0 0 0 .25-.25V6.23a.25.25 0 0 0-.094-.195Z"/></svg>
375
+ /home Cockpit
376
+ </h4>
377
+ <p class="killer-card-desc">Morning command center showing your active PRs, pending reviews, repo watchtower alerts, and rising ecosystem highlights.</p>
378
+ </div>
379
+
380
+ <div class="killer-card">
381
+ <h4 class="killer-card-title">
382
+ <svg width="18" height="18" viewBox="0 0 16 16" fill="var(--gh-purple)"><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.92 6.085h.001a.749.749 0 0 1 1.059-.062 1.488 1.488 0 0 1 .494 1.102c0 .546-.3.923-.627 1.258-.293.301-.597.613-.597 1.117a.75.75 0 0 1-1.5 0c0-.987.585-1.59 1.002-2.018.232-.238.472-.484.472-.757a.253.253 0 0 0-.083-.188.27.27 0 0 0-.174-.052c-.176 0-.31.092-.41.228a.75.75 0 0 1-1.135-.628ZM8 12.5a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z"/></svg>
383
+ /why Archaeology
384
+ </h4>
385
+ <p class="killer-card-desc">Trace any file and line change back through Commit -> Pull Request -> Originating Issue to answer why a piece of code exists.</p>
386
+ </div>
387
+
388
+ <div class="killer-card">
389
+ <h4 class="killer-card-title">
390
+ <svg width="18" height="18" viewBox="0 0 16 16" fill="var(--gh-green)"><path d="M6.5 1.75a.25.25 0 0 1 .25-.25h2.5a.25.25 0 0 1 .25.25V3h-3ZM11 3V1.75A1.75 1.75 0 0 0 9.25 0h-2.5A1.75 1.75 0 0 0 5 1.75V3H1.75C.784 3 0 3.784 0 4.75v8.5C0 14.216.784 15 1.75 15h12.5A1.75 1.75 0 0 0 16 13.25v-8.5A1.75 1.75 0 0 0 14.25 3Z"/></svg>
391
+ /connect Vault
392
+ </h4>
393
+ <p class="killer-card-desc">Store GitHub Personal Access Tokens safely with AES-256-GCM encryption. Public repos never require credentials.</p>
394
+ </div>
395
+
396
+ <div class="killer-card">
397
+ <h4 class="killer-card-title">
398
+ <svg width="18" height="18" viewBox="0 0 16 16" fill="var(--gh-amber)"><path d="M8 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm9 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0Zm-.25-6.25a.75.75 0 0 0-1.5 0v3.5a.75.75 0 0 0 1.5 0Z"/></svg>
399
+ /ask Engine
400
+ </h4>
401
+ <p class="killer-card-desc">Deterministic query helper to answer questions like pull requests waiting for review over 24 hours or frequently modified files.</p>
402
+ </div>
403
+ </div>
404
+ </div>
405
+ </section>
406
+
407
+ <!-- Architecture & Security -->
408
+ <section class="arch-section" id="architecture">
409
+ <div class="container">
410
+ <div class="section-header">
411
+ <div class="section-tag">Security & Infrastructure</div>
412
+ <h2 class="section-title">Zero-Trust Architecture</h2>
413
+ <p class="section-desc">Engineered for security-conscious teams, open-source communities, and enterprise organizations.</p>
414
+ </div>
415
+
416
+ <div class="arch-box">
417
+ <h3 style="font-size: 1.25rem; font-weight: 700; margin-bottom: 12px;">Data Isolation and Security Pipeline</h3>
418
+ <p style="color: var(--text-secondary); font-size: 0.95rem;">
419
+ DevPulse operates as an outbound-only Discord Gateway client with zero inbound open ports required. All token interactions are isolated per user and encrypted at rest.
420
+ </p>
421
+
422
+ <div class="arch-flow-grid">
423
+ <div class="arch-flow-step">
424
+ <span class="step-num">STAGE 01</span>
425
+ <h4 class="step-title">Discord Gateway</h4>
426
+ <p class="step-desc">Slash commands and button clicks received via authenticated Discord WebSocket Gateway v10.</p>
427
+ </div>
428
+
429
+ <div class="arch-flow-step">
430
+ <span class="step-num">STAGE 02</span>
431
+ <h4 class="step-title">AES-256-GCM Vault</h4>
432
+ <p class="step-desc">Personal Access Tokens decrypted ephemerally in-memory with unique initialization vectors.</p>
433
+ </div>
434
+
435
+ <div class="arch-flow-step">
436
+ <span class="step-num">STAGE 03</span>
437
+ <h4 class="step-title">GitHub API Engine</h4>
438
+ <p class="step-desc">Direct REST and GraphQL calls with rate-limiting protection, ETag caching, and response deduplication.</p>
439
+ </div>
440
+
441
+ <div class="arch-flow-step">
442
+ <span class="step-num">STAGE 04</span>
443
+ <h4 class="step-title">Multi-Tenant Store</h4>
444
+ <p class="step-desc">Multi-tenant server configs and alert routing persisted in Turso (libSQL) with zero token logging.</p>
445
+ </div>
446
+ </div>
447
+ </div>
448
+ </div>
449
+ </section>
450
+
451
+ <!-- Quick Start Walkthrough -->
452
+ <section class="install-section" id="quickstart">
453
+ <div class="container">
454
+ <div class="section-header">
455
+ <div class="section-tag">Self-Hosting & Setup</div>
456
+ <h2 class="section-title">Get Started in Under 3 Minutes</h2>
457
+ <p class="section-desc">Clone the repository, configure your Discord bot token, and launch DevPulse with Bun.</p>
458
+ </div>
459
+
460
+ <div class="terminal-box" style="max-width: 800px; margin: 0 auto;">
461
+ <div class="terminal-topbar">
462
+ <div class="window-dots">
463
+ <span class="window-dot dot-red"></span>
464
+ <span class="window-dot dot-yellow"></span>
465
+ <span class="window-dot dot-green"></span>
466
+ </div>
467
+ <span style="font-family: var(--font-mono); font-size: 0.8rem; color: var(--text-secondary);">bash β€’ terminal</span>
468
+ <button class="terminal-copy-btn" onclick="copyText('git clone [email protected]:husteno-o/git-discord-bot.git\ncd git-discord-bot\nbun install\ncp .env.example .env\nbun run start', this)" title="Copy all commands">
469
+ <svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor">
470
+ <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"/>
471
+ <path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"/>
472
+ </svg>
473
+ </button>
474
+ </div>
475
+ <div class="terminal-content">
476
+ <div class="terminal-comment"># 1. Clone repository from GitHub</div>
477
+ <div class="terminal-line">
478
+ <span class="terminal-cmd"><span style="color:#58a6ff">$</span> git clone [email protected]:husteno-o/git-discord-bot.git</span>
479
+ </div>
480
+
481
+ <div class="terminal-comment"># 2. Enter directory and install with Bun</div>
482
+ <div class="terminal-line">
483
+ <span class="terminal-cmd"><span style="color:#58a6ff">$</span> cd git-discord-bot &amp;&amp; bun install</span>
484
+ </div>
485
+
486
+ <div class="terminal-comment"># 3. Setup environment configuration</div>
487
+ <div class="terminal-line">
488
+ <span class="terminal-cmd"><span style="color:#58a6ff">$</span> cp .env.example .env</span>
489
+ </div>
490
+
491
+ <div class="terminal-comment"># 4. Run tests and launch DevPulse bot</div>
492
+ <div class="terminal-line">
493
+ <span class="terminal-cmd"><span style="color:#58a6ff">$</span> bun run test &amp;&amp; bun run start</span>
494
+ </div>
495
+ </div>
496
+ </div>
497
+
498
+ <!-- Cloudflare Pages Badge -->
499
+ <div style="text-align: center; margin-top: 40px;">
500
+ <p style="color: var(--text-secondary); font-size: 0.9rem; margin-bottom: 12px;">
501
+ Hosting this landing page on Cloudflare Pages:
502
+ </p>
503
+ <div style="display: inline-flex; align-items: center; gap: 8px; padding: 8px 16px; background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: 8px; font-family: var(--font-mono); font-size: 0.85rem; color: var(--gh-blue);">
504
+ <span>Deploy Output: <strong>apps/web/dist</strong> β€’ Build Command: <strong>bun run build:web</strong></span>
505
+ </div>
506
+ </div>
507
+ </div>
508
+ </section>
509
+
510
+ <!-- Footer -->
511
+ <footer class="footer">
512
+ <div class="container">
513
+ <div class="footer-grid">
514
+ <div>
515
+ <div class="brand-logo" style="margin-bottom: 8px;">
516
+ <div class="brand-icon-wrapper" style="width: 30px; height: 30px;">
517
+ <svg viewBox="0 0 16 16"><path d="M5 3.254V3.25v.004a.75.75 0 1 1 0-.004Zm1.5 0a2.25 2.25 0 1 0-3 2.122V8.75a2.25 2.25 0 0 0 1.5 2.122v.378a2.25 2.25 0 1 0 1.5 0v-.378a2.25 2.25 0 0 0 1.5-2.122V5.376A2.25 2.25 0 0 0 6.5 3.254Z"/></svg>
518
+ </div>
519
+ <span style="font-size: 1.1rem;">DevPulse</span>
520
+ </div>
521
+ <p class="footer-col-desc">
522
+ The GitHub Power-User Operating System for Discord. Never leave Discord for your daily GitHub workflow.
523
+ </p>
524
+ </div>
525
+
526
+ <div>
527
+ <h4 class="footer-col-title">Core Areas</h4>
528
+ <ul class="footer-col-links">
529
+ <li><a href="#simulator">/repo Intelligence</a></li>
530
+ <li><a href="#simulator">/pr Power Tools</a></li>
531
+ <li><a href="#simulator">/actions CI/CD</a></li>
532
+ <li><a href="#simulator">/investigate Trace</a></li>
533
+ <li><a href="#features">/security &amp; Leaks</a></li>
534
+ </ul>
535
+ </div>
536
+
537
+ <div>
538
+ <h4 class="footer-col-title">Resources</h4>
539
+ <ul class="footer-col-links">
540
+ <li><a href="https://github.com/husteno-o/git-discord-bot" target="_blank" rel="noopener noreferrer">GitHub Repository</a></li>
541
+ <li><a href="https://github.com/husteno-o/git-discord-bot/blob/master/README.md" target="_blank" rel="noopener noreferrer">Documentation</a></li>
542
+ <li><a href="https://github.com/husteno-o/git-discord-bot/issues" target="_blank" rel="noopener noreferrer">Issue Tracker</a></li>
543
+ <li><a href="https://discord.com/developers/docs" target="_blank" rel="noopener noreferrer">Discord Developer Portal</a></li>
544
+ </ul>
545
+ </div>
546
+
547
+ <div>
548
+ <h4 class="footer-col-title">Deployment</h4>
549
+ <ul class="footer-col-links">
550
+ <li><a href="https://pages.cloudflare.com" target="_blank" rel="noopener noreferrer">Cloudflare Pages</a></li>
551
+ <li><a href="#quickstart">Docker Setup</a></li>
552
+ <li><a href="#quickstart">Bun Runtime</a></li>
553
+ <li><a href="#architecture">Zero-Trust Vault</a></li>
554
+ </ul>
555
+ </div>
556
+ </div>
557
+
558
+ <div class="footer-bottom">
559
+ <div>
560
+ Repository: <a href="https://github.com/husteno-o/git-discord-bot" target="_blank" style="color: var(--gh-blue); text-decoration: none;">[email protected]:husteno-o/git-discord-bot.git</a>
561
+ </div>
562
+ <div>
563
+ Licensed under MIT. Open-source developer productivity platform.
564
+ </div>
565
+ </div>
566
+ </div>
567
+ </footer>
568
+
569
+ <script type="module" src="./app.js"></script>
570
+</body>
571
+</html>
0
572
β–Όapps/web/src/styles.css
+1149-0
1
+/* ==============================================================================
2
+ DevPulse - GitHub Power-User Discord Platform Theme
3
+ GitHub Dark High-End Developer Styling
4
+ ============================================================================== */
5
+
6
+:root {
7
+ --bg-canvas: #090d16;
8
+ --bg-canvas-subtle: #0d1117;
9
+ --bg-surface: #161b22;
10
+ --bg-surface-hover: #1c2128;
11
+ --bg-surface-active: #21262d;
12
+ --border-default: #30363d;
13
+ --border-muted: #21262d;
14
+ --border-glow: rgba(56, 139, 253, 0.4);
15
+
16
+ --text-primary: #f0f6fc;
17
+ --text-secondary: #8b949e;
18
+ --text-muted: #6e7681;
19
+
20
+ --gh-green: #2ea043;
21
+ --gh-green-hover: #3fb950;
22
+ --gh-green-subtle: rgba(46, 160, 67, 0.15);
23
+ --gh-green-border: rgba(46, 160, 67, 0.4);
24
+
25
+ --gh-blue: #58a6ff;
26
+ --gh-blue-subtle: rgba(88, 166, 255, 0.15);
27
+ --gh-blue-border: rgba(88, 166, 255, 0.4);
28
+
29
+ --gh-purple: #a371f7;
30
+ --gh-purple-subtle: rgba(163, 113, 247, 0.15);
31
+ --gh-purple-border: rgba(163, 113, 247, 0.4);
32
+
33
+ --gh-coral: #f85149;
34
+ --gh-coral-subtle: rgba(248, 81, 73, 0.15);
35
+ --gh-amber: #d29922;
36
+
37
+ --discord-blurple: #5865f2;
38
+ --discord-blurple-hover: #4752c4;
39
+ --discord-embed-bg: #2b2d31;
40
+ --discord-dark: #1e1f22;
41
+
42
+ --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial,
43
+ sans-serif;
44
+ --font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
45
+
46
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.5);
47
+ --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.6);
48
+ --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.8);
49
+ --shadow-glow-green: 0 0 30px rgba(46, 160, 67, 0.25);
50
+ --shadow-glow-blue: 0 0 30px rgba(88, 166, 255, 0.2);
51
+}
52
+
53
+* {
54
+ box-sizing: border-box;
55
+ margin: 0;
56
+ padding: 0;
57
+}
58
+
59
+html {
60
+ scroll-behavior: smooth;
61
+ color-scheme: dark;
62
+}
63
+
64
+body {
65
+ font-family: var(--font-sans);
66
+ background-color: var(--bg-canvas);
67
+ color: var(--text-primary);
68
+ line-height: 1.6;
69
+ overflow-x: hidden;
70
+ position: relative;
71
+ -webkit-font-smoothing: antialiased;
72
+}
73
+
74
+/* Background grid effect */
75
+.bg-grid {
76
+ position: fixed;
77
+ top: 0;
78
+ left: 0;
79
+ right: 0;
80
+ bottom: 0;
81
+ background-image: linear-gradient(to right, rgba(48, 54, 61, 0.1) 1px, transparent 1px),
82
+ linear-gradient(to bottom, rgba(48, 54, 61, 0.1) 1px, transparent 1px);
83
+ background-size: 40px 40px;
84
+ pointer-events: none;
85
+ z-index: -2;
86
+}
87
+
88
+/* Ambient glow spheres */
89
+.ambient-glow-1 {
90
+ position: fixed;
91
+ top: -100px;
92
+ left: 20%;
93
+ width: 600px;
94
+ height: 600px;
95
+ border-radius: 50%;
96
+ background: radial-gradient(circle, rgba(46, 160, 67, 0.12) 0%, rgba(13, 17, 23, 0) 70%);
97
+ filter: blur(80px);
98
+ pointer-events: none;
99
+ z-index: -1;
100
+ animation: floatGlow 14s ease-in-out infinite alternate;
101
+}
102
+
103
+.ambient-glow-2 {
104
+ position: fixed;
105
+ top: 400px;
106
+ right: 15%;
107
+ width: 500px;
108
+ height: 500px;
109
+ border-radius: 50%;
110
+ background: radial-gradient(circle, rgba(88, 166, 255, 0.1) 0%, rgba(13, 17, 23, 0) 70%);
111
+ filter: blur(80px);
112
+ pointer-events: none;
113
+ z-index: -1;
114
+ animation: floatGlow 18s ease-in-out infinite alternate-reverse;
115
+}
116
+
117
+@keyframes floatGlow {
118
+ 0% {
119
+ transform: translate(0, 0) scale(1);
120
+ }
121
+ 50% {
122
+ transform: translate(40px, -30px) scale(1.1);
123
+ }
124
+ 100% {
125
+ transform: translate(-30px, 40px) scale(0.95);
126
+ }
127
+}
128
+
129
+/* Container */
130
+.container {
131
+ max-width: 1200px;
132
+ margin: 0 auto;
133
+ padding: 0 24px;
134
+}
135
+
136
+/* Navigation */
137
+.navbar {
138
+ position: sticky;
139
+ top: 0;
140
+ z-index: 100;
141
+ background-color: rgba(13, 17, 23, 0.85);
142
+ backdrop-filter: blur(12px);
143
+ -webkit-backdrop-filter: blur(12px);
144
+ border-bottom: 1px solid var(--border-muted);
145
+ transition: border-color 0.2s ease;
146
+}
147
+
148
+.nav-container {
149
+ display: flex;
150
+ align-items: center;
151
+ justify-content: space-between;
152
+ height: 70px;
153
+}
154
+
155
+.brand-logo {
156
+ display: flex;
157
+ align-items: center;
158
+ gap: 12px;
159
+ text-decoration: none;
160
+ color: var(--text-primary);
161
+ font-weight: 700;
162
+ font-size: 1.25rem;
163
+ letter-spacing: -0.5px;
164
+}
165
+
166
+.brand-icon-wrapper {
167
+ position: relative;
168
+ display: flex;
169
+ align-items: center;
170
+ justify-content: center;
171
+ width: 38px;
172
+ height: 38px;
173
+ background: linear-gradient(135deg, #238636 0%, #1f6feb 100%);
174
+ border-radius: 8px;
175
+ box-shadow: 0 0 16px rgba(46, 160, 67, 0.4);
176
+}
177
+
178
+.brand-icon-wrapper svg {
179
+ width: 22px;
180
+ height: 22px;
181
+ fill: #ffffff;
182
+}
183
+
184
+.brand-text {
185
+ font-weight: 700;
186
+}
187
+
188
+.brand-tag {
189
+ font-size: 0.7rem;
190
+ text-transform: uppercase;
191
+ font-weight: 600;
192
+ padding: 2px 6px;
193
+ border-radius: 4px;
194
+ background: var(--gh-green-subtle);
195
+ color: var(--gh-green-hover);
196
+ border: 1px solid var(--gh-green-border);
197
+ margin-left: 4px;
198
+ letter-spacing: 0.5px;
199
+}
200
+
201
+.nav-links {
202
+ display: flex;
203
+ align-items: center;
204
+ gap: 28px;
205
+ list-style: none;
206
+}
207
+
208
+.nav-links a {
209
+ color: var(--text-secondary);
210
+ text-decoration: none;
211
+ font-size: 0.92rem;
212
+ font-weight: 500;
213
+ transition: color 0.2s ease;
214
+}
215
+
216
+.nav-links a:hover {
217
+ color: var(--text-primary);
218
+}
219
+
220
+.nav-actions {
221
+ display: flex;
222
+ align-items: center;
223
+ gap: 12px;
224
+}
225
+
226
+/* Buttons */
227
+.btn {
228
+ display: inline-flex;
229
+ align-items: center;
230
+ justify-content: center;
231
+ gap: 8px;
232
+ padding: 8px 16px;
233
+ border-radius: 6px;
234
+ font-size: 0.9rem;
235
+ font-weight: 600;
236
+ text-decoration: none;
237
+ cursor: pointer;
238
+ transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1);
239
+ border: 1px solid transparent;
240
+ font-family: inherit;
241
+ white-space: nowrap;
242
+}
243
+
244
+.btn-sm {
245
+ padding: 6px 12px;
246
+ font-size: 0.82rem;
247
+}
248
+
249
+.btn-lg {
250
+ padding: 12px 24px;
251
+ font-size: 1.05rem;
252
+}
253
+
254
+.btn-primary {
255
+ background-color: var(--gh-green);
256
+ color: #ffffff;
257
+ border-color: rgba(240, 246, 252, 0.1);
258
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15);
259
+}
260
+
261
+.btn-primary:hover {
262
+ background-color: var(--gh-green-hover);
263
+ box-shadow: var(--shadow-glow-green);
264
+ transform: translateY(-1px);
265
+}
266
+
267
+.btn-secondary {
268
+ background-color: var(--bg-surface);
269
+ color: var(--text-primary);
270
+ border-color: var(--border-default);
271
+}
272
+
273
+.btn-secondary:hover {
274
+ background-color: var(--bg-surface-hover);
275
+ border-color: var(--text-secondary);
276
+ transform: translateY(-1px);
277
+}
278
+
279
+.btn-discord {
280
+ background-color: var(--discord-blurple);
281
+ color: #ffffff;
282
+}
283
+
284
+.btn-discord:hover {
285
+ background-color: var(--discord-blurple-hover);
286
+ box-shadow: 0 0 20px rgba(88, 101, 242, 0.4);
287
+ transform: translateY(-1px);
288
+}
289
+
290
+.btn-github {
291
+ background-color: #21262d;
292
+ color: var(--text-primary);
293
+ border-color: var(--border-default);
294
+}
295
+
296
+.btn-github:hover {
297
+ background-color: #30363d;
298
+ border-color: #8b949e;
299
+}
300
+
301
+/* Mobile Toggle */
302
+.mobile-toggle {
303
+ display: none;
304
+ background: none;
305
+ border: none;
306
+ color: var(--text-primary);
307
+ cursor: pointer;
308
+ padding: 4px;
309
+}
310
+
311
+/* Hero Section */
312
+.hero-section {
313
+ padding: 90px 0 60px;
314
+ text-align: center;
315
+ position: relative;
316
+}
317
+
318
+.hero-pill {
319
+ display: inline-flex;
320
+ align-items: center;
321
+ gap: 8px;
322
+ padding: 6px 14px;
323
+ background: rgba(33, 38, 45, 0.8);
324
+ border: 1px solid var(--border-default);
325
+ border-radius: 9999px;
326
+ font-size: 0.82rem;
327
+ font-weight: 500;
328
+ color: var(--text-secondary);
329
+ margin-bottom: 24px;
330
+ backdrop-filter: blur(8px);
331
+}
332
+
333
+.pill-dot {
334
+ width: 8px;
335
+ height: 8px;
336
+ border-radius: 50%;
337
+ background-color: var(--gh-green);
338
+ box-shadow: 0 0 8px var(--gh-green);
339
+ animation: pulseDot 2s infinite;
340
+}
341
+
342
+@keyframes pulseDot {
343
+ 0% {
344
+ transform: scale(0.95);
345
+ opacity: 0.8;
346
+ }
347
+ 50% {
348
+ transform: scale(1.2);
349
+ opacity: 1;
350
+ }
351
+ 100% {
352
+ transform: scale(0.95);
353
+ opacity: 0.8;
354
+ }
355
+}
356
+
357
+.hero-title {
358
+ font-size: clamp(2.5rem, 6vw, 4.2rem);
359
+ font-weight: 800;
360
+ line-height: 1.15;
361
+ letter-spacing: -1.5px;
362
+ margin-bottom: 24px;
363
+ max-width: 900px;
364
+ margin-left: auto;
365
+ margin-right: auto;
366
+}
367
+
368
+.hero-title-gradient {
369
+ background: linear-gradient(135deg, #ffffff 30%, #58a6ff 70%, #a371f7 100%);
370
+ -webkit-background-clip: text;
371
+ -webkit-text-fill-color: transparent;
372
+}
373
+
374
+.hero-subtitle {
375
+ font-size: clamp(1.05rem, 2vw, 1.25rem);
376
+ color: var(--text-secondary);
377
+ max-width: 720px;
378
+ margin: 0 auto 36px;
379
+ font-weight: 400;
380
+ line-height: 1.6;
381
+}
382
+
383
+.hero-actions {
384
+ display: flex;
385
+ align-items: center;
386
+ justify-content: center;
387
+ gap: 16px;
388
+ flex-wrap: wrap;
389
+ margin-bottom: 32px;
390
+}
391
+
392
+.clone-pill {
393
+ display: inline-flex;
394
+ align-items: center;
395
+ background: var(--bg-surface);
396
+ border: 1px solid var(--border-default);
397
+ border-radius: 8px;
398
+ padding: 6px 12px;
399
+ font-family: var(--font-mono);
400
+ font-size: 0.85rem;
401
+ color: var(--gh-blue);
402
+ cursor: pointer;
403
+ transition: all 0.2s ease;
404
+}
405
+
406
+.clone-pill:hover {
407
+ border-color: var(--gh-blue);
408
+ background: var(--bg-surface-hover);
409
+}
410
+
411
+.clone-pill svg {
412
+ margin-right: 8px;
413
+ fill: var(--text-secondary);
414
+}
415
+
416
+.clone-btn-icon {
417
+ margin-left: 10px;
418
+ color: var(--text-muted);
419
+}
420
+
421
+/* Feature highlights banner */
422
+.hero-badges {
423
+ display: flex;
424
+ align-items: center;
425
+ justify-content: center;
426
+ gap: 24px;
427
+ flex-wrap: wrap;
428
+ padding-top: 20px;
429
+}
430
+
431
+.hero-badge-item {
432
+ display: flex;
433
+ align-items: center;
434
+ gap: 6px;
435
+ font-size: 0.85rem;
436
+ color: var(--text-muted);
437
+}
438
+
439
+.hero-badge-item svg {
440
+ width: 14px;
441
+ height: 14px;
442
+ fill: var(--gh-green);
443
+}
444
+
445
+/* ==============================================================================
446
+ Interactive Simulator Section
447
+ ============================================================================== */
448
+.simulator-section {
449
+ padding: 40px 0 80px;
450
+}
451
+
452
+.simulator-wrapper {
453
+ background: var(--bg-surface);
454
+ border: 1px solid var(--border-default);
455
+ border-radius: 12px;
456
+ box-shadow: var(--shadow-lg), 0 0 40px rgba(0, 0, 0, 0.4);
457
+ overflow: hidden;
458
+ max-width: 1050px;
459
+ margin: 0 auto;
460
+}
461
+
462
+.simulator-header {
463
+ display: flex;
464
+ align-items: center;
465
+ justify-content: space-between;
466
+ padding: 12px 20px;
467
+ background: var(--bg-canvas-subtle);
468
+ border-bottom: 1px solid var(--border-default);
469
+}
470
+
471
+.window-dots {
472
+ display: flex;
473
+ gap: 8px;
474
+}
475
+
476
+.window-dot {
477
+ width: 12px;
478
+ height: 12px;
479
+ border-radius: 50%;
480
+}
481
+
482
+.dot-red {
483
+ background-color: #ff5f56;
484
+}
485
+.dot-yellow {
486
+ background-color: #ffbd2e;
487
+}
488
+.dot-green {
489
+ background-color: #27c93f;
490
+}
491
+
492
+.simulator-title {
493
+ font-size: 0.85rem;
494
+ font-family: var(--font-mono);
495
+ color: var(--text-secondary);
496
+ display: flex;
497
+ align-items: center;
498
+ gap: 8px;
499
+}
500
+
501
+.simulator-tabs {
502
+ display: flex;
503
+ gap: 4px;
504
+ padding: 8px 16px;
505
+ background: var(--bg-surface);
506
+ border-bottom: 1px solid var(--border-muted);
507
+ overflow-x: auto;
508
+ scrollbar-width: thin;
509
+}
510
+
511
+.sim-tab-btn {
512
+ background: transparent;
513
+ border: 1px solid transparent;
514
+ color: var(--text-secondary);
515
+ padding: 8px 14px;
516
+ border-radius: 6px;
517
+ font-family: var(--font-mono);
518
+ font-size: 0.82rem;
519
+ cursor: pointer;
520
+ white-space: nowrap;
521
+ transition: all 0.15s ease;
522
+ display: flex;
523
+ align-items: center;
524
+ gap: 8px;
525
+}
526
+
527
+.sim-tab-btn:hover {
528
+ background: var(--bg-surface-hover);
529
+ color: var(--text-primary);
530
+}
531
+
532
+.sim-tab-btn.active {
533
+ background: var(--bg-surface-active);
534
+ color: var(--gh-blue);
535
+ border-color: var(--border-default);
536
+ font-weight: 600;
537
+}
538
+
539
+.simulator-body {
540
+ padding: 24px;
541
+ min-height: 440px;
542
+ background: var(--discord-dark);
543
+}
544
+
545
+/* Discord Simulated Message */
546
+.discord-message {
547
+ display: flex;
548
+ gap: 16px;
549
+ font-size: 0.95rem;
550
+}
551
+
552
+.discord-avatar {
553
+ width: 42px;
554
+ height: 42px;
555
+ border-radius: 50%;
556
+ background: linear-gradient(135deg, #238636 0%, #1f6feb 100%);
557
+ display: flex;
558
+ align-items: center;
559
+ justify-content: center;
560
+ flex-shrink: 0;
561
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
562
+}
563
+
564
+.discord-avatar svg {
565
+ width: 24px;
566
+ height: 24px;
567
+ fill: #ffffff;
568
+}
569
+
570
+.discord-content {
571
+ flex-grow: 1;
572
+}
573
+
574
+.discord-header {
575
+ display: flex;
576
+ align-items: center;
577
+ gap: 8px;
578
+ margin-bottom: 6px;
579
+}
580
+
581
+.bot-name {
582
+ font-weight: 600;
583
+ color: var(--text-primary);
584
+}
585
+
586
+.bot-tag {
587
+ background: var(--discord-blurple);
588
+ color: #ffffff;
589
+ font-size: 0.65rem;
590
+ font-weight: 700;
591
+ padding: 1px 4px;
592
+ border-radius: 3px;
593
+ text-transform: uppercase;
594
+}
595
+
596
+.message-time {
597
+ font-size: 0.75rem;
598
+ color: var(--text-muted);
599
+}
600
+
601
+.command-echo {
602
+ font-family: var(--font-mono);
603
+ font-size: 0.8rem;
604
+ color: var(--gh-blue);
605
+ margin-bottom: 8px;
606
+}
607
+
608
+/* Discord Embed */
609
+.discord-embed {
610
+ background: var(--discord-embed-bg);
611
+ border-left: 4px solid var(--gh-green);
612
+ border-radius: 4px;
613
+ padding: 16px;
614
+ max-width: 650px;
615
+ box-shadow: var(--shadow-sm);
616
+ transition: border-color 0.2s ease;
617
+}
618
+
619
+.embed-author {
620
+ display: flex;
621
+ align-items: center;
622
+ gap: 8px;
623
+ font-size: 0.8rem;
624
+ font-weight: 600;
625
+ color: var(--text-secondary);
626
+ margin-bottom: 6px;
627
+}
628
+
629
+.embed-title {
630
+ font-size: 1.05rem;
631
+ font-weight: 700;
632
+ color: var(--text-primary);
633
+ margin-bottom: 8px;
634
+ display: flex;
635
+ align-items: center;
636
+ gap: 8px;
637
+}
638
+
639
+.embed-desc {
640
+ font-size: 0.88rem;
641
+ color: var(--text-secondary);
642
+ margin-bottom: 14px;
643
+ white-space: pre-line;
644
+}
645
+
646
+.embed-grid {
647
+ display: grid;
648
+ grid-template-columns: repeat(2, 1fr);
649
+ gap: 12px;
650
+ margin-bottom: 14px;
651
+}
652
+
653
+.embed-field-name {
654
+ font-size: 0.75rem;
655
+ text-transform: uppercase;
656
+ letter-spacing: 0.5px;
657
+ color: var(--text-muted);
658
+ font-weight: 700;
659
+ margin-bottom: 2px;
660
+}
661
+
662
+.embed-field-value {
663
+ font-size: 0.9rem;
664
+ color: var(--text-primary);
665
+ font-family: var(--font-mono);
666
+}
667
+
668
+.embed-code-block {
669
+ background: #111214;
670
+ border-radius: 4px;
671
+ padding: 10px 12px;
672
+ font-family: var(--font-mono);
673
+ font-size: 0.82rem;
674
+ color: #dbdee1;
675
+ overflow-x: auto;
676
+ margin: 10px 0;
677
+ border: 1px solid rgba(255, 255, 255, 0.05);
678
+ line-height: 1.45;
679
+}
680
+
681
+.discord-action-row {
682
+ display: flex;
683
+ gap: 8px;
684
+ margin-top: 14px;
685
+ flex-wrap: wrap;
686
+}
687
+
688
+.discord-btn {
689
+ display: inline-flex;
690
+ align-items: center;
691
+ gap: 6px;
692
+ background: #4e5058;
693
+ color: #ffffff;
694
+ border: none;
695
+ padding: 6px 14px;
696
+ border-radius: 4px;
697
+ font-size: 0.82rem;
698
+ font-weight: 600;
699
+ cursor: pointer;
700
+ transition: all 0.15s ease;
701
+ font-family: inherit;
702
+}
703
+
704
+.discord-btn:hover {
705
+ background: #6d6f78;
706
+}
707
+
708
+.discord-btn-primary {
709
+ background: var(--discord-blurple);
710
+}
711
+.discord-btn-primary:hover {
712
+ background: var(--discord-blurple-hover);
713
+}
714
+
715
+.discord-btn-success {
716
+ background: var(--gh-green);
717
+}
718
+.discord-btn-success:hover {
719
+ background: var(--gh-green-hover);
720
+}
721
+
722
+.discord-btn-danger {
723
+ background: #da373c;
724
+}
725
+.discord-btn-danger:hover {
726
+ background: #a1282c;
727
+}
728
+
729
+.discord-btn-disabled {
730
+ opacity: 0.5;
731
+ cursor: not-allowed;
732
+}
733
+
734
+/* Status Badges inside simulator */
735
+.status-tag {
736
+ display: inline-flex;
737
+ align-items: center;
738
+ gap: 4px;
739
+ padding: 2px 8px;
740
+ border-radius: 12px;
741
+ font-size: 0.75rem;
742
+ font-weight: 600;
743
+}
744
+
745
+.status-tag-green {
746
+ background: var(--gh-green-subtle);
747
+ color: var(--gh-green-hover);
748
+ border: 1px solid var(--gh-green-border);
749
+}
750
+
751
+.status-tag-blue {
752
+ background: var(--gh-blue-subtle);
753
+ color: var(--gh-blue);
754
+ border: 1px solid var(--gh-blue-border);
755
+}
756
+
757
+.status-tag-purple {
758
+ background: var(--gh-purple-subtle);
759
+ color: var(--gh-purple);
760
+ border: 1px solid var(--gh-purple-border);
761
+}
762
+
763
+/* ==============================================================================
764
+ 12 Core Features Section
765
+ ============================================================================== */
766
+.features-section {
767
+ padding: 80px 0;
768
+ position: relative;
769
+}
770
+
771
+.section-header {
772
+ text-align: center;
773
+ max-width: 700px;
774
+ margin: 0 auto 50px;
775
+}
776
+
777
+.section-tag {
778
+ font-family: var(--font-mono);
779
+ font-size: 0.8rem;
780
+ color: var(--gh-green);
781
+ text-transform: uppercase;
782
+ letter-spacing: 1px;
783
+ font-weight: 600;
784
+ margin-bottom: 8px;
785
+}
786
+
787
+.section-title {
788
+ font-size: clamp(2rem, 4vw, 2.75rem);
789
+ font-weight: 800;
790
+ letter-spacing: -1px;
791
+ margin-bottom: 16px;
792
+}
793
+
794
+.section-desc {
795
+ color: var(--text-secondary);
796
+ font-size: 1.05rem;
797
+}
798
+
799
+.features-grid {
800
+ display: grid;
801
+ grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
802
+ gap: 24px;
803
+}
804
+
805
+.feature-card {
806
+ background: var(--bg-surface);
807
+ border: 1px solid var(--border-default);
808
+ border-radius: 10px;
809
+ padding: 24px;
810
+ transition: all 0.25s cubic-bezier(0.16, 1, 0.3, 1);
811
+ position: relative;
812
+ overflow: hidden;
813
+ display: flex;
814
+ flex-direction: column;
815
+}
816
+
817
+.feature-card::before {
818
+ content: "";
819
+ position: absolute;
820
+ top: 0;
821
+ left: 0;
822
+ right: 0;
823
+ height: 2px;
824
+ background: linear-gradient(90deg, transparent, var(--border-glow), transparent);
825
+ opacity: 0;
826
+ transition: opacity 0.3s ease;
827
+}
828
+
829
+.feature-card:hover {
830
+ border-color: var(--border-glow);
831
+ transform: translateY(-4px);
832
+ box-shadow: var(--shadow-md);
833
+}
834
+
835
+.feature-card:hover::before {
836
+ opacity: 1;
837
+}
838
+
839
+.feature-top {
840
+ display: flex;
841
+ align-items: center;
842
+ justify-content: space-between;
843
+ margin-bottom: 16px;
844
+}
845
+
846
+.feature-icon-box {
847
+ width: 44px;
848
+ height: 44px;
849
+ border-radius: 8px;
850
+ background: var(--bg-surface-active);
851
+ border: 1px solid var(--border-muted);
852
+ display: flex;
853
+ align-items: center;
854
+ justify-content: center;
855
+}
856
+
857
+.feature-icon-box svg {
858
+ width: 22px;
859
+ height: 22px;
860
+ fill: var(--gh-blue);
861
+}
862
+
863
+.feature-command-badge {
864
+ font-family: var(--font-mono);
865
+ font-size: 0.78rem;
866
+ padding: 3px 8px;
867
+ background: var(--bg-canvas);
868
+ border: 1px solid var(--border-muted);
869
+ border-radius: 6px;
870
+ color: var(--gh-green);
871
+ font-weight: 600;
872
+}
873
+
874
+.feature-name {
875
+ font-size: 1.2rem;
876
+ font-weight: 700;
877
+ margin-bottom: 10px;
878
+ color: var(--text-primary);
879
+}
880
+
881
+.feature-text {
882
+ font-size: 0.92rem;
883
+ color: var(--text-secondary);
884
+ line-height: 1.55;
885
+ margin-bottom: 16px;
886
+ flex-grow: 1;
887
+}
888
+
889
+.feature-bullets {
890
+ list-style: none;
891
+ font-size: 0.84rem;
892
+ color: var(--text-muted);
893
+ display: flex;
894
+ flex-direction: column;
895
+ gap: 6px;
896
+}
897
+
898
+.feature-bullets li {
899
+ display: flex;
900
+ align-items: flex-start;
901
+ gap: 8px;
902
+}
903
+
904
+.feature-bullets li svg {
905
+ width: 14px;
906
+ height: 14px;
907
+ fill: var(--gh-blue);
908
+ flex-shrink: 0;
909
+ margin-top: 3px;
910
+}
911
+
912
+/* ==============================================================================
913
+ Killer Feature Highlights (Home, Connect, Why, Ask)
914
+ ============================================================================== */
915
+.killer-section {
916
+ padding: 80px 0;
917
+ background: linear-gradient(180deg, var(--bg-canvas) 0%, var(--bg-canvas-subtle) 100%);
918
+ border-top: 1px solid var(--border-muted);
919
+ border-bottom: 1px solid var(--border-muted);
920
+}
921
+
922
+.killer-grid {
923
+ display: grid;
924
+ grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
925
+ gap: 20px;
926
+}
927
+
928
+.killer-card {
929
+ background: var(--bg-surface);
930
+ border: 1px solid var(--border-default);
931
+ border-radius: 8px;
932
+ padding: 20px;
933
+}
934
+
935
+.killer-card-title {
936
+ font-size: 1.1rem;
937
+ font-weight: 700;
938
+ margin-bottom: 8px;
939
+ display: flex;
940
+ align-items: center;
941
+ gap: 8px;
942
+ color: var(--text-primary);
943
+}
944
+
945
+.killer-card-desc {
946
+ font-size: 0.88rem;
947
+ color: var(--text-secondary);
948
+ line-height: 1.5;
949
+}
950
+
951
+/* ==============================================================================
952
+ Architecture & Security
953
+ ============================================================================== */
954
+.arch-section {
955
+ padding: 80px 0;
956
+}
957
+
958
+.arch-box {
959
+ background: var(--bg-surface);
960
+ border: 1px solid var(--border-default);
961
+ border-radius: 12px;
962
+ padding: 36px;
963
+ margin-bottom: 40px;
964
+}
965
+
966
+.arch-flow-grid {
967
+ display: grid;
968
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
969
+ gap: 20px;
970
+ margin-top: 28px;
971
+}
972
+
973
+.arch-flow-step {
974
+ background: var(--bg-canvas);
975
+ border: 1px solid var(--border-muted);
976
+ border-radius: 8px;
977
+ padding: 16px;
978
+ position: relative;
979
+}
980
+
981
+.step-num {
982
+ display: inline-block;
983
+ font-family: var(--font-mono);
984
+ font-size: 0.75rem;
985
+ background: var(--gh-blue-subtle);
986
+ color: var(--gh-blue);
987
+ border: 1px solid var(--gh-blue-border);
988
+ border-radius: 4px;
989
+ padding: 2px 6px;
990
+ margin-bottom: 8px;
991
+}
992
+
993
+.step-title {
994
+ font-size: 0.98rem;
995
+ font-weight: 700;
996
+ margin-bottom: 6px;
997
+}
998
+
999
+.step-desc {
1000
+ font-size: 0.84rem;
1001
+ color: var(--text-secondary);
1002
+}
1003
+
1004
+/* Quick Start Terminal Walkthrough */
1005
+.install-section {
1006
+ padding: 60px 0 90px;
1007
+}
1008
+
1009
+.terminal-box {
1010
+ background: #0d1117;
1011
+ border: 1px solid var(--border-default);
1012
+ border-radius: 8px;
1013
+ overflow: hidden;
1014
+ box-shadow: var(--shadow-md);
1015
+ margin-top: 24px;
1016
+}
1017
+
1018
+.terminal-topbar {
1019
+ display: flex;
1020
+ align-items: center;
1021
+ justify-content: space-between;
1022
+ padding: 10px 16px;
1023
+ background: #161b22;
1024
+ border-bottom: 1px solid var(--border-default);
1025
+}
1026
+
1027
+.terminal-content {
1028
+ padding: 20px;
1029
+ font-family: var(--font-mono);
1030
+ font-size: 0.9rem;
1031
+ line-height: 1.7;
1032
+}
1033
+
1034
+.terminal-line {
1035
+ display: flex;
1036
+ align-items: center;
1037
+ justify-content: space-between;
1038
+ margin-bottom: 12px;
1039
+}
1040
+
1041
+.terminal-cmd {
1042
+ color: var(--text-primary);
1043
+}
1044
+
1045
+.terminal-comment {
1046
+ color: var(--text-muted);
1047
+ font-style: italic;
1048
+ font-size: 0.82rem;
1049
+}
1050
+
1051
+.terminal-copy-btn {
1052
+ background: transparent;
1053
+ border: none;
1054
+ color: var(--text-muted);
1055
+ cursor: pointer;
1056
+ padding: 4px;
1057
+ border-radius: 4px;
1058
+ transition: color 0.15s ease;
1059
+}
1060
+
1061
+.terminal-copy-btn:hover {
1062
+ color: var(--text-primary);
1063
+ background: var(--bg-surface-active);
1064
+}
1065
+
1066
+/* Footer */
1067
+.footer {
1068
+ border-top: 1px solid var(--border-muted);
1069
+ background: var(--bg-canvas-subtle);
1070
+ padding: 60px 0 30px;
1071
+}
1072
+
1073
+.footer-grid {
1074
+ display: grid;
1075
+ grid-template-columns: 2fr 1fr 1fr 1fr;
1076
+ gap: 40px;
1077
+ margin-bottom: 40px;
1078
+}
1079
+
1080
+.footer-col-desc {
1081
+ color: var(--text-secondary);
1082
+ font-size: 0.88rem;
1083
+ margin-top: 12px;
1084
+ max-width: 320px;
1085
+}
1086
+
1087
+.footer-col-title {
1088
+ font-size: 0.9rem;
1089
+ font-weight: 700;
1090
+ text-transform: uppercase;
1091
+ letter-spacing: 0.5px;
1092
+ color: var(--text-primary);
1093
+ margin-bottom: 16px;
1094
+}
1095
+
1096
+.footer-col-links {
1097
+ list-style: none;
1098
+ display: flex;
1099
+ flex-direction: column;
1100
+ gap: 10px;
1101
+}
1102
+
1103
+.footer-col-links a {
1104
+ color: var(--text-secondary);
1105
+ text-decoration: none;
1106
+ font-size: 0.88rem;
1107
+ transition: color 0.15s ease;
1108
+}
1109
+
1110
+.footer-col-links a:hover {
1111
+ color: var(--gh-blue);
1112
+}
1113
+
1114
+.footer-bottom {
1115
+ padding-top: 24px;
1116
+ border-top: 1px solid var(--border-muted);
1117
+ display: flex;
1118
+ align-items: center;
1119
+ justify-content: space-between;
1120
+ font-size: 0.82rem;
1121
+ color: var(--text-muted);
1122
+ flex-wrap: wrap;
1123
+ gap: 12px;
1124
+}
1125
+
1126
+/* Responsive */
1127
+@media (max-width: 900px) {
1128
+ .nav-links {
1129
+ display: none;
1130
+ }
1131
+ .mobile-toggle {
1132
+ display: block;
1133
+ }
1134
+ .footer-grid {
1135
+ grid-template-columns: 1fr 1fr;
1136
+ }
1137
+}
1138
+
1139
+@media (max-width: 600px) {
1140
+ .features-grid {
1141
+ grid-template-columns: 1fr;
1142
+ }
1143
+ .footer-grid {
1144
+ grid-template-columns: 1fr;
1145
+ }
1146
+ .embed-grid {
1147
+ grid-template-columns: 1fr;
1148
+ }
1149
+}
0
1150
β–Όapps/web/tsconfig.json
+10-0
1
+{
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "rootDir": "./src",
5
+ "outDir": "./dist",
6
+ "types": ["bun-types"],
7
+ "lib": ["DOM", "DOM.Iterable", "ESNext"]
8
+ },
9
+ "include": ["src/**/*"]
10
+}
0
11
β–Όpackage.json
+3-2
17
17
"start:bot": "bun run --filter @devpulse/bot start",
18
18
"start:api": "bun run --filter @devpulse/api start",
19
19
"dev:bot": "bun run --filter @devpulse/bot dev",
20
- "dev:api": "bun run --filter @devpulse/api dev",
21
20
"db:generate": "bun run --filter @devpulse/database db:generate",
22
21
"db:migrate": "bun run --filter @devpulse/database db:migrate",
23
- "db:push": "bun run --filter @devpulse/database db:push"
22
+ "db:push": "bun run --filter @devpulse/database db:push",
23
+ "build:web": "bun run --filter @devpulse/web build",
24
+ "preview:web": "bun run --filter @devpulse/web preview"
24
25
},
25
26
"devDependencies": {
26
27
"@biomejs/biome": "1.9.4",
27
28