-
+
@@ -106,7 +104,9 @@ export const Header = forwardRef<
diff --git a/src/components/layout/Navigation.tsx b/src/components/layout/Navigation.tsx
deleted file mode 100644
index 67da1105b..000000000
--- a/src/components/layout/Navigation.tsx
+++ /dev/null
@@ -1,239 +0,0 @@
-'use client'
-
-import { useRef } from 'react'
-import Link from 'next/link'
-import { usePathname } from 'next/navigation'
-import clsx from 'clsx'
-import { AnimatePresence, motion, useIsPresent } from 'framer-motion'
-
-import { Button } from '@/components/Button'
-import { useIsInsideMobileNavigation } from '@/components/MobileNavigation'
-import { Tag } from '@/components/Tag'
-import { remToPx } from '@/lib/remToPx'
-import { NavGroup, navigation } from '@/siteConfig'
-
-function useInitialValue
(value: T, condition = true) {
- let initialValue = useRef(value).current
- return condition ? initialValue : value
-}
-
-function TopLevelNavItem({
- href,
- children,
-}: {
- href: string
- children: React.ReactNode
-}) {
- return (
-
-
- {children}
-
-
- )
-}
-
-function NavLink({
- href,
- children,
- tag,
- active = false,
- isAnchorLink = false,
-}: {
- href: string
- children: React.ReactNode
- tag?: string
- active?: boolean
- isAnchorLink?: boolean
-}) {
- return (
-
- {children}
- {tag && (
-
- {tag}
-
- )}
-
- )
-}
-
-function VisibleSectionHighlight({
- group,
- pathname,
-}: {
- group: NavGroup
- pathname: string
-}) {
- // let [sections, visibleSections] = useInitialValue(
- // [
- // useSectionStore((s) => s.sections),
- // useSectionStore((s) => s.visibleSections),
- // ],
- // useIsInsideMobileNavigation(),
- // )
- let sections = []
- let visibleSections = []
-
- let isPresent = useIsPresent()
- let firstVisibleSectionIndex = Math.max(
- 0,
- [{ id: '_top' }, ...sections].findIndex(
- (section) => section.id === visibleSections[0],
- ),
- )
- let itemHeight = remToPx(2)
- let height = isPresent
- ? Math.max(1, visibleSections.length) * itemHeight
- : itemHeight
- let top =
- group.links.findIndex((link) => link.href === pathname) * itemHeight +
- firstVisibleSectionIndex * itemHeight
-
- return (
-
- )
-}
-
-function ActivePageMarker({
- group,
- pathname,
-}: {
- group: NavGroup
- pathname: string
-}) {
- let itemHeight = remToPx(2)
- let offset = remToPx(0.25)
- let activePageIndex = group.links.findIndex((link) => link.href === pathname)
- let top = offset + activePageIndex * itemHeight
-
- return (
-
- )
-}
-
-function NavigationGroup({
- group,
- className,
-}: {
- group: NavGroup
- className?: string
-}) {
- // If this is the mobile navigation then we always render the initial
- // state, so that the state does not change during the close animation.
- // The state will still update when we re-open (re-render) the navigation.
- let isInsideMobileNavigation = useIsInsideMobileNavigation()
- const pathname = usePathname()
-
- let sections = []
-
- let isActiveGroup =
- group.links.findIndex((link) => link.href === pathname) !== -1
-
- return (
-
-
- {group.title}
-
-
-
- {isActiveGroup && (
-
- )}
-
-
-
- {isActiveGroup && (
-
- )}
-
-
- {group.links.map((link) => (
-
-
- {link.title}
-
-
- {link.href === pathname && sections.length > 0 && (
-
- {sections.map((section) => (
- -
-
- {section.title}
-
-
- ))}
-
- )}
-
-
- ))}
-
-
-
- )
-}
-
-export function Navigation(props: React.ComponentPropsWithoutRef<'nav'>) {
- return (
-
- )
-}
diff --git a/src/components/nav/CollapsibleNavItem.tsx b/src/components/nav/CollapsibleNavItem.tsx
new file mode 100644
index 000000000..a50f732ea
--- /dev/null
+++ b/src/components/nav/CollapsibleNavItem.tsx
@@ -0,0 +1,88 @@
+'use client'
+
+import React from 'react'
+import {
+ Collapsible,
+ CollapsibleContent,
+ CollapsibleTrigger,
+} from '../ui/collapsible'
+import { ChevronDownIcon } from '@heroicons/react/24/outline'
+import { cn } from '@/lib/utils'
+import { NavLink } from './NavLink'
+import { usePathname } from 'next/navigation'
+import { Button } from '../ui/button'
+import { NavigationGroup } from './NavigationGroup'
+import { NavGroup } from '@/config/types'
+
+interface Props {
+ group: NavGroup
+ className?: string
+}
+
+const CollapsibleNavItem: React.FC = ({ group, className }) => {
+ const pathname = usePathname()
+
+ const { title, items, icon: Icon } = group
+
+ const isActive = items.some(
+ (link) => 'href' in link && link.href === pathname,
+ )
+ const [isOpen, setIsOpen] = React.useState(isActive)
+
+ return (
+
+
+
+
+
+
+ {items.map((entry, idx) =>
+ 'href' in entry ? (
+ -
+
+ {entry.title}
+
+
+ ) : (
+ -
+ {' '}
+
+
+ ),
+ )}
+
+
+
+ )
+}
+
+export default CollapsibleNavItem
diff --git a/src/components/MobileNavigation.tsx b/src/components/nav/MobileNavigation.tsx
similarity index 98%
rename from src/components/MobileNavigation.tsx
rename to src/components/nav/MobileNavigation.tsx
index a4f05ae61..6dc78f047 100644
--- a/src/components/MobileNavigation.tsx
+++ b/src/components/nav/MobileNavigation.tsx
@@ -12,7 +12,7 @@ import { motion } from 'framer-motion'
import { create } from 'zustand'
import { Header } from '@/components/layout/Header'
-import { Navigation } from '@/components/layout/Navigation'
+import { Navigation } from '@/components/nav/Navigation'
function MenuIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
return (
diff --git a/src/components/nav/NavLink.tsx b/src/components/nav/NavLink.tsx
new file mode 100644
index 000000000..b4a5e5cdc
--- /dev/null
+++ b/src/components/nav/NavLink.tsx
@@ -0,0 +1,59 @@
+import React, { PropsWithChildren } from 'react'
+import Link from 'next/link'
+import { cn } from '@/lib/utils'
+import { Tag } from '../Tag'
+import { Button } from '../ui/button'
+import { NavItem } from '@/config/types'
+
+interface NavLinkProps extends PropsWithChildren> {
+ href: string
+ tag?: string
+ active?: boolean
+ isAnchorLink?: boolean
+ className?: string
+}
+
+export const NavLink: React.FC = ({
+ active,
+ isAnchorLink,
+ href,
+ children,
+ tag,
+ icon: Icon,
+ className,
+}) => {
+ return (
+
+ )
+}
diff --git a/src/components/nav/Navigation.tsx b/src/components/nav/Navigation.tsx
new file mode 100644
index 000000000..7657d18a4
--- /dev/null
+++ b/src/components/nav/Navigation.tsx
@@ -0,0 +1,37 @@
+'use client'
+
+import { usePathname } from 'next/navigation'
+
+import { NavLink } from './NavLink'
+import { cn } from '@/lib/utils'
+import { NavigationGroup } from './NavigationGroup'
+import { navigation } from '@/config'
+
+export function Navigation(props: React.ComponentPropsWithoutRef<'nav'>) {
+ const pathname = usePathname()
+
+ return (
+
+ )
+}
diff --git a/src/components/nav/NavigationGroup.tsx b/src/components/nav/NavigationGroup.tsx
new file mode 100644
index 000000000..40522a896
--- /dev/null
+++ b/src/components/nav/NavigationGroup.tsx
@@ -0,0 +1,49 @@
+import { cn } from '@/lib/utils'
+import { usePathname } from 'next/navigation'
+import { NavLink } from './NavLink'
+import CollapsibleNavItem from './CollapsibleNavItem'
+import { NavGroup } from '@/config/types'
+
+export function NavigationGroup({
+ group,
+ className,
+ isAnchorLinks,
+}: {
+ group: NavGroup
+ className?: string
+ isAnchorLinks?: boolean
+}) {
+ // If this is the mobile navigation then we always render the initial
+ // state, so that the state does not change during the close animation.
+ // The state will still update when we re-open (re-render) the navigation.
+ const pathname = usePathname()
+
+ return (
+
+
+ {group.title}
+
+
+
+ {group.items.map((link) =>
+ 'href' in link ? (
+ -
+
+ {link.title}
+
+
+ ) : (
+ -
+
+
+ ),
+ )}
+
+
+
+ )
+}
diff --git a/src/config/index.ts b/src/config/index.ts
new file mode 100644
index 000000000..ac6447f01
--- /dev/null
+++ b/src/config/index.ts
@@ -0,0 +1,273 @@
+import { CommandLineIcon, HomeIcon } from '@heroicons/react/24/outline'
+import { FaNodeJs, FaPython, FaJava, FaAws, FaGithub } from 'react-icons/fa'
+import { SiDart, SiGo } from 'react-icons/si'
+import { NavEntry } from './types'
+import { NodeReference } from './reference/node'
+import { PyReference } from './reference/python'
+import { DartReference } from './reference/dart'
+import { GoReference } from './reference/go'
+
+export const navigation: NavEntry[] = [
+ {
+ title: 'Introduction',
+ href: '/',
+ },
+ {
+ title: 'Concepts',
+ items: [
+ {
+ title: 'Infrastructure from Code',
+ href: '/infrastructure-from-code',
+ },
+ {
+ title: 'Project',
+ href: '/project',
+ },
+ {
+ title: 'Service',
+ href: '/service',
+ },
+ {
+ title: 'Resource',
+ href: '/resource',
+ },
+ {
+ title: 'Provider',
+ href: '/provider',
+ },
+ {
+ title: 'Stack',
+ href: '/stack',
+ },
+ ],
+ },
+ {
+ title: 'Basics',
+ items: [
+ {
+ title: 'Installation',
+ href: '/getting-started/installation',
+ },
+ {
+ title: 'Configuration',
+ href: '/getting-started/configuration',
+ },
+ {
+ title: 'Project Structure',
+ href: '/getting-started/project-structure',
+ },
+ {
+ title: 'Local Development',
+ href: '/getting-started/local-development',
+ },
+ {
+ title: 'Security',
+ href: '/getting-started/security',
+ },
+ {
+ title: 'Deployment',
+ href: '/getting-started/deploying',
+ },
+ ],
+ },
+ {
+ title: 'Get Started',
+ items: [
+ {
+ title: 'Node.js',
+ icon: FaNodeJs,
+ items: [
+ {
+ title: 'API',
+ href: '/getting-started/node/quick-start',
+ },
+ {
+ title: 'Todo App',
+ href: '/getting-started/node/to-do',
+ },
+ ],
+ },
+ {
+ title: 'Python',
+ icon: FaPython,
+ items: [
+ {
+ title: 'API',
+ href: '/getting-started/python/quick-start',
+ },
+ {
+ title: 'Todo App',
+ href: '/getting-started/python/to-do',
+ },
+ ],
+ },
+ {
+ title: 'Go',
+ icon: SiGo,
+ items: [
+ {
+ title: 'API',
+ href: '/getting-started/go/quick-start',
+ },
+ {
+ title: 'Todo App',
+ href: '/getting-started/go/to-do',
+ },
+ ],
+ },
+ {
+ title: 'Dart',
+ icon: SiDart,
+ items: [
+ {
+ title: 'API',
+ href: '/getting-started/dart/quick-start',
+ },
+ {
+ title: 'Todo App',
+ href: '/getting-started/dart/to-do',
+ },
+ ],
+ },
+ ],
+ },
+ {
+ title: 'Deployment',
+ items: [
+ {
+ title: 'Intro',
+ href: '/getting-started/quick-start',
+ },
+ {
+ title: 'AWS',
+ href: '/getting-started/quick-start',
+ },
+ {
+ title: 'GCP',
+ href: '/getting-started/quick-start',
+ },
+ {
+ title: 'Azure',
+ href: '/getting-started/quick-start',
+ },
+ {
+ title: 'Custom',
+ href: '/getting-started/quick-start',
+ },
+ {
+ title: 'CD/CD',
+ href: '/getting-started/quick-start',
+ },
+ ],
+ },
+ {
+ title: 'Languages',
+ items: [
+ {
+ title: 'Node.js',
+ href: '/getting-started/quick-start',
+ },
+ {
+ title: 'Python',
+ href: '/getting-started/quick-start',
+ },
+ {
+ title: 'Go',
+ href: '/getting-started/quick-start',
+ },
+ {
+ title: 'Dart',
+ href: '/getting-started/quick-start',
+ },
+ ],
+ },
+ {
+ title: 'Extension',
+ items: [
+ {
+ title: 'Overview',
+ href: '/extension/overview',
+ },
+ {
+ title: 'Provider Extension',
+ href: '/extension/provider-extension',
+ },
+ {
+ title: 'Custom Providers',
+ href: '/extension/custom-providers',
+ },
+ {
+ title: 'Custom Containers',
+ href: '/extension/custom-containers',
+ },
+ ],
+ },
+ {
+ title: 'Reference',
+ items: [
+ {
+ title: 'CLI',
+ icon: CommandLineIcon,
+ items: [
+ {
+ title: 'Overview',
+ href: '/reference/cli',
+ },
+ {
+ title: 'Installation',
+ href: '/reference/cli/installation',
+ },
+ {
+ title: 'Local Development',
+ href: '/reference/cli/local-development',
+ },
+ {
+ title: 'Stacks',
+ href: '/reference/cli/stacks',
+ },
+ ],
+ },
+ NodeReference,
+ PyReference,
+ GoReference,
+ DartReference,
+ {
+ title: 'Env Vars',
+ href: '/reference/env-vars',
+ },
+ {
+ title: 'Examples',
+ href: '/reference/examples',
+ },
+ {
+ title: 'Preview Features',
+ href: '/reference/preview-features',
+ },
+ ],
+ },
+ {
+ title: 'FAQ',
+ items: [
+ {
+ title: 'How is nitric different from Pulumi?',
+ href: '/faq/nitric-vs-pulumi',
+ },
+ {
+ title: 'How is nitric different from Terraform?',
+ href: '/faq/nitric-vs-terraform',
+ },
+ {
+ title: 'Comparisons with other tools/frameworks',
+ href: '/faq/comparisons',
+ },
+ {
+ title: 'How to migrate between clouds',
+ href: '/faq/migrate-between-clouds',
+ },
+ {
+ title: 'Ask a question',
+ href: '/faq/ask-a-question',
+ },
+ ],
+ },
+]
diff --git a/src/config/reference/dart.ts b/src/config/reference/dart.ts
new file mode 100644
index 000000000..f83684782
--- /dev/null
+++ b/src/config/reference/dart.ts
@@ -0,0 +1,250 @@
+import { NavGroup } from '../types'
+import { SiDart } from 'react-icons/si'
+
+export const DartReference: NavGroup = {
+ title: 'Dart',
+ icon: SiDart,
+ items: [
+ {
+ title: 'Overview',
+ href: '/reference/dart',
+ },
+ {
+ title: 'APIs',
+ items: [
+ {
+ title: 'api()',
+ href: '/reference/dart/api/api',
+ },
+ {
+ title: 'api.get()',
+ href: '/reference/dart/api/api-get',
+ },
+ {
+ title: 'api.post()',
+ href: '/reference/dart/api/api-post',
+ },
+ {
+ title: 'api.put()',
+ href: '/reference/dart/api/api-put',
+ },
+ {
+ title: 'api.delete()',
+ href: '/reference/dart/api/api-delete',
+ },
+ {
+ title: 'api.patch()',
+ href: '/reference/dart/api/api-patch',
+ },
+ {
+ title: 'api.route()',
+ href: '/reference/dart/api/api-route',
+ },
+ {
+ title: 'api.route.all()',
+ href: '/reference/dart/api/api-route-all',
+ },
+ {
+ title: 'api.route.get()',
+ href: '/reference/dart/api/api-route-get',
+ },
+ {
+ title: 'api.route.post()',
+ href: '/reference/dart/api/api-route-post',
+ },
+ {
+ title: 'api.route.put()',
+ href: '/reference/dart/api/api-route-put',
+ },
+ {
+ title: 'api.route.delete()',
+ href: '/reference/dart/api/api-route-delete',
+ },
+ {
+ title: 'api.route.patch()',
+ href: '/reference/dart/api/api-route-patch',
+ },
+ ],
+ },
+ {
+ title: 'Key Value Stores',
+ items: [
+ {
+ title: 'kv()',
+ href: '/reference/dart/keyvalue/keyvalue',
+ },
+ {
+ title: 'kv.get()',
+ href: '/reference/dart/keyvalue/keyvalue-get',
+ },
+ {
+ title: 'kv.set()',
+ href: '/reference/dart/keyvalue/keyvalue-set',
+ },
+ {
+ title: 'kv.delete()',
+ href: '/reference/dart/keyvalue/keyvalue-delete',
+ },
+ {
+ title: 'kv.keys()',
+ href: '/reference/dart/keyvalue/keyvalue-keys',
+ },
+ ],
+ },
+ {
+ title: 'Topics',
+ items: [
+ {
+ title: 'topic()',
+ href: '/reference/dart/topic/topic',
+ },
+ {
+ title: 'topic.publish()',
+ href: '/reference/dart/topic/topic-publish',
+ },
+ {
+ title: 'topic.subscribe()',
+ href: '/reference/dart/topic/topic-subscribe',
+ },
+ ],
+ },
+ {
+ title: 'Queues',
+ items: [
+ {
+ title: 'queue()',
+ href: '/reference/dart/queues/queue',
+ },
+ {
+ title: 'queue.enqueue()',
+ href: '/reference/dart/queues/queue-enqueue',
+ },
+ {
+ title: 'queue.dequeue()',
+ href: '/reference/dart/queues/queue-dequeue',
+ },
+ ],
+ },
+ {
+ title: 'Secrets',
+ items: [
+ {
+ title: 'secret()',
+ href: '/reference/dart/secrets/secret',
+ },
+ {
+ title: 'secret.put()',
+ href: '/reference/dart/secrets/secret-put',
+ },
+ {
+ title: 'secret.version()',
+ href: '/reference/dart/secrets/secret-version',
+ },
+ {
+ title: 'secret.latest()',
+ href: '/reference/dart/secrets/secret-latest',
+ },
+ {
+ title: 'secret.version.access()',
+ href: '/reference/dart/secrets/secret-version-access',
+ },
+ ],
+ },
+ {
+ title: 'Storage',
+ items: [
+ {
+ title: 'bucket()',
+ href: '/reference/dart/storage/bucket',
+ },
+ {
+ title: 'bucket.on()',
+ href: '/reference/dart/storage/bucket-on',
+ },
+ {
+ title: 'bucket.file()',
+ href: '/reference/dart/storage/bucket-file',
+ },
+ {
+ title: 'bucket.files()',
+ href: '/reference/dart/storage/bucket-files',
+ },
+ {
+ title: 'file.exists()',
+ href: '/reference/dart/storage/bucket-file-exists',
+ },
+ {
+ title: 'file.read()',
+ href: '/reference/dart/storage/bucket-file-read',
+ },
+ {
+ title: 'file.write()',
+ href: '/reference/dart/storage/bucket-file-write',
+ },
+ {
+ title: 'file.delete()',
+ href: '/reference/dart/storage/bucket-file-delete',
+ },
+ {
+ title: 'file.getDownloadUrl()',
+ href: '/reference/dart/storage/bucket-file-downloadurl',
+ },
+ {
+ title: 'file.getUploadUrl()',
+ href: '/reference/dart/storage/bucket-file-uploadurl',
+ },
+ ],
+ },
+ {
+ title: 'SQL',
+ items: [
+ {
+ title: 'sql()',
+ href: '/reference/dart/sql/sql',
+ },
+ {
+ title: 'sql.connectionString()',
+ href: '/reference/dart/sql/sql-connection-string',
+ },
+ ],
+ },
+ {
+ title: 'Schedules',
+ items: [
+ {
+ title: 'schedule()',
+ href: '/reference/dart/schedule/schedule',
+ },
+ {
+ title: 'schedule.every()',
+ href: '/reference/dart/schedule/schedule-every',
+ },
+ {
+ title: 'schedule.cron()',
+ href: '/reference/dart/schedule/schedule-cron',
+ },
+ ],
+ },
+ {
+ title: 'Websockets',
+ items: [
+ {
+ title: 'websocket()',
+ href: '/reference/dart/websocket/websocket',
+ },
+ {
+ title: 'websocket.on()',
+ href: '/reference/dart/websocket/websocket-on',
+ },
+ {
+ title: 'websocket.send()',
+ href: '/reference/dart/websocket/websocket-send',
+ },
+ {
+ title: 'websocket.close()',
+ href: '/reference/dart/websocket/websocket-close',
+ },
+ ],
+ },
+ ],
+}
diff --git a/src/config/reference/go.ts b/src/config/reference/go.ts
new file mode 100644
index 000000000..d14cd1792
--- /dev/null
+++ b/src/config/reference/go.ts
@@ -0,0 +1,239 @@
+import { FaPython } from 'react-icons/fa'
+import { NavGroup } from '../types'
+import { SiGo } from 'react-icons/si'
+
+export const GoReference: NavGroup = {
+ title: 'Go',
+ icon: SiGo,
+ items: [
+ {
+ title: 'Overview',
+ href: '/reference/go',
+ },
+ {
+ title: 'Resources',
+ items: [
+ {
+ title: 'NewApi()',
+ href: '/reference/go/api/api',
+ },
+ {
+ title: 'NewKv()',
+ href: '/reference/go/keyvalue/keyvalue',
+ },
+ {
+ title: 'NewQueue()',
+ href: '/reference/go/queues/queue',
+ },
+ {
+ title: 'NewSecret()',
+ href: '/reference/go/secrets/secret',
+ },
+ {
+ title: 'NewBucket()',
+ href: '/reference/go/storage/bucket',
+ },
+ {
+ title: 'NewTopic()',
+ href: '/reference/go/topic/topic',
+ },
+ {
+ title: 'NewSchedule()',
+ href: '/reference/go/schedule/schedule',
+ },
+ {
+ title: 'NewWebsocket()',
+ href: '/reference/go/websocket/websocket',
+ },
+ ],
+ },
+ {
+ title: 'APIs',
+ items: [
+ {
+ title: 'Api.Get()',
+ href: '/reference/go/api/api-get',
+ },
+ {
+ title: 'Api.Post()',
+ href: '/reference/go/api/api-post',
+ },
+ {
+ title: 'Api.Put()',
+ href: '/reference/go/api/api-put',
+ },
+ {
+ title: 'Api.Delete()',
+ href: '/reference/go/api/api-delete',
+ },
+ {
+ title: 'Api.Patch()',
+ href: '/reference/go/api/api-patch',
+ },
+ {
+ title: 'Api.NewRoute()',
+ href: '/reference/go/api/api-route',
+ },
+ {
+ title: 'Api.Route.All()',
+ href: '/reference/go/api/api-route-all',
+ },
+ {
+ title: 'Api.Route.Get()',
+ href: '/reference/go/api/api-route-get',
+ },
+ {
+ title: 'Api.Route.Post()',
+ href: '/reference/go/api/api-route-post',
+ },
+ {
+ title: 'Api.Route.Put()',
+ href: '/reference/go/api/api-route-put',
+ },
+ {
+ title: 'Api.Route.Delete()',
+ href: '/reference/go/api/api-route-delete',
+ },
+ {
+ title: 'Api.Route.Patch()',
+ href: '/reference/go/api/api-route-patch',
+ },
+ ],
+ },
+ {
+ title: 'Key Value Stores',
+ items: [
+ {
+ title: 'Kv.Get()',
+ href: '/reference/go/keyvalue/keyvalue-get',
+ },
+ {
+ title: 'Kv.Set()',
+ href: '/reference/go/keyvalue/keyvalue-set',
+ },
+ {
+ title: 'Kv.Delete()',
+ href: '/reference/go/keyvalue/keyvalue-delete',
+ },
+ {
+ title: 'Kv.Keys()',
+ href: '/reference/go/keyvalue/keyvalue-keys',
+ },
+ ],
+ },
+ {
+ title: 'Topics',
+ items: [
+ {
+ title: 'Topic.Publish()',
+ href: '/reference/go/topic/topic-publish',
+ },
+ {
+ title: 'Topic.Subscribe()',
+ href: '/reference/go/topic/topic-subscribe',
+ },
+ ],
+ },
+ {
+ title: 'Queues',
+ items: [
+ {
+ title: 'Queue.Enqueue()',
+ href: '/reference/go/queues/queue-enqueue',
+ },
+ {
+ title: 'Queue.Dequeue()',
+ href: '/reference/go/queues/queue-dequeue',
+ },
+ ],
+ },
+ {
+ title: 'Secrets',
+ items: [
+ {
+ title: 'Secret.Put()',
+ href: '/reference/go/secrets/secret-put',
+ },
+ {
+ title: 'Secret.Version()',
+ href: '/reference/go/secrets/secret-version',
+ },
+ {
+ title: 'Secret.Latest()',
+ href: '/reference/go/secrets/secret-latest',
+ },
+ {
+ title: 'Secret.Version.Access()',
+ href: '/reference/go/secrets/secret-version-access',
+ },
+ ],
+ },
+ {
+ title: 'Storage',
+ items: [
+ {
+ title: 'Bucket.On()',
+ href: '/reference/go/storage/bucket-on',
+ },
+ {
+ title: 'Bucket.File()',
+ href: '/reference/go/storage/bucket-file',
+ },
+ {
+ title: 'Bucket.Files()',
+ href: '/reference/go/storage/bucket-files',
+ },
+ {
+ title: 'File.Read()',
+ href: '/reference/go/storage/bucket-file-read',
+ },
+ {
+ title: 'File.Write()',
+ href: '/reference/go/storage/bucket-file-write',
+ },
+ {
+ title: 'File.Delete()',
+ href: '/reference/go/storage/bucket-file-delete',
+ },
+ {
+ title: 'File.DownloadUrl()',
+ href: '/reference/go/storage/bucket-file-downloadurl',
+ },
+ {
+ title: 'File.UploadUrl()',
+ href: '/reference/go/storage/bucket-file-uploadurl',
+ },
+ ],
+ },
+ {
+ title: 'Schedules',
+ items: [
+ {
+ title: 'Schedule.Every()',
+ href: '/reference/go/schedule/schedule-every',
+ },
+ {
+ title: 'Schedule.Cron()',
+ href: '/reference/go/schedule/schedule-cron',
+ },
+ ],
+ },
+ {
+ title: 'Websockets',
+ items: [
+ {
+ title: 'Websocket.On()',
+ href: '/reference/go/websocket/websocket-on',
+ },
+ {
+ title: 'Websocket.Send()',
+ href: '/reference/go/websocket/websocket-send',
+ },
+ {
+ title: 'Websocket.Close()',
+ href: '/reference/go/websocket/websocket-close',
+ },
+ ],
+ },
+ ],
+}
diff --git a/src/config/reference/node.ts b/src/config/reference/node.ts
new file mode 100644
index 000000000..45b2f9dde
--- /dev/null
+++ b/src/config/reference/node.ts
@@ -0,0 +1,259 @@
+import { FaNodeJs } from 'react-icons/fa'
+import { NavGroup } from '../types'
+
+export const NodeReference: NavGroup = {
+ title: 'Node.js',
+ icon: FaNodeJs,
+ items: [
+ {
+ title: 'Overview',
+ href: '/reference/nodejs',
+ },
+ {
+ title: 'APIs',
+ items: [
+ {
+ title: 'api()',
+ href: '/reference/nodejs/api/api',
+ },
+ {
+ title: 'api.get()',
+ href: '/reference/nodejs/api/api-get',
+ },
+ {
+ title: 'api.post()',
+ href: '/reference/nodejs/api/api-post',
+ },
+ {
+ title: 'api.put()',
+ href: '/reference/nodejs/api/api-put',
+ },
+ {
+ title: 'api.delete()',
+ href: '/reference/nodejs/api/api-delete',
+ },
+ {
+ title: 'api.patch()',
+ href: '/reference/nodejs/api/api-patch',
+ },
+ {
+ title: 'api.route()',
+ href: '/reference/nodejs/api/api-route',
+ },
+ {
+ title: 'api.route.all()',
+ href: '/reference/nodejs/api/api-route-all',
+ },
+ {
+ title: 'api.route.get()',
+ href: '/reference/nodejs/api/api-route-get',
+ },
+ {
+ title: 'api.route.post()',
+ href: '/reference/nodejs/api/api-route-post',
+ },
+ {
+ title: 'api.route.put()',
+ href: '/reference/nodejs/api/api-route-put',
+ },
+ {
+ title: 'api.route.delete()',
+ href: '/reference/nodejs/api/api-route-delete',
+ },
+ {
+ title: 'api.route.patch()',
+ href: '/reference/nodejs/api/api-route-patch',
+ },
+ ],
+ },
+ {
+ title: 'HTTP',
+ items: [
+ {
+ title: 'http()',
+ href: '/reference/nodejs/http/http',
+ },
+ ],
+ },
+ {
+ title: 'Key Value Stores',
+ items: [
+ {
+ title: 'kv()',
+ href: '/reference/nodejs/keyvalue/keyvalue',
+ },
+ {
+ title: 'kv.get()',
+ href: '/reference/nodejs/keyvalue/keyvalue-get',
+ },
+ {
+ title: 'kv.set()',
+ href: '/reference/nodejs/keyvalue/keyvalue-set',
+ },
+ {
+ title: 'kv.delete()',
+ href: '/reference/nodejs/keyvalue/keyvalue-delete',
+ },
+ {
+ title: 'kv.keys()',
+ href: '/reference/nodejs/keyvalue/keyvalue-keys',
+ },
+ ],
+ },
+ {
+ title: 'Topics',
+ items: [
+ {
+ title: 'topic()',
+ href: '/reference/nodejs/topic/topic',
+ },
+ {
+ title: 'topic.publish()',
+ href: '/reference/nodejs/topic/topic-publish',
+ },
+ {
+ title: 'topic.subscribe()',
+ href: '/reference/nodejs/topic/topic-subscribe',
+ },
+ ],
+ },
+ {
+ title: 'Queues',
+ items: [
+ {
+ title: 'queue()',
+ href: '/reference/nodejs/queues/queue',
+ },
+ {
+ title: 'queue.enqueue()',
+ href: '/reference/nodejs/queues/queue-enqueue',
+ },
+ {
+ title: 'queue.dequeue()',
+ href: '/reference/nodejs/queues/queue-dequeue',
+ },
+ ],
+ },
+ {
+ title: 'Secrets',
+ items: [
+ {
+ title: 'secret()',
+ href: '/reference/nodejs/secrets/secret',
+ },
+ {
+ title: 'secret.put()',
+ href: '/reference/nodejs/secrets/secret-put',
+ },
+ {
+ title: 'secret.version()',
+ href: '/reference/nodejs/secrets/secret-version',
+ },
+ {
+ title: 'secret.latest()',
+ href: '/reference/nodejs/secrets/secret-latest',
+ },
+ {
+ title: 'secret.version.access()',
+ href: '/reference/nodejs/secrets/secret-version-access',
+ },
+ ],
+ },
+ {
+ title: 'Storage',
+ items: [
+ {
+ title: 'bucket()',
+ href: '/reference/nodejs/storage/bucket',
+ },
+ {
+ title: 'bucket.on()',
+ href: '/reference/nodejs/storage/bucket-on',
+ },
+ {
+ title: 'bucket.file()',
+ href: '/reference/nodejs/storage/bucket-file',
+ },
+ {
+ title: 'bucket.files()',
+ href: '/reference/nodejs/storage/bucket-files',
+ },
+ {
+ title: 'file.exists()',
+ href: '/reference/nodejs/storage/bucket-file-exists',
+ },
+ {
+ title: 'file.read()',
+ href: '/reference/nodejs/storage/bucket-file-read',
+ },
+ {
+ title: 'file.write()',
+ href: '/reference/nodejs/storage/bucket-file-write',
+ },
+ {
+ title: 'file.delete()',
+ href: '/reference/nodejs/storage/bucket-file-delete',
+ },
+ {
+ title: 'file.getDownloadUrl()',
+ href: '/reference/nodejs/storage/bucket-file-downloadurl',
+ },
+ {
+ title: 'file.getUploadUrl()',
+ href: '/reference/nodejs/storage/bucket-file-uploadurl',
+ },
+ ],
+ },
+ {
+ title: 'SQL',
+ items: [
+ {
+ title: 'sql()',
+ href: '/reference/nodejs/sql/sql',
+ },
+ {
+ title: 'sql.connectionString()',
+ href: '/reference/nodejs/sql/sql-connection-string',
+ },
+ ],
+ },
+ {
+ title: 'Schedules',
+ items: [
+ {
+ title: 'schedule()',
+ href: '/reference/nodejs/schedule/schedule',
+ },
+ {
+ title: 'schedule.every()',
+ href: '/reference/nodejs/schedule/schedule-every',
+ },
+ {
+ title: 'schedule.cron()',
+ href: '/reference/nodejs/schedule/schedule-cron',
+ },
+ ],
+ },
+ {
+ title: 'Websockets',
+ items: [
+ {
+ title: 'websocket()',
+ href: '/reference/nodejs/websocket/websocket',
+ },
+ {
+ title: 'websocket.on()',
+ href: '/reference/nodejs/websocket/websocket-on',
+ },
+ {
+ title: 'websocket.send()',
+ href: '/reference/nodejs/websocket/websocket-send',
+ },
+ {
+ title: 'websocket.close()',
+ href: '/reference/nodejs/websocket/websocket-close',
+ },
+ ],
+ },
+ ],
+}
diff --git a/src/config/reference/python.ts b/src/config/reference/python.ts
new file mode 100644
index 000000000..11bb17c5d
--- /dev/null
+++ b/src/config/reference/python.ts
@@ -0,0 +1,214 @@
+import { FaPython } from 'react-icons/fa'
+import { NavGroup } from '../types'
+
+export const PyReference: NavGroup = {
+ title: 'Python',
+ icon: FaPython,
+ items: [
+ {
+ title: 'Overview',
+ href: '/reference/python',
+ },
+ {
+ title: 'APIs',
+ items: [
+ {
+ title: 'api()',
+ href: '/reference/python/api/api',
+ },
+ {
+ title: 'api.get()',
+ href: '/reference/python/api/api-get',
+ },
+ {
+ title: 'api.post()',
+ href: '/reference/python/api/api-post',
+ },
+ {
+ title: 'api.put()',
+ href: '/reference/python/api/api-put',
+ },
+ {
+ title: 'api.delete()',
+ href: '/reference/python/api/api-delete',
+ },
+ {
+ title: 'api.patch()',
+ href: '/reference/python/api/api-patch',
+ },
+ {
+ title: 'api.methods()',
+ href: '/reference/python/api/api-methods',
+ },
+ {
+ title: 'api.all()',
+ href: '/reference/python/api/api-all',
+ },
+ ],
+ },
+ {
+ title: 'Key Value Stores',
+ items: [
+ {
+ title: 'kv()',
+ href: '/reference/python/keyvalue/keyvalue',
+ },
+ {
+ title: 'kv.get()',
+ href: '/reference/python/keyvalue/keyvalue-get',
+ },
+ {
+ title: 'kv.set()',
+ href: '/reference/python/keyvalue/keyvalue-set',
+ },
+ {
+ title: 'kv.delete()',
+ href: '/reference/python/keyvalue/keyvalue-delete',
+ },
+ {
+ title: 'kv.keys()',
+ href: '/reference/python/keyvalue/keyvalue-keys',
+ },
+ ],
+ },
+ {
+ title: 'Sql',
+ items: [
+ {
+ title: 'sql()',
+ href: '/reference/python/sql/sql',
+ },
+ {
+ title: 'sql.connection_string()',
+ href: '/reference/python/sql/sql-connection-string',
+ },
+ ],
+ },
+ {
+ title: 'Topics',
+ items: [
+ {
+ title: 'topic()',
+ href: '/reference/python/topic/topic',
+ },
+ {
+ title: 'topic.publish()',
+ href: '/reference/python/topic/topic-publish',
+ },
+ {
+ title: 'topic.subscribe()',
+ href: '/reference/python/topic/topic-subscribe',
+ },
+ ],
+ },
+ {
+ title: 'Queues',
+ items: [
+ {
+ title: 'queue()',
+ href: '/reference/python/queues/queue',
+ },
+ {
+ title: 'queue.enqueue()',
+ href: '/reference/python/queues/queue-enqueue',
+ },
+ {
+ title: 'queue.dequeue()',
+ href: '/reference/python/queues/queue-dequeue',
+ },
+ ],
+ },
+ {
+ title: 'Secrets',
+ items: [
+ {
+ title: 'secret()',
+ href: '/reference/python/secrets/secret',
+ },
+ {
+ title: 'secret.put()',
+ href: '/reference/python/secrets/secret-put',
+ },
+ {
+ title: 'secret.version()',
+ href: '/reference/python/secrets/secret-version',
+ },
+ {
+ title: 'secret.latest()',
+ href: '/reference/python/secrets/secret-latest',
+ },
+ {
+ title: 'secret.version.access()',
+ href: '/reference/python/secrets/secret-version-access',
+ },
+ ],
+ },
+ {
+ title: 'Storage',
+ items: [
+ {
+ title: 'bucket()',
+ href: '/reference/python/storage/bucket',
+ },
+ {
+ title: 'bucket.on()',
+ href: '/reference/python/storage/bucket-on',
+ },
+ {
+ title: 'bucket.file()',
+ href: '/reference/python/storage/bucket-file',
+ },
+ {
+ title: 'bucket.files()',
+ href: '/reference/python/storage/bucket-files',
+ },
+ {
+ title: 'file.read()',
+ href: '/reference/python/storage/bucket-file-read',
+ },
+ {
+ title: 'file.write()',
+ href: '/reference/python/storage/bucket-file-write',
+ },
+ {
+ title: 'file.delete()',
+ href: '/reference/python/storage/bucket-file-delete',
+ },
+ {
+ title: 'file.download_url()',
+ href: '/reference/python/storage/bucket-file-downloadurl',
+ },
+ {
+ title: 'file.upload_url()',
+ href: '/reference/python/storage/bucket-file-uploadurl',
+ },
+ ],
+ },
+ {
+ title: 'Schedules',
+ items: [
+ {
+ title: 'schedule()',
+ href: '/reference/python/schedules/schedule',
+ },
+ ],
+ },
+ {
+ title: 'Websockets',
+ items: [
+ {
+ title: 'websocket()',
+ href: '/reference/python/websocket/websocket',
+ },
+ {
+ title: 'websocket.on()',
+ href: '/reference/python/websocket/websocket-on',
+ },
+ {
+ title: 'websocket.send()',
+ href: '/reference/python/websocket/websocket-send',
+ },
+ ],
+ },
+ ],
+}
diff --git a/src/config/types.ts b/src/config/types.ts
new file mode 100644
index 000000000..1bbadb7d3
--- /dev/null
+++ b/src/config/types.ts
@@ -0,0 +1,17 @@
+export interface BaseNavItem {
+ title: string
+ icon?: React.ComponentType<{ className?: string }>
+}
+
+export interface NavItem extends BaseNavItem {
+ href: string
+ collapsible?: boolean
+ items?: NavItem[]
+}
+
+export interface NavGroup extends BaseNavItem {
+ items: NavEntry[]
+ dividerBottom?: boolean
+}
+
+export type NavEntry = NavItem | NavGroup
diff --git a/src/siteConfig.ts b/src/siteConfig.ts
deleted file mode 100644
index 6529c68a1..000000000
--- a/src/siteConfig.ts
+++ /dev/null
@@ -1,173 +0,0 @@
-export interface NavGroup {
- title: string
- collapsible?: boolean
- icon?: React.ComponentType<{ className?: string }>
- links: Array<{
- title: string
- href: string
- }>
-}
-
-export const navigation: NavGroup[] = [
- {
- title: 'Intro',
- links: [
- {
- title: 'Intro',
- href: '/',
- },
- ],
- },
- {
- title: 'Concepts',
- links: [
- {
- title: 'Infrastructure from Code',
- href: '/infrastructure-from-code',
- },
- ],
- },
- {
- title: 'Basics',
- links: [
- {
- title: 'Installation',
- href: '/getting-started/installation',
- },
- {
- title: 'Configuration',
- href: '/getting-started/configuration',
- },
- ],
- },
- {
- title: 'Get Started',
- links: [
- {
- title: 'Quick Start',
- href: '/getting-started/quick-start',
- },
- ],
- },
- {
- title: 'Deployment',
- links: [
- {
- title: 'Intro',
- href: '/getting-started/quick-start',
- },
- {
- title: 'AWS',
- href: '/getting-started/quick-start',
- },
- {
- title: 'GCP',
- href: '/getting-started/quick-start',
- },
- {
- title: 'Azure',
- href: '/getting-started/quick-start',
- },
- {
- title: 'Custom',
- href: '/getting-started/quick-start',
- },
- {
- title: 'CD/CD',
- href: '/getting-started/quick-start',
- },
- ],
- },
- {
- title: 'Languages',
- links: [
- {
- title: 'Node.js',
- href: '/getting-started/quick-start',
- },
- {
- title: 'Python',
- href: '/getting-started/quick-start',
- },
- {
- title: 'Go',
- href: '/getting-started/quick-start',
- },
- {
- title: 'Dart',
- href: '/getting-started/quick-start',
- },
- ],
- },
- {
- title: 'Extension',
- links: [
- {
- title: 'Overview',
- href: '/extension/overview',
- },
- {
- title: 'Provider Extension',
- href: '/extension/provider-extension',
- },
- {
- title: 'Custom Providers',
- href: '/extension/custom-providers',
- },
- {
- title: 'Custom Containers',
- href: '/extension/custom-containers',
- },
- ],
- },
- {
- title: 'Reference',
- links: [
- {
- title: 'CLI',
- href: '/reference/cli',
- },
- {
- title: 'SDKs',
- href: '/reference/sdks',
- },
- {
- title: 'Env Vars',
- href: '/reference/env-vars',
- },
- {
- title: 'Examples',
- href: '/reference/examples',
- },
- {
- title: 'Preview Features',
- href: '/reference/preview-features',
- },
- ],
- },
- {
- title: 'FAQ',
- links: [
- {
- title: 'How is nitric different from Pulumi?',
- href: '/faq/nitric-vs-pulumi',
- },
- {
- title: 'How is nitric different from Terraform?',
- href: '/faq/nitric-vs-terraform',
- },
- {
- title: 'Comparisons with other tools/frameworks',
- href: '/faq/comparisons',
- },
- {
- title: 'How to migrate between clouds',
- href: '/faq/migrate-between-clouds',
- },
- {
- title: 'Ask a question',
- href: '/faq/ask-a-question',
- },
- ],
- },
-]
diff --git a/typography.ts b/typography.ts
index a41215e68..ab30ed56b 100644
--- a/typography.ts
+++ b/typography.ts
@@ -4,8 +4,8 @@ export default function typographyStyles({ theme }: PluginUtils) {
return {
DEFAULT: {
css: {
- '--tw-prose-body': theme('colors.zinc.300'),
- '--tw-prose-headings': theme('colors.white'),
+ '--tw-prose-body': theme('colors.zinc.900'),
+ '--tw-prose-headings': theme('colors.zinc.900'),
'--tw-prose-links': theme('colors.purple.500'),
'--tw-prose-links-hover': theme('colors.purple.600'),
'--tw-prose-links-underline': theme('colors.purple.500 / 0.3'),