diff --git a/.github/workflows/ci-documentation.yml b/.github/workflows/ci-documentation.yml
new file mode 100644
index 00000000..67f051b7
--- /dev/null
+++ b/.github/workflows/ci-documentation.yml
@@ -0,0 +1,75 @@
+name: Documentation Website CI
+
+on:
+ push:
+ paths:
+ - '.github/**'
+ - 'apps/documentation/**'
+ pull_request:
+ paths:
+ - '.github/**'
+ - 'apps/documentation/**'
+
+jobs:
+ build:
+ if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
+ timeout-minutes: 15
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: ./apps/documentation
+
+ steps:
+ - name: Check out code
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 2
+
+ - name: Setup Node.js environment
+ uses: actions/setup-node@v4
+ with:
+ node-version: 20
+
+ - name: Setup rust
+ uses: actions-rust-lang/setup-rust-toolchain@v1
+
+ - name: Install tuono
+ run: cargo install tuono@0.8.2
+
+ - name: Install pnpm
+ run: npm i -g pnpm
+
+ - name: Install dependencies
+ run: pnpm install --ignore-workspace
+
+ - name: Build project
+ run: tuono build --static
+
+ fmt-lint-and-types:
+ if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
+ runs-on: ubuntu-latest
+ timeout-minutes: 15
+ defaults:
+ run:
+ working-directory: ./apps/documentation
+
+ steps:
+ - name: Check out code
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 2
+
+ - name: Install pnpm
+ run: npm i -g pnpm
+
+ - name: Install dependencies
+ run: pnpm install --ignore-workspace
+
+ - name: Check formatting
+ run: pnpm format:check
+
+ - name: Lint
+ run: pnpm lint
+
+ - name: Types
+ run: pnpm types
diff --git a/.github/workflows/deploy-documentation.yml b/.github/workflows/deploy-documentation.yml
new file mode 100644
index 00000000..fed312b5
--- /dev/null
+++ b/.github/workflows/deploy-documentation.yml
@@ -0,0 +1,55 @@
+name: Deploy documentation website on AWS S3
+on:
+ push:
+ branches:
+ - main
+ paths:
+ - 'apps/documentation/**'
+
+jobs:
+ deploy-documentation:
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: ./apps/documentation
+ env:
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ steps:
+ - name: Check out code
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 2
+
+ - name: Setup Node.js environment
+ uses: actions/setup-node@v4
+ with:
+ node-version: 20
+
+ - name: Setup rust
+ uses: actions-rust-lang/setup-rust-toolchain@v1
+
+ - name: Install tuono
+ run: cargo install tuono@0.8.2
+
+ - name: Install pnpm
+ run: npm i -g pnpm
+
+ - name: Install dependencies
+ run: pnpm install --ignore-workspace
+
+ - name: Build project
+ run: tuono build --static
+
+ - name: Deploy
+ uses: reggionick/s3-deploy@v4
+ with:
+ folder: out/static
+ bucket: tuono-documentation
+ bucket-region: eu-west-3
+ dist-id: ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }}
+ invalidation: /
+ delete-removed: true
+ no-cache: true
+ private: true
+ files-to-include: '{.*/**,**}'
diff --git a/Cargo.toml b/Cargo.toml
index 5e8613a1..ded17e4a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,6 +6,7 @@ members = [
"crates/tuono_lib_macros",
]
exclude = [
+ "apps/documentation",
"examples/mdx",
"examples/tuono",
"examples/tutorial"
diff --git a/apps/README.md b/apps/README.md
new file mode 100644
index 00000000..33fd8bf7
--- /dev/null
+++ b/apps/README.md
@@ -0,0 +1 @@
+# Stadalone apps folder
diff --git a/apps/documentation/.eslintrc b/apps/documentation/.eslintrc
new file mode 100644
index 00000000..87e55820
--- /dev/null
+++ b/apps/documentation/.eslintrc
@@ -0,0 +1,103 @@
+{
+ "root": true,
+ "reportUnusedDisableDirectives": true,
+ "ignorePatterns": ["**/build", "**/dist"],
+ "parser": "@typescript-eslint/parser",
+ "plugins": ["@typescript-eslint", "import"],
+ "extends": [
+ "eslint:recommended",
+ "plugin:@typescript-eslint/recommended",
+ "plugin:@typescript-eslint/stylistic",
+ "plugin:import/recommended",
+ "plugin:import/typescript",
+ "prettier",
+ ],
+ "env": {
+ "browser": true,
+ "es2020": true,
+ },
+ "parserOptions": {
+ "tsconfigRootDir": ".",
+ "project": true,
+ "sourceType": "module",
+ "ecmaVersion": 2020,
+ },
+ "settings": {
+ "import/parsers": {
+ "@typescript-eslint/parser": [".ts", ".tsx"],
+ },
+ "import/resolver": {
+ "typescript": true,
+ },
+ "react": {
+ "version": "detect",
+ },
+ },
+ "rules": {
+ "@typescript-eslint/array-type": "error",
+ "@typescript-eslint/ban-types": "error",
+ "@typescript-eslint/ban-ts-comment": "error",
+ "@typescript-eslint/consistent-type-definitions": "error",
+ "@typescript-eslint/consistent-type-imports": [
+ "error",
+ { "prefer": "type-imports" },
+ ],
+ "@typescript-eslint/explicit-module-boundary-types": "error",
+ "@typescript-eslint/method-signature-style": ["error", "property"],
+ "@typescript-eslint/naming-convention": [
+ "error",
+ {
+ "selector": "typeParameter",
+ "format": ["PascalCase"],
+ "leadingUnderscore": "forbid",
+ "trailingUnderscore": "forbid",
+ "custom": {
+ "regex": "^(T|T[A-Z][A-Za-z]+)$",
+ "match": true,
+ },
+ },
+ ],
+ "@typescript-eslint/no-empty-function": "error",
+ "@typescript-eslint/no-empty-interface": "error",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-non-null-assertion": "error",
+ "@typescript-eslint/no-unnecessary-condition": "error",
+ "@typescript-eslint/no-unnecessary-type-assertion": "error",
+ "@typescript-eslint/no-unused-vars": "error",
+ "@typescript-eslint/explicit-function-return-type": "error",
+ "@typescript-eslint/no-inferrable-types": [
+ "error",
+ { "ignoreParameters": true },
+ ],
+ "import/default": "error",
+ "import/export": "error",
+ "import/namespace": "error",
+ "import/newline-after-import": "error",
+ "import/no-cycle": "error",
+ "import/no-duplicates": "off",
+ "import/no-named-as-default-member": "error",
+ "import/no-unused-modules": "error",
+ "import/order": [
+ "off",
+ {
+ "groups": [
+ "builtin",
+ "external",
+ "internal",
+ "parent",
+ "sibling",
+ "index",
+ "object",
+ "type",
+ ],
+ },
+ ],
+ "no-case-declarations": "error",
+ "no-empty": "error",
+ "no-prototype-builtins": "error",
+ "no-redeclare": "error",
+ "no-shadow": "error",
+ "no-undef": "off",
+ "sort-imports": "off",
+ },
+}
diff --git a/apps/documentation/.gitignore b/apps/documentation/.gitignore
new file mode 100644
index 00000000..071acad0
--- /dev/null
+++ b/apps/documentation/.gitignore
@@ -0,0 +1,13 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+.tuono
+out
+target
diff --git a/apps/documentation/Cargo.toml b/apps/documentation/Cargo.toml
new file mode 100644
index 00000000..0776c041
--- /dev/null
+++ b/apps/documentation/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "tuono"
+version = "0.0.1"
+edition = "2021"
+
+[[bin]]
+name = "tuono"
+path = ".tuono/main.rs"
+
+[dependencies]
+tuono_lib = "0.8.1"
+serde = { version = "1.0.202", features = ["derive"] }
+
diff --git a/apps/documentation/README.md b/apps/documentation/README.md
new file mode 100644
index 00000000..5ecd43ac
--- /dev/null
+++ b/apps/documentation/README.md
@@ -0,0 +1,7 @@
+# Tuono starter
+
+This is the starter tuono project. To download it run in your terminal:
+
+```shell
+$ tuono new [NAME]
+```
diff --git a/apps/documentation/package.json b/apps/documentation/package.json
new file mode 100644
index 00000000..79bbea69
--- /dev/null
+++ b/apps/documentation/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "tuono",
+ "description": "The react/rust fullstack framework",
+ "version": "0.0.1",
+ "scripts": {
+ "lint": "eslint --ext .ts,.tsx ./src -c .eslintrc",
+ "format": "prettier -u --write --ignore-unknown './src/**/*'",
+ "format:check": "prettier --check --ignore-unknown './src/**/*'",
+ "types": "tsc --noEmit"
+ },
+ "dependencies": {
+ "@mantine/code-highlight": "^7.11.2",
+ "@mantine/core": "^7.11.2",
+ "@mantine/hooks": "^7.11.2",
+ "@mdx-js/react": "^3.0.1",
+ "@tabler/icons-react": "^3.11.0",
+ "clsx": "^2.1.1",
+ "react": "18.3.1",
+ "react-dom": "18.3.1",
+ "tuono": "0.8.1"
+ },
+ "devDependencies": {
+ "@types/mdx": "^2.0.13",
+ "@types/react": "^18.3.3",
+ "@types/react-dom": "^18.3.0",
+ "@typescript-eslint/eslint-plugin": "^7.7.1",
+ "@typescript-eslint/parser": "^7.7.1",
+ "eslint": "^8.56.0",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-import-resolver-typescript": "^3.6.1",
+ "eslint-plugin-import": "^2.29.1",
+ "eslint-plugin-react": "^7.33.2",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "postcss": "^8.4.39",
+ "postcss-preset-mantine": "^1.17.0",
+ "postcss-simple-vars": "^7.0.1",
+ "prettier": "^3.2.4",
+ "typescript": "^5.5.4"
+ }
+}
diff --git a/apps/documentation/postcss.config.cjs b/apps/documentation/postcss.config.cjs
new file mode 100644
index 00000000..6a683623
--- /dev/null
+++ b/apps/documentation/postcss.config.cjs
@@ -0,0 +1,14 @@
+module.exports = {
+ plugins: {
+ 'postcss-preset-mantine': {},
+ 'postcss-simple-vars': {
+ variables: {
+ 'mantine-breakpoint-xs': '36em',
+ 'mantine-breakpoint-sm': '48em',
+ 'mantine-breakpoint-md': '62em',
+ 'mantine-breakpoint-lg': '75em',
+ 'mantine-breakpoint-xl': '88em',
+ },
+ },
+ },
+}
diff --git a/apps/documentation/public/favicon.ico b/apps/documentation/public/favicon.ico
new file mode 100644
index 00000000..d03bcc66
Binary files /dev/null and b/apps/documentation/public/favicon.ico differ
diff --git a/apps/documentation/public/logo.svg b/apps/documentation/public/logo.svg
new file mode 100644
index 00000000..57df3036
--- /dev/null
+++ b/apps/documentation/public/logo.svg
@@ -0,0 +1,5 @@
+
diff --git a/apps/documentation/src/components/edit-page/edit-page.tsx b/apps/documentation/src/components/edit-page/edit-page.tsx
new file mode 100644
index 00000000..f246d424
--- /dev/null
+++ b/apps/documentation/src/components/edit-page/edit-page.tsx
@@ -0,0 +1,23 @@
+import { Button } from '@mantine/core'
+import { IconEdit } from '@tabler/icons-react'
+import { useRouter } from 'tuono'
+
+const GITHUB_URL =
+ 'https://github.com/Valerioageno/tuono/tree/main/apps/documentation/src/routes'
+
+export default function EditPage(): JSX.Element {
+ const { pathname } = useRouter()
+ return (
+ }
+ target="_blank"
+ href={GITHUB_URL.concat(pathname)}
+ >
+ Edit page
+
+ )
+}
diff --git a/apps/documentation/src/components/edit-page/index.ts b/apps/documentation/src/components/edit-page/index.ts
new file mode 100644
index 00000000..9469e890
--- /dev/null
+++ b/apps/documentation/src/components/edit-page/index.ts
@@ -0,0 +1,3 @@
+import EditPage from './edit-page'
+
+export default EditPage
diff --git a/apps/documentation/src/components/hero/hero.tsx b/apps/documentation/src/components/hero/hero.tsx
new file mode 100644
index 00000000..f3f68dbc
--- /dev/null
+++ b/apps/documentation/src/components/hero/hero.tsx
@@ -0,0 +1,53 @@
+import {
+ Button,
+ Center,
+ Container,
+ CopyButton,
+ Group,
+ rem,
+ Text,
+ Title,
+} from '@mantine/core'
+import { IconCopy, IconCheck } from '@tabler/icons-react'
+import { Link } from 'tuono'
+
+export default function Hero(): JSX.Element {
+ return (
+
+
+ The react/rust fullstack framework
+
+
+
+ The technologies we love seamessly working together to unleash the
+ highest web performance ever met on react
+
+
+
+
+
+
+ {({ copied, copy }) => (
+
+ ) : (
+
+ )
+ }
+ />
+ )}
+
+
+
+
+ )
+}
diff --git a/apps/documentation/src/components/hero/index.ts b/apps/documentation/src/components/hero/index.ts
new file mode 100644
index 00000000..2b4b7fec
--- /dev/null
+++ b/apps/documentation/src/components/hero/index.ts
@@ -0,0 +1,3 @@
+import Hero from './hero'
+
+export default Hero
diff --git a/apps/documentation/src/components/mdx-provider/index.ts b/apps/documentation/src/components/mdx-provider/index.ts
new file mode 100644
index 00000000..275c5ecf
--- /dev/null
+++ b/apps/documentation/src/components/mdx-provider/index.ts
@@ -0,0 +1,3 @@
+import MdxProvider from './mdx-provider'
+
+export default MdxProvider
diff --git a/apps/documentation/src/components/mdx-provider/mdx-code/index.ts b/apps/documentation/src/components/mdx-provider/mdx-code/index.ts
new file mode 100644
index 00000000..32dc03c6
--- /dev/null
+++ b/apps/documentation/src/components/mdx-provider/mdx-code/index.ts
@@ -0,0 +1,3 @@
+import MdxCode from './mdx-code'
+
+export default MdxCode
diff --git a/apps/documentation/src/components/mdx-provider/mdx-code/mdx-code.tsx b/apps/documentation/src/components/mdx-provider/mdx-code/mdx-code.tsx
new file mode 100644
index 00000000..3f8c6f2c
--- /dev/null
+++ b/apps/documentation/src/components/mdx-provider/mdx-code/mdx-code.tsx
@@ -0,0 +1,8 @@
+import { Code } from '@mantine/core'
+import type { HTMLAttributes } from 'react'
+
+export default function MdxCode(
+ props: HTMLAttributes,
+): JSX.Element {
+ return
+}
diff --git a/apps/documentation/src/components/mdx-provider/mdx-h2/mdx-h2.tsx b/apps/documentation/src/components/mdx-provider/mdx-h2/mdx-h2.tsx
new file mode 100644
index 00000000..a48e54b1
--- /dev/null
+++ b/apps/documentation/src/components/mdx-provider/mdx-h2/mdx-h2.tsx
@@ -0,0 +1,8 @@
+import { Title } from '@mantine/core'
+import type { HTMLAttributes } from 'react'
+
+export default function MdxH2(
+ props: HTMLAttributes,
+): JSX.Element {
+ return
+}
diff --git a/apps/documentation/src/components/mdx-provider/mdx-link/index.ts b/apps/documentation/src/components/mdx-provider/mdx-link/index.ts
new file mode 100644
index 00000000..9ef1ac78
--- /dev/null
+++ b/apps/documentation/src/components/mdx-provider/mdx-link/index.ts
@@ -0,0 +1,3 @@
+import MdxLink from './mdx-link'
+
+export default MdxLink
diff --git a/apps/documentation/src/components/mdx-provider/mdx-link/mdx-link.tsx b/apps/documentation/src/components/mdx-provider/mdx-link/mdx-link.tsx
new file mode 100644
index 00000000..8e040d80
--- /dev/null
+++ b/apps/documentation/src/components/mdx-provider/mdx-link/mdx-link.tsx
@@ -0,0 +1,37 @@
+import type { AnchorHTMLAttributes } from 'react'
+import { Button } from '@mantine/core'
+import { Link } from 'tuono'
+import { IconExternalLink } from '@tabler/icons-react'
+
+export default function MdxLink(
+ props: AnchorHTMLAttributes,
+): JSX.Element {
+ if (props.href?.startsWith('http')) {
+ return (
+
+ }
+ variant="transparent"
+ style={{ height: '20px' }}
+ mt={-2}
+ p={0}
+ />
+ )
+ }
+ return (
+ }
+ variant="transparent"
+ style={{ height: '20px' }}
+ mt={-2}
+ p={0}
+ />
+ )
+}
diff --git a/apps/documentation/src/components/mdx-provider/mdx-pre/index.ts b/apps/documentation/src/components/mdx-provider/mdx-pre/index.ts
new file mode 100644
index 00000000..54fa53df
--- /dev/null
+++ b/apps/documentation/src/components/mdx-provider/mdx-pre/index.ts
@@ -0,0 +1,3 @@
+import MdxPre from './mdx-pre'
+
+export default MdxPre
diff --git a/apps/documentation/src/components/mdx-provider/mdx-pre/mdx-pre.module.css b/apps/documentation/src/components/mdx-provider/mdx-pre/mdx-pre.module.css
new file mode 100644
index 00000000..bfb74786
--- /dev/null
+++ b/apps/documentation/src/components/mdx-provider/mdx-pre/mdx-pre.module.css
@@ -0,0 +1,5 @@
+.pre {
+ code {
+ font-size: 16px;
+ }
+}
diff --git a/apps/documentation/src/components/mdx-provider/mdx-pre/mdx-pre.tsx b/apps/documentation/src/components/mdx-provider/mdx-pre/mdx-pre.tsx
new file mode 100644
index 00000000..4b8c4fea
--- /dev/null
+++ b/apps/documentation/src/components/mdx-provider/mdx-pre/mdx-pre.tsx
@@ -0,0 +1,16 @@
+import { CodeHighlight } from '@mantine/code-highlight'
+import styles from './mdx-pre.module.css'
+
+interface PreProps {
+ children: any
+}
+export default function MdxPre({ children }: PreProps): JSX.Element {
+ return (
+
+ )
+}
diff --git a/apps/documentation/src/components/mdx-provider/mdx-provider.tsx b/apps/documentation/src/components/mdx-provider/mdx-provider.tsx
new file mode 100644
index 00000000..0342d0ae
--- /dev/null
+++ b/apps/documentation/src/components/mdx-provider/mdx-provider.tsx
@@ -0,0 +1,33 @@
+import { MDXProvider } from '@mdx-js/react'
+
+import MdxLink from './mdx-link'
+import type { ReactNode } from 'react'
+import MdxPre from './mdx-pre'
+import MdxQuote from './mdx-quote'
+import MdxCode from './mdx-code'
+import MdxTitle from './mdx-title'
+import MdxH2 from './mdx-h2/mdx-h2'
+
+interface MdxProviderProps {
+ children: ReactNode
+}
+
+export default function MdxProvider({
+ children,
+}: MdxProviderProps): JSX.Element {
+ return (
+
+ {children}
+
+ )
+}
diff --git a/apps/documentation/src/components/mdx-provider/mdx-quote/index.ts b/apps/documentation/src/components/mdx-provider/mdx-quote/index.ts
new file mode 100644
index 00000000..60c00daa
--- /dev/null
+++ b/apps/documentation/src/components/mdx-provider/mdx-quote/index.ts
@@ -0,0 +1,3 @@
+import MdxQuote from './mdx-quote'
+
+export default MdxQuote
diff --git a/apps/documentation/src/components/mdx-provider/mdx-quote/mdx-quote.tsx b/apps/documentation/src/components/mdx-provider/mdx-quote/mdx-quote.tsx
new file mode 100644
index 00000000..a256f3d3
--- /dev/null
+++ b/apps/documentation/src/components/mdx-provider/mdx-quote/mdx-quote.tsx
@@ -0,0 +1,21 @@
+import { Blockquote, Space } from '@mantine/core'
+import type { HTMLAttributes } from 'react'
+
+export default function MdxQuote(
+ props: HTMLAttributes,
+): JSX.Element {
+ return (
+ <>
+
+
+ >
+ )
+}
diff --git a/apps/documentation/src/components/mdx-provider/mdx-title/index.ts b/apps/documentation/src/components/mdx-provider/mdx-title/index.ts
new file mode 100644
index 00000000..db92451e
--- /dev/null
+++ b/apps/documentation/src/components/mdx-provider/mdx-title/index.ts
@@ -0,0 +1,3 @@
+import MdxTitle from './mdx-title'
+
+export default MdxTitle
diff --git a/apps/documentation/src/components/mdx-provider/mdx-title/mdx-title.tsx b/apps/documentation/src/components/mdx-provider/mdx-title/mdx-title.tsx
new file mode 100644
index 00000000..d562ed9d
--- /dev/null
+++ b/apps/documentation/src/components/mdx-provider/mdx-title/mdx-title.tsx
@@ -0,0 +1,8 @@
+import { Title } from '@mantine/core'
+import type { HTMLAttributes } from 'react'
+
+export default function MdxTitle(
+ props: HTMLAttributes,
+): JSX.Element {
+ return
+}
diff --git a/apps/documentation/src/components/navbar/actions.tsx b/apps/documentation/src/components/navbar/actions.tsx
new file mode 100644
index 00000000..6586057d
--- /dev/null
+++ b/apps/documentation/src/components/navbar/actions.tsx
@@ -0,0 +1,31 @@
+import { Flex, Button, ActionIcon } from '@mantine/core'
+import { IconBrandGithub, IconBook } from '@tabler/icons-react'
+import ThemeBtn from '../theme-btn'
+import { Link } from 'tuono'
+
+export default function Actions(): JSX.Element {
+ return (
+
+ }
+ autoContrast
+ >
+ Get started
+
+
+
+
+
+
+ )
+}
diff --git a/apps/documentation/src/components/navbar/index.ts b/apps/documentation/src/components/navbar/index.ts
new file mode 100644
index 00000000..19eb850e
--- /dev/null
+++ b/apps/documentation/src/components/navbar/index.ts
@@ -0,0 +1,3 @@
+import Navbar from './navbar'
+
+export default Navbar
diff --git a/apps/documentation/src/components/navbar/navbar.tsx b/apps/documentation/src/components/navbar/navbar.tsx
new file mode 100644
index 00000000..7f470356
--- /dev/null
+++ b/apps/documentation/src/components/navbar/navbar.tsx
@@ -0,0 +1,32 @@
+import { AppShell, Burger, Button, Flex } from '@mantine/core'
+import { Link, useRouter } from 'tuono'
+import Actions from './actions'
+
+interface NavbarProps {
+ opened: boolean
+ toggle: () => void
+}
+
+export default function Navbar({ opened, toggle }: NavbarProps): JSX.Element {
+ const { pathname } = useRouter()
+ return (
+
+
+
+ {pathname.startsWith('/documentation') && (
+
+ )}
+
+
+
+
+
+ )
+}
diff --git a/apps/documentation/src/components/sidebar/index.ts b/apps/documentation/src/components/sidebar/index.ts
new file mode 100644
index 00000000..1c6b4eb3
--- /dev/null
+++ b/apps/documentation/src/components/sidebar/index.ts
@@ -0,0 +1,3 @@
+import Sidebar from './sidebar'
+
+export default Sidebar
diff --git a/apps/documentation/src/components/sidebar/sidebar.tsx b/apps/documentation/src/components/sidebar/sidebar.tsx
new file mode 100644
index 00000000..03a96a1e
--- /dev/null
+++ b/apps/documentation/src/components/sidebar/sidebar.tsx
@@ -0,0 +1,33 @@
+import { AppShell, NavLink } from '@mantine/core'
+import { Link } from 'tuono'
+
+export default function Sidebar(): JSX.Element {
+ return (
+
+ Tutorial
+
+ Documentation
+
+
+
+
+
+
+ )
+}
diff --git a/apps/documentation/src/components/theme-btn/index.ts b/apps/documentation/src/components/theme-btn/index.ts
new file mode 100644
index 00000000..20f54231
--- /dev/null
+++ b/apps/documentation/src/components/theme-btn/index.ts
@@ -0,0 +1,3 @@
+import ThemeBtn from './theme-btn'
+
+export default ThemeBtn
diff --git a/apps/documentation/src/components/theme-btn/theme-btn.module.css b/apps/documentation/src/components/theme-btn/theme-btn.module.css
new file mode 100644
index 00000000..e111fe8d
--- /dev/null
+++ b/apps/documentation/src/components/theme-btn/theme-btn.module.css
@@ -0,0 +1,24 @@
+.icon {
+ width: 22px;
+ height: 22px;
+}
+
+.dark {
+ @mixin dark {
+ display: none;
+ }
+
+ @mixin light {
+ display: block;
+ }
+}
+
+.light {
+ @mixin light {
+ display: none;
+ }
+
+ @mixin dark {
+ display: block;
+ }
+}
diff --git a/apps/documentation/src/components/theme-btn/theme-btn.tsx b/apps/documentation/src/components/theme-btn/theme-btn.tsx
new file mode 100644
index 00000000..638e6413
--- /dev/null
+++ b/apps/documentation/src/components/theme-btn/theme-btn.tsx
@@ -0,0 +1,30 @@
+import {
+ ActionIcon,
+ useMantineColorScheme,
+ useComputedColorScheme,
+} from '@mantine/core'
+import { IconSun, IconMoon } from '@tabler/icons-react'
+import cx from 'clsx'
+
+import classes from './theme-btn.module.css'
+
+export default function ThemeBtn(): JSX.Element {
+ const { setColorScheme } = useMantineColorScheme()
+ const computedColorScheme = useComputedColorScheme('light', {
+ getInitialValueInEffect: true,
+ })
+
+ return (
+
+ setColorScheme(computedColorScheme === 'light' ? 'dark' : 'light')
+ }
+ variant="default"
+ size="lg"
+ aria-label="Toggle color scheme"
+ >
+
+
+
+ )
+}
diff --git a/apps/documentation/src/modules.d.ts b/apps/documentation/src/modules.d.ts
new file mode 100644
index 00000000..248c50ee
--- /dev/null
+++ b/apps/documentation/src/modules.d.ts
@@ -0,0 +1,2 @@
+// declaration.d.ts
+declare module '*.css'
diff --git a/apps/documentation/src/routes/__root.tsx b/apps/documentation/src/routes/__root.tsx
new file mode 100644
index 00000000..b063f980
--- /dev/null
+++ b/apps/documentation/src/routes/__root.tsx
@@ -0,0 +1,75 @@
+import type { ReactNode } from 'react'
+import {
+ ColorSchemeScript,
+ createTheme,
+ MantineProvider,
+ AppShell,
+} from '@mantine/core'
+import { useDisclosure } from '@mantine/hooks'
+import { Head } from 'tuono'
+import Navbar from '../components/navbar'
+
+import '@mantine/core/styles.css'
+import '@mantine/code-highlight/styles.css'
+
+interface RootRouteProps {
+ children: ReactNode
+}
+
+const theme = createTheme({
+ primaryColor: 'violet',
+ primaryShade: { light: 6, dark: 9 },
+ fontFamily: 'Roboto',
+ respectReducedMotion: true,
+ fontSizes: {
+ // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
+ xs: '16px',
+ sm: '16px',
+ },
+ colors: {
+ dark: [
+ '#d5d7e0',
+ '#acaebf',
+ '#8c8fa3',
+ '#666980',
+ '#4d4f66',
+ '#34354a',
+ '#2b2c3d',
+ '#1d1e30',
+ '#0c0d21',
+ '#01010a',
+ ],
+ },
+ headings: {
+ sizes: {
+ h1: {
+ fontSize: '48px',
+ },
+ },
+ },
+})
+
+export default function RootRoute({ children }: RootRouteProps): JSX.Element {
+ const [opened, { toggle }] = useDisclosure()
+
+ return (
+ <>
+
+
+
+
+
+
+ {children}
+
+
+ >
+ )
+}
diff --git a/apps/documentation/src/routes/documentation/__root.tsx b/apps/documentation/src/routes/documentation/__root.tsx
new file mode 100644
index 00000000..63e7ae01
--- /dev/null
+++ b/apps/documentation/src/routes/documentation/__root.tsx
@@ -0,0 +1,23 @@
+import type { ReactNode } from 'react'
+import { AppShell, Container } from '@mantine/core'
+import MdxProvider from '../../components/mdx-provider'
+import Sidebar from '../../components/sidebar'
+import EditPage from '../../components/edit-page'
+
+interface RootRouteProps {
+ children: ReactNode
+}
+
+export default function RootRoute({ children }: RootRouteProps): JSX.Element {
+ return (
+ <>
+
+
+
+ {children}
+
+
+
+ >
+ )
+}
diff --git a/apps/documentation/src/routes/documentation/contributing.mdx b/apps/documentation/src/routes/documentation/contributing.mdx
new file mode 100644
index 00000000..8c722d78
--- /dev/null
+++ b/apps/documentation/src/routes/documentation/contributing.mdx
@@ -0,0 +1,9 @@
+import { Head } from 'tuono'
+
+
+ Tuono - Contributing
+
+
+# How to contribute
+
+Todo
diff --git a/apps/documentation/src/routes/documentation/installation.mdx b/apps/documentation/src/routes/documentation/installation.mdx
new file mode 100644
index 00000000..ca10ebbb
--- /dev/null
+++ b/apps/documentation/src/routes/documentation/installation.mdx
@@ -0,0 +1,51 @@
+import { Head } from 'tuono'
+
+
+ Tuono - Installation
+
+
+# Installation
+
+## Requirements
+
+`Tuono` is a development environment built in rust and typescript that outputs a website written with both the
+languages. Since that you need the following tools installed on your computer to work with it:
+
+- `Rust` - The rust programming language toolchain (Go [here](https://rustup.rs/) for installing both `rust` and `cargo`)
+- `Cargo` - The rust package manager
+- `NodeJs` - The Javascript runtime (Go [here](https://nodejs.org/en/download/package-manager) for installing both `nodejs` and `npm`)
+- `npm` or `yarn` or `pnpm` - A javascript package manager
+
+> NodeJs is needed just for the development environment. The final output will run on a rust server.
+
+## Installation
+
+The tuono `CLI` is hosted on [crates.io](https://crates.io/crates/tuono); to download and install it just run on a terminal:
+
+```bash
+cargo install tuono
+```
+
+To check that is correctly installed run:
+
+```bash
+tuono --version
+```
+
+Run `tuono -h` to see all the available commands.
+
+```bash
+The react/rust fullstack framework
+
+Usage: tuono
+
+Commands:
+ dev Start the development environment
+ build Build the production assets
+ new Scaffold a new project
+ help Print this message or the help of the given subcommand(s)
+
+Options:
+ -h, --help Print help
+ -V, --version Print version
+```
diff --git a/apps/documentation/src/routes/documentation/routing/index.mdx b/apps/documentation/src/routes/documentation/routing/index.mdx
new file mode 100644
index 00000000..e611e7a2
--- /dev/null
+++ b/apps/documentation/src/routes/documentation/routing/index.mdx
@@ -0,0 +1,9 @@
+import { Head } from 'tuono'
+
+
+ Tuono - Routing
+
+
+# Routing
+
+Todo
diff --git a/apps/documentation/src/routes/documentation/tutorial/intro.mdx b/apps/documentation/src/routes/documentation/tutorial/intro.mdx
new file mode 100644
index 00000000..adfb42eb
--- /dev/null
+++ b/apps/documentation/src/routes/documentation/tutorial/intro.mdx
@@ -0,0 +1,9 @@
+import { Head } from 'tuono'
+
+
+ Tuono - Tutorial intro
+
+
+# Tutorial intro
+
+TODO
diff --git a/apps/documentation/src/routes/index.tsx b/apps/documentation/src/routes/index.tsx
new file mode 100644
index 00000000..4b96781a
--- /dev/null
+++ b/apps/documentation/src/routes/index.tsx
@@ -0,0 +1,17 @@
+import { Head } from 'tuono'
+import Hero from '../components/hero'
+
+export default function IndexPage(): JSX.Element {
+ return (
+ <>
+
+ Tuono - The react/rust fullstack framework
+
+
+
+ >
+ )
+}
diff --git a/apps/documentation/src/styles/global.css b/apps/documentation/src/styles/global.css
new file mode 100644
index 00000000..9483fd6a
--- /dev/null
+++ b/apps/documentation/src/styles/global.css
@@ -0,0 +1 @@
+@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap');
diff --git a/apps/documentation/tsconfig.json b/apps/documentation/tsconfig.json
new file mode 100644
index 00000000..a7fc6fbf
--- /dev/null
+++ b/apps/documentation/tsconfig.json
@@ -0,0 +1,25 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["src"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/apps/documentation/tsconfig.node.json b/apps/documentation/tsconfig.node.json
new file mode 100644
index 00000000..97ede7ee
--- /dev/null
+++ b/apps/documentation/tsconfig.node.json
@@ -0,0 +1,11 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true,
+ "strict": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index d15a1f0b..582a1f3b 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -1,3 +1,4 @@
packages:
- "packages/*"
- "!**/examples/**"
+ - "!**/apps/**"