Skip to content

Commit 1d99b68

Browse files
authored
feature(docs): we aint rewriting to framer anymore (tldraw#8665)
Follow up to tldraw/tldraw-internal#264 and dotdev release. This PR will stay in WIP until we're ready to pull the plug on the framer dotdev site. It removes all unecessary redirections from docs to framer as now tldraw.dev will point at the new dotdev project and the dotdev project will redirect to docs ## Summary Remove the Framer proxy behavior from the docs app so it can run as a standalone docs deployment behind dotdev. - Drops the marketing-path rewrites that proxied to the Framer site. - Adds `assetPrefix` (via `ASSET_PREFIX`) so when docs pages are served through a silent rewrite from `tldraw.dev`, their `/_next/*` assets load from the docs origin (avoiding collisions with dotdev’s own `/_next/*`). - Updates docs sitemap generation to be docs-only (no Framer URLs); this sitemap is consumed by dotdev to build the single canonical `tldraw.dev/sitemap.xml`. ## Ops notes - Keep a stable hostname on the docs Vercel project (this becomes `DOCS_ORIGIN_URL` on dotdev). - Set `ASSET_PREFIX=https://<docs-origin-host>` on the docs Vercel project (Prod + Preview). ## Test plan - Visit `https://<docs-origin-host>/quick-start` and verify it loads and navigates (JS/CSS assets come from the same origin). - Verify `https://<docs-origin-host>/sitemap.xml` returns docs URLs only.
1 parent 524dad7 commit 1d99b68

4 files changed

Lines changed: 34 additions & 151 deletions

File tree

apps/docs/app/sitemap.ts

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { MetadataRoute } from 'next'
22
import { db } from '@/utils/ContentDatabase'
3-
import { fetchFramerPaths } from '@/utils/framer-sitemap'
43

54
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
65
const paths = await db.getAllPaths()
76

7+
// Docs-only sitemap. Marketing pages are now owned by the dotdev app.
88
const docsSitemap: MetadataRoute.Sitemap = [
99
{
1010
url: 'https://tldraw.dev/',
@@ -15,17 +15,5 @@ export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
1515
lastModified: new Date(),
1616
})),
1717
]
18-
19-
const framerPaths = await fetchFramerPaths()
20-
const docsPaths = new Set(paths.map((p: string) => p.toLowerCase()))
21-
const framerSitemap: MetadataRoute.Sitemap = []
22-
23-
for (const path of framerPaths) {
24-
// Filter out root path and any paths that conflict with docs routes
25-
if (path === '/') continue
26-
if (docsPaths.has(path.toLowerCase())) continue
27-
framerSitemap.push({ url: 'https://tldraw.dev' + path })
28-
}
29-
30-
return [...docsSitemap, ...framerSitemap]
18+
return docsSitemap
3119
}

apps/docs/next.config.js

Lines changed: 2 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
/** @type {import('next').NextConfig} */
22

3-
// Configurable domain for rewrites
4-
const REWRITE_DOMAIN = 'tldrawdotdev.framer.website'
5-
6-
/** Keep in sync with `utils/asset-url.ts` (`resolveAssetOrigin`). */
73
function resolveAssetOrigin() {
84
const explicit =
95
process.env.ASSET_PREFIX?.trim() ||
@@ -212,104 +208,9 @@ const nextConfig = {
212208
]
213209
},
214210
async rewrites() {
215-
const rewrites = {
216-
beforeFiles: [
217-
{
218-
source: '/',
219-
destination: `https://${REWRITE_DOMAIN}/`,
220-
},
221-
{
222-
source: '/404',
223-
destination: `https://${REWRITE_DOMAIN}/404`,
224-
},
225-
{
226-
source: '/accessibility',
227-
destination: `https://${REWRITE_DOMAIN}/accessibility`,
228-
},
229-
{
230-
source: '/blog/announcements',
231-
destination: `https://${REWRITE_DOMAIN}/blog/category/announcements`,
232-
},
233-
{
234-
source: '/blog/case-studies',
235-
destination: `https://${REWRITE_DOMAIN}/blog/category/case-studies`,
236-
},
237-
{
238-
source: '/blog/product',
239-
destination: `https://${REWRITE_DOMAIN}/blog/category/product`,
240-
},
241-
{
242-
source: '/blog/release-notes',
243-
destination: `https://${REWRITE_DOMAIN}/blog/category/release-notes`,
244-
},
245-
{
246-
source: '/blog',
247-
destination: `https://${REWRITE_DOMAIN}/blog`,
248-
},
249-
{
250-
source: '/blog/:path+',
251-
destination: `https://${REWRITE_DOMAIN}/blog/:path*`,
252-
},
253-
{
254-
source: '/careers',
255-
destination: `https://${REWRITE_DOMAIN}/careers`,
256-
},
257-
{
258-
source: '/company',
259-
destination: `https://${REWRITE_DOMAIN}/company`,
260-
},
261-
{
262-
source: '/events',
263-
destination: `https://${REWRITE_DOMAIN}/events`,
264-
},
265-
{
266-
source: '/faq',
267-
destination: `https://${REWRITE_DOMAIN}/faq`,
268-
},
269-
{
270-
source: '/features/:path*',
271-
destination: `https://${REWRITE_DOMAIN}/features/:path*`,
272-
},
273-
{
274-
source: '/get-a-license/:path*',
275-
destination: `https://${REWRITE_DOMAIN}/get-a-license/:path*`,
276-
},
277-
{
278-
source: '/legal/:path*',
279-
destination: `https://${REWRITE_DOMAIN}/legal/:path*`,
280-
},
281-
{
282-
source: '/partner',
283-
destination: `https://${REWRITE_DOMAIN}/partner`,
284-
},
285-
{
286-
source: '/pricing',
287-
destination: `https://${REWRITE_DOMAIN}/pricing`,
288-
},
289-
{
290-
source: '/showcase',
291-
destination: `https://${REWRITE_DOMAIN}/showcase`,
292-
},
293-
{
294-
source: '/thanks',
295-
destination: `https://${REWRITE_DOMAIN}/thanks`,
296-
},
297-
{
298-
source: '/releases',
299-
destination: '/getting-started/releases',
300-
},
301-
{
302-
source: '/quick-start',
303-
destination: '/getting-started/quick-start',
304-
},
305-
{
306-
source: '/installation',
307-
destination: '/getting-started/installation',
308-
},
309-
],
211+
return {
212+
beforeFiles: [],
310213
}
311-
312-
return rewrites
313214
},
314215
}
315216

