Compare commits
4 Commits
6fa0512688
...
d27cfb3e1d
| Author | SHA1 | Date | |
|---|---|---|---|
| d27cfb3e1d | |||
| 189362e78d | |||
| 488c63236c | |||
| a2a11b4850 |
+464
@@ -0,0 +1,464 @@
|
|||||||
|
# Aura Agentic AI Cloud — MASTER.md
|
||||||
|
> Single source of truth for the entire infrastructure.
|
||||||
|
> **Last updated:** 2026-05-02 | **VPS:** root@195.35.7.154
|
||||||
|
> ⚠ Credentials are referenced by location only — never pasted here.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. VPS
|
||||||
|
|
||||||
|
| Field | Value |
|
||||||
|
|-------|-------|
|
||||||
|
| Provider | Hostinger KVM 2 |
|
||||||
|
| Hostname | srv1540635.hstgr.cloud |
|
||||||
|
| IP | 195.35.7.154 |
|
||||||
|
| OS | Ubuntu 24.04.4 LTS |
|
||||||
|
| Kernel | 6.8.0-110-generic x86-64 |
|
||||||
|
| CPU | 2× vCPU (AMD EPYC, KVM) |
|
||||||
|
| RAM | 7.8 GB (4.2 GB used) |
|
||||||
|
| Disk | 96 GB SSD (36 GB used · 61 GB free · 38%) |
|
||||||
|
| Swap | 4 GB (256 KB used) |
|
||||||
|
| SSH Key | C:\Users\Masud\.ssh\id_ed25519 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Live Services & URLs
|
||||||
|
|
||||||
|
### Coolify Services
|
||||||
|
|
||||||
|
| UUID | Service | URL | Status |
|
||||||
|
|------|---------|-----|--------|
|
||||||
|
| `dhcia3tgcvwmwwvexznjw9gr` | OpenClaw (Primary Agent) | https://agent.auraajenticai.cloud | ✅ Healthy |
|
||||||
|
| `m10jif2sbykx4hd33qf97hc6` | OpenClaw (Secondary / App) | https://app.auraajenticai.cloud | ✅ Healthy |
|
||||||
|
| `j9pqq74tuik1oqd5runx5ncb` | n8n + PostgreSQL + Task Runners | https://n8n.auraajenticai.cloud | ✅ Healthy |
|
||||||
|
| `oqwgsn2lcv3hsk13c6ayj8du` | Gitea + PostgreSQL | https://git.auraajenticai.cloud | ✅ Healthy |
|
||||||
|
|
||||||
|
### Coolify Applications
|
||||||
|
|
||||||
|
| UUID | App | URL | Commit | Status |
|
||||||
|
|------|-----|-----|--------|--------|
|
||||||
|
| `q2kkhvkrpdm6ukj20gv69tuk` | Public Site | https://auraajenticai.cloud | a2a11b4 | ⚠ Pending pull (demo URLs commit not yet applied via Coolify) |
|
||||||
|
| `g5ehpyu7i1azk7f1sv1bhctz` | Central Auth | https://auth.auraajenticai.cloud | 923435bf | ✅ Up |
|
||||||
|
| `m43q7n7vlttrzyxy5v2hkaig` | API Gateway | https://api.auraajenticai.cloud | 8c2045a7 | ✅ Up |
|
||||||
|
| `rdqk1mqe0k8fifs64d7jrzfi` | Client Portal | https://client.auraajenticai.cloud | 03a90610 | ✅ Up |
|
||||||
|
| `j8xnv56xhx6wiaeal2bfiktm` | Billing | https://billing.auraajenticai.cloud | fd9aa384 | ✅ Up |
|
||||||
|
| `zu9kxa9iung19q003ybvcdj3` | Owner Dashboard | https://aura.auraajenticai.cloud | 2b652dba | ✅ Up |
|
||||||
|
| `m6fnc3kfy72tf77anuv4o2f4` | [Internal — UUID subdomain] | https://m6fnc3kfy72tf77anuv4o2f4.auraajenticai.cloud | 3df7af00 | ✅ Up |
|
||||||
|
| `rul16lgnv650ic5kv5wgd51h` | [Staging — no FQDN] | — | 03a90610 | — |
|
||||||
|
| `y22x4z5sxh3854tbmiv98s2j` | [Staging — no FQDN] | — | 03a90610 | — |
|
||||||
|
| `z24up798jcmaf4biwshx2kv5` | [Staging — no FQDN] | — | — | — |
|
||||||
|
|
||||||
|
### Coolify System
|
||||||
|
|
||||||
|
| Service | URL |
|
||||||
|
|---------|-----|
|
||||||
|
| Coolify Dashboard | https://coolify.auraajenticai.cloud (port 8000 local) |
|
||||||
|
| Traefik Dashboard | http://195.35.7.154:8080/dashboard/ ⚠ publicly accessible |
|
||||||
|
| Coolify Version | 4.0.0-beta.473 (Laravel 12.55.1) |
|
||||||
|
| Traefik Version | v3.6 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Complete Tech Stack
|
||||||
|
|
||||||
|
### Infrastructure
|
||||||
|
- **Reverse Proxy:** Traefik v3.6 (HTTP :80 → HTTPS :443, Let's Encrypt cert resolver)
|
||||||
|
- **Orchestration:** Coolify 4.0.0-beta.473 (self-hosted)
|
||||||
|
- **Git:** Gitea v1.26.0 (SSH :22222, HTTP git.auraajenticai.cloud)
|
||||||
|
- **Containers:** Docker + Docker Compose
|
||||||
|
- **OS:** Ubuntu 24.04.4 LTS
|
||||||
|
|
||||||
|
### AI / Agents
|
||||||
|
- **Agent Runtime:** OpenClaw v2026.2.6
|
||||||
|
- **Primary Model:** `openrouter/anthropic/claude-sonnet-4.5`
|
||||||
|
- **AI Provider:** OpenRouter (key in Coolify .env)
|
||||||
|
- **Additional Providers:** Google Gemini (GEMINI_API_KEY set), Groq (GROQ_API_KEY set)
|
||||||
|
- **Channels:** Telegram (@tradingbanglaajentic_bot — long-polling)
|
||||||
|
- **Agent Tools:** read, edit, write, exec, browser, canvas, nodes, cron, message, sessions, web_search, memory
|
||||||
|
|
||||||
|
### Automation
|
||||||
|
- **n8n:** v2.10.2 + Task Runners 2.10.2
|
||||||
|
- **Webhooks:** https://n8n.auraajenticai.cloud/webhook/*
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
- **Public Site:** React 18 + Babel Standalone (CDN, no build step)
|
||||||
|
- **Dashboard/Apps:** SvelteKit 2 + Svelte 5 runes + Tailwind CSS + Vite
|
||||||
|
- **Fonts:** Geist, Geist Mono, Instrument Serif (Google Fonts)
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
- **Auth Service:** Hono + Drizzle ORM + JWT + bcrypt (SvelteKit adapter-node)
|
||||||
|
- **API:** Node.js / Hono
|
||||||
|
- **Language:** TypeScript throughout
|
||||||
|
|
||||||
|
### Databases
|
||||||
|
|
||||||
|
| DB | Container | Engine | Database Name | Network IP |
|
||||||
|
|----|-----------|--------|---------------|------------|
|
||||||
|
| Auth/Main | `ernix50nvuq9ur9jy8na8tgr` | Supabase Postgres 17.4 | `aura_auth` | 10.0.1.7:5432 |
|
||||||
|
| n8n | `postgresql-j9pqq74tuik1oqd5runx5ncb` | Postgres 16-alpine | `n8n` | internal |
|
||||||
|
| Gitea | `postgresql-oqwgsn2lcv3hsk13c6ayj8du` | Postgres 16-alpine | `gitea` | internal |
|
||||||
|
| Coolify | `coolify-db` | Postgres 15-alpine | `coolify` | internal |
|
||||||
|
| Document | `b3bhfd7bocb4pm36uv36rebq` | MongoDB 7 | *(various)* | :27017 |
|
||||||
|
| Cache | `coolify-redis` | Redis 7-alpine | — | internal |
|
||||||
|
|
||||||
|
### aura_auth DB Schema
|
||||||
|
Tables: `users`, `sessions`, `api_keys`, `audit_logs`, `clients`, `projects`, `skills`, `invoices`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. OpenClaw Configuration (Primary — `dhcia3tgcvwmwwvexznjw9gr`)
|
||||||
|
|
||||||
|
```
|
||||||
|
AI Provider: OpenRouter
|
||||||
|
Primary Model: openrouter/anthropic/claude-sonnet-4.5
|
||||||
|
Secondary Model: anthropic/claude-3.5-haiku (env var, secondary/fast not in schema)
|
||||||
|
Fast Model: anthropic/claude-3-haiku (env var)
|
||||||
|
Gateway: ws://127.0.0.1:18789 (loopback, behind nginx on :8080)
|
||||||
|
Auth mode: token (OPENCLAW_GATEWAY_TOKEN)
|
||||||
|
nginx auth: SERVICE_USER_OPENCLAW / SERVICE_PASSWORD_OPENCLAW
|
||||||
|
```
|
||||||
|
|
||||||
|
### Telegram Channel
|
||||||
|
```
|
||||||
|
Bot username: @tradingbanglaajentic_bot
|
||||||
|
Bot ID: 8736690733
|
||||||
|
Mode: long-polling (no webhook URL set)
|
||||||
|
Status: enabled, configured, running
|
||||||
|
Channel name: default
|
||||||
|
Token env: TELEGRAM_BOT_TOKEN (in Coolify service .env)
|
||||||
|
```
|
||||||
|
> To test: send any message to @tradingbanglaajentic_bot on Telegram.
|
||||||
|
> OpenClaw routes it to the main agent session → claude-sonnet-4.5 → reply back.
|
||||||
|
|
||||||
|
### Workspace Files
|
||||||
|
Located at: `/var/lib/docker/volumes/dhcia3tgcvwmwwvexznjw9gr_openclaw-data/_data/workspace/`
|
||||||
|
|
||||||
|
| File | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| AGENTS.md | Agent routing rules and capabilities |
|
||||||
|
| BOOTSTRAP.md | Startup context injected every session |
|
||||||
|
| HEARTBEAT.md | Scheduled check-in instructions |
|
||||||
|
| IDENTITY.md | Agent persona and identity rules |
|
||||||
|
| SOUL.md | Core values and behavioral constraints |
|
||||||
|
| TOOLS.md | Available tool descriptions |
|
||||||
|
| USER.md | User (Khondokar) profile and preferences |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. n8n Workflows
|
||||||
|
|
||||||
|
URL: https://n8n.auraajenticai.cloud
|
||||||
|
Contact webhook: `POST https://n8n.auraajenticai.cloud/webhook/contact`
|
||||||
|
|
||||||
|
| Workflow ID | Name |
|
||||||
|
|-------------|------|
|
||||||
|
| `j2JZuCcx38n6hFUa` | skill-code-review |
|
||||||
|
| `ICKS1V8j0rfFRCAM` | skill-analyze |
|
||||||
|
| `tza1cNW0fCZhMd63` | skill-draft-email |
|
||||||
|
| `1FtaniVPKRBKNDwX` | invoice-overdue-checker |
|
||||||
|
| `MeuMN9zV0m2SlPeV` | skill-summarize |
|
||||||
|
| `l2CkZKPgnSyt3Nvt` | Generate AI viral videos (NanoBanana + VEO3 → Blotato) |
|
||||||
|
| `zLqHh5sJ6rT7lyGU` | new-client-deployment |
|
||||||
|
| `sX0KPnr4c0Zh138d` | contact-form |
|
||||||
|
| `8kjRU6YNvtJpcpTD` | client-onboarding |
|
||||||
|
| `m4AB1XlfpvgmNmLF` | api-usage-weekly-report |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Gitea Repositories
|
||||||
|
|
||||||
|
Host: https://git.auraajenticai.cloud
|
||||||
|
User: `khondokar`
|
||||||
|
Token location: `C:\Users\Masud\.claude\projects\C--Users-Masud-aura\memory\project_aura_infrastructure.md`
|
||||||
|
|
||||||
|
| Repo | URL | Last Updated |
|
||||||
|
|------|-----|-------------|
|
||||||
|
| khondokar/auraajenticai-main | git.auraajenticai.cloud/khondokar/auraajenticai-main | 2026-04-27 |
|
||||||
|
|
||||||
|
### GitHub Mirrors (github.com/khondokartowsif171)
|
||||||
|
|
||||||
|
| Repo | GitHub URL | Notes |
|
||||||
|
|------|-----------|-------|
|
||||||
|
| auraajenticai-main | github.com/khondokartowsif171/auraajenticai-main | Main site — latest commit a2a11b4 (demo URLs) |
|
||||||
|
| demo-autostudio-ecomercewebsite | github.com/khondokartowsif171/demo-autostudio-ecomercewebsite | Vite/React ecommerce |
|
||||||
|
| demo-agenticai-website | github.com/khondokartowsif171/demo-agenticai-website | Static HTML portfolio |
|
||||||
|
| demo-cryptotradeanalysis-website | github.com/khondokartowsif171/demo-cryptotradeanalysis-website | React crypto dashboard |
|
||||||
|
| demo-ea-dashboard | github.com/khondokartowsif171/demo-ea-dashboard | Static HTML XAUUSD analyzer |
|
||||||
|
| demo-portfolio-website | github.com/khondokartowsif171/demo-portfolio-website | Vite/React portfolio |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Important File Paths
|
||||||
|
|
||||||
|
### On VPS (root@195.35.7.154)
|
||||||
|
|
||||||
|
```
|
||||||
|
/docs/MASTER.md ← this file
|
||||||
|
|
||||||
|
# Coolify data root
|
||||||
|
/data/coolify/applications/{uuid}/ ← per-app: .env + docker-compose.yaml
|
||||||
|
/data/coolify/services/{uuid}/ ← per-service: .env + docker-compose.yaml
|
||||||
|
/data/coolify/proxy/ ← Traefik dynamic config
|
||||||
|
/data/coolify/ssh/ ← SSH keys for deployments
|
||||||
|
|
||||||
|
# OpenClaw Primary (dhcia3tgcvwmwwvexznjw9gr)
|
||||||
|
/var/lib/docker/volumes/dhcia3tgcvwmwwvexznjw9gr_openclaw-data/_data/
|
||||||
|
.openclaw/openclaw.json ← main config (auto-managed by entrypoint)
|
||||||
|
.openclaw/openclaw.json.bak ← backup (up to 4 kept)
|
||||||
|
.openclaw/credentials/ ← API keys/tokens (never edit directly)
|
||||||
|
.openclaw/agents/main/sessions/sessions.json ← conversation history
|
||||||
|
workspace/ ← agent workspace (AGENTS.md, SOUL.md, etc.)
|
||||||
|
|
||||||
|
# Service .env files (credentials)
|
||||||
|
/data/coolify/services/dhcia3tgcvwmwwvexznjw9gr/.env ← OpenClaw primary
|
||||||
|
/data/coolify/services/m10jif2sbykx4hd33qf97hc6/.env ← OpenClaw secondary
|
||||||
|
/data/coolify/services/j9pqq74tuik1oqd5runx5ncb/.env ← n8n + DB
|
||||||
|
/data/coolify/services/oqwgsn2lcv3hsk13c6ayj8du/.env ← Gitea
|
||||||
|
/data/coolify/applications/{uuid}/.env ← per-app credentials
|
||||||
|
```
|
||||||
|
|
||||||
|
### On Local (Windows — C:\Users\Masud\)
|
||||||
|
|
||||||
|
```
|
||||||
|
.ssh/id_ed25519 ← VPS SSH private key
|
||||||
|
|
||||||
|
.claude/settings.json ← MCP servers + API keys
|
||||||
|
.claude/projects/C--Users-Masud-aura/
|
||||||
|
memory/MEMORY.md ← Memory index
|
||||||
|
memory/project_aura_infrastructure.md ← Infra notes (has tokens)
|
||||||
|
memory/user_khondokar.md ← Founder profile
|
||||||
|
|
||||||
|
aura/
|
||||||
|
auraajenticai-main/ ← Public site source (git)
|
||||||
|
src/data.jsx ← All content + brand data
|
||||||
|
src/nav.jsx ← Navigation + lang toggle
|
||||||
|
src/hero.jsx ← Hero section
|
||||||
|
src/app.jsx ← Root app + lang state
|
||||||
|
src/projects.jsx ← Services grid (6 cards)
|
||||||
|
src/timeline-contact.jsx ← Timeline, contact form, footer
|
||||||
|
src/agent-showcase.jsx ← Agent demo terminal
|
||||||
|
index.html ← Entry point + CSS vars
|
||||||
|
Dockerfile ← nginx:1.27-alpine
|
||||||
|
nginx.conf ← JSX MIME fix + gzip + SPA
|
||||||
|
|
||||||
|
aura-dashboard/ ← Owner Dashboard (SvelteKit 2)
|
||||||
|
n8n-mcp/index.js ← Custom n8n MCP server
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Credentials Locations (NOT values)
|
||||||
|
|
||||||
|
| Credential | Location |
|
||||||
|
|-----------|---------|
|
||||||
|
| VPS root password | Hostinger dashboard (hostinger.com) |
|
||||||
|
| SSH private key | C:\Users\Masud\.ssh\id_ed25519 |
|
||||||
|
| Coolify API token | memory/project_aura_infrastructure.md |
|
||||||
|
| Gitea token (khondokar) | memory/project_aura_infrastructure.md |
|
||||||
|
| OpenRouter API key | /data/coolify/services/dhcia3tgcvwmwwvexznjw9gr/.env → OPENROUTER_API_KEY |
|
||||||
|
| Telegram bot token | /data/coolify/services/dhcia3tgcvwmwwvexznjw9gr/.env → TELEGRAM_BOT_TOKEN |
|
||||||
|
| OpenClaw gateway token | /data/coolify/services/dhcia3tgcvwmwwvexznjw9gr/.env → SERVICE_PASSWORD_64_GATEWAYTOKEN |
|
||||||
|
| OpenClaw nginx auth | /data/coolify/services/dhcia3tgcvwmwwvexznjw9gr/.env → SERVICE_USER/PASSWORD_OPENCLAW |
|
||||||
|
| Gemini API key | /data/coolify/services/dhcia3tgcvwmwwvexznjw9gr/.env → GEMINI_API_KEY |
|
||||||
|
| Groq API key | /data/coolify/services/dhcia3tgcvwmwwvexznjw9gr/.env → GROQ_API_KEY |
|
||||||
|
| n8n admin credentials | /data/coolify/services/j9pqq74tuik1oqd5runx5ncb/.env |
|
||||||
|
| Cloudflare token (n8n) | /data/coolify/services/j9pqq74tuik1oqd5runx5ncb/.env → CLOUDFLARE_TOKEN |
|
||||||
|
| Cloudflare Zone ID | /data/coolify/services/j9pqq74tuik1oqd5runx5ncb/.env → CLOUDFLARE_ZONE_ID |
|
||||||
|
| Supabase DB password | /data/coolify/databases/ernix50nvuq9ur9jy8na8tgr/ or service .env |
|
||||||
|
| MongoDB auth | /data/coolify/databases/b3bhfd7bocb4pm36uv36rebq/ |
|
||||||
|
| JWT secret (shared) | application UUID g5ehpyu7... .env |
|
||||||
|
| aura_auth DB password | application UUIDs (dashboard apps) .env → DATABASE_URL |
|
||||||
|
| Claude Code API key | C:\Users\Masud\.claude\settings.json |
|
||||||
|
| n8n MCP API key | C:\Users\Masud\.claude\settings.json |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. MCP Tools Status
|
||||||
|
|
||||||
|
Configured in: `C:\Users\Masud\.claude\settings.json`
|
||||||
|
|
||||||
|
| MCP Server | Status | Key Tools |
|
||||||
|
|-----------|--------|-----------|
|
||||||
|
| **Coolify** (`04a4937c-...`) | ✅ Connected | d1_database_*, kv_namespace_*, r2_bucket_*, workers_* |
|
||||||
|
| **Gitea** | ✅ Connected | issue_*, pull_request_*, repo_*, user_* |
|
||||||
|
| **n8n** (local node server) | ✅ Connected | list_workflows, execute_workflow, set_workflow_active |
|
||||||
|
| **Google Calendar** (`c00adf3f-...`) | ✅ Connected | list_events, create_event, update_event |
|
||||||
|
| **Gmail** (`0525003c-...`) | ✅ Connected | search_threads, get_thread, create_draft |
|
||||||
|
| **Google Drive** (`d51cbec6-...`) | ✅ Connected | read_file_content, search_files, create_file |
|
||||||
|
| **Vercel** (`39a5e89f-...`) | ✅ Connected | list_projects, list_deployments, get_runtime_logs |
|
||||||
|
| **Claude Preview** | ✅ Available | preview_start, preview_screenshot, preview_eval |
|
||||||
|
| **Computer Use** | ✅ Available | screenshot, left_click, type, key, scroll |
|
||||||
|
| **Claude-in-Chrome** | ✅ Available | navigate, find, read_page, javascript_tool |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Phase Completion Status
|
||||||
|
|
||||||
|
| Phase | Description | Status | Completed |
|
||||||
|
|-------|-------------|--------|-----------|
|
||||||
|
| **0** | VPS audit, health report, swap configured, baseline | ✅ Complete | 2026-04-26 |
|
||||||
|
| **1** | Central Auth Service (SvelteKit + Hono + Drizzle + JWT + bcrypt) | ✅ Complete | 2026-04-26 |
|
||||||
|
| **2** | Owner Dashboard upgrade (sidebar nav, auth gate, Clients CRUD, Brain Console) | ✅ Complete | 2026-04-27 |
|
||||||
|
| **3** | Public site (auraajenticai.cloud) — bilingual EN/BN, 6 services, n8n contact form | ✅ Complete | 2026-04-27 |
|
||||||
|
| **4** | OpenClaw AI Agent — OpenRouter + claude-sonnet-4.5 + model ID fix | ✅ Complete | 2026-04-30 |
|
||||||
|
| **5** | Telegram integration — @tradingbanglaajentic_bot wired to OpenClaw agent | ✅ Complete | 2026-05-01 |
|
||||||
|
| **6** | Client portal (client.auraajenticai.cloud) | ✅ Deployed | — |
|
||||||
|
| **7** | API gateway (api.auraajenticai.cloud) | ✅ Deployed | — |
|
||||||
|
| **8** | Billing service (billing.auraajenticai.cloud) | ✅ Deployed | — |
|
||||||
|
| **9** | n8n automation (10 workflows: skills, contact, onboarding, invoice, AI video) | ✅ Active | — |
|
||||||
|
| **10** | DB backups, monitoring, Traefik hardening, OpenClaw secondary model config | ⏳ Pending | — |
|
||||||
|
| **11** | Demo projects — 5 Vercel deployments, GitHub repos, live demo buttons on public site | ✅ Complete | 2026-05-02 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Pending / Known Gaps
|
||||||
|
|
||||||
|
### High Priority
|
||||||
|
- [ ] **Phase 10:** Automated DB backups (no crontab yet — data loss risk)
|
||||||
|
- [ ] **Traefik dashboard** `:8080` is publicly accessible — restrict to VPN/IP allowlist
|
||||||
|
- [ ] **OpenClaw secondary** (`app.auraajenticai.cloud` — `m10jif2sbykx4hd33qf97hc6`) has no `OPENCLAW_PRIMARY_MODEL` set
|
||||||
|
- [ ] **ANTHROPIC_API_KEY** not set in Owner Dashboard app (required for Brain Console feature)
|
||||||
|
- [ ] **Telegram live test** — send `/start` to @tradingbanglaajentic_bot to verify full round-trip
|
||||||
|
- [ ] **Public site — pull & rebuild** — commit `a2a11b4` (demo URLs) is on GitHub but NOT yet pulled into VPS/Coolify. Run from Hostinger console (see §13)
|
||||||
|
- [ ] **Cloudflare DNS** — `auraajenticai.cloud` A record still points to VPS (195.35.7.154). Vercel domain added (`auraajenticai-main` project) but DNS not yet switched. Need `A → 76.76.21.21` + `www CNAME → cname.vercel-dns.com`. Cloudflare token at `/data/coolify/services/j9pqq74tuik1oqd5runx5ncb/.env → CLOUDFLARE_TOKEN`
|
||||||
|
|
||||||
|
### Medium Priority
|
||||||
|
- [ ] Set up disk/memory monitoring (no alerting configured)
|
||||||
|
- [ ] Configure Traefik rate limiting on API gateway
|
||||||
|
- [ ] Gitea webhook → Coolify auto-deploy (currently triggered manually)
|
||||||
|
- [ ] n8n workflow active/inactive status audit (10 workflows, status not confirmed per-item)
|
||||||
|
- [ ] MongoDB — confirm root credentials and access restriction
|
||||||
|
|
||||||
|
### Low Priority
|
||||||
|
- [ ] `www.auraajenticai.cloud` CNAME redirect to apex
|
||||||
|
- [ ] Log retention policy for OpenClaw gateway logs (`/tmp/openclaw/`)
|
||||||
|
- [ ] Document aura_auth DB migration history
|
||||||
|
- [ ] Add `app.auraajenticai.cloud` source repo to Gitea
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. Auth Service Details
|
||||||
|
|
||||||
|
```
|
||||||
|
URL: https://auth.auraajenticai.cloud
|
||||||
|
Container UUID: g5ehpyu7i1azk7f1sv1bhctz
|
||||||
|
Container IP: 10.0.1.12
|
||||||
|
Framework: SvelteKit + Hono + Drizzle + JWT + bcrypt
|
||||||
|
DB: Supabase Postgres 17.4 @ 10.0.1.7:5432/aura_auth
|
||||||
|
Cookies:
|
||||||
|
aura_access → 15-min JWT
|
||||||
|
aura_refresh → 7-day (path /api/auth/refresh)
|
||||||
|
Cookie domain: .auraajenticai.cloud
|
||||||
|
Login URL: https://auth.auraajenticai.cloud/login?next=<URL>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13. Quick Reference Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# SSH to VPS
|
||||||
|
ssh root@195.35.7.154
|
||||||
|
|
||||||
|
# All containers + status
|
||||||
|
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Image}}'
|
||||||
|
|
||||||
|
# OpenClaw — live logs (primary)
|
||||||
|
docker logs openclaw-dhcia3tgcvwmwwvexznjw9gr --tail=30 -f
|
||||||
|
|
||||||
|
# OpenClaw — test agent
|
||||||
|
docker exec openclaw-dhcia3tgcvwmwwvexznjw9gr \
|
||||||
|
openclaw agent --message "ping" --session-id main --json
|
||||||
|
|
||||||
|
# OpenClaw — Telegram channel status
|
||||||
|
docker exec openclaw-dhcia3tgcvwmwwvexznjw9gr openclaw channels status
|
||||||
|
|
||||||
|
# OpenClaw — restart with updated env
|
||||||
|
cd /data/coolify/services/dhcia3tgcvwmwwvexznjw9gr
|
||||||
|
docker compose up openclaw --force-recreate -d
|
||||||
|
|
||||||
|
# n8n — list workflows
|
||||||
|
docker exec n8n-j9pqq74tuik1oqd5runx5ncb n8n list:workflow
|
||||||
|
|
||||||
|
# Disk usage
|
||||||
|
df -h / && du -sh /var/lib/docker/volumes/*openclaw* /data/coolify/
|
||||||
|
|
||||||
|
# Check all service domains
|
||||||
|
for d in /data/coolify/services/*/; do
|
||||||
|
uuid=$(basename $d)
|
||||||
|
fqdn=$(grep SERVICE_FQDN= $d/.env 2>/dev/null | cut -d= -f2)
|
||||||
|
echo "$uuid: $fqdn"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 14. Vercel Deployments (2026-05-02)
|
||||||
|
|
||||||
|
Team: `khondokartowsif171s-projects` (`team_9DzpWOXgLFfZkFhpYL0QoKAO`)
|
||||||
|
|
||||||
|
| Project | Live URL | GitHub Repo | Notes |
|
||||||
|
|---------|----------|-------------|-------|
|
||||||
|
| auraajenticai-main | https://auraajenticai-main.vercel.app | khondokartowsif171/auraajenticai-main | Main site — domain `auraajenticai.cloud` added to project, DNS not yet switched |
|
||||||
|
| demo-autostudio-ecomercewebsite | https://demo-autostudio-ecomercewebsite.vercel.app | khondokartowsif171/demo-autostudio-ecomercewebsite | Linked to service card: Website & Webapp Dev |
|
||||||
|
| demo-agenticai-website | https://demo-agenticai-website.vercel.app | khondokartowsif171/demo-agenticai-website | Linked to: AI Agent & Automation |
|
||||||
|
| demo-cryptotradeanalysis-website | https://demo-cryptotradeanalysis-website.vercel.app | khondokartowsif171/demo-cryptotradeanalysis-website | Linked to: Web3 & Blockchain |
|
||||||
|
| ea-dashboard | https://ea-dashboard-blush.vercel.app | khondokartowsif171/demo-ea-dashboard | Linked to: MT5 EA & Trading |
|
||||||
|
| portfolio-website | https://portfolio-website-tan-six-24.vercel.app | khondokartowsif171/demo-portfolio-website | Linked to: Scraping & Data Pipeline |
|
||||||
|
|
||||||
|
### Demo URL → Service Card Mapping (`src/data.jsx`)
|
||||||
|
```
|
||||||
|
web-app-dev → https://demo-autostudio-ecomercewebsite.vercel.app
|
||||||
|
ai-agent-automation → https://demo-agenticai-website.vercel.app
|
||||||
|
web3-blockchain → https://demo-cryptotradeanalysis-website.vercel.app
|
||||||
|
mt5-ea-trading → https://ea-dashboard-blush.vercel.app
|
||||||
|
scraping-data-pipeline → https://portfolio-website-tan-six-24.vercel.app
|
||||||
|
infra-devops → (no demo — button hidden)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 15. VPS Console Commands (run from Hostinger web console)
|
||||||
|
|
||||||
|
Use when SSH from local machine is blocked by network routing issues.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pull latest main site source from GitHub into Coolify app dir
|
||||||
|
cd /data/coolify/applications/q2kkhvkrpdm6ukj20gv69tuk
|
||||||
|
git remote get-url github 2>/dev/null || \
|
||||||
|
git remote add github https://github.com/khondokartowsif171/auraajenticai-main.git
|
||||||
|
git pull github main
|
||||||
|
|
||||||
|
# Also push to Gitea to keep it in sync
|
||||||
|
git push origin main
|
||||||
|
|
||||||
|
# Trigger Coolify rebuild for the public site
|
||||||
|
curl -s -X POST http://localhost:8000/api/v1/applications/q2kkhvkrpdm6ukj20gv69tuk/start \
|
||||||
|
-H "Authorization: Bearer 6|aura-claude-ceo-2026-secret"
|
||||||
|
|
||||||
|
# Get Cloudflare token + zone ID for DNS update
|
||||||
|
grep -E "CLOUDFLARE_TOKEN|CLOUDFLARE_ZONE_ID" \
|
||||||
|
/data/coolify/services/j9pqq74tuik1oqd5runx5ncb/.env
|
||||||
|
|
||||||
|
# Update Cloudflare DNS: point auraajenticai.cloud to Vercel (76.76.21.21)
|
||||||
|
# Replace ZONE_ID and TOKEN with values from above
|
||||||
|
CF_ZONE="ZONE_ID_HERE"
|
||||||
|
CF_TOKEN="TOKEN_HERE"
|
||||||
|
# Get existing A record ID
|
||||||
|
curl -s "https://api.cloudflare.com/client/v4/zones/$CF_ZONE/dns_records?type=A&name=auraajenticai.cloud" \
|
||||||
|
-H "Authorization: Bearer $CF_TOKEN" | grep -o '"id":"[^"]*"' | head -1
|
||||||
|
# Update it (replace RECORD_ID)
|
||||||
|
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$CF_ZONE/dns_records/RECORD_ID" \
|
||||||
|
-H "Authorization: Bearer $CF_TOKEN" -H "Content-Type: application/json" \
|
||||||
|
-d '{"type":"A","name":"auraajenticai.cloud","content":"76.76.21.21","ttl":1,"proxied":true}'
|
||||||
|
# Add www CNAME
|
||||||
|
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE/dns_records" \
|
||||||
|
-H "Authorization: Bearer $CF_TOKEN" -H "Content-Type: application/json" \
|
||||||
|
-d '{"type":"CNAME","name":"www","content":"cname.vercel-dns.com","ttl":1,"proxied":false}'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Generated by Claude (Aura AI Brain) on 2026-05-01. Updated 2026-05-02. Update this file after each infrastructure change.*
|
||||||
@@ -204,6 +204,7 @@
|
|||||||
<script type="text/babel" src="src/agent-showcase.jsx"></script>
|
<script type="text/babel" src="src/agent-showcase.jsx"></script>
|
||||||
<script type="text/babel" src="src/timeline-contact.jsx"></script>
|
<script type="text/babel" src="src/timeline-contact.jsx"></script>
|
||||||
<script type="text/babel" src="src/command-palette.jsx"></script>
|
<script type="text/babel" src="src/command-palette.jsx"></script>
|
||||||
|
<script type="text/babel" src="src/chatbox.jsx"></script>
|
||||||
<script type="text/babel" src="src/app.jsx"></script>
|
<script type="text/babel" src="src/app.jsx"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ function App() {
|
|||||||
<T.Footer />
|
<T.Footer />
|
||||||
|
|
||||||
<T.CommandPalette open={paletteOpen} onClose={() => setPaletteOpen(false)} />
|
<T.CommandPalette open={paletteOpen} onClose={() => setPaletteOpen(false)} />
|
||||||
|
<T.ChatboxWidget />
|
||||||
|
|
||||||
<window.TweaksPanel title="Tweaks">
|
<window.TweaksPanel title="Tweaks">
|
||||||
<window.TweakSection label="Theme" />
|
<window.TweakSection label="Theme" />
|
||||||
|
|||||||
+220
@@ -0,0 +1,220 @@
|
|||||||
|
// Aura Chatbox Widget
|
||||||
|
// Fetches config from dashboard API, routes messages through backend.
|
||||||
|
|
||||||
|
const DASHBOARD = 'https://aura.auraajenticai.cloud'
|
||||||
|
|
||||||
|
const ChatboxWidget = () => {
|
||||||
|
const [config, setConfig] = React.useState(null)
|
||||||
|
const [open, setOpen] = React.useState(false)
|
||||||
|
const [messages, setMessages] = React.useState([])
|
||||||
|
const [input, setInput] = React.useState('')
|
||||||
|
const [loading, setLoading] = React.useState(false)
|
||||||
|
const [isAfterHours, setIsAfterHours] = React.useState(false)
|
||||||
|
const messagesEndRef = React.useRef(null)
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
fetch(`${DASHBOARD}/api/public/chatbox`)
|
||||||
|
.then(r => r.ok ? r.json() : null)
|
||||||
|
.then(cfg => {
|
||||||
|
if (!cfg) return
|
||||||
|
setConfig(cfg)
|
||||||
|
if (cfg.isEnabled) {
|
||||||
|
const afterHours = checkAfterHours(cfg.businessHours)
|
||||||
|
setIsAfterHours(afterHours)
|
||||||
|
setMessages([{ role: 'bot', text: cfg.welcomeMessage }])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (open && messagesEndRef.current) {
|
||||||
|
messagesEndRef.current.scrollIntoView({ behavior: 'smooth' })
|
||||||
|
}
|
||||||
|
}, [messages, open])
|
||||||
|
|
||||||
|
function checkAfterHours(businessHours) {
|
||||||
|
if (!businessHours) return false
|
||||||
|
const days = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']
|
||||||
|
const now = new Date()
|
||||||
|
const day = days[now.getDay()]
|
||||||
|
const hours = businessHours[day]
|
||||||
|
if (!hours || hours === 'closed') return true
|
||||||
|
const [open, close] = hours.split('-').map(t => {
|
||||||
|
const [h, m] = t.split(':').map(Number)
|
||||||
|
return h * 60 + (m || 0)
|
||||||
|
})
|
||||||
|
// UTC+6 Bangladesh time
|
||||||
|
const bdMin = ((now.getUTCHours() + 6) % 24) * 60 + now.getUTCMinutes()
|
||||||
|
return bdMin < open || bdMin >= close
|
||||||
|
}
|
||||||
|
|
||||||
|
async function sendMessage() {
|
||||||
|
if (!input.trim() || loading || isAfterHours) return
|
||||||
|
const text = input.trim()
|
||||||
|
setInput('')
|
||||||
|
setMessages(prev => [...prev, { role: 'user', text }])
|
||||||
|
setLoading(true)
|
||||||
|
try {
|
||||||
|
const res = await fetch(`${DASHBOARD}/api/public/chatbox/chat`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'content-type': 'application/json' },
|
||||||
|
body: JSON.stringify({ message: text }),
|
||||||
|
})
|
||||||
|
const data = await res.json()
|
||||||
|
setMessages(prev => [...prev, { role: 'bot', text: data.reply || config?.fallbackMessage }])
|
||||||
|
} catch {
|
||||||
|
setMessages(prev => [...prev, { role: 'bot', text: config?.fallbackMessage || "I'll get back to you soon." }])
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onKey(e) {
|
||||||
|
if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendMessage() }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config?.isEnabled) return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ position: 'fixed', bottom: 24, right: 24, zIndex: 9000, display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 12 }}>
|
||||||
|
{/* Chat window */}
|
||||||
|
{open && (
|
||||||
|
<div style={{
|
||||||
|
width: 340, maxHeight: 480,
|
||||||
|
background: 'var(--bg-elev)',
|
||||||
|
border: '1px solid var(--line-strong)',
|
||||||
|
borderRadius: 16,
|
||||||
|
display: 'flex', flexDirection: 'column',
|
||||||
|
boxShadow: '0 20px 60px rgba(0,0,0,0.4)',
|
||||||
|
overflow: 'hidden',
|
||||||
|
}}>
|
||||||
|
{/* Header */}
|
||||||
|
<div style={{
|
||||||
|
padding: '14px 16px',
|
||||||
|
background: '#0a0a0a',
|
||||||
|
display: 'flex', alignItems: 'center', gap: 10,
|
||||||
|
borderBottom: '1px solid rgba(255,255,255,0.07)',
|
||||||
|
}}>
|
||||||
|
<div style={{
|
||||||
|
width: 32, height: 32, borderRadius: '50%',
|
||||||
|
background: 'linear-gradient(135deg, #c8a961 0%, #1d9e75 100%)',
|
||||||
|
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||||
|
fontSize: 14, flexShrink: 0,
|
||||||
|
}}>⬡</div>
|
||||||
|
<div>
|
||||||
|
<div style={{ fontSize: 13, fontWeight: 600, color: '#f4f5f7' }}>Aura AI</div>
|
||||||
|
<div style={{ fontSize: 11, color: isAfterHours ? '#f59e0b' : '#4ade80', display: 'flex', alignItems: 'center', gap: 4 }}>
|
||||||
|
<span style={{ width: 6, height: 6, borderRadius: '50%', background: 'currentColor', display: 'inline-block' }} />
|
||||||
|
{isAfterHours ? 'After hours' : 'Online'}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button onClick={() => setOpen(false)} style={{
|
||||||
|
marginLeft: 'auto', background: 'none', border: 'none',
|
||||||
|
color: '#6b7080', cursor: 'pointer', fontSize: 16, lineHeight: 1,
|
||||||
|
padding: '2px 4px',
|
||||||
|
}}>✕</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Messages */}
|
||||||
|
<div style={{
|
||||||
|
flex: 1, overflowY: 'auto', padding: '12px 14px',
|
||||||
|
display: 'flex', flexDirection: 'column', gap: 8,
|
||||||
|
minHeight: 200, maxHeight: 280,
|
||||||
|
}}>
|
||||||
|
{messages.map((m, i) => (
|
||||||
|
<div key={i} style={{
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: m.role === 'user' ? 'flex-end' : 'flex-start',
|
||||||
|
}}>
|
||||||
|
<div style={{
|
||||||
|
maxWidth: '80%', padding: '8px 12px',
|
||||||
|
borderRadius: m.role === 'user' ? '12px 12px 2px 12px' : '12px 12px 12px 2px',
|
||||||
|
background: m.role === 'user' ? '#c8a961' : 'rgba(255,255,255,0.06)',
|
||||||
|
color: m.role === 'user' ? '#0a0a0a' : '#e0e2e8',
|
||||||
|
fontSize: 13, lineHeight: 1.5,
|
||||||
|
fontWeight: m.role === 'user' ? 500 : 400,
|
||||||
|
}}>{m.text}</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
{loading && (
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'flex-start' }}>
|
||||||
|
<div style={{
|
||||||
|
padding: '8px 14px', borderRadius: '12px 12px 12px 2px',
|
||||||
|
background: 'rgba(255,255,255,0.06)', color: '#6b7080',
|
||||||
|
fontSize: 13, letterSpacing: 4,
|
||||||
|
}}>•••</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{isAfterHours && (
|
||||||
|
<div style={{
|
||||||
|
padding: '8px 10px', background: 'rgba(245,158,11,0.1)',
|
||||||
|
border: '1px solid rgba(245,158,11,0.2)', borderRadius: 8,
|
||||||
|
fontSize: 12, color: '#f59e0b',
|
||||||
|
}}>
|
||||||
|
{config.afterHoursMessage}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div ref={messagesEndRef} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Input */}
|
||||||
|
<div style={{
|
||||||
|
padding: '10px 12px',
|
||||||
|
borderTop: '1px solid rgba(255,255,255,0.07)',
|
||||||
|
display: 'flex', gap: 8,
|
||||||
|
}}>
|
||||||
|
<input
|
||||||
|
value={input}
|
||||||
|
onChange={e => setInput(e.target.value)}
|
||||||
|
onKeyDown={onKey}
|
||||||
|
disabled={isAfterHours || loading}
|
||||||
|
placeholder={isAfterHours ? 'Chat unavailable right now' : 'Ask me anything…'}
|
||||||
|
style={{
|
||||||
|
flex: 1, padding: '8px 12px',
|
||||||
|
background: 'rgba(255,255,255,0.05)',
|
||||||
|
border: '1px solid rgba(255,255,255,0.1)',
|
||||||
|
borderRadius: 8, color: '#f4f5f7',
|
||||||
|
fontSize: 13,
|
||||||
|
outline: 'none',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={sendMessage}
|
||||||
|
disabled={!input.trim() || loading || isAfterHours}
|
||||||
|
style={{
|
||||||
|
width: 34, height: 34, flexShrink: 0,
|
||||||
|
background: input.trim() && !isAfterHours ? '#c8a961' : 'rgba(255,255,255,0.06)',
|
||||||
|
border: 'none', borderRadius: 8,
|
||||||
|
color: input.trim() && !isAfterHours ? '#0a0a0a' : '#6b7080',
|
||||||
|
cursor: input.trim() && !isAfterHours ? 'pointer' : 'not-allowed',
|
||||||
|
fontSize: 15, display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||||
|
transition: 'background 0.15s',
|
||||||
|
}}
|
||||||
|
>↑</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Toggle button */}
|
||||||
|
<button
|
||||||
|
onClick={() => setOpen(o => !o)}
|
||||||
|
title="Chat with Aura AI"
|
||||||
|
style={{
|
||||||
|
width: 52, height: 52, borderRadius: '50%',
|
||||||
|
background: open ? '#0a0a0a' : 'linear-gradient(135deg, #c8a961 0%, #1d9e75 100%)',
|
||||||
|
border: open ? '2px solid rgba(255,255,255,0.15)' : 'none',
|
||||||
|
color: open ? '#f4f5f7' : '#0a0a0a',
|
||||||
|
fontSize: 20, cursor: 'pointer',
|
||||||
|
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||||
|
boxShadow: open ? '0 4px 20px rgba(0,0,0,0.4)' : '0 4px 20px rgba(200,169,97,0.4)',
|
||||||
|
transition: 'all 0.2s',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{open ? '✕' : '⬡'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
window.ChatboxWidget = ChatboxWidget
|
||||||
@@ -83,6 +83,7 @@ const PORTFOLIO_DATA = {
|
|||||||
stack: ["SvelteKit", "Next.js", "React", "Tailwind", "PostgreSQL"],
|
stack: ["SvelteKit", "Next.js", "React", "Tailwind", "PostgreSQL"],
|
||||||
impact: { primary: "50k+", secondary: "daily users served" },
|
impact: { primary: "50k+", secondary: "daily users served" },
|
||||||
color: "violet",
|
color: "violet",
|
||||||
|
demo: "https://demo-autostudio-ecomercewebsite.vercel.app",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "ai-agent-automation",
|
id: "ai-agent-automation",
|
||||||
@@ -94,6 +95,7 @@ const PORTFOLIO_DATA = {
|
|||||||
stack: ["Anthropic Claude", "n8n", "LangGraph", "Node.js", "Hono"],
|
stack: ["Anthropic Claude", "n8n", "LangGraph", "Node.js", "Hono"],
|
||||||
impact: { primary: "1.2M+", secondary: "agent runs / month" },
|
impact: { primary: "1.2M+", secondary: "agent runs / month" },
|
||||||
color: "cyan",
|
color: "cyan",
|
||||||
|
demo: "https://demo-agenticai-website.vercel.app",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "web3-blockchain",
|
id: "web3-blockchain",
|
||||||
@@ -105,6 +107,7 @@ const PORTFOLIO_DATA = {
|
|||||||
stack: ["Solidity", "viem", "wagmi", "Cloudflare Workers"],
|
stack: ["Solidity", "viem", "wagmi", "Cloudflare Workers"],
|
||||||
impact: { primary: "12 chains", secondary: "EVM + Solana" },
|
impact: { primary: "12 chains", secondary: "EVM + Solana" },
|
||||||
color: "green",
|
color: "green",
|
||||||
|
demo: "https://demo-cryptotradeanalysis-website.vercel.app",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "mt5-ea-trading",
|
id: "mt5-ea-trading",
|
||||||
@@ -116,6 +119,7 @@ const PORTFOLIO_DATA = {
|
|||||||
stack: ["MQL5", "Go", "ClickHouse", "WebSockets", "React"],
|
stack: ["MQL5", "Go", "ClickHouse", "WebSockets", "React"],
|
||||||
impact: { primary: "<80ms", secondary: "tick-to-render latency" },
|
impact: { primary: "<80ms", secondary: "tick-to-render latency" },
|
||||||
color: "amber",
|
color: "amber",
|
||||||
|
demo: "https://ea-dashboard-blush.vercel.app",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "scraping-data-pipeline",
|
id: "scraping-data-pipeline",
|
||||||
@@ -127,6 +131,7 @@ const PORTFOLIO_DATA = {
|
|||||||
stack: ["Playwright", "Puppeteer", "Python", "Airflow", "PostgreSQL"],
|
stack: ["Playwright", "Puppeteer", "Python", "Airflow", "PostgreSQL"],
|
||||||
impact: { primary: "10M+", secondary: "records extracted / month" },
|
impact: { primary: "10M+", secondary: "records extracted / month" },
|
||||||
color: "violet",
|
color: "violet",
|
||||||
|
demo: "https://portfolio-website-tan-six-24.vercel.app",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "infra-devops",
|
id: "infra-devops",
|
||||||
|
|||||||
+34
-9
@@ -1,7 +1,17 @@
|
|||||||
// Top nav — minimal, sticky, blurred — mobile-responsive
|
// Top nav — minimal, sticky, blurred — mobile-responsive
|
||||||
|
const DASHBOARD = 'https://aura.auraajenticai.cloud'
|
||||||
|
const NAV_FALLBACK = [
|
||||||
|
{ id: "work", label: "Services", url: "#work" },
|
||||||
|
{ id: "stack", label: "Stack", url: "#stack" },
|
||||||
|
{ id: "agents", label: "Agents", url: "#agents" },
|
||||||
|
{ id: "timeline", label: "Timeline", url: "#timeline" },
|
||||||
|
{ id: "contact", label: "Contact", url: "#contact" },
|
||||||
|
]
|
||||||
|
|
||||||
const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang }) => {
|
const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang }) => {
|
||||||
const [scrolled, setScrolled] = React.useState(false);
|
const [scrolled, setScrolled] = React.useState(false);
|
||||||
const [menuOpen, setMenuOpen] = React.useState(false);
|
const [menuOpen, setMenuOpen] = React.useState(false);
|
||||||
|
const [links, setLinks] = React.useState(NAV_FALLBACK);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const onScroll = () => setScrolled(window.scrollY > 12);
|
const onScroll = () => setScrolled(window.scrollY > 12);
|
||||||
@@ -9,13 +19,28 @@ const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang }) => {
|
|||||||
return () => window.removeEventListener("scroll", onScroll);
|
return () => window.removeEventListener("scroll", onScroll);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const links = [
|
// Fetch nav links from Control Center API (stale-while-revalidate)
|
||||||
{ id: "work", label: "Services" },
|
React.useEffect(() => {
|
||||||
{ id: "stack", label: "Stack" },
|
const CACHE_KEY = 'aura_nav_links'
|
||||||
{ id: "agents", label: "Agents" },
|
const CACHE_TTL = 5 * 60 * 1000 // 5 min
|
||||||
{ id: "timeline", label: "Timeline" },
|
const cached = sessionStorage.getItem(CACHE_KEY)
|
||||||
{ id: "contact", label: "Contact" },
|
if (cached) {
|
||||||
];
|
try {
|
||||||
|
const { data, ts } = JSON.parse(cached)
|
||||||
|
if (Date.now() - ts < CACHE_TTL) { setLinks(data.length ? data : NAV_FALLBACK); return }
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
fetch(`${DASHBOARD}/api/public/links?page=home`, { signal: AbortSignal.timeout(3000) })
|
||||||
|
.then(r => r.ok ? r.json() : null)
|
||||||
|
.then(data => {
|
||||||
|
if (Array.isArray(data) && data.length > 0) {
|
||||||
|
const mapped = data.map(l => ({ id: l.id, label: l.label, url: l.url }))
|
||||||
|
setLinks(mapped)
|
||||||
|
sessionStorage.setItem(CACHE_KEY, JSON.stringify({ data: mapped, ts: Date.now() }))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -55,7 +80,7 @@ const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang }) => {
|
|||||||
{/* Center links — hidden on mobile */}
|
{/* Center links — hidden on mobile */}
|
||||||
<div style={{ display: "flex", gap: 4, alignItems: "center" }} className="nav-links">
|
<div style={{ display: "flex", gap: 4, alignItems: "center" }} className="nav-links">
|
||||||
{links.map(l => (
|
{links.map(l => (
|
||||||
<a key={l.id} href={"#" + l.id} style={{
|
<a key={l.id} href={l.url || `#${l.id}`} style={{
|
||||||
fontSize: 13.5,
|
fontSize: 13.5,
|
||||||
color: "var(--text-dim)",
|
color: "var(--text-dim)",
|
||||||
padding: "6px 12px",
|
padding: "6px 12px",
|
||||||
@@ -216,7 +241,7 @@ const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang }) => {
|
|||||||
{links.map(l => (
|
{links.map(l => (
|
||||||
<a
|
<a
|
||||||
key={l.id}
|
key={l.id}
|
||||||
href={"#" + l.id}
|
href={l.url || `#${l.id}`}
|
||||||
onClick={() => setMenuOpen(false)}
|
onClick={() => setMenuOpen(false)}
|
||||||
style={{
|
style={{
|
||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
|
|||||||
+14
-10
@@ -152,16 +152,20 @@ const ProjectCard = ({ p }) => {
|
|||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
color: "var(--text-dim)",
|
color: "var(--text-dim)",
|
||||||
}} title="GitHub"><Icons.Github size={14} /></button>
|
}} title="GitHub"><Icons.Github size={14} /></button>
|
||||||
<button style={{
|
{p.demo && (
|
||||||
padding: "0 14px", height: 34,
|
<a href={p.demo} target="_blank" rel="noopener noreferrer" style={{
|
||||||
display: "inline-flex", alignItems: "center", gap: 6,
|
padding: "0 14px", height: 34,
|
||||||
background: "var(--text)",
|
display: "inline-flex", alignItems: "center", gap: 6,
|
||||||
color: "var(--bg)",
|
background: "var(--text)",
|
||||||
border: "none",
|
color: "var(--bg)",
|
||||||
borderRadius: 8,
|
border: "none",
|
||||||
fontSize: 13,
|
borderRadius: 8,
|
||||||
fontWeight: 500,
|
fontSize: 13,
|
||||||
}}>Demo <Icons.ArrowUpRight size={12} /></button>
|
fontWeight: 500,
|
||||||
|
textDecoration: "none",
|
||||||
|
cursor: "pointer",
|
||||||
|
}}>Demo <Icons.ArrowUpRight size={12} /></a>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user