Skip to content
This repository was archived by the owner on May 20, 2025. It is now read-only.

Commit 6d9e356

Browse files
committed
add lang switcher to guides and replace existing lang pages
1 parent f06776a commit 6d9e356

15 files changed

+287
-86
lines changed

docs/guides/dart.mdx

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

docs/guides/go.mdx

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

docs/guides/go/serverless-rest-api-example.mdx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
export const description =
2-
'Use the Nitric framework to easily build and deploy Go REST APIs for AWS, Azure or GCP'
3-
4-
export const title_meta = 'Building your first API with Go and Nitric'
1+
---
2+
description: Use the Nitric framework to easily build and deploy Go REST APIs for AWS, Azure or GCP
3+
title_seo: Building your first API with Go and Nitric
4+
tags:
5+
- API
6+
- Key Value Store
7+
---
58

69
# Building your first API with Nitric
710

docs/guides/jvm.mdx

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

docs/guides/nodejs.mdx

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

docs/guides/nodejs/serverless-rest-api-example.mdx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
export const description =
2-
'Use the Nitric framework to easily build and deploy Node.js REST APIs for AWS, Azure or GCP'
3-
4-
export const title_meta = 'Building your first API with Node.js and Nitric'
1+
---
2+
description: Use the Nitric framework to easily build and deploy Node.js REST APIs for AWS, Azure or GCP
3+
title_seo: Building your first API with Node.js and Nitric
4+
tags:
5+
- API
6+
- Key Value Store
7+
---
58

69
# Building a REST API with Nitric
710

docs/guides/python.mdx

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

