13 Commits

Author SHA1 Message Date
Ben Senescu
45234e6945
Fix backlink tab states (#218)
* Fix tab active state wiring across result views

* Add spam filters to referring domains
2026-05-22 22:49:05 -04:00
Ben Senescu
44073498ed
Use TanStack links for internal table and shell navigation (#215)
* Use TanStack Link for audit issues and external RD links

* Use router link for billing menu

* Fix brand lookup tooltip clipping
2026-05-22 21:29:45 -04:00
Ben Senescu
2484f93ce6
Refactor pages to improve performance and consistency (#205) 2026-05-20 17:23:09 -04:00
Ben Senescu
fb265e3a3a ci: run prettier 2026-05-06 15:45:09 -04:00
Ben Senescu
0c356fac19 fix: change google sheets export copy 2026-05-06 15:43:26 -04:00
Ben Senescu
c1a9c1f57d
Replace mutation-based search with URL-driven state management (#145)
* fix: preserve cmd+click on tracked domain rows

Tracked-domain rows used <div role="button" onClick={navigate(...)}>,
which prevented standard browser open-in-new-tab behavior (cmd+click,
middle-click, right-click → open). Use TanStack Router's <Link> as a
stretched overlay so the row is a real <a href> while the archive
button stays interactive.

* fix: use <Link> for tab toggles and history navigation

Replace onClick={() => navigate(...)} / setSearchParams patterns with
TanStack Router's <Link> across surfaces that change the URL on click.
<Link> renders a real <a href> and only intercepts plain left-clicks,
so cmd/ctrl+click, middle-click, and right-click → open-in-new-tab
all work natively.

- Audit: history "View" button + Pages/Performance tab toggles.
- Domain overview: Top Keywords / Top Pages tab toggles. The keyword-
  only sort fallback now happens in the Link's search updater.
- Backlinks: history items, Backlinks/Domains/Pages tab toggles, and
  "Recent searches" back-link. Removes now-unused
  navigateToBacklinksHistory / navigateToBacklinksTab helpers.

Keyword research and domain history items, and AI search histories,
are not converted: those pages don't trigger their data fetch from
URL params alone, so a plain link target wouldn't reproduce the
current click behavior without a deeper refactor.

* refactor: unify search-page state around URL-driven fetching

Drive Keyword Research, Brand Lookup, and Prompt Explorer from URL
search params so a search is reproducible from a link alone. With
that, all three history surfaces become <Link>s and cmd+click /
right-click → "open in new tab" work natively.

- Shared SearchHistorySection now takes a renderItemLink slot so
  callers wrap history items in a <Link> with the right destination.
- Prompt Explorer: added URL search params (q, models, web, cc, hb)
  via promptExplorerSearchSchema; switched the explore mutation to
  useQuery keyed on the URL params; addSearch now fires from a
  success effect; "Recent searches" back-button is a <Link>.
- Brand Lookup: history items + "Recent searches" back-button are
  <Link>s; local form state stays in sync with URL via an effect.
- Keyword Research: form submit still navigates+kicks off a search
  for the same-URL re-submit case, but the controller also runs an
  URL-driven search trigger (with a dedup ref against the form path).
  Direct URLs, cmd+click on history, and browser back/forward all
  reproduce the same fetch. "Recent searches" back-button and the
  history items are <Link>s; the bespoke resetView path is gone.

Also drops now-unused clearKeywordSearchParams,
navigateToBacklinksHistory/Tab helpers' last consumers, and the
PromptExplorerPage's onQueryChange/onSelectHistoryItem callbacks.

* format

* refactor: replace useMutation with manual state in keyword research

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-05-04 13:00:37 -04:00
Ben Senescu
ab50e59ff8
feat: add 'Export to Google Sheets' to every data table (#144) 2026-05-03 15:25:25 -04:00
Ben Senescu
bbed7c760a fix: lock lighthouse launch flow to auto sampling (#80)
* fix: lock lighthouse launch flow to auto sampling

* save
2026-04-08 14:09:02 -04:00
Ben Senescu
ae7712238e refactor: use TanStack Form everywhere (#49)
* refactor: move lighthouse audits to dataforseo (#43)

* refactor: move lighthouse audits to dataforseo

* chore: remove obsolete audit settings modal

* refactor: rename psi flows to lighthouse

* save

* refactor: simplify audit lighthouse storage flow

* fix: separate lighthouse metrics from actionable audits

* refactor: remove redundant audit project inputs

* feat: redesign lighthouse issues screen with score gauges and table layout

Replace flat score cards with circular SVG gauges, condense metrics into
a compact grid, and switch issue list from cards to an expandable table
with fixed column widths.


* test: harden lighthouse regression coverage

* fix: restore project-scoped audit inputs

* refactor: simplify lighthouse payload handling

* refactor: inline lighthouse server handlers

* refactor: share audit workflow types

* refactor: simplify lighthouse payload flows

* save

* refactor: drop project pagespeed api key

* fix: restore lighthouse issues loading with resilient project context

* fix: restore audit issues back navigation

* refactor: simplify project context and lighthouse error handling

* fix: tolerate DataForSEO lighthouse payload drift

* refactor: route audit lighthouse through dataforseo client

---------


* refactor: unify app forms with TanStack Form

Replace bespoke field and submit error state so validation, async submit handling, and router-synced inputs behave consistently across the app.

* fix: remove dead code from ci check

* fix: delay required form errors until input interaction

* fix: preserve detailed DataForSEO error messages

* fix: sanitize internal errors and delay domain validation

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 13:38:08 -04:00
Ben Senescu
638f5a6602 refactor: move lighthouse audits to dataforseo (#43)
* refactor: move lighthouse audits to dataforseo

* chore: remove obsolete audit settings modal

* refactor: rename psi flows to lighthouse

* save

* refactor: simplify audit lighthouse storage flow

* fix: separate lighthouse metrics from actionable audits

* refactor: remove redundant audit project inputs

* feat: redesign lighthouse issues screen with score gauges and table layout

Replace flat score cards with circular SVG gauges, condense metrics into
a compact grid, and switch issue list from cards to an expandable table
with fixed column widths.

* test: harden lighthouse regression coverage

* fix: restore project-scoped audit inputs

* refactor: simplify lighthouse payload handling

* refactor: inline lighthouse server handlers

* refactor: share audit workflow types

* refactor: simplify lighthouse payload flows

* save

* refactor: drop project pagespeed api key

* fix: restore lighthouse issues loading with resilient project context

* fix: restore audit issues back navigation

* refactor: simplify project context and lighthouse error handling

* fix: tolerate DataForSEO lighthouse payload drift

* refactor: route audit lighthouse through dataforseo client
2026-03-26 20:25:27 -04:00
Ben Senescu
4040a854a7
feat: Add better auth (#24)
* refactor: rename delegated auth user table

* feat: scaffold hosted better auth setup

* feat: add hosted auth flows

* refactor: scope project access to organizations

* fix: harden hosted auth entry points

* fix: stabilize org backfills and auth state

* refactor: simplify hosted organization setup

* fix: restore hosted auth signup flow

* fix: preserve hosted workspace access

* fix: preserve hosted auth redirects

* Improve hosted auth UX: auto-redirect to sign-up, hide header on auth pages, add form placeholders, and trust portless dev origins

- Auto-redirect unauthenticated users to /sign-up in hosted mode
- Hide top nav on /sign-in and /sign-up for a cleaner auth experience
- Add input placeholders across sign-in and sign-up forms
- Make name field optional on sign-up (falls back to email username)
- Update copy: remove 'hosted' from user-facing text, rename link to 'Create account'
- Trust *.open-seo.localhost:1355 in dev mode to fix Better Auth origin rejection with portless worktrees

* Simplify hosted auth flow and remove standalone PSI

Use TanStack Form for sign-in and sign-up, make hosted unauthenticated handling redirect-focused, and inline auth route errors. Remove the leftover standalone PSI route, services, and table so PSI only exists within site audits.

* Align project auth with Better Auth organizations

* Make server function auth middleware global

* Reduce auth server function boilerplate

* delete migrations

* fix regenerated migration data backfills

* Simplify hosted auth flow and project audit scoping

* Use active project context for audit actions

* Allow hosted session project updates

* Let agent dev server inherit auth mode

* Match hosted header to gateway account menu

* Scope project session updates to active project

* Inline authenticated server function setup

* Polish header project and account controls

* restore auth generate script

* Use explicit project access in server functions

Make project-scoped server functions take projectId input and enforce ownership through shared middleware instead of session-backed current project state. Document the tradeoffs in an ADR so future changes can follow the same boundary.

* fix ci dependency detection for auth tooling

* Harden project auth in server middleware

Authorize projectId automatically in authenticated server middleware and add a requireProject guard for project-scoped handlers. This makes the auth boundary harder to bypass and removes ad hoc non-null assertions from server functions.

* Inline project id input schemas

Remove tiny shared projectId schema helpers where they were adding indirection without reducing real complexity. Keep project-scoped validation explicit at each server function boundary.

* Skip hosted backlinks access checks

* Simplify auth mode helpers

* Avoid rerunning auth server middleware

* Simplify server function scoping ADR

* Fix backlinks project scoping in hosted auth

* Refine auth route foundations

* Simplify ensure user auth resolution

Split auth-mode context resolvers into focused modules so the middleware reads as request orchestration instead of implementation details. Reuse a shared ensured-user context type across server middleware.

* Simplify hosted organization bootstrap

Use Better Auth to own hosted organization creation and membership so hosted auth only needs to resolve a default active organization. Keep delegated-mode compatibility records isolated in a separate helper.

* Clarify hosted auth and backlinks behavior

Document the hosted AUTH_MODE deploy contract and explain why hosted deployments skip manual backlinks verification. This makes the platform-managed behavior explicit in the code paths that differ from self-serve mode.

* Document hosted org creation callback

Explain why auth.ts injects createOrganization into the hosted org helper. This makes the dependency direction explicit and avoids future import cycles while keeping the helper reusable.

* Fix CI check failures

* Fix nav link prop forwarding

* save
2026-03-19 19:24:34 -04:00
Ben Senescu
c0d64f366e
feat: add support for more countries (#25)
* fix: cap per-user audit capacity

Block new audits before a user exceeds the temporary 100k audit footprint cap. Surface a clear delete-old-audits message in the audit launch UI.

* fix: reserve audit capacity with Drizzle

* fix: add Ireland keyword location support

* feat: expand keyword country defaults

* test: add keyword location smoke test

* test: load keyword smoke test env locally

* chore: remove keyword location smoke test

* refactor: simplify keyword location state

* fix: preserve explicit keyword location params
2026-03-16 14:20:16 -04:00
Ben Senescu
75f9868500
fix: Refactor folder structure & services (#17)
* refactor: simplify keyword source selection flow

* fix: improve stacked keyword page layout

* fix: keep SERP tied to searched keyword

Stop silently falling back SERP lookups to related keywords and show a keyword-specific empty message so missing coverage is explicit to users.

* refactor: extract keyword controller and switch SERP to live

Move keyword research orchestration out of the route, call DataForSEO organic live SERP, and harden response normalization with runtime validation for safer typed handling.

* refactor: split keyword research page state into focused hooks

* fix: aggregate auto keyword fallback and reuse cached results

* scope keyword metrics to projectId

* refactor: modularize SEO routes and harden parsing for CI checks

* refactor: adopt zod json codecs at parse boundaries

* refactor: adopt papaparse, tldts, and zod error enums

* refactor: reorganize client and server feature layout

Group keyword UI/controller files and server repositories/services by feature while keeping serverFunctions as the stable API surface. This improves navigation and maintainability without changing runtime behavior.

* refactor: move PSI business logic into service layer

Keep serverFunctions/psi as thin transport handlers by delegating orchestration, export shaping, and source resolution to PsiAuditService. This aligns PSI with the existing service-first backend pattern without changing endpoint behavior.

* refactor: enforce 350/120 size limits across modules

* move self host

* fix: show dynamic range for search trends

Replace the static 'Past 12 months' subtitle with a computed range from the actual plotted trend points so the UI reflects data lag correctly.

* fix: bind audit workflow writes to workflow instance

* chore: make ci checks pass
2026-03-11 23:01:52 -04:00