Skip to content

Commit 3e5c7e6

Browse files
authored
Initial setup and layout (#1)
* cleanup from base-stack * sidebar initial working version * functional table of content component * small change in the knip.json * custom script to validate content folder positions inside frontmatter, and some fixes in sidebar, toc and ocumentation page * updated readme.md file * updated readme.md file * small refactoring and added documnetation for some components * footer component * initial theme switcher, changes on UI, additional components * fonts, some fixes * small change * convention xx-file-name.mdx update - still updates needed * refactoring * small changes and updated package.json * ts fix? * ts fix? * ts fix? * ts fix? * ts fix? * sidebar fix * added content folder and some fixes and improvements in UI * removed _index route, added index.mdx file for hopemage, reorganized routes.ts * refactoring * small update in update-frontmatter logic * small refactoring * small ui improvements * small ui improvements * refactoring * refactoring * theme toggle fix * refactoring ad vitest tests for some helper functions * small refactoring * fix in breadcrumbs building * fix in breadcrumbs building * unit tests and small improvements * comments and tests * fixed so it doesnt contains v1.0.1 now * fixes * small update * small fixes * small change * small fix in sidebar * refactoring * improvements
1 parent 13114f7 commit 3e5c7e6

File tree

155 files changed

+5969
-795
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

155 files changed

+5969
-795
lines changed

.env.example

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# Add your env variables here
2-
3-
# The environment of the app. This is different from NODE_ENV, and will be used for deployments.
4-
# Default: development
5-
#APP_ENV="staging"
1+
GITHUB_OWNER="github-owner" # Your username or organization name (Optional. For edit/report an issue for the documentation page)
2+
GITHUB_REPO="github-repo" # Repository name (Optional. For edit/report an issue for the documentation page)
3+
APP_ROOT_PATH="/path/to/your/app" # Optional. Default is `process.cwd()`

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,7 @@ blob-report
8080
*.sqlite
8181
*.sqlite3
8282
*.db-journal
83+
84+
85+
# Content collections output files
86+
.content-collections

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,6 @@
4242
},
4343
"[typescriptreact]": {
4444
"editor.defaultFormatter": "biomejs.biome"
45-
}
45+
},
46+
"editor.formatOnPaste": true
4647
}

README.md

Lines changed: 85 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,89 @@
1+
# Welcome to Forge 42 Documentation Template
12