next.config.mjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,12 @@ const nextConfig = {
346346
basePath: false,
347347
permanent: true,
348348
},
349+
...['nodejs', 'dart', 'go', 'jvm', 'python'].map((page) => ({
350+
source: `/docs/guides/${page}`,
351+
destination: `/docs/guides`,
352+
basePath: false,
353+
permanent: true,
354+
})),
349355
]
350356
},
351357
async headers() {

src/components/guides/GuideList.tsx

Lines changed: 70 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,66 +5,93 @@ import React from 'react'
55
import GuideItem from './GuideItem'
66
import { Checkbox } from '../ui/checkbox'
77
import useParams from '@/hooks/useParams'
8+
import { LanguageSwitch } from './LanguageSwitch'
9+
import useLang from '@/hooks/useLang'
810

911
interface Props {
1012
guides: Doc[]
1113
allTags: string[]
1214
}
1315

16+
const langPathMap: Record<string, string> = {
17+
javascript: 'guides/nodejs',
18+
typescript: 'guides/nodejs',
19+
python: 'guides/python',
20+
go: 'guides/go',
21+
dart: 'guides/dart',
22+
}
23+
24+
const isLangSlug = (slug: string) => {
25+
return Object.values(langPathMap).some((path) => slug.startsWith(path))
26+
}
27+
1428
const GuideList: React.FC<Props> = ({ guides, allTags }) => {
1529
const { searchParams, setParams } = useParams()
1630
const selectedTags = searchParams.get('tags')?.split(',') || []
31+
const { currentLanguage } = useLang()
1732

1833
const filteredGuides = guides.filter((guide) => {
19-
if (!selectedTags.length) return true
20-
return selectedTags.some((tag) => guide.tags?.includes(tag))
34+
let include = true
35+
36+
if (isLangSlug(guide.slug)) {
37+
include = guide.slug.startsWith(langPathMap[currentLanguage])
38+
}
39+
40+
if (!selectedTags.length) return include
41+
42+
return include && selectedTags.some((tag) => guide.tags?.includes(tag))
2143
})
2244

2345
return (
24-
<div className="mt-10 grid grid-cols-[280px,1fr]">
25-
<aside
26-
aria-label="Sidebar"
27-
className="sticky top-[calc(var(--header-height)+1px+2rem)] max-h-[calc(100vh-var(--header-height)-3rem)] w-80 overflow-y-auto"
28-
>
29-
<ul className="space-y-4">
30-
{allTags.map((tag) => (
31-
<li key={tag}>
32-
<div className="flex items-center space-x-4">
33-
<Checkbox
34-
id={tag}
35-
checked={selectedTags.includes(tag)}
36-
onCheckedChange={(checked) => {
37-
if (checked) {
38-
setParams('tags', [...selectedTags, tag].join(','))
39-
} else {
40-
setParams(
41-
'tags',
42-
selectedTags
43-
.filter((selectedTag) => selectedTag !== tag)
44-
.join(','),
45-
)
46-
}
47-
}}
48-
className="h-5 w-5 border-primary-400 data-[state=checked]:bg-primary"
49-
/>
50-
<label
51-
htmlFor={tag}
52-
className="cursor-pointer text-base font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
53-
>
54-
{tag}
55-
</label>
56-
</div>
46+
<div>
47+
<div className="gap-x-4 lg:grid lg:grid-cols-[280px,1fr]">
48+
<div className="border-r">
49+
<aside
50+
aria-label="Sidebar"
51+
className="sticky top-[calc(var(--header-height)+1px+2rem)] mt-10 hidden max-h-[calc(100vh-var(--header-height)-3rem)] w-80 space-y-10 overflow-y-auto lg:block"
52+
>
53+
<ul className="space-y-4">
54+
{allTags.map((tag) => (
55+
<li key={tag}>
56+
<div className="flex items-center space-x-4">
57+
<Checkbox
58+
id={tag}
59+
checked={selectedTags.includes(tag)}
60+
onCheckedChange={(checked) => {
61+
if (checked) {
62+
setParams('tags', [...selectedTags, tag].join(','))
63+
} else {
64+
setParams(
65+
'tags',
66+
selectedTags
67+
.filter((selectedTag) => selectedTag !== tag)
68+
.join(','),
69+
)
70+
}
71+
}}
72+
className="h-5 w-5 border-primary-400 data-[state=checked]:bg-primary"
73+
/>
74+
<label
75+
htmlFor={tag}
76+
className="cursor-pointer text-base font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
77+
>
78+
{tag}
79+
</label>
80+
</div>
81+
</li>
82+
))}
83+
</ul>
84+
<LanguageSwitch />
85+
</aside>
86+
</div>
87+
<ul className="relative mx-8 mt-10 w-full space-y-4">
88+
{filteredGuides.map((guide) => (
89+
<li key={guide.slug}>
90+
<GuideItem guide={guide} />
5791
</li>
5892
))}
5993
</ul>
60-
</aside>
61-
<ul className="space-y-4">
62-
{filteredGuides.map((guide) => (
63-
<li key={guide.slug}>
64-
<GuideItem guide={guide} />
65-
</li>
66-
))}
67-
</ul>
94+
</div>
6895
</div>
6996
)
7097
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
'use client'
2+
3+
import useLang, { LanguageId } from '@/hooks/useLang'
4+
import { cn } from '@/lib/utils'
5+
import React from 'react'
6+
import { Button } from '../ui/button'
7+
import JavaScriptLogoColour from '@/components/icons/JavaScriptLogoColour'
8+
import TypeScriptLogoColour from '@/components/icons/TypeScriptLogoColour'
9+
import PythonColorLogo from '@/components/icons/PythonLogoColour'
10+
import GoColorLogo from '@/components/icons/GoLogoColour'
11+
import DartLogoNoTextColour from '@/components/icons/DartLogoNoTextColour'
12+
13+
const languages = [
14+
{
15+
name: 'javascript',
16+
icon: <JavaScriptLogoColour className={'size-8'} />,
17+
},
18+
{
19+
name: 'typescript',
20+
icon: <TypeScriptLogoColour className={'size-8'} />,
21+
},
22+
{
23+
name: 'python',
24+
icon: <PythonColorLogo className={'size-8'} />,
25+
},
26+
{
27+
name: 'go',
28+
icon: <GoColorLogo className={'size-8'} />,
29+
},
30+
{
31+
name: 'dart',
32+
icon: <DartLogoNoTextColour className={'size-8'} />,
33+
},
34+
]
35+
36+
export const LanguageSwitch = () => {
37+
const { currentLanguage, setCurrentLanguage } = useLang()
38+
39+
return (
40+
<ul className="flex gap-x-4">
41+
{languages.map(({ name, icon }) => (
42+
<li
43+
key={name}
44+
className={cn(
45+
'cursor-pointer transition-all',
46+
currentLanguage !== name ? 'grayscale hover:grayscale-0' : '',
47+
)}
48+
>
49+
<Button
50+
variant="unstyled"
51+
onClick={() => setCurrentLanguage(name as LanguageId)}
52+
>
53+
{icon}
54+
<span className="sr-only">set language to {name}</span>
55+
</Button>
56+
</li>
57+
))}
58+
</ul>
59+
)
60+
}

0 commit comments

Comments
 (0)