apps/docs/scripts/lib/checkBrokenLinks.ts

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { fetchFramerPaths } from '@/utils/framer-sitemap'
21
import { nicelog } from '@/utils/nicelog'
32
import { connect } from './connect'
43

@@ -16,6 +15,32 @@ const INTERNAL_REWRITES: Record<string, string> = {
1615
'/installation': '/getting-started/installation',
1716
}
1817

18+
// Path prefixes that are served by another system (e.g. the marketing site)
19+
// rather than this Next.js app, so they will never appear in the docs DB.
20+
// Matches the prefix as an exact path OR as a parent of a subpath:
21+
// e.g. '/legal' matches '/legal' and '/legal/tldraw-license' but not '/legal-foo'.
22+
const EXTERNAL_ROUTE_PREFIXES = [
23+
'/accessibility',
24+
'/blog',
25+
'/careers',
26+
'/company',
27+
'/events',
28+
'/faq',
29+
'/features',
30+
'/get-a-license',
31+
'/legal',
32+
'/partner',
33+
'/pricing',
34+
'/showcase',
35+
'/thanks',
36+
]
37+
38+
function isExternalRoute(urlPath: string): boolean {
39+
return EXTERNAL_ROUTE_PREFIXES.some(
40+
(prefix) => urlPath === prefix || urlPath.startsWith(prefix + '/')
41+
)
42+
}
43+
1944
/**
2045
* Strip fenced code blocks from markdown, replacing them with blank lines
2146
* to preserve line numbering for error reporting.
@@ -109,9 +134,6 @@ function tryRedirect(urlPath: string): string | null {
109134
export async function checkBrokenLinks(): Promise<number> {
110135
const db = await connect({ mode: 'readonly' })
111136

112-
// Fetch framer paths from the live sitemap so we don't maintain a stale list
113-
const framerPaths = await fetchFramerPaths()
114-
115137
// Build set of all valid paths
116138
const validPaths = new Set<string>()
117139

@@ -198,6 +220,10 @@ export async function checkBrokenLinks(): Promise<number> {
198220
const urlPath = hashIdx >= 0 ? url.slice(0, hashIdx) : url
199221
const fragment = hashIdx >= 0 ? url.slice(hashIdx + 1).toLowerCase() : null
200222

223+
// Skip paths served by an external system (marketing site etc.)
224+
// — they will never appear in the docs DB but are still valid in production.
225+
if (isExternalRoute(urlPath)) continue
226+
201227
// Empty path with fragment = same-page anchor
202228
if (urlPath === '' && fragment) {
203229
const slugs = headingMap.get(article.path)
@@ -222,8 +248,6 @@ export async function checkBrokenLinks(): Promise<number> {
222248
// Case-insensitive fallback (handles macOS FS collisions
223249
// where e.g. Atom.mdx and atom.mdx map to the same file)
224250
pathValid = true
225-
} else if (framerPaths.has(urlPath)) {
226-
pathValid = true
227251
} else {
228252
// Try redirect resolution
229253
const redirected = tryRedirect(urlPath)

apps/docs/utils/framer-sitemap.ts

Lines changed: 0 additions & 30 deletions
This file was deleted.

0 commit comments

Comments
 (0)