diff --git a/public/Metatron_Full_logo.png b/public/Metatron_Full_logo.png new file mode 100644 index 0000000..29569bc Binary files /dev/null and b/public/Metatron_Full_logo.png differ diff --git a/public/Metatroncube_logo.png b/public/Metatroncube_logo.png new file mode 100644 index 0000000..1823514 Binary files /dev/null and b/public/Metatroncube_logo.png differ diff --git a/public/crawlerx-mark.png b/public/crawlerx-mark.png new file mode 100644 index 0000000..1823514 Binary files /dev/null and b/public/crawlerx-mark.png differ diff --git a/public/site.webmanifest b/public/site.webmanifest index 63f961f..6721b6b 100644 --- a/public/site.webmanifest +++ b/public/site.webmanifest @@ -1,6 +1,6 @@ { - "name": "OpenSEO", - "short_name": "OpenSEO", + "name": "CrawlerX", + "short_name": "CrawlerX", "icons": [ { "src": "/android-chrome-192x192.png", @@ -13,7 +13,7 @@ "type": "image/png" } ], - "theme_color": "#0a0f0d", - "background_color": "#0a0f0d", + "theme_color": "#3779b9", + "background_color": "#ffffff", "display": "standalone" } diff --git a/public/transparent-logo.png b/public/transparent-logo.png index 9805f31..1823514 100644 Binary files a/public/transparent-logo.png and b/public/transparent-logo.png differ diff --git a/src/client/components/Markdown.tsx b/src/client/components/Markdown.tsx index fc566e3..34766b9 100644 --- a/src/client/components/Markdown.tsx +++ b/src/client/components/Markdown.tsx @@ -11,7 +11,7 @@ type Props = { /** * Shared Markdown renderer with explicit per-element Tailwind classes. * - * OpenSEO doesn't ship `@tailwindcss/typography`, so `prose` classes are + * CrawlerX doesn't ship `@tailwindcss/typography`, so `prose` classes are * no-ops — every block element is styled here instead. Tables use daisyUI's * `table table-sm` so model- and strategy-generated tables stay readable. * diff --git a/src/client/components/Sidebar.tsx b/src/client/components/Sidebar.tsx index e85b140..849434f 100644 --- a/src/client/components/Sidebar.tsx +++ b/src/client/components/Sidebar.tsx @@ -129,9 +129,14 @@ export function Sidebar({ projectId, onNavigate, onClose }: SidebarProps) { - OpenSEO + + CrawlerX {onClose ? (

- Want advice from other OpenSEO users?{" "} + Want advice from other CrawlerX users?{" "}

- Upgrade to keep working with Sam and unlock the full OpenSEO app. + Upgrade to keep working with Sam and unlock the full CrawlerX app.

- For more powerful AI workflows, use the OpenSEO MCP with your own agent + For more powerful AI workflows, use the CrawlerX MCP with your own agent like Claude Code or Hermes.

diff --git a/src/client/layout/AppShell.tsx b/src/client/layout/AppShell.tsx index f4231f9..ced7521 100644 --- a/src/client/layout/AppShell.tsx +++ b/src/client/layout/AppShell.tsx @@ -180,8 +180,16 @@ function MobileTopBar({ > - - OpenSEO + + + CrawlerX ); diff --git a/src/client/layout/AppShellParts.tsx b/src/client/layout/AppShellParts.tsx index c451762..3a15ae1 100644 --- a/src/client/layout/AppShellParts.tsx +++ b/src/client/layout/AppShellParts.tsx @@ -19,7 +19,7 @@ function SeoApiStatusBanners({
- Setup needed: add your DataForSEO API key to use OpenSEO + Setup needed: add your DataForSEO API key to use CrawlerX features. See the quick steps on the{" "} - Add your DataForSEO API key to start using OpenSEO. + Add your DataForSEO API key to start using CrawlerX.

diff --git a/src/client/lib/error-messages.test.ts b/src/client/lib/error-messages.test.ts index 6f5b6d4..7d271ec 100644 --- a/src/client/lib/error-messages.test.ts +++ b/src/client/lib/error-messages.test.ts @@ -7,7 +7,7 @@ import { describe("getStandardErrorMessage", () => { it("maps known error codes to standard copy", () => { expect(getStandardErrorMessage(new Error("PAYMENT_REQUIRED"))).toBe( - "An active hosted subscription is required before you can use OpenSEO.", + "An active hosted subscription is required before you can use CrawlerX.", ); }); diff --git a/src/client/lib/error-messages.ts b/src/client/lib/error-messages.ts index 09973b3..9dbc16f 100644 --- a/src/client/lib/error-messages.ts +++ b/src/client/lib/error-messages.ts @@ -4,9 +4,9 @@ import { isErrorCode, type ErrorCode } from "@/shared/error-codes"; const STANDARD_MESSAGES: Record = { UNAUTHENTICATED: "Please sign in and try again.", AUTH_CONFIG_MISSING: - "OpenSEO auth is not configured. Follow the README setup steps for Cloudflare Access.", + "CrawlerX auth is not configured. Follow the README setup steps for Cloudflare Access.", PAYMENT_REQUIRED: - "An active hosted subscription is required before you can use OpenSEO.", + "An active hosted subscription is required before you can use CrawlerX.", INSUFFICIENT_CREDITS: "You've run out of credits. Add more credits or upgrade your plan to continue.", FORBIDDEN: "You do not have access to this resource.", diff --git a/src/client/lib/theme.ts b/src/client/lib/theme.ts index e59012d..19d719f 100644 --- a/src/client/lib/theme.ts +++ b/src/client/lib/theme.ts @@ -2,8 +2,8 @@ import * as React from "react"; export type ThemePreference = "system" | "light" | "dark"; -const LIGHT_THEME_NAME = "openseo"; -const DARK_THEME_NAME = "openseo-dark"; +const LIGHT_THEME_NAME = "crawlerx"; +const DARK_THEME_NAME = "crawlerx-dark"; const THEME_STORAGE_KEY = "theme-preference"; const THEME_CHANGE_EVENT = "theme-preference-change"; diff --git a/src/client/styles/app.css b/src/client/styles/app.css index f8564f1..7cb240f 100644 --- a/src/client/styles/app.css +++ b/src/client/styles/app.css @@ -1,7 +1,26 @@ +@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"); @import "tailwindcss"; @theme { --container-8xl: 88rem; + --font-sans: + "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, + "Helvetica Neue", Arial, sans-serif; +} + +/* CrawlerX brand gradient (MetatronCube blue → deep black), used on the + sign-in surface and the sidebar header. */ +:root { + --brand-gradient: linear-gradient( + 135deg, + #3779b9 0%, + #0f1d34 70%, + #00060c 100% + ); +} + +.brand-gradient { + background-image: var(--brand-gradient); } :root { @@ -19,26 +38,26 @@ exclude: properties; } -/* Light theme */ +/* Light theme — CrawlerX / MetatronCube brand (primary #3779b9) */ @plugin "daisyui/theme" { - name: "openseo"; + name: "crawlerx"; default: true; prefersdark: false; color-scheme: light; - --color-base-100: oklch(100% 0 0); - --color-base-200: oklch(97% 0 0); - --color-base-300: oklch(92% 0 0); - --color-base-content: oklch(20% 0 0); - --color-primary: oklch(50% 0.12 262); - --color-primary-content: oklch(100% 0 0); - --color-secondary: oklch(55% 0.15 145); - --color-secondary-content: oklch(100% 0 0); - --color-accent: oklch(50% 0.12 262); - --color-accent-content: oklch(100% 0 0); - --color-neutral: oklch(25% 0 0); - --color-neutral-content: oklch(100% 0 0); - --color-info: oklch(70% 0.15 230); - --color-info-content: oklch(100% 0 0); + --color-base-100: #ffffff; + --color-base-200: #f6f8fa; + --color-base-300: #e6eaef; + --color-base-content: #151515; + --color-primary: #3779b9; + --color-primary-content: #ffffff; + --color-secondary: #0f1d34; + --color-secondary-content: #ffffff; + --color-accent: #4faede; + --color-accent-content: #06263a; + --color-neutral: #151515; + --color-neutral-content: #ffffff; + --color-info: #3779b9; + --color-info-content: #ffffff; --color-success: oklch(65% 0.18 145); --color-success-content: oklch(100% 0 0); --color-warning: oklch(80% 0.15 80); @@ -57,23 +76,23 @@ /* Dark theme - auto-activates via prefers-color-scheme */ @plugin "daisyui/theme" { - name: "openseo-dark"; + name: "crawlerx-dark"; prefersdark: true; color-scheme: dark; - --color-base-100: oklch(18% 0 0); - --color-base-200: oklch(12% 0 0); - --color-base-300: oklch(27% 0 0); - --color-base-content: oklch(92% 0 0); - --color-primary: oklch(66% 0.12 262); - --color-primary-content: oklch(100% 0 0); - --color-secondary: oklch(60% 0.15 145); - --color-secondary-content: oklch(100% 0 0); - --color-accent: oklch(66% 0.12 262); - --color-accent-content: oklch(100% 0 0); - --color-neutral: oklch(85% 0 0); - --color-neutral-content: oklch(20% 0 0); - --color-info: oklch(70% 0.15 230); - --color-info-content: oklch(100% 0 0); + --color-base-100: #141821; + --color-base-200: #0e121b; + --color-base-300: #232a37; + --color-base-content: #e8ebf0; + --color-primary: #3f8ad4; + --color-primary-content: #ffffff; + --color-secondary: #9fb3c8; + --color-secondary-content: #0e121b; + --color-accent: #4faede; + --color-accent-content: #06263a; + --color-neutral: #e8ebf0; + --color-neutral-content: #141821; + --color-info: #3f8ad4; + --color-info-content: #ffffff; --color-success: oklch(65% 0.18 145); --color-success-content: oklch(100% 0 0); --color-warning: oklch(80% 0.15 80); @@ -153,7 +172,7 @@ select { base-200, which is darker than the base-100 content panel in dark mode, so they read as sunken/disabled. Colored variants (primary, error, ...) set their own --btn-color and are excluded. */ -html[data-theme="openseo-dark"] +html[data-theme="crawlerx-dark"] .btn:not( .btn-primary, .btn-error, @@ -168,7 +187,7 @@ html[data-theme="openseo-dark"] /* Light mode: the base-200 default button is nearly invisible on the base-100 content panel; use a white surface with a visible border, matching inputs/selects. */ -html[data-theme="openseo"] +html[data-theme="crawlerx"] .btn:not( .btn-primary, .btn-error, @@ -251,28 +270,28 @@ html[data-theme="openseo"] --tw-ring-color: color-mix(in oklab, #d946ef 30%, transparent); } -html[data-theme="openseo-dark"] .tag-chip-slate { +html[data-theme="crawlerx-dark"] .tag-chip-slate { color: #cbd5e1; } -html[data-theme="openseo-dark"] .tag-chip-rose { +html[data-theme="crawlerx-dark"] .tag-chip-rose { color: #fda4af; } -html[data-theme="openseo-dark"] .tag-chip-amber { +html[data-theme="crawlerx-dark"] .tag-chip-amber { color: #fcd34d; } -html[data-theme="openseo-dark"] .tag-chip-lime { +html[data-theme="crawlerx-dark"] .tag-chip-lime { color: #d9f99d; } -html[data-theme="openseo-dark"] .tag-chip-emerald { +html[data-theme="crawlerx-dark"] .tag-chip-emerald { color: #6ee7b7; } -html[data-theme="openseo-dark"] .tag-chip-sky { +html[data-theme="crawlerx-dark"] .tag-chip-sky { color: #7dd3fc; } -html[data-theme="openseo-dark"] .tag-chip-violet { +html[data-theme="crawlerx-dark"] .tag-chip-violet { color: #c4b5fd; } -html[data-theme="openseo-dark"] .tag-chip-fuchsia { +html[data-theme="crawlerx-dark"] .tag-chip-fuchsia { color: #f5d0fe; } @@ -323,29 +342,29 @@ html[data-theme="openseo-dark"] .tag-chip-fuchsia { --tw-ring-color: color-mix(in oklab, #b91c1c 32%, transparent); } -html[data-theme="openseo-dark"] .score-tier-na { +html[data-theme="crawlerx-dark"] .score-tier-na { color: #cbd5e1; } -html[data-theme="openseo-dark"] .score-tier-1 { +html[data-theme="crawlerx-dark"] .score-tier-1 { color: #6ee7b7; } -html[data-theme="openseo-dark"] .score-tier-2 { +html[data-theme="crawlerx-dark"] .score-tier-2 { color: #bef264; } -html[data-theme="openseo-dark"] .score-tier-3 { +html[data-theme="crawlerx-dark"] .score-tier-3 { color: #fde047; } -html[data-theme="openseo-dark"] .score-tier-4 { +html[data-theme="crawlerx-dark"] .score-tier-4 { color: #fdba74; } -html[data-theme="openseo-dark"] .score-tier-5 { +html[data-theme="crawlerx-dark"] .score-tier-5 { color: #fca5a5; } -html[data-theme="openseo-dark"] .score-tier-6 { +html[data-theme="crawlerx-dark"] .score-tier-6 { color: #fda4af; } -html[data-theme="openseo-dark"] { +html[data-theme="crawlerx-dark"] { --trend-grid-color: oklch(78% 0.01 255 / 0.22); --trend-axis-color: oklch(84% 0.01 255 / 0.62); --trend-fill-start-opacity: 0.24; @@ -355,18 +374,18 @@ html[data-theme="openseo-dark"] { --trend-tooltip-shadow: oklch(0% 0 0 / 0.35); } -html[data-theme="openseo-dark"] .alert-warning { +html[data-theme="crawlerx-dark"] .alert-warning { @apply border-warning/60 bg-warning/20; } -html[data-theme="openseo-dark"] .alert-info { +html[data-theme="crawlerx-dark"] .alert-info { @apply border-info/60 bg-info/20; } -html[data-theme="openseo-dark"] .alert-success { +html[data-theme="crawlerx-dark"] .alert-success { @apply border-success/60 bg-success/20; } -html[data-theme="openseo-dark"] .alert-error { +html[data-theme="crawlerx-dark"] .alert-error { @apply border-error/60 bg-error/20; } diff --git a/src/routes/__root.tsx b/src/routes/__root.tsx index 66178a0..0d7b772 100644 --- a/src/routes/__root.tsx +++ b/src/routes/__root.tsx @@ -37,7 +37,7 @@ export const Route = createRootRoute({ head: () => ({ meta: [ { - title: "OpenSEO", + title: "CrawlerX", }, { charSet: "utf-8", diff --git a/src/routes/_app/ai.tsx b/src/routes/_app/ai.tsx index 872b176..07b5e0c 100644 --- a/src/routes/_app/ai.tsx +++ b/src/routes/_app/ai.tsx @@ -53,8 +53,9 @@ function AiPage() {

AI & MCP

- Connect your AI agent to OpenSEO. Run keyword research, SERP analysis, - domain lookups, and backlink reviews from your editor or chat. + Connect your AI agent to CrawlerX. Run keyword research, SERP + analysis, domain lookups, and backlink reviews from your editor or + chat.

{getAuthMode(import.meta.env.AUTH_MODE) === "cloudflare_access" ? ( @@ -92,9 +93,9 @@ function AiPage() {

- Paste this into any MCP client. This URL points at the OpenSEO + Paste this into any MCP client. This URL points at the CrawlerX instance you are using now, whether hosted, self-hosted, or local. - Sign in with OpenSEO when prompted. + Sign in with CrawlerX when prompted.

{isHostedClientAuthMode() ? (

@@ -154,9 +155,9 @@ function AiPage() { .

  • Paste the MCP URL above and click Add.
  • -
  • Approve the OpenSEO login when prompted.
  • +
  • Approve the CrawlerX login when prompted.
  • - Optional: after OpenSEO connects, click{" "} + Optional: after CrawlerX connects, click{" "} Configure @@ -216,17 +217,17 @@ function AiPage() { .
  • Paste the MCP URL above.
  • -
  • Approve the OpenSEO login when prompted.
  • +
  • Approve the CrawlerX login when prompted.
  • -

    OpenSEO Skills

    +

    CrawlerX Skills

    Skills give Codex and Claude Code reusable SEO workflows that can - call your OpenSEO MCP tools when live SERP, keyword, backlink, or + call your CrawlerX MCP tools when live SERP, keyword, backlink, or domain data is needed.

    @@ -237,7 +238,7 @@ function AiPage() { >

    - You can also auto-accept each OpenSEO skill: + You can also auto-accept each CrawlerX skill:

    @@ -320,7 +321,7 @@ function AiPage() { { title: "In-app SEO Research Agent", description: - "Ask questions and run research without leaving OpenSEO", + "Ask questions and run research without leaving CrawlerX", }, { title: "Content Assistant", diff --git a/src/routes/_app/billing.tsx b/src/routes/_app/billing.tsx index d64c0d4..9880ac4 100644 --- a/src/routes/_app/billing.tsx +++ b/src/routes/_app/billing.tsx @@ -196,7 +196,7 @@ function BillingPage() {
      {[ - "Access to all OpenSEO features", + "Access to all CrawlerX features", "Includes $10.00 of Usage Credits each month", ].map((item) => (
    • - OpenSEO needs the DATAFORSEO_API_KEY secret before + CrawlerX needs the DATAFORSEO_API_KEY secret before keyword, domain, and SEO data workflows can run.

      @@ -62,7 +62,7 @@ function DataforseoApiKeyHelpPage() {
    • In Cloudflare, go to Compute ->{" "} Workers & Pages - and open your OpenSEO Worker. + and open your CrawlerX Worker.
    • Open Settings. diff --git a/src/routes/_app/help/openrouter-api-key.tsx b/src/routes/_app/help/openrouter-api-key.tsx index 3f56edb..e363c72 100644 --- a/src/routes/_app/help/openrouter-api-key.tsx +++ b/src/routes/_app/help/openrouter-api-key.tsx @@ -16,9 +16,9 @@ function OpenrouterApiKeyHelpPage() { Set up your OpenRouter API key

      - OpenSEO needs the OPENROUTER_API_KEY secret before AI - features like SAM, the in-app SEO agent, can run. It is optional — - everything else in OpenSEO works without it. + CrawlerX needs the OPENROUTER_API_KEY secret before + AI features like SAM, the in-app SEO agent, can run. It is + optional — everything else in CrawlerX works without it.

      @@ -64,7 +64,7 @@ function OpenrouterApiKeyHelpPage() {
    -
  • Restart OpenSEO.
  • +
  • Restart CrawlerX.
  • @@ -78,7 +78,7 @@ function OpenrouterApiKeyHelpPage() {
  • In Cloudflare, go to Compute ->{" "} Workers & Pages - and open your OpenSEO Worker. + and open your CrawlerX Worker.
  • Open Settings. diff --git a/src/routes/_app/index.tsx b/src/routes/_app/index.tsx index c26beea..45238ad 100644 --- a/src/routes/_app/index.tsx +++ b/src/routes/_app/index.tsx @@ -76,7 +76,7 @@ function IndexRedirect() { return (
    { void refetch(); }} diff --git a/src/routes/_app/settings/index.tsx b/src/routes/_app/settings/index.tsx index e23ab89..525ed06 100644 --- a/src/routes/_app/settings/index.tsx +++ b/src/routes/_app/settings/index.tsx @@ -95,7 +95,7 @@ function PersonalSettings() {
    -

    Help improve OpenSEO

    +

    Help improve CrawlerX

    Share analytics and usage data.

    diff --git a/src/routes/_app/support.tsx b/src/routes/_app/support.tsx index a3bdce7..79e10df 100644 --- a/src/routes/_app/support.tsx +++ b/src/routes/_app/support.tsx @@ -32,7 +32,7 @@ function SupportPage() {

    We want to talk to you! We're super open to feedback and want to learn - how you work so we can make OpenSEO better. + how you work so we can make CrawlerX better.

    diff --git a/src/routes/_auth.sign-up.tsx b/src/routes/_auth.sign-up.tsx index 00cf51e..a448037 100644 --- a/src/routes/_auth.sign-up.tsx +++ b/src/routes/_auth.sign-up.tsx @@ -87,7 +87,7 @@ function SignUpPage() { redirect_to: redirectTo, }); const resolvedName = - value.name.trim() || email.split("@")[0] || "OpenSEO User"; + value.name.trim() || email.split("@")[0] || "CrawlerX User"; const verificationCallbackURL = new URL( "/verify-email", window.location.origin, diff --git a/src/routes/_authenticated.oauth-consent.tsx b/src/routes/_authenticated.oauth-consent.tsx index 35f7629..878cbdc 100644 --- a/src/routes/_authenticated.oauth-consent.tsx +++ b/src/routes/_authenticated.oauth-consent.tsx @@ -11,7 +11,7 @@ export const Route = createFileRoute("/_authenticated/oauth-consent")({ const SCOPES = [ { icon: Database, - label: "Read your OpenSEO data", + label: "Read your CrawlerX data", description: "Projects, keyword reports, and audit results.", }, { @@ -74,12 +74,12 @@ function OAuthConsentPage() {
    OpenSEO

    Authorize MCP access

    - An MCP client is requesting access to your OpenSEO workspace. + An MCP client is requesting access to your CrawlerX workspace.

    diff --git a/src/routes/_authenticated.subscribe.tsx b/src/routes/_authenticated.subscribe.tsx index 37326f0..c66da7e 100644 --- a/src/routes/_authenticated.subscribe.tsx +++ b/src/routes/_authenticated.subscribe.tsx @@ -136,7 +136,7 @@ function SubscribePage() {
    OpenSEO

    @@ -163,7 +163,7 @@ function SubscribePage() {
    OpenSEO

    Billing unavailable

    @@ -223,15 +223,15 @@ function SubscribePage() {
    OpenSEO

    {isUpgradeFlow ? "Upgrade your plan" : firstName - ? `Welcome to OpenSEO, ${firstName}!` - : "Welcome to OpenSEO!"} + ? `Welcome to CrawlerX, ${firstName}!` + : "Welcome to CrawlerX!"}

    SEO on your terms. All your SEO tools in one place at a fair price. diff --git a/src/routes/accept-invitation.$id.tsx b/src/routes/accept-invitation.$id.tsx index c4975ab..f3e758e 100644 --- a/src/routes/accept-invitation.$id.tsx +++ b/src/routes/accept-invitation.$id.tsx @@ -39,7 +39,7 @@ function SignedOutInvitationCard({ invitationId }: { invitationId: string }) { return (

    - You’ve been invited to join an organization on OpenSEO. Sign in + You’ve been invited to join an organization on CrawlerX. Sign in with the email address that received the invitation to accept it.

    @@ -212,7 +212,7 @@ function InvitationCard({ {invitationQuery.data.organizationName} {" "} - on OpenSEO. + on CrawlerX.

    {actionError ?

    {actionError}

    : null}
    diff --git a/src/routes/auth-error.tsx b/src/routes/auth-error.tsx index c64c432..6280c27 100644 --- a/src/routes/auth-error.tsx +++ b/src/routes/auth-error.tsx @@ -39,7 +39,7 @@ function AuthErrorPage() { } > - Back to OpenSEO + Back to CrawlerX