[docs] Separate some pages out of the Docs section (#1626)

This PR changes the structure of the docs site's sidebar.


![image](https://github.com/tldraw/tldraw/assets/15892272/ffe1e152-c921-43f0-9ba2-d084bda5e1e3)

I think this signposts more clearly what the different pages are for.
And it also paves the way for some work I want to do on
expanding+refining the Editor docs.

This PR also simplifies URL for all sidebar links.
It's a bit scrappy, but I think it feels simple enough to work with, and
easy-enough to change in the future.
> But hey! I've been doing this a couple times recently. Maybe we should
refactor? Or maybe we should keep going with what we've got and focus on
getting these docs *done*.

### Change Type

- [x] `documentation` — Changes to the documentation only[^2]

[^1]: publishes a `patch` release, for devDependencies use `internal`
[^2]: will not publish a new version

### Test Plan

1. Check that all the sidebar links go to where you expect.
2. Check that old URLs redirect to the right pages, eg: `/docs/usage`
should go to the usage page.


### Release Notes

- Documentation: Restructured the sidebar for clarity.
This commit is contained in:
Lu Wilson 2023-06-23 10:53:22 +01:00 committed by GitHub
parent d2c51ae3ba
commit c5fe399842
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 119 additions and 36 deletions

View file

@ -15,8 +15,12 @@ export function Breadcrumb({
<Link href={`/`}>tldraw</Link>
{section && (
<>
{` / `}
<Link href={`/${section.id}`}>{section.title}</Link>
{section.title && (
<>
{` / `}
<Link href={`/${section.id}`}>{section.title}</Link>
</>
)}
{category && (
<>
{category.id === 'ucg' ? null : (

View file

@ -106,11 +106,13 @@ function SidebarLink(props: SidebarContentLink) {
function SidebarSection({ title, url, children }: SidebarContentSectionLink) {
return (
<li className="sidebar__section">
<Link href={url}>
<div className="sidebar__link sidebar__section__title" data-active={false}>
{title}
</div>
</Link>
{title && (
<Link href={url}>
<div className="sidebar__link sidebar__section__title" data-active={false}>
{title}
</div>
</Link>
)}
<ul className="sidebar__list sidebar__section__list">
{children.map((link) => (
<SidebarLink key={link.url} {...link} />

View file

@ -1,7 +1,13 @@
[
{
"id": "getting-started",
"title": "",
"description": "",
"categories": []
},
{
"id": "docs",
"title": "Docs",
"title": "Documentation",
"description": "Developer documentation for tldraw.",
"categories": []
},

View file

@ -8,10 +8,35 @@ const nextConfig = {
async redirects() {
return [
{
// For reverse compatibility with old links
source: '/:sectionId/ucg/:articleId',
destination: '/:sectionId/:articleId',
permanent: true,
},
{
// For reverse compatibility with old links
source: '/docs/introduction',
destination: '/introduction',
permanent: true,
},
{
// For reverse compatibility with old links
source: '/docs/installation',
destination: '/installation',
permanent: true,
},
{
// For reverse compatibility with old links
source: '/docs/usage',
destination: '/usage',
permanent: true,
},
{
// To reflect that these are at the top level of the sidebar
source: '/getting-started/:childId',
destination: '/:childId',
permanent: true,
},
]
},
}

View file

@ -3,22 +3,39 @@ import { Mdx } from '@/components/Mdx'
import { MetaHead } from '@/components/MetaHead'
import { Sidebar } from '@/components/Sidebar'
import { Article, Category, Section, SidebarContentList } from '@/types/content-types'
import { getArticleSource, getArticles, getSection, getSections } from '@/utils/content'
import {
getArticle,
getArticleSource,
getArticles,
getCategory,
getLinks,
getSection,
getSections,
} from '@/utils/content'
import { getSidebarContentList } from '@/utils/getSidebarContentList'
import { GetStaticPaths, GetStaticProps } from 'next'
import { MDXRemoteSerializeResult } from 'next-mdx-remote'
import { useTheme } from 'next-themes'
import Link from 'next/link'
import ArticlePage, { ArticleProps } from './[childId]/[articleId]'
type Props = {
type SectionProps = {
type: 'section'
sidebar: SidebarContentList
section: Section
categories: { category: Category; articles: Article[] }[]
mdxSource: MDXRemoteSerializeResult | null
}
export default function SectionListPage({ sidebar, section, categories, mdxSource }: Props) {
type Props = SectionProps | ArticleProps
export default function SectionListPage(props: Props) {
const theme = useTheme()
if (props.type === 'article') {
return <ArticlePage {...props} />
}
const { sidebar, section, categories, mdxSource } = props
const ucg = categories.find((category) => category.category.id === 'ucg')!
return (
<>
@ -62,20 +79,58 @@ export const getStaticPaths: GetStaticPaths = async () => {
const paths: { params: { sectionId: string } }[] = []
for (const section of sections) {
paths.push({ params: { sectionId: section.id } })
if (section.id !== 'getting-started') {
paths.push({ params: { sectionId: section.id } })
continue
}
// Add paths for getting-started articles (not the section itself)
// ... because we keep those at the top level of the sidebar
for (const category of section.categories) {
if (category.id !== 'ucg') continue
for (const articleId of category.articleIds) {
paths.push({ params: { sectionId: articleId } })
}
}
}
return { paths, fallback: false }
}
export const getStaticProps: GetStaticProps<Props> = async (ctx) => {
const sectionId = ctx.params?.sectionId?.toString()
if (!sectionId) throw Error()
const id = ctx.params?.sectionId?.toString()
if (!id) throw Error()
const sidebar = await getSidebarContentList({
sectionId,
})
// If the path goes to an article in the getting-started section
// ... show the article page instead
// ... because we keep those ones at the top level
const sections = await getSections()
if (!sections.some((section) => section.id === id)) {
const sectionId = 'getting-started'
const categoryId = 'ucg'
const articleId = id
const sidebar = await getSidebarContentList({ sectionId, categoryId, articleId })
const section = await getSection(sectionId)
const category = await getCategory(sectionId, categoryId)
const article = await getArticle(articleId)
const links = await getLinks(articleId)
const mdxSource = await getArticleSource(articleId)
return {
props: {
type: 'article',
sidebar,
section,
category,
article,
links,
mdxSource,
},
}
}
// Otherwise, show the section page
const sectionId = id
const sidebar = await getSidebarContentList({ sectionId })
const articles = await getArticles()
const section = await getSection(sectionId)
const categories = [] as { category: Category; articles: Article[] }[]
@ -87,5 +142,5 @@ export const getStaticProps: GetStaticProps<Props> = async (ctx) => {
const article = articles[sectionId + '_index'] ?? null
const mdxSource = article ? await getArticleSource(sectionId + '_index') : null
return { props: { sidebar, section, categories, mdxSource } }
return { props: { type: 'section', sidebar, section, categories, mdxSource } }
}

View file

@ -19,23 +19,14 @@ export async function getSidebarContentList({
if (section.id === 'gen') {
links.push({ type: 'article', title: 'API Reference', url: '/gen' })
// for (const category of section.categories) {
// if (category.id === 'ucg') {
// continue
// } else {
// children.push({
// type: 'article',
// title: category.title,
// url: `/${section.id}/${category.id}`,
// })
// }
// }
// links.push({ type: 'section', title: 'API Reference', url: '/gen', children })
continue
}
// If the article is in the getting-started section
// ... we place it at the top level of the sidebar
// ... so let's simplify its URL to reflect that
const sectionUrl = section.id === 'getting-started' ? '' : `/${section.id}`
for (const category of section.categories) {
if (category.id === 'ucg') {
continue
@ -43,13 +34,13 @@ export async function getSidebarContentList({
children.push({
type: 'category',
title: category.title,
url: `/${section.id}/${category.id}`,
url: `${sectionUrl}/${category.id}`,
children: category.articleIds.map((articleId) => {
const article = articles[articleId]
return {
type: 'article' as const,
title: article.title,
url: `/${section.id}/${category.id}/${articleId}`,
url: `${sectionUrl}/${category.id}/${articleId}`,
}
}),
})
@ -64,14 +55,14 @@ export async function getSidebarContentList({
return {
type: 'article' as const,
title: article.title,
url: `/${section.id}/${category.id}/${articleId}`,
url: `${sectionUrl}/${articleId}`,
}
})
)
}
}
links.push({ type: 'section', title: section.title, url: `/${section.id}`, children })
links.push({ type: 'section', title: section.title, url: sectionUrl, children })
}
return {