Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a22ddbd
chore: prune old docs
steveiliop56 Sep 30, 2025
e14bb11
feat: init fumadocs app
steveiliop56 Sep 30, 2025
f80cc3f
refactor: refactor reference docs for v4 and fumadocs
steveiliop56 Sep 30, 2025
72db389
refactor: adapt docs to mdx
steveiliop56 Oct 3, 2025
4e9fd02
refactor: rework documentation phrasing
steveiliop56 Oct 3, 2025
4234fa3
chore: add umami analytics
steveiliop56 Oct 3, 2025
606eee4
refactor: rework 404 screen
steveiliop56 Oct 3, 2025
a46755c
Merge branch 'main' into feat/fumadocs
steveiliop56 Oct 3, 2025
f08a7c7
refactor: use static search
steveiliop56 Oct 3, 2025
38ef0d0
refactor: use prerender on all pages
steveiliop56 Oct 3, 2025
ef2d6e1
fix: disable ssr on react router
steveiliop56 Oct 3, 2025
43c3077
fix: use latest node in deploy workflow
steveiliop56 Oct 3, 2025
30d3596
chore: delete preview workflow
steveiliop56 Oct 5, 2025
1f9c358
feat: add migration guide
steveiliop56 Oct 6, 2025
4c59831
feat: add changelog to docs
steveiliop56 Oct 6, 2025
9f2e959
feat: add note on telemetry
steveiliop56 Oct 6, 2025
9a2c514
feat: add docs for healthcheck command
steveiliop56 Oct 7, 2025
00d7762
feat: add api changes to migration guide
steveiliop56 Oct 7, 2025
9f3d330
refactor: updates in migration guide
steveiliop56 Oct 7, 2025
cdc140f
feat: add route to redirect to discord
steveiliop56 Oct 7, 2025
558c3b3
feat: add kubernetes and helm chart note
steveiliop56 Oct 8, 2025
3fb347f
fix: use info as tip is not a thing
steveiliop56 Oct 8, 2025
af94f8d
chore: update changelog
steveiliop56 Oct 8, 2025
05de658
fix: fix discord and search endpoints
steveiliop56 Oct 8, 2025
3b1babe
chore: use frozen lockfile in cd
steveiliop56 Oct 8, 2025
8041555
chore: remove mdx extension from changelog
steveiliop56 Oct 8, 2025
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
10 changes: 7 additions & 3 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,31 @@ jobs:
with:
fetch-depth: 0

- uses: actions/setup-node@v5
with:
node-version: "20"

- name: Setup bun
uses: oven-sh/setup-bun@v2

