332 Commits

Author SHA1 Message Date
Ben Senescu
103b6fe91c
fix: add additional well known for claude.ai + Claude Desktop (#170)
* Simplify MCP discovery metadata and lazy auth flow

* Fix ci check for MCP discovery branch
2026-05-08 15:59:43 -04:00
Ben Senescu
36b60f240f
Merge pull request #165 from bensenescu/codex/update-ai-tab
Update the AI tab for MCP setup and usage guidance
2026-05-08 15:30:18 -04:00
Ben Senescu
38fbac159f ci: run prettier on AI page 2026-05-08 15:27:12 -04:00
Ben Senescu
239a5a9e2b Add Claude and Codex desktop setup guides with brand logos
- 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
2026-05-08 15:20:42 -04:00
Ben Senescu
93ee343c63 Polish AI & MCP page and move out of project scope
- 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
2026-05-08 14:56:26 -04:00
Ben Senescu
f861d1d57e
Merge pull request #164 from bensenescu/codex/fix-invalid-offlineaccess-scope
fix: support claude for mcp
2026-05-08 14:18:59 -04:00
Ben Senescu
02fcfb9834 Update AI page for MCP setup guidance 2026-05-08 13:40:51 -04:00
Ben Senescu
4cd02e36f4 Advertise offline_access in MCP scope metadata 2026-05-08 13:40:26 -04:00
Ben Senescu
04497dd90e
Merge pull request #163 from bensenescu/feat/mcp
feature: implement mcp server
2026-05-08 00:35:10 -04:00
Ben Senescu
57790b930f
feat: add OpenSEO MCP tools (#161) 2026-05-08 00:34:29 -04:00
Ben Senescu
0ff7bc96b2
Add stateless MCP server (#162) 2026-05-07 23:38:00 -04:00
Ben Senescu
6231424e88
feat: add personal access tokens (#159)
* feat: add personal access tokens

* feat: replace MCP tokens with OAuth foundation

* fix: keep OAuth constants private in auth foundation

* fix: clean up mcp oauth branch scope

* fix: expose oauth metadata endpoints

* fix: trim mcp oauth config to non-default options

Drop OIDC scopes, the org-id JWT claim, and the openid-configuration
metadata endpoint since the MCP integration is OAuth-only and the org
gets resolved server-side. Also remove options that just duplicated
better-auth defaults.

* fix: drop redundant oauth metadata helpers

Remove `session.storeSessionInDatabase: true` since better-auth only
enforces it when secondaryStorage is configured. Inline the
`getHostedBaseUrlForOAuthMetadata` alias and skip the async
`getOAuthServerConfig()` call in the protected-resource metadata handler
— the issuer is just `baseURL` without a custom jwt.issuer override.

* docs: explain cache headers on mcp metadata response

* Use escaped file routes for OAuth metadata

* save
2026-05-06 22:41:02 -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
53f8a6e186
v0.0.10 (#158) 2026-05-06 15:35:51 -04:00
Ben Senescu
ca260f544b
feat: improve mobile UX (#155) 2026-05-06 12:52:05 -04:00
Ben Senescu
b9ad31704f
Clarify keyword intent badges (#157) 2026-05-06 12:30:33 -04:00
Ben Senescu
9e5afc9d48
feat: Add shared table component (#154)
* fix rank tracking unranked filters

* improve modal dismissal and range selection

* refactor: create shared table component
2026-05-06 11:23:07 -04:00
Ben Senescu
7f892ca433
Merge pull request #19 from every-app/split-modal-dismissal
fix: exit closes modal + accessible labels
2026-05-06 10:46:45 -04:00
Ben Senescu
6f50850b5a
fix rank tracking unranked filters (#18)
Co-authored-by: Granata005 <granata005@gmail.com>
2026-05-06 10:46:33 -04:00
Ben Senescu
6b7d0464f7
feat: add shift range table selection (#20)
* add shift range table selection

* format keyword suggestion selection

* credit original draft author

Co-authored-by: Granata005 <granata005@gmail.com>

---------

Co-authored-by: Granata005 <granata005@gmail.com>
2026-05-06 10:46:21 -04:00
Ben Senescu
89091ca9d5
refactor: simplify rank tracking backend (#125) 2026-05-05 22:18:35 -04:00
Ben Senescu
db1a1d723f
fix: use Tanstack Query for Keyword Research (#150)
* keywords: use query cache for research requests

* keywords: simplify research request dedupe
2026-05-05 14:11:28 -04:00
Ben Senescu
2fc568f73c
release: v0.0.9 (#149) 2026-05-04 15:55:15 -04:00
Ben Senescu
def9390cea
feat: Implement server-side pagination and filtering for domain keywords (#143) 2026-05-04 15:26:36 -04:00
Ben Senescu
a42fe4d350
keywords: consolidate export buttons into dropdown (#147) 2026-05-04 14:04:44 -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
11252f8088
fix: improve spreadsheet exports (#146) 2026-05-04 12:49:42 -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
368b3ce375 website: add faq 2026-04-28 21:03:17 -04:00
Ben Senescu
2130dccc81 hosted: add posthog opt out + session replay 2026-04-28 20:56:06 -04:00
Ben Senescu
3e39c65265
docs: clarify self-hosting troubleshooting (#140)
* docs: clarify self-hosting troubleshooting

* docs: simplify Docker env troubleshooting
2026-04-28 17:39:38 -04:00
Ben Senescu
17298da7ee
fix: capture DataForSEO errors with context (#138) 2026-04-24 00:16:20 -04:00
Ben Senescu
94d1ee7bd5
chore: release v0.0.8 (#132) 2026-04-23 18:25:37 -04:00
Ben Senescu
ebc9e0b4fa
fix: prompt explorer bugs (#136) 2026-04-23 18:25:11 -04:00
Ben Senescu
1108cdd9a7
feat: gate llm mentions in self hosted product (#134) 2026-04-23 18:02:24 -04:00
Ben Senescu
65d62f0eed
website: fix mobile header and footer layout (#135)
Hide Sign in and GitHub text label on small screens, wrap footer
links onto multiple rows, and clip any horizontal overflow globally.
2026-04-23 11:54:54 -04:00
Ben Senescu
4c8a3305ed
fix: preserve query case in brand lookup cache key (#133)
Drop the .toLowerCase() call when building the cache key's targetValue so
it matches whatever detectTarget returns. detectTarget already normalizes
domains to lowercase; keywords are passed through as-is, so lowercasing
again folded otherwise-distinct keyword queries into the same cache
entry.
2026-04-23 11:41:44 -04:00
Ben Senescu
faf7a294a3
feat: AI Visibility — Brand Lookup and Prompt Explorer (#128) 2026-04-23 10:48:38 -04:00
Ben Senescu
da2509ec74
ci: use correct posthog-cli env var names (#131) 2026-04-22 17:49:44 -04:00
Ben Senescu
61cc64f2af hosted: switch non-secrets to vars 2026-04-22 17:32:30 -04:00
Ben Senescu
d23cad7abf
hosted: upload sitemaps to posthog in ci (#130) 2026-04-22 17:29:37 -04:00
Ben Senescu
c779d83cda
fix: fix cloudlfare self hosting (#129) 2026-04-22 15:21:30 -04:00
Ben Senescu
29a0c9cc43
website: add seo for startups guide (#33) 2026-04-22 13:30:07 -04:00
Ben Senescu
ed65d6976c
feat: support all 94 DataForSEO countries across features (#127) 2026-04-20 15:23:25 -04:00
Ben Senescu
021ec830af
website: add rank tracking + format (#126) 2026-04-16 19:19:21 -04:00
Ben Senescu
5c2b71d340
feat: bulk delete for saved keywords (#122) 2026-04-16 19:14:50 -04:00
Ben Senescu
a52cf0bf95 docs: tweak readme 2026-04-16 18:54:25 -04:00
Ben Senescu
bf58af3752
release: bump to 0.0.6 (#124)
* save

* save
2026-04-16 16:35:54 -04:00
Ben Senescu
ed27b64eb4
fix: pass only required fields in workflow billingCustomer params (#123)
The callers of startAudit and beginRankCheckRun were forwarding the
incoming billingCustomer object directly into workflow.create params.
At runtime the object can be an EnsuredUserContext with extra fields
beyond BillingCustomerContext, which pollutes the workflow instance's
persisted params payload. Explicitly pick the four required fields so
only the intended data is serialized into the workflow.
2026-04-16 16:24:27 -04:00