-
Hey, I’m Sam — welcome to OpenSEO.
+
Hey, I’m Sam — welcome to CrawlerX.
- To get full access to OpenSEO, you need to upgrade to the paid plan.
- But, I’m here if you have any questions.
+ To get full access to CrawlerX, you need to upgrade to the paid
+ plan. But, I’m here if you have any questions.
You can also{" "}
@@ -146,7 +146,9 @@ export function UpgradeSidebar({
-
Previewing OpenSEO
+
+ Previewing CrawlerX
+
{domain}
@@ -187,7 +189,7 @@ export function UpgradeSidebar({
{isStartingCheckout ? "Redirecting..." : "Upgrade to continue"}
- 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.
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() {