3+
This template is designed to support a flexible content structure using `.md` and `.mdx` files organized into folders. It enables deeply nested sections and subsections, making it easy to manage complex documentation with a clear and scalable hierarchy.
4+
5+
The project is built using the [@forge-42/base-stack](https://github.com/forge-42/base-stack) and leverages the [content-collections](https://github.com/sdorra/content-collections).
6+
7+
8+
## Documentation Template Structure Overview
9+
10+
`app/`
11+
12+
This folder contains React Router v7 web application folders and files, including components and UI primitives for the documentation site’s interface, internal hooks and utilities, and the tailwind.css file for styling.
13+
14+
15+
`resources/`
16+
17+
This folder contains all the resources used by the documentation site, such as SVG icons, fonts, and other assets.
18+
19+
`content/`
20+
21+
This folder contains sections and subsections with .mdx files that hold your documentation content. Below is the recommended structure to follow.
22+
23+
24+
An example of a valid content/ folder structure for organizing your package documentation:
225

3-
<p align="middle">
4-
<img width="900px" height="500px" src="./public/base-stack.png" />
5-
</p>
6-
7-
# Welcome to Forge 42 base-stack
8-
9-
This is a base-stack for Forge 42 projects. This stack is a starting point for all Forge 42 stacks with more
10-
advanced features. This is an ESM Vite stack with Remix.run / React Router v7.
11-
12-
It includes a basic setup for a project with react-router v7 framework mode and:
13-
- React 19 & react-compiler
14-
- TypeScript
15-
- TailwindCSS
16-
- Vite
17-
- Vitest (unit tests)
18-
- Scripting
19-
- Biome (linter & formatter)
20-
- i18n support (client and server)
21-
- Icons spritesheet generator
22-
- lefthook hooks
23-
- CI checks for quality control
24-
- react-router-devtools
25-
- Hono server
26-
- .env var handling for server and client
27-
- SEO robots.txt, sitemap-index and sitemap built in.
28-
29-
## Internationalization
30-
31-
This stack uses i18next for internationalization. It supports both client and server side translations.
32-
Features included out of the box:
33-
- Support for multiple languages
34-
- Typesafe resources
35-
- client side translations are fetched only when needed
36-
- language switcher
37-
- language detector (uses the request to detect the language, falls back to your fallback language)
38-
39-
## Hono server
40-
41-
This stack uses Hono for the server. More information about Hono can be found [here](https://honojs.dev/).
42-
Another important thing to note is that we use a dependency called `react-router-hono-server` which is a wrapper for Hono that allows us to use Hono in our React Router application.
43-
44-
The server comes preconfigured with:
45-
- i18next middleware
46-
- caching middleware for assets
47-
- easily extendable global application context
48-
- .env injection into context
49-
50-
In order to add your own middleware, extend the context, or anything along those lines, all you have to do is edit the server
51-
inside the `entry.server.tsx` file.
52-
53-
## .env handling
54-
55-
This stack parses your `.env` file and injects it into the server context. For the client side, in the `root.tsx` file, we use the `useLoaderData` hook to get the `clientEnv` from the server and set it as a global variable on the `window` called `env`.
56-
If you need to access the env variables in both environments, you can create a polyEnv helper like this:
57-
```ts
58-
// app/utils/env.ts
59-
// This will return the process.env on the server and window.env on the client
60-
export const polyEnv = typeof process !== "undefined" ? process.env : window.env;
6126
```
62-
The server will fail at runtime if you don't set your `.env` file properly.
27+
content/
28+
├── _index.mdx
29+
├── 01-changelog.mdx
30+
├── 02-introduction.mdx
31+
├── 03-overview.mdx
32+
├── 04-getting-started/
33+
│ ├── index.md
34+
│ ├── 01-installation.mdx
35+
│ ├── 02-quick-start.mdx
36+
│ └── 03-project-setup.mdx
37+
└── 05-core-features/
38+
├── index.md
39+
├── 01-authentication.mdx
40+
├── 02-authorization.mdx
41+
├── 03-data-management/
42+
│ ├── index.md
43+
│ ├── 01-fetching-data.mdx
44+
│ └── 02-caching-strategies.mdx
45+
└── 04-ui-components/
46+
├── index.md
47+
├── 01-buttons.mdx
48+
└── 02-modals.mdx
49+
```
50+
- Top-level .mdx files (like 01-changelog.mdx) are allowed.
51+
- Sections (like 04-getting-started, 05-core-features) are subfolders inside the content/ folder.
52+
- Subsections (like 03-data-management, 04-ui-components) are nested folders within sections.
53+
- Each section or subsection should have an index.md file for its sidebar title.
54+
55+
### Example of the valid `02-introduction.mdx` file:
56+
```
57+
---
58+
title: "Introduction to Forge42 Base Stack"
59+
summary: "Overview of the Stack"
60+
description: "Get started with the Forge42 Base Stack — a modern web app starter template designed for speed, scalability, and developer experience."
61+
---
62+
63+
## What is Forge42 Base Stack?
64+
65+
The Forge42 Base Stack is a full-featured web application starter template. It combines modern tools and technologies like **Remix**, **Tailwind CSS**, **TypeScript**, **Vitest**, and **React Aria Components** to help you build accessible and scalable web apps quickly.
66+
67+
This documentation will guide you through setting up the project, understanding its structure, and customizing it for your needs.
68+
69+
## Installation
70+
71+
To get started with the base stack, simply clone the repository and install dependencies:
72+
73+
```bash
74+
npx degit forge42/base-stack my-app
75+
cd my-app
76+
npm install
77+
```
78+
79+
### Example of the valid `04-getting-started/index.md` file:
80+
```
81+
---
82+
title: Getting Started
83+
---
84+
85+
```
86+
6387

6488
## Getting started
6589

@@ -71,17 +95,10 @@ pnpm install
7195
```
7296
3. Read through the README.md files in the project to understand our decisions.
7397

74-
4. Run the cleanup script:
75-
```bash
76-
pnpm cleanup
77-
```
78-
79-
This will remove everything in the project related to the base-stack like README.md etc.
80-
This is the first thing you should run after initializing the project.
81-
After it is run it will remove itself from the package.json.
98+
4. Add `content` folder
8299

83100
5. Start the development server:
84101
```bash
85102
pnpm run dev
86103
```
87-
6. Happy coding!
104+
5. Happy coding!
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* This module provides utilities for processing and styling lines of a text diff.
3+
*/
4+
const DIFF_STYLES = {
5+
added: {
6+
backgroundColor: "var(--color-diff-added-bg)",
7+
borderLeft: "2px solid",
8+
borderLeftColor: "var(--color-diff-added-border)",
9+
indicator: "+",
10+
},
11+
removed: {
12+
backgroundColor: "var(--color-diff-removed-bg)",
13+
borderLeft: "2px solid",
14+
borderLeftColor: "var(--color-diff-removed-border)",
15+
indicator: "-",
16+
},
17+
normal: {
18+
backgroundColor: "transparent",
19+
borderLeft: "none",
20+
borderLeftColor: "transparent",
21+
indicator: "",
22+
},
23+
} as const
24+
25+
type DiffType = keyof typeof DIFF_STYLES
26+
27+
const DIFF_PATTERNS = {
28+
"+ ": "added",
29+
"- ": "removed",
30+
} as const
31+
32+
type DiffPatternPrefix = keyof typeof DIFF_PATTERNS
33+
34+
const isDiffPatternPrefix = (prefix: string): prefix is DiffPatternPrefix => {
35+
return prefix in DIFF_PATTERNS
36+
}
37+
38+
export const getDiffType = (line: string): DiffType => {
39+
const prefix = line.trimStart().slice(0, 2)
40+
return isDiffPatternPrefix(prefix) ? DIFF_PATTERNS[prefix] : "normal"
41+
}
42+
43+
export const cleanDiffLine = (line: string) => line.replace(/^(\s*)[+-] /, "$1")
44+
45+
export const getDiffStyles = (diffType: DiffType) => DIFF_STYLES[diffType]
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import type { ComponentPropsWithoutRef } from "react"
2+
import { cn } from "~/utils/css"
3+
import { createLineData } from "./code-block-parser"
4+
import { getTokenColor, isTokenType, type tokenize } from "./code-block-syntax-highlighter"
5+
6+
const TokenElement = ({ token }: { token: ReturnType<typeof tokenize>[0] }) => {
7+
const { type, value } = token
8+
const color = isTokenType(type) ? getTokenColor(type) : ""
9+
10+
return <span style={{ color }}>{value}</span>
11+
}
12+
13+
const DiffIndicator = ({ indicator }: { indicator: string }) => (
14+
<span className="absolute top-0 left-0 w-4 select-none text-center font-medium text-[var(--color-diff-indicator)]">
15+
{indicator}
16+
</span>
17+
)
18+
19+
const LineElement = ({ line }: { line: string }) => {
20+
const { tokens, styles, isNormalDiff } = createLineData(line)
21+
22+
return (
23+
<div className="relative">
24+
<div
25+
className="flex min-h-[1.5rem] items-center pr-4 pl-4"
26+
style={{
27+
backgroundColor: styles.backgroundColor,
28+
borderLeft: styles.borderLeft,
29+
borderLeftColor: styles.borderLeftColor,
30+
}}
31+
>
32+
{!isNormalDiff && <DiffIndicator indicator={styles.indicator} />}
33+
<span className="block">
34+
{tokens.map((token, index) => (
35+
<TokenElement key={`${token.value}-${index}`} token={token} />
36+
))}
37+
</span>
38+
</div>
39+
</div>
40+
)
41+
}
42+
43+
const CodeElement = ({ lines }: { lines: string[] }) => (
44+
<code className="relative block">
45+
{lines.map((line, index) => (
46+
<LineElement key={`${index}-${line}`} line={line} />
47+
))}
48+
</code>
49+
)
50+
51+
interface PreElementProps extends Omit<ComponentPropsWithoutRef<"pre">, "children"> {
52+
lines: string[]
53+
className?: string
54+
}
55+
56+
export const PreElement = ({ lines, className = "", ...props }: PreElementProps) => (
57+
<pre
58+
{...props}
59+
className={cn(
60+
"relative overflow-x-auto rounded-lg border border-[var(--color-border)] bg-[var(--color-code-block-bg)] py-4 font-mono text-[var(--color-code-block-text)] text-xs leading-relaxed sm:text-sm md:text-base",
61+
className
62+
)}
63+
>
64+
<CodeElement lines={lines} />
65+
</pre>
66+
)
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { cleanDiffLine, getDiffStyles, getDiffType } from "./code-block-diff"
2+
import { tokenize } from "./code-block-syntax-highlighter"
3+
4+
interface CodeBlockChild {
5+
props?: {
6+
children?: string
7+
}
8+
}
9+
10+
export const extractCodeContent = (children: string | CodeBlockChild) => {
11+
const code = typeof children === "string" ? children : (children?.props?.children ?? "")
12+
return { code }
13+
}
14+
15+
export const processLines = (content: string) => {
16+
const lines = content.split("\n")
17+
return filterEmptyLines(lines)
18+
}
19+
20+
const filterEmptyLines = (lines: string[]) => {
21+
return lines.filter((line, index, array) => {
22+
const isLastLine = index === array.length - 1
23+
const isEmpty = line.trim() === ""
24+
return !(isEmpty && isLastLine)
25+
})
26+
}
27+
28+
export const createLineData = (line: string) => {
29+
const diffType = getDiffType(line)
30+
const cleanLine = cleanDiffLine(line)
31+
const tokens = tokenize(cleanLine)
32+
const styles = getDiffStyles(diffType)
33+
const isNormalDiff = diffType === "normal"
34+
35+
return {
36+
diffType,
37+
cleanLine,
38+
tokens,
39+
styles,
40+
isNormalDiff,
41+
}
42+
}
43+
44+
export const processCopyContent = (content: string): { code: string } => {
45+
// removes diff markers from content
46+
const code = content
47+
.split("\n")
48+
.filter((line) => !line.trimStart().startsWith("- "))
49+
.map((line) => line.replace(/^(\s*)\+ /, "$1"))
50+
.join("\n")
51+
52+
return { code }
53+
}

0 commit comments

Comments
 (0)