Repository avatar
AI Tools
v1.0.0
active

suite

com.luminarasuite/suite

Projects, context, and reports. Paid research needs Agency or your own DataForSEO login.

Documentation

Luminara Suite

Open-source AI search visibility: see how your brand shows up in Google, AI Overviews, ChatGPT and Perplexity, then get a plain-English action plan.

luminarasuite.com · Quick start · Bring your own keys · Deploy · Contribute

CI License AGPL-3.0 Runs on Cloudflare Telegram Mini App TypeScript


Luminara Suite home: Ask a question, Audit my website, My business profile

What it does

Luminara Suite is a web app and Telegram Mini App for Answer Engine Optimization (AEO): the practice of getting your brand cited by AI answers, not just ranked by Google.

  • Instant Audit: enter a domain, get an SEO / AEO / GEO brief grounded in a live scrape of the site and live search results, with a visibility radar, competitor map, schema gaps and prioritised recommendations.
  • Oracle Agent: a chat analyst with conversation memory that pulls fresh search evidence when a question needs it and cites its sources.
  • Business DNA: extract your mission, USP, audience and competitors once; every audit and answer is personalised to it.
  • Plain English mode: one click rewrites any report at an 8th-grade reading level for non-technical stakeholders.
  • Strategy tools: red-team stress test, data analyst, thought organiser, grounded market research.
  • Telegram Mini App: the same product inside Telegram, with Stars payments and TON wallet connect.

It runs on your own AI account: Groq, NVIDIA NIM or Ollama (local or cloud), with Gemini as an optional fallback. No Luminara account is needed to self-host.

Website audit: paste a domain, choose SEO, AEO or GEOAsk Luminara: chat grounded in live search results
Audit my websiteAsk a question, with plain-English rewrite and sources
Business profile: what you sell, to whom, and your competitorsLuminara Suite landing page
Business profile that personalises every answerluminarasuite.com

Labs. OracleMind SLM Studio, the TimesFM forecaster and the Archy harness are demonstrations. Their numbers are simulated and the UI says so. They are kept for exploration, not measurement.

Quick start

git clone https://github.com/LuminaraDigital/Luminara-Search-Oracle-Agent.git
cd Luminara-Search-Oracle-Agent
npm ci
npm run dev

Open http://localhost:3000, click the gear icon, and paste a key from one of:

ProviderWhere to get a keyNotes
Groqhttps://console.groq.com/keysFastest. Default model openai/gpt-oss-120b.
NVIDIA NIMhttps://build.nvidia.com/settings/api-keysNVIDIA's API blocks browsers, so calls are relayed through the Worker with your key (never stored). Needs npm run cf:dev or the hosted site.
OllamaLocal daemon at http://127.0.0.1:11434 on the desktop app or localhost. Hosted web does not probe that address unless you save a different endpoint. Cloud keys: https://ollama.com/settings/keysLocal runs fully offline.
Google Gemini (optional)https://aistudio.google.com/apikeyFallback model, Google Search grounding, and Live Voice.
Tavily (optional)https://tavily.comLive SERP evidence for audits and chat.
Firecrawl (optional)https://firecrawl.devScrapes the audited site for real on-page evidence.

Keys are stored in your browser only.

Bring your own keys

Luminara never needs your keys on its servers. In the browser build every provider is called directly from your device. Two exceptions are relayed through the Cloudflare Worker because the vendor blocks browser requests: NVIDIA NIM, and Gemini when you use the hosted key. Relayed requests carry your key in the x-provider-key header and the Worker forwards it without storing it.

On luminarasuite.com, hosted keys exist for convenience. They are only used when a request carries a valid Telegram Mini App sign-in or a verified Firebase Auth ID token, are metered per user (25 free requests per day by default), and are unlimited on a paid plan. Nobody can consume the hosted keys anonymously. Bring-your-own-key in Settings is never gated.

SEO methodology (playbooks)

