Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions apps/web/next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,16 +176,14 @@ const nextConfig: NextConfig = {
source: "/c/:token",
destination: `${apiBase}/c/:token`,
},
// Hosted dashboard builds use basePath="/app". Public share links must
// remain top-level no-auth URLs, so /s/* is rewritten into the app route
// without changing the browser URL.
...(APP_BASE_PATH
? [{
source: "/s/:path*",
destination: `${APP_BASE_PATH}/s/:path*`,
basePath: false as const,
}]
: []),
// /s/* public share links: NOT rewritten here. A dashboard self-rewrite of
// a top-level path into the basePath is rejected by Next.js ("rewrites urls
// outside of the basePath. Please use a destination that starts with
// http(s)://") and broke hosted (basePath="/app") builds. It was also
// ineffective: on the hosted host the apex URL `/s/*` reaches the landing,
// not this dashboard, so the apex is where `/s/*` must be rewritten into
// `/app/s/*` (mirroring how `/app/*` is served). OSS (no basePath) serves
// /s/[token] directly with no rewrite.
];
},
async headers() {
Expand Down
13 changes: 9 additions & 4 deletions apps/web/tests/approval-batch-share-public.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,16 @@ describe("public approval batch share route", () => {
expect(fetchMock).not.toHaveBeenCalled();
});

it("keeps minted /s links top-level when the hosted app uses basePath /app", () => {
it("does NOT self-rewrite /s/* in the dashboard config (apex handles it)", () => {
// A dashboard self-rewrite of top-level /s/* into the basePath is rejected by
// Next.js ("rewrites urls outside of the basePath") and broke hosted
// (basePath="/app") builds. It was also ineffective: the hosted /s/* URL
// reaches the landing apex, not this dashboard, so the apex rewrites
// /s/* -> /app/s/* (mirroring /app/*). OSS (no basePath) serves /s/[token]
// directly. So next.config must NOT contain the /s/ rewrite.
const config = readFileSync(join(process.cwd(), "next.config.ts"), "utf-8");
expect(config).toContain('source: "/s/:path*"');
expect(config).toContain("destination: `${APP_BASE_PATH}/s/:path*`");
expect(config).toContain("basePath: false");
expect(config).not.toContain('source: "/s/:path*"');
expect(config).not.toContain("destination: `${APP_BASE_PATH}/s/:path*`");
});

it("does not call API_BASE directly from the logged-out share card", () => {
Expand Down
Loading