- name: Cache bun dependencies
uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-web-${{ hashFiles('bun.lockb') }}
key: ${{ runner.os }}-bun-web-${{ hashFiles('bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-web-
Comment on lines 26 to 31
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Restore cache key to hash the actual Bun lockfile.

Switching the cache key to hashFiles('bun.lock') breaks cache busting because Bun still generates bun.lockb by default, so the hash is now empty and the job falls back to a static key. That means dependency updates will keep reusing stale cache entries. Please keep hashing bun.lockb, or include both patterns if you’re intentionally migrating to the text lockfile.

Apply this diff (or equivalent) to fix it:

-          key: ${{ runner.os }}-bun-web-${{ hashFiles('bun.lock') }}
+          key: ${{ runner.os }}-bun-web-${{ hashFiles('bun.lockb') }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-web-${{ hashFiles('bun.lockb') }}
key: ${{ runner.os }}-bun-web-${{ hashFiles('bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-web-
uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-web-${{ hashFiles('bun.lockb') }}
restore-keys: |
${{ runner.os }}-bun-web-
🤖 Prompt for AI Agents
.github/workflows/deploy.yml around lines 26 to 31: the cache key currently
hashes bun.lock which is empty when Bun generates bun.lockb by default, causing
cache misses and stale reuse; change the key to hash the binary lockfile
(bun.lockb) or include both files so hashing falls back correctly (e.g., use
hashFiles('bun.lockb') or hashFiles('bun.lock','bun.lockb')) and update any
restore-keys accordingly so dependency changes produce new cache keys.


- name: Install dependencies
run: bun install
run: bun install --frozen-lockfile

- name: Build website
run: bun run build

- name: Upload Build Artifact
uses: actions/upload-pages-artifact@v3
with:
path: build
path: build/client

deploy:
name: Deploy to GitHub Pages
Expand Down
43 changes: 0 additions & 43 deletions .github/workflows/preview.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
/build

# Generated files
.docusaurus
.react-router
.cache-loader

# Misc
Expand Down
4 changes: 2 additions & 2 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Docusaurus build output
.docusaurus
# React router build output
.react-router

# Node modules
node_modules
12 changes: 11 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
{
"cSpell.enabled": true
"cSpell.enabled": true,
"cSpell.words": [
"appstore",
"Healthcheck",
"homelab",
"homeserver",
"Runtipi",
"Tinyauth",
"TOTP",
"Traefik"
]
}
3 changes: 3 additions & 0 deletions app/app.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@import 'tailwindcss';
@import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css';
11 changes: 11 additions & 0 deletions app/cli.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"aliases": {
"uiDir": "./components/ui",
"componentsDir": "./components",
"blockDir": "./components",
"cssDir": "./styles",
"libDir": "./lib"
},
"baseDir": "",
"commands": {}
}
Comment on lines +1 to +11
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify the cssDir alias path

The cssDir alias points to "./styles", but the actual CSS file (app/app.css) is located in the root of the app/ directory. If this configuration is used by tooling to locate CSS files, this mismatch could cause issues.

Run the following script to check the actual CSS file locations:


🏁 Script executed:

#!/bin/bash
# Description: Verify CSS file locations vs. cssDir alias

# Check if ./styles directory exists
fd -t d -d 1 '^styles$' app/

# List all CSS files in the app directory
fd -e css -t f . app/

Length of output: 11


Update cssDir alias to match actual CSS location
In app/cli.json, change "cssDir": "./styles" to "cssDir": "./" so it points to app/app.css.

🤖 Prompt for AI Agents
In app/cli.json around lines 1 to 11 the cssDir alias currently points to
"./styles" but the actual CSS file is app/app.css; update the cssDir value to
"./" so the alias resolves to the project root where app.css lives, saving the
file after the change.

24 changes: 24 additions & 0 deletions app/components/card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
interface FeatureCardProps {
title: string;
description: string;
icon?: React.ReactNode;
children?: React.ReactNode;
}

export const Card = ({
title,
description,
icon,
children,
}: FeatureCardProps) => {
return (
<div className="flex flex-col gap-4 p-4 shadow-xs border border-fd-border rounded-md hover:border-fd-accent transition-colors max-w-xs">
{icon}
<div className="flex flex-col gap-2">
<p className="text-md font-semibold">{title}</p>
<p className="text-sm">{description}</p>
</div>
{children}
</div>
);
};
18 changes: 18 additions & 0 deletions app/components/discord.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { SVGProps } from "react";

export function IcBaselineDiscord(props: SVGProps<SVGSVGElement>) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width={24}
height={24}
viewBox="0 0 24 24"
{...props}
>
<path
fill="currentColor"
d="M19.27 5.33C17.94 4.71 16.5 4.26 15 4a.1.1 0 0 0-.07.03c-.18.33-.39.76-.53 1.09a16.1 16.1 0 0 0-4.8 0c-.14-.34-.35-.76-.54-1.09c-.01-.02-.04-.03-.07-.03c-1.5.26-2.93.71-4.27 1.33c-.01 0-.02.01-.03.02c-2.72 4.07-3.47 8.03-3.1 11.95c0 .02.01.04.03.05c1.8 1.32 3.53 2.12 5.24 2.65c.03.01.06 0 .07-.02c.4-.55.76-1.13 1.07-1.74c.02-.04 0-.08-.04-.09c-.57-.22-1.11-.48-1.64-.78c-.04-.02-.04-.08-.01-.11c.11-.08.22-.17.33-.25c.02-.02.05-.02.07-.01c3.44 1.57 7.15 1.57 10.55 0c.02-.01.05-.01.07.01c.11.09.22.17.33.26c.04.03.04.09-.01.11c-.52.31-1.07.56-1.64.78c-.04.01-.05.06-.04.09c.32.61.68 1.19 1.07 1.74c.03.01.06.02.09.01c1.72-.53 3.45-1.33 5.25-2.65c.02-.01.03-.03.03-.05c.44-4.53-.73-8.46-3.1-11.95c-.01-.01-.02-.02-.04-.02M8.52 14.91c-1.03 0-1.89-.95-1.89-2.12s.84-2.12 1.89-2.12c1.06 0 1.9.96 1.89 2.12c0 1.17-.84 2.12-1.89 2.12m6.97 0c-1.03 0-1.89-.95-1.89-2.12s.84-2.12 1.89-2.12c1.06 0 1.9.96 1.89 2.12c0 1.17-.83 2.12-1.89 2.12"
></path>
</svg>
);
}
18 changes: 18 additions & 0 deletions app/components/github.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { SVGProps } from "react";

export function MdiGithub(props: SVGProps<SVGSVGElement>) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width={24}
height={24}
viewBox="0 0 24 24"
{...props}
>
<path
fill="currentColor"
d="M12 2A10 10 0 0 0 2 12c0 4.42 2.87 8.17 6.84 9.5c.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34c-.46-1.16-1.11-1.47-1.11-1.47c-.91-.62.07-.6.07-.6c1 .07 1.53 1.03 1.53 1.03c.87 1.52 2.34 1.07 2.91.83c.09-.65.35-1.09.63-1.34c-2.22-.25-4.55-1.11-4.55-4.92c0-1.11.38-2 1.03-2.71c-.1-.25-.45-1.29.1-2.64c0 0 .84-.27 2.75 1.02c.79-.22 1.65-.33 2.5-.33s1.71.11 2.5.33c1.91-1.29 2.75-1.02 2.75-1.02c.55 1.35.2 2.39.1 2.64c.65.71 1.03 1.6 1.03 2.71c0 3.82-2.34 4.66-4.57 4.91c.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2"
></path>
</svg>
);
}
68 changes: 68 additions & 0 deletions app/components/language-toggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
'use client';
import { type ButtonHTMLAttributes, type HTMLAttributes } from 'react';
import { useI18n } from 'fumadocs-ui/contexts/i18n';
import {
Popover,
PopoverContent,
PopoverTrigger,
} from './ui/popover';
import { cn } from '../lib/cn';
import { buttonVariants } from './ui/button';

export type LanguageSelectProps = ButtonHTMLAttributes<HTMLButtonElement>;

export function LanguageToggle(props: LanguageSelectProps): React.ReactElement {
const context = useI18n();
if (!context.locales) throw new Error('Missing `<I18nProvider />`');

return (
<Popover>
<PopoverTrigger
aria-label={context.text.chooseLanguage}
{...props}
className={cn(
buttonVariants({
color: 'ghost',
className: 'gap-1.5 p-1.5',
}),
props.className,
)}
>
{props.children}
</PopoverTrigger>
<PopoverContent className="flex flex-col overflow-hidden p-0">
<p className="mb-1 p-2 text-xs font-medium text-fd-muted-foreground">
{context.text.chooseLanguage}
</p>
{context.locales.map((item) => (
<button
key={item.locale}
type="button"
className={cn(
'p-2 text-start text-sm',
item.locale === context.locale
? 'bg-fd-primary/10 font-medium text-fd-primary'
: 'hover:bg-fd-accent hover:text-fd-accent-foreground',
)}
onClick={() => {
context.onChange?.(item.locale);
}}
>
{item.name}
</button>
))}
</PopoverContent>
</Popover>
);
}

export function LanguageToggleText(
props: HTMLAttributes<HTMLSpanElement>,
): React.ReactElement {
const context = useI18n();
const text = context.locales?.find(
(item) => item.locale === context.locale,
)?.name;

return <span {...props}>{text}</span>;
}
81 changes: 81 additions & 0 deletions app/components/layout/docs/client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
'use client';

import { Sidebar as SidebarIcon } from 'lucide-react';
import { type ComponentProps } from 'react';
import { cn } from '../../../lib/cn';
import { buttonVariants } from '../../ui/button';
import { useSidebar } from 'fumadocs-ui/contexts/sidebar';
import { useNav } from 'fumadocs-ui/contexts/layout';
import { SidebarCollapseTrigger } from '../../sidebar';
import { SearchToggle } from '../../search-toggle';

export function Navbar(props: ComponentProps<'header'>) {
const { isTransparent } = useNav();

return (
<header
id="nd-subnav"
{...props}
className={cn(
'fixed top-(--fd-banner-height) left-0 right-(--removed-body-scroll-bar-size,0) z-30 flex items-center ps-4 pe-2.5 border-b transition-colors backdrop-blur-sm',
!isTransparent && 'bg-fd-background/80',
props.className,
)}
>
{props.children}
</header>
);
}

export function LayoutBody(props: ComponentProps<'main'>) {
const { collapsed } = useSidebar();

return (
<main
id="nd-docs-layout"
{...props}
className={cn(
'flex flex-1 flex-col pt-(--fd-nav-height) transition-[padding] fd-default-layout',
!collapsed && 'mx-(--fd-layout-offset)',
props.className,
)}
style={{
...props.style,
paddingInlineStart: collapsed
? 'min(calc(100vw - var(--fd-page-width)), var(--fd-sidebar-width))'
: 'var(--fd-sidebar-width)',
}}
>
{props.children}
</main>
);
}

export function CollapsibleControl() {
const { collapsed } = useSidebar();

return (
<div
className={cn(
'fixed flex shadow-lg transition-opacity rounded-xl p-0.5 border bg-fd-muted text-fd-muted-foreground z-10 max-md:hidden xl:start-4 max-xl:end-4',
!collapsed && 'pointer-events-none opacity-0',
)}
style={{
top: 'calc(var(--fd-banner-height) + var(--fd-tocnav-height) + var(--spacing) * 4)',
}}
>
<SidebarCollapseTrigger
className={cn(
buttonVariants({
color: 'ghost',
size: 'icon-sm',
className: 'rounded-lg',
}),
)}
>
<SidebarIcon />
</SidebarCollapseTrigger>
<SearchToggle className="rounded-lg" hideIfDisabled />
</div>
);
}
Loading