Audits and answers follow a published methodology rather than whatever the model improvises. The claude-seo skill set (MIT, by AgriciDaniel and contributors) is vendored under .claude/skills/ so Claude Code users of this repo get the full /seo skills, and scripts/build-playbooks.mjs compiles the methodology into services/skills/playbooks.generated.json for the app:

Audit focusPlaybooks injected
SEOscoring rules, technical SEO (9 categories), content quality / E-E-A-T, Schema.org status
AEOscoring rules, AI search (AI Overviews, ChatGPT, Perplexity), Schema.org
GEOscoring rules, AI search, content quality
Lenses (optional)Local business, Online store, Content quality, Structured data, Search experience

Reports carry a Health Score (0-100) with the playbook weights, Critical / High / Medium / Low findings, and for every recommendation a "how we'd know it failed" check and a leading indicator. Deprecation rules (no HowTo schema, FAQPage earns no rich result, INP not FID) are enforced in the prompt. Anything not observable from the scrape and search evidence is reported as "not measured".

Edit the skill files, run npm run playbooks, commit the JSON. Attribution: THIRD_PARTY_NOTICES.md.

Architecture

Browser / Telegram Mini App / Windows Electron shell  (React 19, Vite, Tailwind)
   │  desktop loads https://luminarasuite.com (same origin as web)
   │  direct calls with your keys ──────────────► Groq · Ollama · Tavily · Firecrawl · Exa
   │
   └─ /api/* ─► Cloudflare Worker (worker/)
                 ├─ /api/providers/:id/*   allow-listed proxy: BYOK relay or metered hosted keys
                 ├─ /api/sidecars/:id/*    relay to self-hosted Writing check / Results tracking
                 ├─ /api/auth/session      Telegram or Firebase identity for the current request
                 ├─ /api/telegram/auth     validates Mini App initData (HMAC-SHA256)
                 ├─ /api/telegram/invoice  Telegram Stars checkout
                 ├─ /api/telegram/webhook  bot commands, payments → KV
                 └─ static assets          the built app, SPA fallback, /desktop download page

Key files: App.tsx (shell and routing), electron/ (Windows desktop shell), services/geminiService.ts (audit and chat pipelines), services/aiProviderService.ts (Groq / NIM / Ollama with failover), services/apiClient.ts (proxy and BYOK relay), worker/ (Cloudflare Worker), services/telegram/tma.ts (Telegram bridge). Desktop guide: docs/desktop.md.

Scripts

CommandWhat it does
npm run devVite dev server on :3000
npm run desktop:devVite + Electron against localhost (Windows shell)
npm run desktop:dist:winOne-click NSIS installer under release/
npm run cf:devBuild and run the full Worker on :8787 (copy .dev.vars.example to .dev.vars)
npm testUnit and integration tests (vitest)
npm run test:coverageSame tests with coverage report + thresholds
npm run lintESLint across app and worker sources
npm run typecheckTypeScript, app and worker
npm run buildTypecheck + production build
npm run deployBuild and wrangler deploy
npm run tg:setupRegister webhook, menu button and commands with Telegram
npm run secrets:checkFail if credential-shaped strings or secret files are in the tree
npm run preparePoint git at .githooks (secret scan on commit and push)

Secrets never belong in git. Use .env / .dev.vars (gitignored) and wrangler secret put for production. GitHub secret scanning, push protection, Dependabot security updates, and branch protection on main are enabled. Local hooks and CI run secrets:check as a second line of defense. After clone, run npm install once so hooks install.

Reliability and quality

  • CI on every PR and push: secrets scan, env schema validation, typecheck, ESLint, Vitest with coverage thresholds, npm audit, production build, bundle secret-leak guard, smoke dry-run, Wrangler staging/production dry-run.
  • Protected main: pull requests required; force pushes and branch deletion blocked; CI status check required.
  • Hosted Worker: staging and production deploy workflows with live verification; see .github/workflows/deploy-cloudflare.yml.
  • Honesty gates: Labs and simulated metrics are labeled in the UI; audits report not measured when evidence is missing.

Maintainer

Built and maintained by Babatundji Williams-Fulwood (@LuminaraDigital) / Luminara Digital Agency. Product site: luminarasuite.com.

Deploy: Cloudflare + Telegram Mini App

One Worker serves everything. Provider keys and the bot token live in Worker secrets only.

npx wrangler login
npx wrangler kv namespace create LUMINARA_KV      # paste the id into wrangler.jsonc
npx wrangler secret put BOT_TOKEN                 # from @BotFather
npx wrangler secret put TELEGRAM_WEBHOOK_SECRET   # any long random string
npx wrangler secret put GROQ_API_KEY              # hosted keys are optional; add the ones you offer
npx wrangler secret put TAVILY_API_KEY
npx wrangler secret put FIRECRAWL_API_KEY
npm run deploy

Add your domain to Cloudflare first; wrangler.jsonc declares luminarasuite.com as a custom domain (change it for your own deployment). Then in @BotFather run /newbot, then /newapp with the Web App URL set to your domain, and wire the bot:

BOT_TOKEN=... TELEGRAM_WEBHOOK_SECRET=... WEBAPP_URL=https://your-domain/ npm run tg:setup

Gating is configured in wrangler.jsonc vars: REQUIRE_TG_AUTH (hosted keys need Telegram or Firebase sign-in), FIREBASE_PROJECT_ID (enables Firebase ID token verification), FREE_DAILY_LIMIT, REQUIRE_SUBSCRIPTION. Web signup/signin uses Firebase Auth (VITE_FIREBASE_* in .env); the Worker verifies tokens with Google JWKS (no Admin SDK private key). Plans and Stars prices are in worker/telegramBot.ts. Telegram's Mini App policy allows TON assets only; the TON Connect manifest is in public/.

Firebase Auth setup (web signup / signin)

  1. Create a Firebase project and enable Authentication → Email/Password (and optionally Google).
  2. Register a Web app; copy the config into .env as VITE_FIREBASE_*. Local development uses those values as they are. A production build (vite build) uses them only when you also set VITE_FIREBASE_SELF_HOSTED=true and all four of the API key, auth domain, project id and app id are present; without the switch it signs in with the values in services/auth/firebasePublicConfig.ts, so values left on a build machine cannot ship by accident.
  3. Set the same project id on the Worker: FIREBASE_PROJECT_ID in wrangler.jsonc.
  4. Under Authentication → Settings → Authorized domains, add luminarasuite.com, www.luminarasuite.com, and localhost.
  5. Web: Settings → Account for email/password or Google. Product tools require this sign-in.
  6. Telegram Mini App: Telegram initData is the account. Do not require Firebase inside TMA; Google popups are unreliable in Telegram WebViews.

User profiles are upserted on each verified session into Cloudflare KV (user:{id}). Optional D1 SQL is prepared in migrations/0001_users.sql (see comment in wrangler.jsonc).

A static Docker image (no Worker) is also available: docker build -t luminara-suite .

Writing check and results tracking (self-hosted, free)

Two optional helpers run next to the crawler. Writing check grades how clearly a page reads and lists wording fixes in the report. Results tracking shows real visitors to the site and how many arrived from AI assistants such as ChatGPT and Perplexity, so a business owner can see whether the fixes worked. Both are free, open-source tools you host yourself; the app only ever reads from them.

Under the hood these are LanguageTool (LGPL-2.1) and Umami (MIT). Both are used over HTTP only and are not bundled into the app; see THIRD_PARTY_NOTICES.md.

Operator steps:

  1. In .env set CRAWLER_TOKEN, UMAMI_APP_SECRET and UMAMI_DB_PASSWORD to long random values (openssl rand -hex 32 for each), and UMAMI_DB_USER / UMAMI_DB_NAME (for example umami). Compose refuses to start while any of them is missing. Then start the whole helper stack (crawler on :3001, writing check on :8010, tracking dashboard on :3002, all published on 127.0.0.1 only):

    docker compose up -d
    

    Upgrading an existing install that used the old built-in umami/umami database login: Postgres only reads these variables when the umami-db-data volume is first created. Run docker compose exec umami-db psql -U umami -d umami, type \password umami and enter the new UMAMI_DB_PASSWORD, then docker compose up -d again (or delete the volume, which also deletes tracking data).

    Crawler settings: paste the same CRAWLER_TOKEN into Settings > Crawler token. A browser can only call the crawler from origins listed in CRAWLER_ALLOWED_ORIGINS (comma-separated exact origins, never *; unset defaults to the local dev app http://localhost:3000,http://127.0.0.1:3000, empty allows none, and you add https://luminarasuite.com to use the hosted app with your own crawler). CRAWLER_MAX_CONCURRENCY (default 2) caps browser sessions and CRAWLER_RATE_LIMIT_PER_MIN (default 30) caps requests per client IP; both answer 429 with Retry-After. Set CRAWLER_TRUST_PROXY=true only behind a reverse proxy you control.

  2. Open http://localhost:3002, sign in with the default admin / umami and change the password right away.

  3. In the dashboard add the website, then paste the tracking snippet it gives you into the site's pages.

  4. Create an API key in the dashboard (Profile, API keys), or plan to use the username and password.

  5. For the hosted app, expose both services behind HTTPS with any reverse proxy, then point the Worker at them:

    # wrangler.jsonc vars (public config)
    #   "LANGUAGETOOL_URL": "https://writing.your-domain",
    #   "UMAMI_URL": "https://stats.your-domain"      # or https://api.umami.is for Umami Cloud
    npx wrangler secret put UMAMI_API_KEY            # or UMAMI_USERNAME + UMAMI_PASSWORD
    npm run deploy
    

    /api/health then reports sidecars: { languagetool: true, umami: true } and the app uses the relay at /api/sidecars/<id>/.... The relay only forwards the read-only endpoints the report needs, and callers follow the same Telegram sign-in rule as hosted keys (no daily quota).

  6. Local development without the Worker: add LANGUAGETOOL_URL, UMAMI_URL and UMAMI_API_KEY to .env (no VITE_ prefix) and the Vite dev server proxies the same /api/sidecars/... paths for you. See .env.example.

Users can also enter their own service URL in Settings, in which case the browser calls it directly.

Business model and moat

The code is open. The business is the hosted service and what it accumulates:

  • Plans (card checkout through Stripe for a one-off 30-day pass, or Telegram Stars in the Mini App): Starter A$79, Growth A$229, Agency A$549. A pass does not renew. The Mini App takes Stars only. Starter covers 2 sites with monthly re-audit reminders; Growth covers 10 sites with weekly reminders; Agency adds white-label reports and client workspaces.
  • Done-for-you: schema and content fixes shipped by Luminara Digital Agency, priced per finding.
  • The dataset: weekly, per-vertical records of how AI engines answer commercial queries. Every audit improves with every other customer. That compounds; a prompt does not.

Commercial licensing and trademarks: COMMERCIAL-LICENSE.md.

Roadmap

  1. Real AI-visibility measurement: query ChatGPT, Gemini, Perplexity and Google AI Overviews and record whether the brand is cited.
  2. Findings as trackable cards with an evidence drawer, instead of one long report.
  3. Weekly re-runs with diffs and alerts (Visibility Trends already stores per-audit SoV snapshots in-browser; Worker KV mirror next).
  4. Real technical signals (PageSpeed, rank data) in the audit.
  5. Agency workspaces, white-label PDF export, share links.
  6. Card checkout for web subscriptions alongside Telegram Stars and TON.
  7. Optional SOC 2 Type 1 engagement against the Enterprise Trust Pack evidence map (checklist shipped; certification is a separate audit).

Contributing

Issues and pull requests are welcome. Read CONTRIBUTING.md (DCO sign-off and the contributor license grant) and SECURITY.md.

License

GNU AGPL-3.0 © Luminara Digital Agency. "Luminara", "Luminara Suite", "Oracle Agent" and the logo are trademarks and are not covered by the code license.

No installation packages available.