- Drop redundant codex mcp login step from the CLI flow
- Add Claude Desktop and Codex Desktop accordion entries
- Lead each setup-guide row with its product logo
- Move /p/$projectId/ai to /ai so the page can be linked directly
- Lead with a copyable MCP server URL and trim the surrounding copy
- Make Claude Code and Codex setup guides collapsible accordions
- Add an Available tools section grouped into Keywords and Domain
* 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>
Replace DOMAIN_REGEX with URL-based normalization so users can paste
full URLs (e.g. https://example.com/path) into the domain config form
without getting a ZodError. The URL class handles protocol stripping,
hostname extraction, and validation natively.
* feat: group navigation into Keywords, Domain, and AI dropdowns
Reorganize the top nav from 7 flat items into grouped dropdowns:
- Keywords: Keyword Research, Saved Keywords, Rank Tracking
- Domain: Domain Overview, Backlinks, Site Audit
- AI: standalone link
Mobile sidebar uses section headers for the same groupings.
Active dropdown items are highlighted with primary tint.
* fix: use matchSegment lookup instead of hardcoded array indices in nav groups
* fix: default backlinks search to site-wide scope for root URLs
URLs with an explicit protocol but no path (e.g. https://example.com/)
were incorrectly auto-selecting "Exact page" scope. Now only URLs with
an actual path beyond "/" trigger page scope auto-selection.
* test: update backlinks scope tests for root URL behavior change
* feat: add structured filters to backlinks tables
Add per-tab filter panels (Backlinks, Referring Domains, Top Pages) with
include/exclude text search, numeric range filters, link type selector,
and visibility toggles. Filter values persist in localStorage across
searches and page reloads.
* fix: improve backlinks filter layout and hide domain overview filters on pages tab
- Add w-full to text filter inputs so they fill their grid columns
- Restructure backlinks results card to use border-separated sections
matching the domain overview pattern
- Hide filter button and panel on domain overview's Top Pages tab since
keyword filters don't apply there
* fix: move backlinks filter button to its own toolbar row below tabs
Match the domain overview layout: tabs in their own header row, then a
separate toolbar row with the Filters button underneath.
* style: fix prettier formatting in backlinks filter files
* fix: resolve all ci:check issues
- Remove unused BacklinksResultsHeader.tsx and useBacklinksSpamPreferences.ts
- Un-export DEFAULT_BACKLINKS_SPAM_THRESHOLD and normalizeBacklinksSpamThreshold
(only used internally)
- Remove unused BacklinksAllFilterValues type
- Fix oxlint unsafe type assertions in useBacklinksFilters.ts
* fix: wire spam filter options through to server and remove spam filters from non-backlinks tabs
The client was not passing hideSpam/spamThreshold to the server, so the
server always defaulted to hideSpam:true with threshold 40. This made
the new client-side spam score filters on the backlinks tab silently
filter an already-truncated dataset. Now the client sends hideSpam:false
so the server returns all rows and client-side filtering works correctly.
Removed spam score filters from the Referring Domains tab since spam
filtering is not needed there.
* fix: restore backlinks spam filtering and safe filter hydration
* simplify: remove server-side spam filter wiring, keep client-side only
All backlinks filtering (including spam score) is now done client-side.
Server-side spam filtering adds complexity without meaningful benefit
at current data volumes. This removes the bridging code added in the
last two commits and simplifies filter hydration.
* feat: add top-level persistent filters for keyword research
Add a collapsible filter bar below the search bar so users can set
default filters (volume, CPC, difficulty, include/exclude terms) that
persist across searches and sessions via localStorage.
* simplify: remove top-level filter UI, keep only localStorage persistence
Revert the search bar to its original state. The existing in-table
filters already provide good UX — all we needed was persistence.
Auto-expand the filter panel when persisted filters are active on load.
* feat: show filtered keyword count as "Showing X of Y keywords"
When filters are active, display "Showing 14 of 150 keywords" instead
of just "14 keywords". When no filters are active, show "Showing X
keywords". Applied to both desktop and mobile views.
* style: fix prettier formatting
* feat: add backlink search history
Save recent backlink searches so users can quickly rerun previous lookups instead of starting from an empty state each time. Also widen the keyword research empty state layout to better use the available space.
* update dev tools
* update recent search navigation across SEO pages
* refine search layouts and recent search navigation
* simplify recent search resets and history storage
* save
* fix recent search hydration mismatch
* fix ci lint issues