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 ( + + ) +} 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<HTMLAnchorElement>, +): JSX.Element { + if (props.href?.startsWith('http')) { + return ( + <Button + component="a" + {...props} + target="_blank" + rightSection={ + <IconExternalLink size="16px" style={{ marginLeft: -5 }} /> + } + variant="transparent" + style={{ height: '20px' }} + mt={-2} + p={0} + /> + ) + } + return ( + <Button + component={Link} + {...props} + target="_blank" + rightSection={<IconExternalLink size="16px" style={{ marginLeft: -5 }} />} + 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 ( + <CodeHighlight + className={styles.pre} + style={{ borderRadius: 8 }} + code={children.props.children || ''} + language={children.props.className?.replace('language-', '')} + /> + ) +} 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 ( + <MDXProvider + components={{ + a: MdxLink, + // @ts-expect-error: useless finding the correct props types + pre: MdxPre, + blockquote: MdxQuote, + code: MdxCode, + h1: MdxTitle, + h2: MdxH2, + }} + > + {children} + </MDXProvider> + ) +} 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<HTMLQuoteElement>, +): JSX.Element { + return ( + <> + <Blockquote + color="violet" + p={8} + px={20} + mt={30} + iconSize={30} + {...props} + style={{ borderRadius: 8 }} + /> + <Space h="md" /> + </> + ) +} 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<HTMLHeadingElement>, +): JSX.Element { + return <Title {...props} order={1} /> +} 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 ( + <Flex gap={8}> + <Button + href="/documentation/installation" + component={Link} + size="compact-lg" + rightSection={<IconBook />} + autoContrast + > + Get started + </Button> + <ActionIcon + variant="default" + size="lg" + aria-label="Check the project on github" + href="https://github.com/Valerioageno/tuono" + target="_blank" + component="a" + > + <IconBrandGithub /> + </ActionIcon> + <ThemeBtn /> + </Flex> + ) +} 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 ( + <AppShell.Header p="sm"> + <Flex justify="space-between"> + <Flex align="center" gap={8}> + {pathname.startsWith('/documentation') && ( + <Burger + opened={opened} + onClick={toggle} + hiddenFrom="sm" + size="sm" + /> + )} + <Button component={Link} href="/" variant="transparent" p={0} fz={28}> + Tuono + </Button> + </Flex> + <Actions /> + </Flex> + </AppShell.Header> + ) +} 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 ( + <AppShell.Navbar p="md"> + <h3>Tutorial</h3> + <NavLink + href="/documentation/tutorial/intro" + component={Link} + label="Intro" + /> + <h3>Documentation</h3> + <NavLink + href="/documentation/installation" + component={Link} + label="Installation" + /> + <NavLink label="Routing" href="#required-for-focus" defaultOpened> + <NavLink + href="/documentation/routing" + component={Link} + label="FS routing" + /> + </NavLink> + <NavLink + label="Contributing" + component={Link} + href="/documentation/contributing" + /> + </AppShell.Navbar> + ) +} 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 ( + <ActionIcon + onClick={() => + setColorScheme(computedColorScheme === 'light' ? 'dark' : 'light') + } + variant="default" + size="lg" + aria-label="Toggle color scheme" + > + <IconSun className={cx(classes.icon, classes.light)} stroke={1.5} /> + <IconMoon className={cx(classes.icon, classes.dark)} stroke={1.5} /> + </ActionIcon> + ) +} 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 ( + <> + <Head> + <ColorSchemeScript /> + </Head> + <MantineProvider theme={theme}> + <AppShell + header={{ height: 60 }} + navbar={{ + width: 300, + breakpoint: 'sm', + collapsed: { mobile: !opened }, + }} + > + <Navbar opened={opened} toggle={toggle} /> + {children} + </AppShell> + </MantineProvider> + </> + ) +} 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 ( + <> + <Sidebar /> + <AppShell.Main> + <Container component="article" p={20}> + <MdxProvider>{children}</MdxProvider> + <EditPage /> + </Container> + </AppShell.Main> + </> + ) +} 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' + +<Head> + <title>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/**"