Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
6d70057
small improvements
abrulic Sep 7, 2025
3503ff6
fix for standalone .mdx files + typesafety for generated pages and se…
abrulic Sep 7, 2025
f60013e
small changes
abrulic Sep 8, 2025
0ce7516
updates
abrulic Sep 10, 2025
933ad24
small updates
abrulic Sep 10, 2025
5d145a4
fixes
abrulic Sep 11, 2025
324471b
fixes
abrulic Sep 11, 2025
978887a
small updates
abrulic Sep 11, 2025
45e5517
deployed app using standard fly launch and fly deploy commands
abrulic Sep 12, 2025
9831bb1
Merge branch 'main' into improvements
abrulic Sep 12, 2025
8b73a61
fixes in loding content collections and some UI fixes
abrulic Sep 12, 2025
66675a5
removed content-collections:build script from package.json
abrulic Sep 12, 2025
ab416e8
accordion component updated
abrulic Sep 12, 2025
c1a4fbe
added on PR fly deploy action
abrulic Sep 12, 2025
219f3aa
removed flydotio/dockerfile
abrulic Sep 12, 2025
69144df
fixed content-ollections Page imports
abrulic Sep 12, 2025
747aefe
fly deploy workflow update
abrulic Sep 12, 2025
b231a6c
fly deploy workflow update
abrulic Sep 12, 2025
2222945
content-collections cli returned
abrulic Sep 12, 2025
1e49bd5
added small console log for debugging
abrulic Sep 12, 2025
cb8a2f3
added small console log for debugging
abrulic Sep 12, 2025
e225d77
added small console log for debugging
abrulic Sep 12, 2025
1f1f090
added small console log for debugging and pr-close workflow
abrulic Sep 12, 2025
0104233
small fix
abrulic Sep 12, 2025
eec49e9
updated env_vars in ci.yml
abrulic Sep 12, 2025
b649f7b
debounced search
abrulic Sep 12, 2025
1e653ee
small update in seo.ts and favion.ico changed
abrulic Sep 12, 2025
849285b
added meta for index page
abrulic Sep 12, 2025
fb234fa
small fix in filename
abrulic Sep 12, 2025
a802352
fix with seo image?
abrulic Sep 12, 2025
5dbf938
small fixes in padding, leading, font size
abrulic Sep 15, 2025
5a7a8c8
update in fly.toml, dockerfile and package.json
abrulic Sep 15, 2025
2b2c5b3
small change in dockerifle
abrulic Sep 15, 2025
2ae70d1
added http_checks in fly.toml
abrulic Sep 15, 2025
38abb62
small update in fly.toml
abrulic Sep 15, 2025
40b3f9d
small update?
abrulic Sep 15, 2025
5578c64
fly tol update
abrulic Sep 15, 2025
2926f85
previous state?
abrulic Sep 15, 2025
13504f9
check?
abrulic Sep 15, 2025
f68730a
previous state
abrulic Sep 15, 2025
d2c3788
small fix
abrulic Sep 16, 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
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
GITHUB_OWNER="github-owner" # Your username or organization name (Optional. For edit/report an issue for the documentation page)
GITHUB_REPO="github-repo" # Repository name (Optional. For edit/report an issue for the documentation page)
APP_ROOT_PATH="/path/to/your/app" # Optional. Default is `process.cwd()`
GITHUB_REPO_URL="github-repo-url" #Optional - if you want to have discord icon link in the header or footer
Comment thread
abrulic marked this conversation as resolved.
Outdated
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ This folder contains all the resources used by the documentation site, such as S

`content/`

This folder contains sections and subsections with .mdx files that hold your documentation content. Below is the recommended structure to follow.
This folder contains .md and .mdx files that hold your documentation content. Below is the recommended structure to follow.


An example of a valid content/ folder structure for organizing your package documentation:
Expand Down Expand Up @@ -46,12 +46,15 @@ content/
├── 01-buttons.mdx
└── 02-modals.mdx
```
- Top-level .mdx files (like 01-changelog.mdx) are allowed.
- Sections (like 04-getting-started, 05-core-features) are subfolders inside the content/ folder.
- Subsections (like 03-data-management, 04-ui-components) are nested folders within sections.
- Each section or subsection should have an index.md file for its sidebar title.
- Top-level .mdx files (like 01-changelog.mdx) are allowed, but we recommend placing them in order before the sections, as shown in the example.

### Example of the valid `02-introduction.mdx` file:
- Sections (like 04-getting-started, 05-core-features) are subfolders inside the `content` folder.

- Subsections (like 03-data-management, 04-ui-components) are nested folders within sections. Filenames inside them should start with `01-*.mdx`.

- Each section or subsection should include an `index.md` file, which defines its sidebar title.

### Example of the valid `**/*.mdx` file:
```
---
title: "Introduction to Forge42 Base Stack"
Expand All @@ -75,7 +78,7 @@ cd my-app
npm install
```

### Example of the valid `04-getting-started/index.md` file:
### Example of the valid `**/*.md` file:
```
---
title: Getting Started
Expand Down
32 changes: 32 additions & 0 deletions app/components/documentation-page-view.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import type { Page } from "content-collections"
import { extractHeadingTreeFromMarkdown } from "~/utils/extract-heading-tree-from-mdx"
import GithubContributeLinks from "./github-contribute-links"
import PageMdxArticle from "./page-mdx-article"
import { PageNavigation, type PageNavigationItem } from "./page-navigation"
import { TableOfContents } from "./table-of-content"

