- DaisyUI themes openseo/openseo-dark -> crawlerx/crawlerx-dark on the
MetatronCube palette (primary #3779b9, secondary #0f1d34, accent #4faede)
- Load Inter as the app font; add --brand-gradient / .brand-gradient
- Cube mark + "CrawlerX" wordmark in the sidebar and mobile top bar
- Add public/crawlerx-mark.png; point transparent-logo.png at the cube mark
- <title>, site.webmanifest, and all user-facing "OpenSEO" copy across
src/client and src/routes -> "CrawlerX"
Deferred: favicons (need resizing), agent-facing identity (MCP server
name, SAM/onboarding prompts, fact sheet), web/ marketing site.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* feat(onboarding): hide agent chat step; subscribe after intro steps
Remove the hosted-only strategy-chat diversion from the onboarding
sequence. After the three intro questions, hosted users now hit the
subscribe paywall directly, then return to the GSC and MCP connect
steps. The chat route and components stay in place but unlinked, to be
revisited later. Preserve the post-payment 'You're in!' interstitial by
carrying checkout=success through validateSearch.
* fix(onboarding): set checkout=success from subscribe route, not speculatively
The previous redirect baked checkout=success into the onboarding return
URL at the point needsSubscription is true — i.e. before the user had
paid. It only worked because the subscribe route gates its redirect on
actual access. Move the marker to the subscribe route's redirect-to-app
path, where checkoutCompleted reflects a real returned-from-Stripe
payment, so the 'You're in!' screen can never show pre-payment.
Bump all customer-facing references to the managed base plan price from
$10/month to $20/month, and scale the bundled "Includes $X of Usage
Credits" copy from $10 to $20 to match the price.
Covers the subscribe/billing pages, onboarding plan card and fact sheet,
backlinks/AI-search access gates, and the marketing pricing/comparison/
GSC pages plus the README.
Claude-Session: https://claude.ai/code/session_017QayWXGubs1JNbLbqRF4CS
Co-authored-by: Claude <noreply@anthropic.com>
* track core product analytics flows
Track auth, search, export, audit, and credit-consumption events with canonical route IDs so PostHog funnels and usage dashboards stay low-noise and privacy-safe.
* fix: keep auth actions usable after session loss
* refactor: simplify analytics and auth helpers
- Replace isRecord/getActiveOrganizationId type guards with simple cast
- Refactor getAnalyticsRouteContext from if/return chain to route tables
- Replace toVerificationIssueType switch with zod enum
- Merge duplicate credits_consume events into single event per API call
- Merge two PostHogBootstrap useEffects into one
* refactor: add projectId to middleware context to reduce boilerplate
The requireProjectContext middleware now includes projectId directly,
eliminating repeated manual construction of BillingCustomerContext
objects across all server function handlers.
* remove unused BILLING_* env var fallbacks from cost profile script
* remove before_send event enrichment to preserve native PostHog URL tracking
The before_send hook was stripping $pathname, $current_url, $referrer and
other URL properties, which breaks PostHog web analytics dashboards, paths
analysis, session replay, and attribution. The route_id/route_group injection
it provided is unnecessary since PostHog already captures $pathname natively.
* remove route mapping layer, pass raw redirect paths to analytics events
The route ID registry (STATIC_ROUTES, PROJECT_ROUTES, getAnalyticsRouteContext,
getRedirectRouteId) duplicated what PostHog already captures via $pathname.
Replace redirect_route_id with redirect_to containing the raw path, and remove
~80 lines of route mapping infrastructure.
* clean up analytics events: drop redundant submit events and derived properties
- Remove search_submit events for keywords, domain overview, and backlinks
(the search_complete events capture the meaningful outcome data)
- Remove target_type from backlinks events (derived 1:1 from search_scope)
- Remove result_limit from keyword research (requested limit, not useful
alongside actual result_count)
- Remove export_format from data:export events (always "csv")
* refactor: inline wrappers, colocate helpers, deduplicate getActiveOrganizationId
- Inline toVerificationIssueType into verify-email.tsx (single-use wrapper)
- Move mapDataforseoPathToCreditFeature into dataforseoClient.ts (only consumer)
- Extract shared getActiveOrganizationId into lib/auth-session.ts (was
duplicated in __root.tsx and middleware/ensure-user/hosted.ts)
- Rename shared/analytics.ts → shared/internal-user.ts (only email helpers
remain after removing route mapping, verification, and dataforseo helpers)
* remove internal user tracking and email domain properties
Drop is_internal_user super property, email_domain person property, and all
supporting code (shared/internal-user.ts, getEmailDomain, isInternalUserEmail).
Simplifies initPostHog and identifyAnalyticsUser signatures.
* remove backlinks:search_complete effect-based tracking
The reactive useEffect + useRef dedup pattern added ~30 lines of plumbing
inside a data hook for a single analytics event. Not worth the complexity.
* simplify: replace manual type guards with zod, deduplicate posthog and sign-out helpers
- Replace hand-rolled typeof checks in getActiveOrganizationId and
isAuthenticatedServerFunctionContext with zod safeParse
- Extract withPostHogClient helper to deduplicate client posthog wrapper
- Move apiKey guard into getServerPostHogClient factory
- Extract signOutAndRedirect to avoid duplicated sign-out logic
- Drop derivable has_results from analytics events
- Remove unnecessary path normalization in mapDataforseoPathToCreditFeature
* fix: strip email from pageview URLs, restore sign-out guard, harden server posthog, fix path mapper
- Sanitize $current_url on pageviews to remove email query param (PII)
- Restore onSuccess for sign-out redirect to avoid bounce-back on failure
- Swallow shutdown() errors so PostHog outages can't fail billed work
- Rewrite mapDataforseoPathToCreditFeature to match real API path structure
(path[1] = module, path[3] = endpoint) instead of scanning all segments
* simplify: remove redundant refs in verify-email, infer middleware context type
- Remove unnecessary useRef guards in verify-email effects (deps already prevent re-firing)
- Use z.ZodType<EnsuredUserContext> annotation to infer return type instead of casting
- Add comment explaining one-shot PostHog client on Workers
* fix: reset PostHog identity on sign-out before redirect
* fix: require POSTHOG_HOST env var instead of defaulting to us.i.posthog.com
* fix: annotate url as unknown to satisfy no-unsafe-assignment
* format
* feat: add theme switcher with system/light/dark segmented control
Add a three-way theme toggle (system, light, dark) as a segmented
icon control in the account dropdown menu. Rename placeholder daisyUI
theme names from "todo" to "openseo".
* refactor: always resolve data-theme explicitly, remove duplicated dark CSS
Instead of removing data-theme in "system" mode and relying on
@media (prefers-color-scheme: dark) CSS, always resolve to an
explicit theme name via matchMedia. This eliminates the duplicated
dark-mode CSS overrides.
* fix: use full page reload after email verification
Client-side navigation via TanStack Router during the auth→app
transition can race with Vite HMR, causing "action is not a function"
server function errors.
* feat: add minimal /subscribe onboarding page
New post-auth subscribe page at /subscribe using the same centered
layout as auth pages. Shows plan details and a single Subscribe CTA.
Redirects PAYMENT_REQUIRED users here instead of /billing.
* redesign: rewrite billing page with usage chart and cleaner layout
Delete the sprawling multi-component billing page and replace it with a
single-file implementation. Two cards sit side by side at the top
(subscription summary + buy credits), with a 30-day usage bar chart
below powered by Autumn's useAggregateEvents hook and recharts.
Removed BillingRouteParts.tsx, HostedBillingContent.tsx, and trimmed
HostedBillingContentUtils to only parseTopUpAmount.
* polish: billing page improvements and OpenSEO nav link
- Two-column layout with subscription summary and buy credits side by side
- Usage bar chart using ResizeObserver instead of ResponsiveContainer
- Input validation with inline error message
- Full-page redirect state when navigating to Stripe
- Make OpenSEO logo in navbar link to /
* fix: guard app routes and include top-up usage
* fix: restore billing onboarding guards
Keep unpaid orgs on /subscribe and avoid misleading billing states when Autumn customer lookups fail.
* fix: split billing usage chart for ci checks