From 889adb09b34b70c871a39fab4e8da4d4a2966f90 Mon Sep 17 00:00:00 2001
From: Anthony Ettinger
Date: Mon, 17 Aug 2026 06:40:10 +0000
Subject: [PATCH] feat(routing): move the signed-in app under /dashboard, add a
public /ads page
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The top level was doing two jobs: /pricing and /about were public, while
/projects, /settings and /ads were the signed-in app. That left no room for a
marketing page on any path the app had already claimed — /ads in particular,
which is the one product here with two sides to sell and nowhere to sell them.
Split it: every authenticated resource now lives under /dashboard/**, and the
top level belongs entirely to public pages.
- app/(app)/* moves wholesale into app/(app)/dashboard/*. The auth gate is the
(app) layout, which still wraps all of it, so nothing changes about who can
reach what.
- next.config redirects every old top-level path to its /dashboard equivalent,
so bookmarks, links in already-sent report emails and the URLs in past
invoices keep working. 307 rather than 308: none of these were ever indexed
(they sat behind a login), so there is no SEO to preserve, and a temporary
redirect stays reversible instead of being cached in browsers forever.
- /ads is the exception at both ends. The bare path is now the public marketing
page, and /ads/house/* is artwork in public/ — redirects run before the
filesystem, so a blanket /ads/:path* would have 404'd every house creative.
The redirect excludes it explicitly.
- The proxy's auth check drops the now-dead /projects, /audits and /settings
prefixes. /dashboard is the whole contract.
The marketing page sells both sides of the network, and every figure on it is
imported from lib/ads/pricing rather than typed in — the publisher's per-click
number comes from creditsToPayoutCents, the same function ad_charge_click()
mirrors, so what a publisher reads is what actually accrues.
Verified against a production build: /ads renders publicly, /ads/house artwork
still serves 200, every legacy prefix 307s to its new home, and /dashboard/**
302s signed-out visitors to /login with the new path in ?redirect.
---
.../email-broadcast/EmailBroadcastForm.tsx | 0
.../admin/email-broadcast/page.tsx | 2 +-
app/(app)/{ => dashboard}/admin/form.tsx | 0
.../admin/github/setup/done/client.tsx | 2 +-
.../admin/github/setup/done/page.tsx | 4 +-
.../admin/github/setup/page.tsx | 2 +-
.../admin/integrations-form.tsx | 0
.../{ => dashboard}/admin/leads/page.tsx | 2 +-
app/(app)/{ => dashboard}/admin/page.tsx | 6 +-
.../admin/provider-costs-panel.tsx | 0
.../ads/[id]/edit/edit-form.tsx | 0
.../{ => dashboard}/ads/[id]/edit/page.tsx | 2 +-
app/(app)/{ => dashboard}/ads/[id]/page.tsx | 4 +-
.../{ => dashboard}/ads/earnings/page.tsx | 6 +-
app/(app)/{ => dashboard}/ads/new/form.tsx | 2 +-
app/(app)/{ => dashboard}/ads/new/page.tsx | 4 +-
app/(app)/{ => dashboard}/ads/page.tsx | 14 +-
app/(app)/{ => dashboard}/ads/slots/page.tsx | 8 +-
app/(app)/{ => dashboard}/analytics/page.tsx | 6 +-
.../{ => dashboard}/audits/[id]/page.tsx | 2 +-
app/(app)/{ => dashboard}/autoblog/page.tsx | 4 +-
.../{ => dashboard}/github/dashboard/page.tsx | 2 +-
app/(app)/dashboard/page.tsx | 8 +-
.../projects/[id]/autoblog/actions.tsx | 0
.../autoblog/articles/[articleId]/page.tsx | 2 +-
.../articles/[articleId]/publish-button.tsx | 0
.../projects/[id]/autoblog/auto-refresh.tsx | 0
.../[id]/autoblog/backlinks/chart.tsx | 0
.../projects/[id]/autoblog/backlinks/page.tsx | 10 +-
.../projects/[id]/autoblog/countdown.tsx | 0
.../[id]/autoblog/delete-autoblog-button.tsx | 0
.../projects/[id]/autoblog/guest-posts.tsx | 2 +-
.../projects/[id]/autoblog/history/page.tsx | 12 +-
.../projects/[id]/autoblog/page.tsx | 14 +-
.../projects/[id]/autoblog/plan/actions.ts | 4 +-
.../projects/[id]/autoblog/plan/page.tsx | 10 +-
.../projects/[id]/autoblog/setup/form.tsx | 2 +-
.../projects/[id]/autoblog/setup/page.tsx | 6 +-
.../projects/[id]/delete-project-button.tsx | 0
.../projects/[id]/edit-url-form.tsx | 0
.../projects/[id]/getting-started/page.tsx | 10 +-
.../projects/[id]/layout-client.tsx | 0
.../{ => dashboard}/projects/[id]/layout.tsx | 0
.../projects/[id]/leads/page.tsx | 0
.../projects/[id]/members/members-client.tsx | 0
.../projects/[id]/members/page.tsx | 0
.../{ => dashboard}/projects/[id]/page.tsx | 8 +-
.../projects/[id]/performance/page.tsx | 0
.../projects/[id]/repos/add-repo-modal.tsx | 0
.../projects/[id]/repos/page.tsx | 4 +-
.../projects/[id]/repos/remove-button.tsx | 0
.../projects/[id]/runs/[runId]/page.tsx | 2 +-
.../projects/[id]/scans/page.tsx | 4 +-
.../projects/[id]/security/page.tsx | 0
.../[id]/security/request-scan-button.tsx | 2 +-
.../projects/[id]/security/stream/route.ts | 0
.../projects/[id]/settings/page.tsx | 0
.../[id]/social/api-tokens/client.tsx | 0
.../projects/[id]/social/api-tokens/page.tsx | 2 +-
.../projects/[id]/social/auto-refresh.tsx | 0
.../projects/[id]/social/feed-settings.tsx | 0
.../projects/[id]/social/page.tsx | 4 +-
.../projects/[id]/social/post-now.tsx | 0
.../[id]/social/retry-feed-item-button.tsx | 0
.../[id]/social/retry-post-button.tsx | 0
.../[id]/social/setup/app-password-reveal.tsx | 0
.../projects/[id]/social/setup/form.tsx | 0
.../projects/[id]/social/setup/page.tsx | 4 +-
.../projects/[id]/social/social-profile.tsx | 0
.../projects/[id]/stats/auto-install.tsx | 2 +-
.../projects/[id]/stats/careers-toggle.tsx | 0
.../[id]/stats/careers/applications.tsx | 0
.../[id]/stats/careers/careers-install.tsx | 0
.../[id]/stats/careers/job-manager.tsx | 0
.../projects/[id]/stats/careers/page.tsx | 2 +-
.../projects/[id]/stats/install-snippet.tsx | 0
.../stats/integrations/integration-form.tsx | 0
.../projects/[id]/stats/integrations/page.tsx | 0
.../projects/[id]/stats/live-chart.tsx | 0
.../projects/[id]/stats/live-visitors.tsx | 0
.../projects/[id]/stats/page.tsx | 4 +-
.../projects/[id]/stats/stats-subnav.tsx | 6 +-
.../projects/[id]/stats/tracker-toggle.tsx | 0
.../projects/[id]/stats/visitor-globe.tsx | 0
.../projects/[id]/uptime/add-monitor-form.tsx | 0
.../projects/[id]/uptime/monitor-actions.tsx | 0
.../projects/[id]/uptime/page.tsx | 0
.../{ => dashboard}/projects/new/form.tsx | 2 +-
.../{ => dashboard}/projects/new/page.tsx | 0
.../{ => dashboard}/promote/[id]/page.tsx | 4 +-
.../{ => dashboard}/promote/accounts/page.tsx | 4 +-
.../{ => dashboard}/promote/new/page.tsx | 0
app/(app)/{ => dashboard}/promote/page.tsx | 12 +-
.../settings/billing/buy-credits-button.tsx | 0
.../{ => dashboard}/settings/billing/page.tsx | 2 +-
.../billing/purchase-status-banner.tsx | 0
app/(app)/{ => dashboard}/settings/form.tsx | 0
.../integrations/github/bind-button.tsx | 0
.../settings/integrations/github/page.tsx | 2 +-
.../integrations/github/repos-filter.tsx | 0
app/(app)/{ => dashboard}/settings/page.tsx | 4 +-
app/(app)/{ => dashboard}/social/page.tsx | 4 +-
.../{ => dashboard}/social/setup/page.tsx | 4 +-
app/(app)/layout.tsx | 16 +-
app/(app)/site-picker.tsx | 4 +-
app/(marketing)/ads/page.tsx | 277 ++++++++++++++++++
.../docs/autoblog-webhook/page.tsx | 4 +-
app/(marketing)/page.tsx | 4 +-
app/(marketing)/pricing/page.tsx | 2 +-
app/(marketing)/recent/outreach-form.tsx | 2 +-
app/actions/abortScanRun.ts | 4 +-
app/actions/admin.ts | 4 +-
app/actions/ads.ts | 26 +-
app/actions/auditOps.ts | 8 +-
app/actions/careers.ts | 6 +-
app/actions/coinpay.ts | 4 +-
app/actions/currentSite.ts | 2 +-
app/actions/integrations.ts | 4 +-
app/actions/leads.ts | 2 +-
app/actions/linkExchange.ts | 30 +-
app/actions/mailbox.ts | 4 +-
app/actions/monitors.ts | 6 +-
app/actions/orgs.ts | 2 +-
app/actions/portScans.ts | 2 +-
app/actions/project-members.ts | 8 +-
app/actions/projects.ts | 8 +-
app/actions/promote.ts | 22 +-
app/actions/seedCredentials.ts | 6 +-
app/actions/socialPosting.ts | 32 +-
app/actions/tracker-integrations.ts | 4 +-
app/api/credits/create-invoice/route.ts | 4 +-
app/api/github/callback/route.ts | 2 +-
app/api/github/setup-callback/route.ts | 6 +-
app/api/sp/oauth/facebook/callback/route.ts | 4 +-
app/api/sp/oauth/linkedin/callback/route.ts | 4 +-
app/api/sp/oauth/mastodon/callback/route.ts | 4 +-
app/api/sp/oauth/mastodon/start/route.ts | 2 +-
app/api/sp/oauth/reddit/callback/route.ts | 4 +-
app/api/sp/oauth/threads/callback/route.ts | 4 +-
app/api/sp/oauth/x/callback/route.ts | 4 +-
app/invite/[token]/page.tsx | 4 +-
components/engines-panel.tsx | 2 +-
components/project-tabs-nav.tsx | 54 ++--
components/promote/list-actions.tsx | 2 +-
components/promote/promote-form.tsx | 4 +-
components/report/apply-fix-button.tsx | 2 +-
components/report/premium-engines.tsx | 2 +-
components/run-now-button.tsx | 2 +-
components/scan-run-poller.tsx | 2 +-
components/scan-run-results.tsx | 2 +-
components/site-header.tsx | 1 +
lib/email.ts | 2 +-
lib/lx/currentSite.ts | 2 +-
lib/mcp/promote.ts | 4 +-
lib/perfReport.ts | 4 +-
next.config.ts | 40 +++
proxy.ts | 12 +-
.../lx-article-embeds.integration.test.ts | 2 +-
tests/e2e/autoblog-plan.spec.ts | 4 +-
tests/leads-page-columns.test.ts | 2 +-
worker/index.ts | 8 +-
161 files changed, 621 insertions(+), 301 deletions(-)
rename app/(app)/{ => dashboard}/admin/email-broadcast/EmailBroadcastForm.tsx (100%)
rename app/(app)/{ => dashboard}/admin/email-broadcast/page.tsx (97%)
rename app/(app)/{ => dashboard}/admin/form.tsx (100%)
rename app/(app)/{ => dashboard}/admin/github/setup/done/client.tsx (98%)
rename app/(app)/{ => dashboard}/admin/github/setup/done/page.tsx (89%)
rename app/(app)/{ => dashboard}/admin/github/setup/page.tsx (98%)
rename app/(app)/{ => dashboard}/admin/integrations-form.tsx (100%)
rename app/(app)/{ => dashboard}/admin/leads/page.tsx (99%)
rename app/(app)/{ => dashboard}/admin/page.tsx (96%)
rename app/(app)/{ => dashboard}/admin/provider-costs-panel.tsx (100%)
rename app/(app)/{ => dashboard}/ads/[id]/edit/edit-form.tsx (100%)
rename app/(app)/{ => dashboard}/ads/[id]/edit/page.tsx (96%)
rename app/(app)/{ => dashboard}/ads/[id]/page.tsx (97%)
rename app/(app)/{ => dashboard}/ads/earnings/page.tsx (97%)
rename app/(app)/{ => dashboard}/ads/new/form.tsx (99%)
rename app/(app)/{ => dashboard}/ads/new/page.tsx (93%)
rename app/(app)/{ => dashboard}/ads/page.tsx (93%)
rename app/(app)/{ => dashboard}/ads/slots/page.tsx (93%)
rename app/(app)/{ => dashboard}/analytics/page.tsx (99%)
rename app/(app)/{ => dashboard}/audits/[id]/page.tsx (99%)
rename app/(app)/{ => dashboard}/autoblog/page.tsx (80%)
rename app/(app)/{ => dashboard}/github/dashboard/page.tsx (73%)
rename app/(app)/{ => dashboard}/projects/[id]/autoblog/actions.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/autoblog/articles/[articleId]/page.tsx (99%)
rename app/(app)/{ => dashboard}/projects/[id]/autoblog/articles/[articleId]/publish-button.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/autoblog/auto-refresh.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/autoblog/backlinks/chart.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/autoblog/backlinks/page.tsx (97%)
rename app/(app)/{ => dashboard}/projects/[id]/autoblog/countdown.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/autoblog/delete-autoblog-button.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/autoblog/guest-posts.tsx (99%)
rename app/(app)/{ => dashboard}/projects/[id]/autoblog/history/page.tsx (90%)
rename app/(app)/{ => dashboard}/projects/[id]/autoblog/page.tsx (96%)
rename app/(app)/{ => dashboard}/projects/[id]/autoblog/plan/actions.ts (92%)
rename app/(app)/{ => dashboard}/projects/[id]/autoblog/plan/page.tsx (95%)
rename app/(app)/{ => dashboard}/projects/[id]/autoblog/setup/form.tsx (99%)
rename app/(app)/{ => dashboard}/projects/[id]/autoblog/setup/page.tsx (93%)
rename app/(app)/{ => dashboard}/projects/[id]/delete-project-button.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/edit-url-form.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/getting-started/page.tsx (95%)
rename app/(app)/{ => dashboard}/projects/[id]/layout-client.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/layout.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/leads/page.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/members/members-client.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/members/page.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/page.tsx (97%)
rename app/(app)/{ => dashboard}/projects/[id]/performance/page.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/repos/add-repo-modal.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/repos/page.tsx (98%)
rename app/(app)/{ => dashboard}/projects/[id]/repos/remove-button.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/runs/[runId]/page.tsx (98%)
rename app/(app)/{ => dashboard}/projects/[id]/scans/page.tsx (96%)
rename app/(app)/{ => dashboard}/projects/[id]/security/page.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/security/request-scan-button.tsx (96%)
rename app/(app)/{ => dashboard}/projects/[id]/security/stream/route.ts (100%)
rename app/(app)/{ => dashboard}/projects/[id]/settings/page.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/social/api-tokens/client.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/social/api-tokens/page.tsx (98%)
rename app/(app)/{ => dashboard}/projects/[id]/social/auto-refresh.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/social/feed-settings.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/social/page.tsx (99%)
rename app/(app)/{ => dashboard}/projects/[id]/social/post-now.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/social/retry-feed-item-button.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/social/retry-post-button.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/social/setup/app-password-reveal.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/social/setup/form.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/social/setup/page.tsx (98%)
rename app/(app)/{ => dashboard}/projects/[id]/social/social-profile.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/stats/auto-install.tsx (99%)
rename app/(app)/{ => dashboard}/projects/[id]/stats/careers-toggle.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/stats/careers/applications.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/stats/careers/careers-install.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/stats/careers/job-manager.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/stats/careers/page.tsx (98%)
rename app/(app)/{ => dashboard}/projects/[id]/stats/install-snippet.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/stats/integrations/integration-form.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/stats/integrations/page.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/stats/live-chart.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/stats/live-visitors.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/stats/page.tsx (99%)
rename app/(app)/{ => dashboard}/projects/[id]/stats/stats-subnav.tsx (80%)
rename app/(app)/{ => dashboard}/projects/[id]/stats/tracker-toggle.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/stats/visitor-globe.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/uptime/add-monitor-form.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/uptime/monitor-actions.tsx (100%)
rename app/(app)/{ => dashboard}/projects/[id]/uptime/page.tsx (100%)
rename app/(app)/{ => dashboard}/projects/new/form.tsx (98%)
rename app/(app)/{ => dashboard}/projects/new/page.tsx (100%)
rename app/(app)/{ => dashboard}/promote/[id]/page.tsx (97%)
rename app/(app)/{ => dashboard}/promote/accounts/page.tsx (98%)
rename app/(app)/{ => dashboard}/promote/new/page.tsx (100%)
rename app/(app)/{ => dashboard}/promote/page.tsx (93%)
rename app/(app)/{ => dashboard}/settings/billing/buy-credits-button.tsx (100%)
rename app/(app)/{ => dashboard}/settings/billing/page.tsx (98%)
rename app/(app)/{ => dashboard}/settings/billing/purchase-status-banner.tsx (100%)
rename app/(app)/{ => dashboard}/settings/form.tsx (100%)
rename app/(app)/{ => dashboard}/settings/integrations/github/bind-button.tsx (100%)
rename app/(app)/{ => dashboard}/settings/integrations/github/page.tsx (99%)
rename app/(app)/{ => dashboard}/settings/integrations/github/repos-filter.tsx (100%)
rename app/(app)/{ => dashboard}/settings/page.tsx (94%)
rename app/(app)/{ => dashboard}/social/page.tsx (78%)
rename app/(app)/{ => dashboard}/social/setup/page.tsx (86%)
create mode 100644 app/(marketing)/ads/page.tsx
diff --git a/app/(app)/admin/email-broadcast/EmailBroadcastForm.tsx b/app/(app)/dashboard/admin/email-broadcast/EmailBroadcastForm.tsx
similarity index 100%
rename from app/(app)/admin/email-broadcast/EmailBroadcastForm.tsx
rename to app/(app)/dashboard/admin/email-broadcast/EmailBroadcastForm.tsx
diff --git a/app/(app)/admin/email-broadcast/page.tsx b/app/(app)/dashboard/admin/email-broadcast/page.tsx
similarity index 97%
rename from app/(app)/admin/email-broadcast/page.tsx
rename to app/(app)/dashboard/admin/email-broadcast/page.tsx
index da14809c..652f8698 100644
--- a/app/(app)/admin/email-broadcast/page.tsx
+++ b/app/(app)/dashboard/admin/email-broadcast/page.tsx
@@ -27,7 +27,7 @@ export default async function EmailBroadcastPage() {
← Admin
diff --git a/app/(app)/admin/form.tsx b/app/(app)/dashboard/admin/form.tsx
similarity index 100%
rename from app/(app)/admin/form.tsx
rename to app/(app)/dashboard/admin/form.tsx
diff --git a/app/(app)/admin/github/setup/done/client.tsx b/app/(app)/dashboard/admin/github/setup/done/client.tsx
similarity index 98%
rename from app/(app)/admin/github/setup/done/client.tsx
rename to app/(app)/dashboard/admin/github/setup/done/client.tsx
index 257b4314..0b720ddb 100644
--- a/app/(app)/admin/github/setup/done/client.tsx
+++ b/app/(app)/dashboard/admin/github/setup/done/client.tsx
@@ -111,7 +111,7 @@ export function SetupDoneClient() {
Install App →
. End users do the same from their{" "}
-
+
personal GitHub settings page
.
diff --git a/app/(app)/admin/github/setup/done/page.tsx b/app/(app)/dashboard/admin/github/setup/done/page.tsx
similarity index 89%
rename from app/(app)/admin/github/setup/done/page.tsx
rename to app/(app)/dashboard/admin/github/setup/done/page.tsx
index ed4f66cb..c66b0010 100644
--- a/app/(app)/admin/github/setup/done/page.tsx
+++ b/app/(app)/dashboard/admin/github/setup/done/page.tsx
@@ -30,7 +30,7 @@ export default async function AdminGithubSetupDonePage() {
return (
-
+
← Admin
@@ -39,7 +39,7 @@ export default async function AdminGithubSetupDonePage() {
Copy each value into Railway, set them on both the Next.js app
and the worker service, then redeploy. After deploy, end users
can install the App from their own{" "}
-
+
GitHub settings page
.
diff --git a/app/(app)/admin/github/setup/page.tsx b/app/(app)/dashboard/admin/github/setup/page.tsx
similarity index 98%
rename from app/(app)/admin/github/setup/page.tsx
rename to app/(app)/dashboard/admin/github/setup/page.tsx
index 0ade5b7e..886b08fc 100644
--- a/app/(app)/admin/github/setup/page.tsx
+++ b/app/(app)/dashboard/admin/github/setup/page.tsx
@@ -86,7 +86,7 @@ export default async function AdminGithubSetupPage({
return (
-
+
← Admin
diff --git a/app/(app)/admin/integrations-form.tsx b/app/(app)/dashboard/admin/integrations-form.tsx
similarity index 100%
rename from app/(app)/admin/integrations-form.tsx
rename to app/(app)/dashboard/admin/integrations-form.tsx
diff --git a/app/(app)/admin/leads/page.tsx b/app/(app)/dashboard/admin/leads/page.tsx
similarity index 99%
rename from app/(app)/admin/leads/page.tsx
rename to app/(app)/dashboard/admin/leads/page.tsx
index 8fa8ae5f..0112c18c 100644
--- a/app/(app)/admin/leads/page.tsx
+++ b/app/(app)/dashboard/admin/leads/page.tsx
@@ -125,7 +125,7 @@ export default async function AdminLeadsPage() {
Leads
-
+
← Admin
diff --git a/app/(app)/admin/page.tsx b/app/(app)/dashboard/admin/page.tsx
similarity index 96%
rename from app/(app)/admin/page.tsx
rename to app/(app)/dashboard/admin/page.tsx
index 3cdba2f3..1ea9dfde 100644
--- a/app/(app)/admin/page.tsx
+++ b/app/(app)/dashboard/admin/page.tsx
@@ -95,7 +95,7 @@ export default async function AdminPage() {
URLs, and live audience counts per segment.
No monetized sites yet.{" "}
-
+
Monetize a site
.
@@ -126,7 +126,7 @@ export default async function EarningsPage() {
{model.campaigns.length === 0 ? (
No ad campaigns yet.{" "}
-
+
Create an ad
.
diff --git a/app/(app)/ads/new/form.tsx b/app/(app)/dashboard/ads/new/form.tsx
similarity index 99%
rename from app/(app)/ads/new/form.tsx
rename to app/(app)/dashboard/ads/new/form.tsx
index 53af5d7b..2f4153f4 100644
--- a/app/(app)/ads/new/form.tsx
+++ b/app/(app)/dashboard/ads/new/form.tsx
@@ -88,7 +88,7 @@ export function NewAdForm() {
setError(res.error);
return;
}
- router.push(`/ads?created=${res.refSlug}`);
+ router.push(`/dashboard/ads?created=${res.refSlug}`);
});
}
diff --git a/app/(app)/ads/new/page.tsx b/app/(app)/dashboard/ads/new/page.tsx
similarity index 93%
rename from app/(app)/ads/new/page.tsx
rename to app/(app)/dashboard/ads/new/page.tsx
index 1170ee44..938a34d9 100644
--- a/app/(app)/ads/new/page.tsx
+++ b/app/(app)/dashboard/ads/new/page.tsx
@@ -29,7 +29,7 @@ export default async function NewAdPage() {
return (
-
+
← Ad campaigns
Create an ad
@@ -42,7 +42,7 @@ export default async function NewAdPage() {
🎁 Launch offer: your first deposit is matched 100% in bonus ad
credits (up to $100 free).{" "}
-
+
Add credits
.
diff --git a/app/(app)/ads/page.tsx b/app/(app)/dashboard/ads/page.tsx
similarity index 93%
rename from app/(app)/ads/page.tsx
rename to app/(app)/dashboard/ads/page.tsx
index 765092d2..3be82d35 100644
--- a/app/(app)/ads/page.tsx
+++ b/app/(app)/dashboard/ads/page.tsx
@@ -96,13 +96,13 @@ export default async function AdsPage({
Ad campaigns
-
+
Earnings & reports
-
+
Monetize a site
-
+
Create an ad
No campaigns yet.{" "}
-
+
Create your first ad
.
@@ -185,7 +185,7 @@ export default async function AdsPage({
-
+
{c.name}
@@ -194,13 +194,13 @@ export default async function AdsPage({
-
+
{display.label}
-
+
Edit
diff --git a/app/(app)/ads/slots/page.tsx b/app/(app)/dashboard/ads/slots/page.tsx
similarity index 93%
rename from app/(app)/ads/slots/page.tsx
rename to app/(app)/dashboard/ads/slots/page.tsx
index 62fe1523..14ee88b4 100644
--- a/app/(app)/ads/slots/page.tsx
+++ b/app/(app)/dashboard/ads/slots/page.tsx
@@ -92,19 +92,19 @@ export default async function SlotsPage() {
return (
-
+
← Ad campaigns
Monetize your site
-
+
Earnings & reports
{/* Always-visible way to add a site to monetize — a site is a project,
so this starts the project-creation flow. Previously the only link
to it was hidden inside the empty state. */}
-
+
Monetize a new site
No sites yet — a site is a CrawlProof project.{" "}
-
+
Add one
{" "}
to enable a slot.
diff --git a/app/(app)/analytics/page.tsx b/app/(app)/dashboard/analytics/page.tsx
similarity index 99%
rename from app/(app)/analytics/page.tsx
rename to app/(app)/dashboard/analytics/page.tsx
index 2882d33a..efd59c0d 100644
--- a/app/(app)/analytics/page.tsx
+++ b/app/(app)/dashboard/analytics/page.tsx
@@ -139,7 +139,7 @@ export default async function PortfolioAnalyticsPage({
No projects yet.{" "}
-
+
Add your first property
{" "}
to start seeing portfolio-wide analytics.
@@ -578,7 +578,7 @@ function ProjectTrendTable({ rows }: { rows: ProjectRow[] }) {
>
-
+
← Back to report
Dashboard
-
+
New project
@@ -191,7 +191,7 @@ export default async function DashboardPage({
{projects.map((p) => (
-
+
No projects yet.{" "}
-
+
Create one
.
@@ -298,7 +298,7 @@ export default async function DashboardPage({
{audits.map((a) => (
-
+
{a.target_url}
diff --git a/app/(app)/projects/[id]/autoblog/actions.tsx b/app/(app)/dashboard/projects/[id]/autoblog/actions.tsx
similarity index 100%
rename from app/(app)/projects/[id]/autoblog/actions.tsx
rename to app/(app)/dashboard/projects/[id]/autoblog/actions.tsx
diff --git a/app/(app)/projects/[id]/autoblog/articles/[articleId]/page.tsx b/app/(app)/dashboard/projects/[id]/autoblog/articles/[articleId]/page.tsx
similarity index 99%
rename from app/(app)/projects/[id]/autoblog/articles/[articleId]/page.tsx
rename to app/(app)/dashboard/projects/[id]/autoblog/articles/[articleId]/page.tsx
index b5c84c9e..db75b330 100644
--- a/app/(app)/projects/[id]/autoblog/articles/[articleId]/page.tsx
+++ b/app/(app)/dashboard/projects/[id]/autoblog/articles/[articleId]/page.tsx
@@ -54,7 +54,7 @@ export default async function AutoblogArticlePage({
← Article history
diff --git a/app/(app)/projects/[id]/autoblog/articles/[articleId]/publish-button.tsx b/app/(app)/dashboard/projects/[id]/autoblog/articles/[articleId]/publish-button.tsx
similarity index 100%
rename from app/(app)/projects/[id]/autoblog/articles/[articleId]/publish-button.tsx
rename to app/(app)/dashboard/projects/[id]/autoblog/articles/[articleId]/publish-button.tsx
diff --git a/app/(app)/projects/[id]/autoblog/auto-refresh.tsx b/app/(app)/dashboard/projects/[id]/autoblog/auto-refresh.tsx
similarity index 100%
rename from app/(app)/projects/[id]/autoblog/auto-refresh.tsx
rename to app/(app)/dashboard/projects/[id]/autoblog/auto-refresh.tsx
diff --git a/app/(app)/projects/[id]/autoblog/backlinks/chart.tsx b/app/(app)/dashboard/projects/[id]/autoblog/backlinks/chart.tsx
similarity index 100%
rename from app/(app)/projects/[id]/autoblog/backlinks/chart.tsx
rename to app/(app)/dashboard/projects/[id]/autoblog/backlinks/chart.tsx
diff --git a/app/(app)/projects/[id]/autoblog/backlinks/page.tsx b/app/(app)/dashboard/projects/[id]/autoblog/backlinks/page.tsx
similarity index 97%
rename from app/(app)/projects/[id]/autoblog/backlinks/page.tsx
rename to app/(app)/dashboard/projects/[id]/autoblog/backlinks/page.tsx
index cf709c91..445be8d4 100644
--- a/app/(app)/projects/[id]/autoblog/backlinks/page.tsx
+++ b/app/(app)/dashboard/projects/[id]/autoblog/backlinks/page.tsx
@@ -136,7 +136,7 @@ export default async function AutoblogBacklinksPage({
domain: string;
blog_root_url: string | null;
} | null;
- if (!site) redirect(`/projects/${projectId}/autoblog/setup`);
+ if (!site) redirect(`/dashboard/projects/${projectId}/autoblog/setup`);
const currentSitePublic = { blog_root_url: site.blog_root_url };
const svc = serviceClient();
@@ -197,7 +197,7 @@ export default async function AutoblogBacklinksPage({
@@ -93,7 +93,7 @@ export default async function AutoblogHistoryPage({
{a.title}
diff --git a/app/(app)/projects/[id]/autoblog/page.tsx b/app/(app)/dashboard/projects/[id]/autoblog/page.tsx
similarity index 96%
rename from app/(app)/projects/[id]/autoblog/page.tsx
rename to app/(app)/dashboard/projects/[id]/autoblog/page.tsx
index 69bd4621..fcbc490c 100644
--- a/app/(app)/projects/[id]/autoblog/page.tsx
+++ b/app/(app)/dashboard/projects/[id]/autoblog/page.tsx
@@ -76,7 +76,7 @@ export default async function AutoblogDashboardPage({
You haven't set up Autoblog yet for this project.
Get started
@@ -197,16 +197,16 @@ export default async function AutoblogDashboardPage({
@@ -156,7 +156,7 @@ export default async function AutoblogPlanPage({
{row.keyword}
{row.article_id && (
Open article
diff --git a/app/(app)/projects/[id]/autoblog/setup/form.tsx b/app/(app)/dashboard/projects/[id]/autoblog/setup/form.tsx
similarity index 99%
rename from app/(app)/projects/[id]/autoblog/setup/form.tsx
rename to app/(app)/dashboard/projects/[id]/autoblog/setup/form.tsx
index 945a785b..e21e7329 100644
--- a/app/(app)/projects/[id]/autoblog/setup/form.tsx
+++ b/app/(app)/dashboard/projects/[id]/autoblog/setup/form.tsx
@@ -593,7 +593,7 @@ export function SetupForm({
}
setNotice("Settings saved.");
if (!initial) {
- router.push(`/projects/${projectId}/autoblog`);
+ router.push(`/dashboard/projects/${projectId}/autoblog`);
} else {
router.refresh();
}
diff --git a/app/(app)/projects/[id]/autoblog/setup/page.tsx b/app/(app)/dashboard/projects/[id]/autoblog/setup/page.tsx
similarity index 93%
rename from app/(app)/projects/[id]/autoblog/setup/page.tsx
rename to app/(app)/dashboard/projects/[id]/autoblog/setup/page.tsx
index 627d5d57..fa990710 100644
--- a/app/(app)/projects/[id]/autoblog/setup/page.tsx
+++ b/app/(app)/dashboard/projects/[id]/autoblog/setup/page.tsx
@@ -71,13 +71,13 @@ export default async function AutoblogSetupPage({
{site ? "Autoblog settings" : "Set up Autoblog"}
-
+
Dashboard
-
+
History
-
+
Backlinks
diff --git a/app/(app)/projects/[id]/delete-project-button.tsx b/app/(app)/dashboard/projects/[id]/delete-project-button.tsx
similarity index 100%
rename from app/(app)/projects/[id]/delete-project-button.tsx
rename to app/(app)/dashboard/projects/[id]/delete-project-button.tsx
diff --git a/app/(app)/projects/[id]/edit-url-form.tsx b/app/(app)/dashboard/projects/[id]/edit-url-form.tsx
similarity index 100%
rename from app/(app)/projects/[id]/edit-url-form.tsx
rename to app/(app)/dashboard/projects/[id]/edit-url-form.tsx
diff --git a/app/(app)/projects/[id]/getting-started/page.tsx b/app/(app)/dashboard/projects/[id]/getting-started/page.tsx
similarity index 95%
rename from app/(app)/projects/[id]/getting-started/page.tsx
rename to app/(app)/dashboard/projects/[id]/getting-started/page.tsx
index e9a25d41..b2ff96df 100644
--- a/app/(app)/projects/[id]/getting-started/page.tsx
+++ b/app/(app)/dashboard/projects/[id]/getting-started/page.tsx
@@ -69,15 +69,15 @@ export default async function GettingStartedPage({
body: "Scan your site with one or more AI engines to produce your first audit. Each engine reports what it can find — content, schema, robots, AI-bot rules — and gives you concrete fixes.",
done: hasFirstScan,
cta: hasFirstScan
- ? { href: `/projects/${id}/scans`, label: "View scans" }
- : { href: `/projects/${id}`, label: "Run a scan" },
+ ? { href: `/dashboard/projects/${id}/scans`, label: "View scans" }
+ : { href: `/dashboard/projects/${id}`, label: "Run a scan" },
},
{
id: "stats-tracker",
title: "Enable the stats tracker",
body: "Add one