export function DocumentationPageView({
page,
previous,
next,
}: {
page: Page
previous: PageNavigationItem | undefined
next: PageNavigationItem | undefined
}) {
const toc = extractHeadingTreeFromMarkdown(page.rawMdx)
return (
<div className="flex min-h-screen flex-row">
<div className="mx-auto flex w-full max-w-screen-4xl flex-col gap-4 pt-4 lg:gap-8 xl:pt-0">
<PageMdxArticle page={page} />
<PageNavigation previous={previous} next={next} />
</div>
<aside className="hidden w-56 min-w-min flex-shrink-0 xl:block">
<div className="sticky top-37 pb-10">
<GithubContributeLinks pagePath={page._meta.filePath} />
<TableOfContents items={toc} />
</div>
</aside>
</div>
)
}
28 changes: 28 additions & 0 deletions app/components/icon-link.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { ComponentProps } from "react"
import { Icon } from "~/ui/icon/icon"
import type { IconName } from "~/ui/icon/icons/types"
import { cn } from "~/utils/css"

interface IconLinkProps extends ComponentProps<"a"> {
name: IconName
}

export const IconLink = ({ name, className, ...props }: IconLinkProps) => {
const { href } = props
const isExternal = typeof href === "string" && /^https?:\/\//i.test(href)
return (
<a
className={cn(
"group relative inline-flex cursor-pointer items-center justify-center rounded-full p-2 text-[var(--color-text-active)] transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-border)] focus-visible:ring-offset-2",
className
)}
target={isExternal ? "_blank" : undefined}
rel="noopener noreferrer"
aria-label={name}
href={href}
{...props}
>
<Icon name={name} className="size-4 transition-all duration-300 xl:size-5" />
</a>
)
}
6 changes: 3 additions & 3 deletions app/components/page-mdx-article.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Page } from "~/routes/documentation-page"
import type { Page } from "content-collections"
import { Title } from "~/ui/title"
import { MDXWrapper } from "./mdx-wrapper"

Expand All @@ -10,9 +10,9 @@ export default function PageMdxArticle({ page }: { page: Page }) {
{page.title}
</Title>
{page.description && (
<Title as="h5" className="my-6 text-[var(--color-text-muted)] text-lg">
<p className="my-6 font-normal text-[var(--color-text-muted)] text-base sm:text-lg md:text-xl">
{page.description}
</Title>
</p>
)}
</header>
<MDXWrapper content={page.content} />
Expand Down
2 changes: 1 addition & 1 deletion app/components/page-navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Link } from "react-router"
import { Icon } from "~/ui/icon/icon"
import { cn } from "~/utils/css"

interface PageNavigationItem {
export interface PageNavigationItem {
title: string
to: string
}
Expand Down
42 changes: 42 additions & 0 deletions app/components/sidebar/build-breadcrumbs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type { Page } from "content-collections"
import { buildDocPathFromSlug } from "~/utils/build-doc-path-from-slug"
import type { SidebarSection } from "~/utils/create-sidebar-tree"

export const buildBreadcrumbs = (
items: SidebarSection[],
pathname: string,
documentationPages: Pick<Page, "title" | "slug">[] = []
) => {
// for standalone pages: /:filename
for (const page of documentationPages) {
const filename = buildDocPathFromSlug(page.slug)
const docPath = `/${filename}`
if (docPath === pathname) {
return [page.title]
}
}

// for sectioned pages: /:section/:subsection?/:filename
let trail: string[] = []

const walk = (section: SidebarSection, acc: string[]): boolean => {
for (const doc of section.documentationPages) {
const docPath = buildDocPathFromSlug(doc.slug)
if (docPath === pathname) {
trail = [...acc, section.title, doc.title]
return true
}
}

for (const sub of section.subsections) {
if (walk(sub, [...acc, section.title])) return true
}
return false
}

for (const root of items) {
if (walk(root, [])) break
}

return trail
}
29 changes: 0 additions & 29 deletions app/components/sidebar/build-breadcrumbs.tsx

This file was deleted.

6 changes: 3 additions & 3 deletions app/components/sidebar/desktop-sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import type { SidebarTree } from "~/utils/create-sidebar-tree"
import { cn } from "~/utils/css"
import type { SidebarSection } from "./sidebar"
import { SidebarContent } from "./sidebar-content"

export const DesktopSidebarPanel = ({ items, className }: { items: SidebarSection[]; className: string }) => (
export const DesktopSidebarPanel = ({ sidebarTree, className }: { sidebarTree: SidebarTree; className: string }) => (
<div
className={cn(
"sticky top-[var(--header-height)] flex h-[calc(100vh-var(--header-height))] w-80 flex-col overflow-hidden bg-[var(--color-background)] p-4",
className
)}
>
<SidebarContent items={items} />
<SidebarContent sidebarTree={sidebarTree} />
</div>
)
23 changes: 17 additions & 6 deletions app/components/sidebar/mobile-sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { useParams } from "react-router"
import { useDocumentationLayoutLoaderData } from "~/hooks/use-documentation-layout-loader-data"
import { BreadcrumbItem, Breadcrumbs } from "~/ui/breadcrumbs"
import { Icon } from "~/ui/icon/icon"
import type { SidebarTree } from "~/utils/create-sidebar-tree"
import { cn } from "~/utils/css"
import { buildBreadcrumbs } from "./build-breadcrumbs"
import { useMobileSidebar } from "./mobile-sidebar-context"
import type { SidebarSection } from "./sidebar"
import { SidebarContent } from "./sidebar-content"

const MobileSidebarMenuButton = () => {
Expand All @@ -20,7 +23,16 @@ const MobileSidebarMenuButton = () => {
)
}

export const MobileSidebarHeader = ({ breadcrumbs }: { breadcrumbs: string[] }) => {
export const MobileSidebarHeader = () => {
const params = useParams()
const {
sidebarTree: { sections, documentationPages },
} = useDocumentationLayoutLoaderData()
const { section, subsection, filename } = params
//
Comment thread
abrulic marked this conversation as resolved.
Outdated
const currentPath = `/${[section, subsection, filename].filter(Boolean).join("/")}`

const breadcrumbs = buildBreadcrumbs(sections, currentPath, documentationPages)
return (
<div className="fixed z-40 flex h-fit w-full items-center gap-3 border-[var(--color-border)] border-b-2 bg-[var(--color-background)] px-4 py-2">
<MobileSidebarMenuButton />
Expand Down Expand Up @@ -64,10 +76,10 @@ const MobileSidebarCloseButton = () => {
}

export const MobileSidebarPanel = ({
items,
sidebarTree,
className,
}: {
items: SidebarSection[]
sidebarTree: SidebarTree
className: string
}) => {
const { close, isOpen } = useMobileSidebar()
Expand All @@ -78,10 +90,9 @@ export const MobileSidebarPanel = ({
isOpen ? "translate-x-0" : "-translate-x-full",
className
)}
aria-modal="true"
aria-label="Navigation menu"
>
<SidebarContent items={items} onClose={close} />
<SidebarContent sidebarTree={sidebarTree} onClose={close} />
<MobileSidebarCloseButton />
</div>
)
Expand Down
36 changes: 30 additions & 6 deletions app/components/sidebar/sidebar-content.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,43 @@
import { useMobileView } from "~/hooks/use-mobile-view"
import { Accordion } from "~/ui/accordion"
import type { SidebarSection } from "./sidebar"
import { SectionItem } from "./sidebar-section"
import type { SidebarTree } from "~/utils/create-sidebar-tree"
import { buildStandaloneTo } from "~/utils/path-builders"
import { useCurrentVersion } from "~/utils/version-resolvers"
import { DocumentationNavLink, SectionItem } from "./sidebar-items"

export const SidebarContent = ({ items, onClose }: { items: SidebarSection[]; onClose?: () => void }) => {
export const SidebarContent = ({
sidebarTree,
onClose,
}: {
sidebarTree: SidebarTree
onClose?: () => void
}) => {
const { isMobile } = useMobileView()

const handle = isMobile ? onClose : undefined
const { sections, documentationPages } = sidebarTree
const version = useCurrentVersion()
return (
<nav
className="max-h-[calc(100vh-var(--header-height))] min-h-0 flex-1 overflow-y-auto pr-4"
aria-label="Documentation navigation"
>
{documentationPages.length > 0 && (
<div className="mb-6 space-y-1">
{documentationPages.map((p) => (
// TODO maybe send whole page, not title etc
Comment thread
abrulic marked this conversation as resolved.
Outdated
<DocumentationNavLink
key={p.slug}
title={p.title}
onClick={handle}
to={buildStandaloneTo(version, p.slug)}
/>
))}
</div>
)}

<Accordion>
{items.map((item) => (
<SectionItem key={item.slug} item={item} onItemClick={isMobile ? onClose : undefined} />
{sections.map((item) => (
<SectionItem key={item.slug} item={item} onItemClick={handle} />
))}
</Accordion>
</nav>
Expand Down
Loading