Compare commits

...

118 Commits

Author SHA1 Message Date
Valerio Ageno d33c211a01 chore: bump version to v0.17.5 (#417) 2025-01-25 21:16:36 +01:00
Marco Pasqualetti 21ee89ada4 fix(packages/tuono): build error when config contains vite plugins (#415) 2025-01-25 18:12:57 +01:00
Marco Pasqualetti dcedb1c6c0 refactor: create TuonoContext (#413) 2025-01-25 15:56:10 +01:00
Jacob Marshall d5cc65983e feat(crates/tuono): add --head flag to download most recent template (#408)
Co-authored-by: Valerio Ageno <51341197+Valerioageno@users.noreply.github.com>
2025-01-25 13:42:29 +01:00
Valerio Ageno 3cb150b090 chore: bump version 0.17.4 (#409) 2025-01-23 18:57:14 +01:00
Valerio Ageno 305ae59086 feat: pass config from server to client (#407) 2025-01-23 18:43:17 +01:00
Robert Lawson 8fe8930def feat: Improve error handling (#398) 2025-01-22 20:41:59 +01:00
Valerio Ageno 8730bdbfb9 refactor: streamline readme (#403) 2025-01-22 19:07:30 +01:00
Valerio Ageno 3ee47e9481 feat: load config in tuono CLI (#399) 2025-01-22 18:01:29 +01:00
Marco Pasqualetti 4e649acd60 ci(docs): use tuono 0.17.3 in docs workflows (#404) 2025-01-22 16:07:21 +01:00
Valerio Ageno 4768d70a8a docs: remove "Components > Head" entry from sidebar (#402)
Co-authored-by: Marco Pasqualetti <marco.pasqualetti@live.com>
2025-01-22 13:55:19 +01:00
Marco Pasqualetti c7bff7ed09 fix(deps): update dependency vite to v5.4.12 [security] (#401) 2025-01-22 08:32:23 +01:00
Valerio Ageno 3035d2a645 feat: create tuono_internal crate (#395) 2025-01-21 19:01:37 +01:00
renovate[bot] 0750037385 fix(deps): update mantine monorepo to v7.16.1 (#388)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-21 09:49:18 +01:00
Marco Pasqualetti 8c4d61ee65 chore(deps): update dependency @types/react to v19.0.7 (#392)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-21 09:09:37 +01:00
Valerio Ageno 1a3ccb112e feat: add host and port support to TuonoConfig (#366)
Co-authored-by: Marco Pasqualetti <marco.pasqualetti@live.com>
2025-01-20 21:00:47 +01:00
Jacob Marshall 118172d27f refactor: add TuonoEntryPoint (#374)
Co-authored-by: Marco Pasqualetti <marco.pasqualetti@live.com>
2025-01-20 20:17:49 +01:00
renovate[bot] 69f1d85360 chore(deps): update dependency @types/node to v22.10.7 (#375)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-20 19:58:11 +01:00
Marco Pasqualetti f0d042c85b chore(packages/tuono): remove dynamic orphan files (#385) 2025-01-20 16:30:30 +01:00
Jacob Marshall 550830c232 chore: update documentation to tuono 0.17.x (#364) 2025-01-20 16:21:35 +01:00
Valerio Ageno 6be12b4e58 chore: bump version to v0.17.3 (#372) 2025-01-19 16:24:19 +01:00
Valerio Ageno 33aa37ed7d fix: create a component tree that matches between client and server to avoid useId output mismatch (#371)
Co-authored-by: Marco Pasqualetti <marco.pasqualetti@live.com>
2025-01-19 16:23:30 +01:00
Marco Pasqualetti 43910fd75d ci: add unique names on ci_ok jobs (#370) 2025-01-19 11:52:57 +01:00
LeNei 5efcc86a63 fix: propagate build error and check if js files exist (#297) 2025-01-19 09:35:11 +01:00
Valerio Ageno 17b61a5a41 chore: bump to v0.17.2 (#365) 2025-01-18 20:51:28 +01:00
Jacob Marshall 5dae5c31b7 feat: add a with-tailwind example (#359)
Co-authored-by: Marco Pasqualetti <marco.pasqualetti@live.com>
2025-01-18 20:44:45 +01:00
Marco Pasqualetti 96deea7f31 ci: redesign CI-related workflows to allow marking them as "Required” before merging a PR (#368) 2025-01-18 20:36:06 +01:00
Jacob Marshall 7632e6a464 fix: broken docs tables (#361) 2025-01-17 15:11:57 +01:00
Jacob Marshall 23e2a2e3ff docs(styles): add Tailwind CSS (#351)
Co-authored-by: Marco Pasqualetti <marco.pasqualetti@live.com>
2025-01-16 18:50:56 +01:00
Jacob Marshall b19512dffc docs: move from bullet points to tables for reference docs (#352)
Co-authored-by: Marco Pasqualetti <marco.pasqualetti@live.com>
2025-01-16 18:42:37 +01:00
Valerio Ageno 11c6fc820b chore: bump version to v0.17.1 (#357) 2025-01-16 12:34:59 +01:00
Valerio Ageno 1a8231851d feat: add support for client only lazy loading with dynamic (#331) 2025-01-16 12:34:06 +01:00
Valerio Ageno 1dfb83b1aa fix: revert "chore: bump version to v0.17.1" (#356) 2025-01-16 12:23:46 +01:00
Valerio Ageno 93cb1ae8ba chore: bump version to v0.17.1 (#354) 2025-01-15 19:24:34 +01:00
Jacob Marshall 631b168e05 docs: more cohesive documentation for linking and navigation, Link and useRouter (#335) 2025-01-15 19:17:35 +01:00
Marco Pasqualetti af8a43c93a docs: use PascalCase for file name (#350) 2025-01-15 16:59:36 +01:00
Valerio Ageno 875d12f514 docs(configuration): remove unclear doc (#349) 2025-01-15 13:02:48 +01:00
Jacob Marshall a9a2ef67ea fix(packages/tuono): config - correct vite.plugins type (#346) 2025-01-14 21:32:51 +01:00
Marco Pasqualetti 5caf3ed6e7 chore(renovate): fix schedule (#345) 2025-01-14 21:19:14 +01:00
Marco Pasqualetti 580ec704f2 chore: dedupe deps (#347) 2025-01-14 21:12:47 +01:00
Marco Pasqualetti a9918ae555 chore(renovate): change prConcurrentLimit to 5 (default 10) and schedule once per week (#340) 2025-01-14 20:43:25 +01:00
Marco Pasqualetti 4b3f4bfab8 docs(configuration): add types and reformat vite properties (#342) 2025-01-14 20:42:54 +01:00
Jacob Marshall fed3b1581b chore: remove RouterProvider from tuono exports (#337) 2025-01-14 16:43:16 +01:00
Jacob Marshall 9b2f0aab32 chore: refine useRouter return type and update docs (#339) 2025-01-14 16:42:27 +01:00
renovate[bot] 818a6bd2ff chore(deps): update dependency typescript to v5.7.3 (#309)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-14 09:43:27 +01:00
renovate[bot] 94a43347a1 chore(deps): update dependency turbo to v2.3.3 (#308)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-14 09:14:00 +01:00
renovate[bot] 16d793c588 chore(deps): update devdependencies (eslint) (#311)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-14 08:56:10 +01:00
renovate[bot] 0322e5bd8d chore(deps): update dependency postcss to v8.5.0 (#334)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-14 08:55:44 +01:00
renovate[bot] cfe76a9ab3 chore(deps): update dependency @types/node to v22.10.6 (#329)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-14 08:45:25 +01:00
renovate[bot] ff6014317b chore(deps): update pnpm to v9.15.4 (#333)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-14 08:42:06 +01:00
PRAMOD A JINGADE 64220f2e27 docs(configuration): fill page content (#307)
Co-authored-by: Marco Pasqualetti <marco.pasqualetti@live.com>
2025-01-14 06:48:57 +01:00
Marco Pasqualetti e75414abfc fix(deps): revert update dependency @babel/types to v7.26.5 (#328) 2025-01-13 20:31:34 +01:00
Jacob Marshall d6fae42dc3 docs: Add useRouter Documentation (#325) 2025-01-13 18:41:31 +01:00
renovate[bot] 0db1245a6b fix(deps): update rust crate ssr_rs to 0.8.0 (#324)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-13 18:26:50 +01:00
renovate[bot] 91c0a9ec31 fix(deps): update dependency @babel/types to v7.26.5 (#304)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-13 15:44:21 +01:00
renovate[bot] 7670c37685 fix(deps): update dependency react-intersection-observer to v9.14.1 (#318)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-13 15:18:24 +01:00
renovate[bot] ae41c5629c chore(deps): update rust crate serial_test to 0.10.0 (#314)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-13 14:07:29 +01:00
renovate[bot] 3e7fa05fce chore(deps): update react monorepo (#301)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-13 12:54:43 +01:00
renovate[bot] 6833640c47 chore(deps): update node.js to v22.13.0 (#312)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-13 12:14:33 +01:00
renovate[bot] 18541c45de chore(deps): update pnpm to v9.15.3 (#313)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-13 12:14:06 +01:00
Marco Pasqualetti 45bb0dd0d2 chore: add PR labeler (#310) 2025-01-13 08:58:26 +01:00
Marco Pasqualetti db0aad2c37 chore(deps): update dependency prettier to v3.4.2 (#306) 2025-01-13 05:04:50 +01:00
Valerio Ageno d55ca12125 fix: dev script (#298) 2025-01-12 18:47:21 +01:00
Valerio Ageno ad2cada94b chore: remove benches folder (#294)
Co-authored-by: Marco Pasqualetti <marco.pasqualetti@live.com>
2025-01-12 13:45:20 +01:00
spacecodeur f9545f513b chore: dockerization of the tuono repo! (#276)
Co-authored-by: Marco Pasqualetti <marco.pasqualetti@live.com>
2025-01-12 09:54:54 +01:00
Marco Pasqualetti c75d83dc7c ci: add pr title check to enforce a consistent git history (#290) 2025-01-05 10:41:23 +01:00
Valerio Ageno 91236e5533 fix: catch-all server side handler (#287) 2025-01-04 12:07:20 +01:00
Valerio Ageno 1356be248e Revert "fix: catch-all server side handler"
This reverts commit 7e8be92cd5.
2025-01-04 10:33:52 +01:00
Valerio Ageno 7e8be92cd5 fix: catch-all server side handler 2025-01-04 10:33:17 +01:00
Valerio Ageno c3fda4a3a5 doc: update tutorial seo page 2025-01-03 17:20:46 +01:00
Valerio Ageno dfc66cfd50 doc: update tutorial 2025-01-03 17:19:09 +01:00
Marco Pasqualetti 0ef1252e1f feat(packages/tuono-(router|fs-router-vite-plugin)): replace __route with __layout (#283) 2025-01-03 17:08:18 +01:00
Valerio Ageno cf56b3a53e Load template by tag (#284) 2025-01-03 17:08:10 +01:00
Marco Pasqualetti 592f402ffd feat: add support for react 19 (#264)
Co-authored-by: Valerio Ageno <valerioageno@yahoo.it>
2025-01-03 11:00:44 +01:00
renovate[bot] 1dc77fc473 fix(deps): update babel monorepo (#271)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-02 13:36:04 +01:00
Marco Pasqualetti 09cd772d74 chore: refine eslint ignores and fix format script of tuono-fs-router-vite-plugin (#265) 2025-01-02 13:35:22 +01:00
Marco Pasqualetti 1c69e10e6a docs: update tuono to 0.16.9 (#280) 2025-01-02 10:57:39 +01:00
Marco Pasqualetti 1af18e4c91 chore(renovate): setup a package rule for eslint (#279) 2025-01-02 10:19:28 +01:00
renovate[bot] a3709609c5 chore(deps): update dependency @testing-library/react to v16.1.0 (#275)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-02 10:11:38 +01:00
renovate[bot] 70a79faee0 fix(deps): update dependency @types/node to v22.10.3 (#272)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-02 09:37:33 +01:00
renovate[bot] 07cb7dae9d chore(deps): update dependency vitest to v2.1.8 (#269)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-02 09:34:03 +01:00
renovate[bot] 9a1fb9c4a1 chore(deps): update dependency eslint-plugin-react to v7.37.3 (#267)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-02 09:32:48 +01:00
renovate[bot] a3f7ed7f61 fix(deps): update dependency prettier to v3.4.2 (#273)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-02 09:28:52 +01:00
renovate[bot] 5302fd2779 chore(deps): update react monorepo (#270)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-02 08:57:01 +01:00
Marco Pasqualetti ccd4e02b6a docs(local-development): use pnpm instead of turbo (#277) 2025-01-02 08:43:41 +01:00
Valerio Ageno f6593097b6 feat: update version to v0.16.9 2024-12-24 16:20:55 +01:00
gravity 230cd22bff feat(crates/tuono): tuono new - download template by cli version and git tag (#261) 2024-12-24 16:03:29 +01:00
Valerio Ageno f4367f1755 feat: update version to v0.16.8 2024-12-24 11:57:21 +01:00
Marco Pasqualetti 7b7447f9a0 feat(packages/vite-plugins): use named export and consistent names across plugins (#260) 2024-12-24 11:41:58 +01:00
Valerio Ageno d12d8404ec feat(packages/tuono-router): replace zustand with React.Context (#256)
Co-authored-by: Marco Pasqualetti <marco.pasqualetti@live.com>
2024-12-24 11:41:45 +01:00
Valerio Ageno d1b12173d5 feat: update version to v0.16.7 2024-12-23 18:32:15 +01:00
Marco Pasqualetti f3bf13da59 refactor(packages/*): add tuono- prefix to all relevant folders (#255) 2024-12-23 18:28:06 +01:00
Marco Pasqualetti f236b75f55 refactor(packages/*): use @vitejs/plugin-react-swc and make all package dependencies explicit (#254) 2024-12-23 18:20:29 +01:00
Marco Pasqualetti 2434231f9b chore: add eslint-plugin-react (#251) 2024-12-23 11:43:04 +01:00
Valerio Ageno b8b39e69a1 Add message event polyfill (#250) 2024-12-22 21:35:08 +01:00
Jovan Milosevic f8158dfd8e chore(examples): Remove tsconfig.node.js file from examples (#245) 2024-12-22 20:12:19 +01:00
Valerio Ageno f1ab7df5ce feat: udpdate version to v0.16.6 2024-12-22 18:06:40 +01:00
Marco Pasqualetti 986de49052 refactor: add eslint-plugin-react-hooks (#248) 2024-12-22 18:03:03 +01:00
Marco Pasqualetti d09ca5548a chore: add .editorconfig (#249) 2024-12-22 17:52:03 +01:00
Marco Pasqualetti 77e22c40b6 refactor: enable typescript-eslint strict rules (#243) 2024-12-22 12:08:21 +01:00
Marco Pasqualetti de74647c43 test(packages/tuono): messageChannel - use vi.fn (#241) 2024-12-22 09:30:18 +01:00
Mustafa Zaki Assagaf 498601c21a feat: add MessageChannel polyfill to support react 19 (#238) 2024-12-21 16:55:04 +01:00
Marco Pasqualetti e99f06ddf5 chore(bug_report): make system-info fields required and add CLI command to retrieve them (#239) 2024-12-20 07:34:55 +01:00
Marco Pasqualetti f06af59168 chore: add CODEOWNERS (#237) 2024-12-19 08:22:16 +01:00
Valerio Ageno d50e3a7fc0 feat: update version to v0.16.5 2024-12-18 22:10:05 +01:00
Valerio Ageno 3e4e7ff1ab feat: update rendering from renderToString to renderToReadableStream (#233)
Co-authored-by: Marco Pasqualetti <marco.pasqualetti@live.com>
2024-12-18 21:58:19 +01:00
Marco Pasqualetti 21ff3c8655 docs: update tuono (#236) 2024-12-18 21:53:24 +01:00
Valerio Ageno 166e61bab4 feat: update version to v0.16.4 2024-12-18 14:14:51 +01:00
Mustafa Zaki Assagaf 93cd8bd8da fix: catch-all paths replace double underscore with single underscore (#229) 2024-12-18 14:06:14 +01:00
Marco Pasqualetti f5c1641af2 chore(apps/documentation): remove tsconfig.node.json (#228) 2024-12-18 09:54:52 +01:00
Mustafa Zaki Assagaf 62ffed0624 docs: added website link to creates documentation (#230) 2024-12-18 09:13:03 +01:00
Marco Pasqualetti 8d0a4a7417 refactor(packages/lazy-fn-vite-plugin): add filter to avoid processing unrelated files (#227) 2024-12-18 09:11:30 +01:00
Mustafa Zaki Assagaf b1b274ea12 feat: update tuono macro handler naming to avoid naming collisions (#225) 2024-12-17 16:47:23 +01:00
Valerio Ageno fc38865965 fix: README.md 2024-12-16 13:57:25 +01:00
Valerio Ageno 911adaaecb feat: update version to v0.16.3 2024-12-16 08:08:27 +01:00
Marco Pasqualetti 7626ed8d1d fix(packages/lazy-fn-vite-plugin): make dynamic function detection stricter (#223) 2024-12-16 08:03:37 +01:00
Valerio Ageno 6135fd7e1b docs: add dynamic routes page (#219)
Co-authored-by: Valerio Ageno <valerio.ageno@qonto.com>
Co-authored-by: Marco Pasqualetti <marco.pasqualetti@live.com>
Co-authored-by: Marco Pasqualetti <24919330+marcalexiei@users.noreply.github.com>
2024-12-15 13:39:06 +01:00
Valerio Ageno 14bea36356 fix: update lazyLoadComponent fn name to __tuono__internal__lazyLoadComponent (#222) 2024-12-15 09:22:19 +01:00
349 changed files with 5576 additions and 8717 deletions
+7
View File
@@ -0,0 +1,7 @@
[*]
charset = utf-8
insert_final_newline = true
end_of_line = lf
indent_style = space
indent_size = 2
max_line_length = 80
+14 -45
View File
@@ -32,55 +32,24 @@ body:
description: If applicable, add screenshots to help explain your problem.
validations:
required: false
- type: input
id: tuono-version
- type: textarea
id: system-info
attributes:
label: Tuono version
placeholder: '[e.g. 0.4.0]'
label: System Info
description: Output of `npx envinfo --system --npmPackages 'tuono' --binaries --browsers`
render: shell
placeholder: System, Binaries, Browsers
validations:
required: false
- type: input
id: os-version
required: true
- type: textarea
id: system-info-rust
attributes:
label: OS
placeholder: '[e.g. MacOS, Windows]'
label: System info (Rust)
description: Output of `rustc --version && cargo --version && tuono --version`
render: shell
placeholder: 'rustc, cargo and tuono binary version'
validations:
required: false
- type: input
id: browser-version
attributes:
label: Browser
placeholder: '[e.g. chrome, safari]'
validations:
required: false
- type: input
id: node-version
attributes:
label: Node version
placeholder: '[e.g. 20.0.0]'
validations:
required: false
- type: input
id: rust-version
attributes:
label: Rust version
placeholder: '[e.g. 1.79.0]'
validations:
required: false
- type: input
id: create-version
attributes:
label: Crate version
placeholder: '[e.g. 1.78.0]'
validations:
required: false
- type: input
id: node-package-manager-version
attributes:
label: Node Package Manger version
placeholder: '[e.g. pnpm: 9.5.0] '
validations:
required: false
required: true
- type: textarea
id: additional-context
attributes:
+36
View File
@@ -0,0 +1,36 @@
# @see https://github.com/actions/labeler
rust:
- changed-files:
- any-glob-to-any-file: ['crates/**', 'Cargo.toml']
typescript:
- changed-files:
- any-glob-to-any-file:
[
'packages/**',
'package.json',
'pnpm-*.yaml',
'eslint.config.js',
'tsconfig.json',
]
documentation:
- changed-files:
- any-glob-to-any-file: ['apps/documentation/**']
'CI/CD':
- changed-files:
- any-glob-to-any-file: ['.github/**']
'repo maintenance':
- changed-files:
- any-glob-to-any-file:
[
'.npmrc',
'.nvmrc',
'.prettierrc',
'.prettierignore',
'renovate.json',
'turbo.json',
]
+5 -4
View File
@@ -3,11 +3,12 @@
<!--
Thank you for your Pull Request.
Explain the context and why you're making that change. What is the problem
you're trying to solve? If a new feature is being added, describe the intended
use case that feature fulfills.
Explain the context and why you're making that change.
What is the problem you're trying to solve?
If a new feature is being added,
describe the intended use case that feature fulfills.
Bug fixes and new features should include tests.
Contributors guide: https://github.com/Valerioageno/tuono/blob/main/CONTRIBUTING.md
PR guide: https://tuono.dev/documentation/contributing/pull-requests
-->
+5 -5
View File
@@ -4,20 +4,20 @@ on:
push:
branches:
- 'main'
# match
# - all files inside `apps/documentation` and `.github`
# - all files in the root expect `Cargo.toml`
paths:
# ⬇ Keep paths in sync with `typescript.yml`
- '.github/**'
- '*'
- '!Cargo.toml'
# ⬆ Keep paths in sync with `typescript.yml`
- 'apps/documentation/**'
pull_request:
# same as `on.push.paths`
paths:
# ⬇ Keep paths in sync with `typescript.yml`
- '.github/**'
- '*'
- '!Cargo.toml'
# ⬆ Keep paths in sync with `typescript.yml`
- 'apps/documentation/**'
jobs:
@@ -37,7 +37,7 @@ jobs:
uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Install tuono
run: cargo install tuono@0.15.0
run: cargo install tuono@0.17.3
- name: Build project
working-directory: ./apps/documentation
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Install tuono
run: cargo install tuono@0.16.0
run: cargo install tuono@0.17.3
- name: Build project
working-directory: ./apps/documentation
+27
View File
@@ -0,0 +1,27 @@
name: 'PR Labeler'
# @see https://github.com/actions/labeler
# @see .github/labeler.yml
on:
- pull_request_target
jobs:
labeler:
name: 'Manage labels'
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
# Add checkout step to load labeler.yml locally,
# rather than from an API request
- name: Checkout code
uses: actions/checkout@v4
- uses: actions/labeler@v5
with:
sync-labels: true
+61
View File
@@ -0,0 +1,61 @@
name: 'PR Title Checker'
# This workflow ensures that PR titles adhere to a pattern
# similar to conventional commits standard
on:
pull_request:
types:
- opened
- edited
- synchronize
- labeled
- unlabeled
env:
PR_TITLE: ${{ github.event.pull_request.title }}
jobs:
check_pr_title:
name: 'PR Title Checker'
runs-on: ubuntu-latest
steps:
- name: Check type
id: type
# @warning Keep in sync with apps/documentation/src/routes/documentation/contributing/pull-requests.mdx
run: |
VALID_COMMIT_TYPES="chore|ci|docs|feat|fix|refactor|test"
REGEX="^${VALID_COMMIT_TYPES})(\(.*\))?!?: .*"
if ! [[ $PR_TITLE =~ $REGEX ]]; then
echo "::error title=Type::The title has an incorrect type. Valid types are ${VALID_COMMIT_TYPES}"
echo "result=fail" >> "$GITHUB_OUTPUT"
else
echo "::notice title=Type::The title is using a valid type"
echo "result=ok" >> "$GITHUB_OUTPUT"
fi
- name: Check length
id: length
run: |
MAX_LENGTH=100
LENGTH=${#PR_TITLE}
if [ $LENGTH -gt $MAX_LENGTH ]; then
echo "::error title=Length::The title is longer than $MAX_LENGTH characters"
echo "result=fail" >> "$GITHUB_OUTPUT"
else
echo "::notice title=Length::The title length is within the maximum value of $MAX_LENGTH characters"
echo "result=ok" >> "$GITHUB_OUTPUT"
fi
- name: Check result
env:
FAILURE: ${{ contains(join(steps.*.outputs.result, ','), 'fail') }}
run: |
echo "Failure: $FAILURE"
if [ "$FAILURE" = "false" ]; then
exit 0
else
exit 1
fi
+21 -7
View File
@@ -8,16 +8,10 @@ on:
push:
branches:
- 'main'
paths:
- '.github/**'
- '*'
pull_request:
paths:
- '.github/**'
- '*'
jobs:
build-and-test:
format:
name: Check format
runs-on: ubuntu-latest
timeout-minutes: 15
@@ -31,3 +25,23 @@ jobs:
- name: Test project
run: pnpm repo:root:format:check
ci_ok:
name: Repo root CI OK
runs-on: ubuntu-latest
timeout-minutes: 1
if: always()
needs: [format]
env:
FAILURE: ${{ contains(join(needs.*.result, ','), 'failure') }}
CANCELLED: ${{ contains(join(needs.*.result, ','), 'cancelled') }}
steps:
- name: Check for failure or cancelled jobs result
shell: bash
run: |
echo "Failure: $FAILURE - Cancelled: $CANCELLED"
if [ "$FAILURE" = "false" ] && [ "$CANCELLED" = "false" ]; then
exit 0
else
exit 1
fi
+22 -8
View File
@@ -4,15 +4,7 @@ on:
push:
branches:
- 'main'
paths:
- '.github/**'
- 'Cargo.toml'
- 'crates/**'
pull_request:
paths:
- '.github/**'
- 'Cargo.toml'
- 'crates/**'
env:
CARGO_TERM_COLOR: always
@@ -40,6 +32,7 @@ jobs:
os: 'ubuntu-latest'
runs-on: ${{ matrix.os }}
timeout-minutes: 15
steps:
- name: Checkout code
@@ -56,6 +49,7 @@ jobs:
lint_and_fmt:
name: Check format and lint rust crates
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout code
@@ -66,3 +60,23 @@ jobs:
- run: cargo fmt --all -- --check
- run: cargo clippy -- -D warnings
ci_ok:
name: Rust CI OK
runs-on: ubuntu-latest
timeout-minutes: 1
if: always()
needs: [build_and_test, lint_and_fmt]
env:
FAILURE: ${{ contains(join(needs.*.result, ','), 'failure') }}
CANCELLED: ${{ contains(join(needs.*.result, ','), 'cancelled') }}
steps:
- name: Check for failure or cancelled jobs result
shell: bash
run: |
echo "Failure: $FAILURE - Cancelled: $CANCELLED"
if [ "$FAILURE" = "false" ] && [ "$CANCELLED" = "false" ]; then
exit 0
else
exit 1
fi
+21 -15
View File
@@ -4,26 +4,11 @@ on:
push:
branches:
- 'main'
paths:
# ⬇ Keep paths in sync with `ci-documentation.yml`
- '.github/**'
- '*'
- '!Cargo.toml'
# ⬆ Keep paths in sync with `ci-documentation.yml`
- 'packages/**'
pull_request:
paths:
# ⬇ Keep paths in sync with `ci-documentation.yml`
- '.github/**'
- '*'
- '!Cargo.toml'
# ⬆ Keep paths in sync with `ci-documentation.yml`
- 'packages/**'
jobs:
build_and_test:
name: Check build and test
timeout-minutes: 15
strategy:
fail-fast: true
@@ -34,6 +19,7 @@ jobs:
- 'windows-latest'
runs-on: ${{ matrix.os }}
timeout-minutes: 15
steps:
- name: Checkout code
@@ -68,3 +54,23 @@ jobs:
- name: Types
run: pnpm types
ci_ok:
name: Typescript CI OK
runs-on: ubuntu-latest
timeout-minutes: 1
if: always()
needs: [build_and_test, lint_and_fmt]
env:
FAILURE: ${{ contains(join(needs.*.result, ','), 'failure') }}
CANCELLED: ${{ contains(join(needs.*.result, ','), 'cancelled') }}
steps:
- name: Check for failure or cancelled jobs result
shell: bash
run: |
echo "Failure: $FAILURE - Cancelled: $CANCELLED"
if [ "$FAILURE" = "false" ] && [ "$CANCELLED" = "false" ]; then
exit 0
else
exit 1
fi
+2
View File
@@ -8,6 +8,8 @@ dist/
examples/*/pnpm-lock.yaml
vite.config.ts.timestamp*
## Rust related ignores
# Generated by Cargo
+1 -1
View File
@@ -1 +1 @@
22.11.0
22.13.0
+8 -1
View File
@@ -1 +1,8 @@
pnpm-lock.yaml
pnpm-lock.yaml
dist
.tuono
vite.config.ts.timestamp-*
packages/tuono-lazy-fn-vite-plugin/tests/sources/*
+9
View File
@@ -0,0 +1,9 @@
* @Valerioageno @marcalexiei
# Rust
/crates/ @Valerioageno
/Cargo.toml @Valerioageno
# Misc
/.github/ @marcalexiei
+1 -3
View File
@@ -23,6 +23,4 @@ Consider [opening a new issue](https://github.com/tuono-labs/tuono/issues/new/ch
**Did you write a patch that fixes a bug?**
- Open a new GitHub pull request with the patch.
- Ensure the PR description clearly describes the problem and solution. Include the relevant issue number, if applicable.
- The pull requests must pass all the CI pipelines
[Visit the documentation to learn how to open a pull request](https://tuono.dev/documentation/contributing/pull-requests)
+9 -8
View File
@@ -1,14 +1,15 @@
[workspace]
resolver = "2"
members = [
"crates/tuono",
"crates/tuono_lib",
"crates/tuono_lib_macros",
"crates/tuono",
"crates/tuono_internal",
"crates/tuono_lib",
"crates/tuono_lib_macros"
]
exclude = [
"apps/documentation",
"examples/with-mdx",
"examples/tuono-app",
"examples/tuono-tutorial",
"benches/tuono"
"apps/documentation",
"examples/with-mdx",
"examples/tuono-app",
"examples/tuono-tutorial",
"examples/with-tailwind",
]
+16 -33
View File
@@ -24,51 +24,34 @@ Some of its features are:
- 🧬 Server Side Rendering
- 🔥 Hot Module Reload
## 📖 Documentation
## Documentation
The [documentation](https://tuono.dev/documentation) is available on
The [documentation](https://tuono.dev/) is available on
[tuono.dev](https://tuono.dev/).
## Introduction
## Installation
**NodeJs/Deno/Bun are the only runtimes that allow a React app to be full-stack right? (no)**
Available on MacOS, Linux and Windows.
Tuono is a full-stack React framework with the server side written in Rust.
Because of this, Tuono is extremely fast, and the requests are handled by a multithreaded Rust server.
React is still React - it is just superpowered.
**Rust is a hard language, then writing server-side code is hard as well, right? (no again)**
Tuono provides a collection of utilities to handle the server side code seamlessly with the React code.
Each server-side route is managed in a separate file alongside the React route. The routing is handled
by Tuono based on the files defined within the `./src/routes` directory.
**How is Tuono different from Next.js?**
The Tuono API tries to stick as much as possible to the Next.js one (or at least takes a huge inspiration
from it). The major difference is the backend system. While Next.js relies entirely on Node/Deno/Bun,
Tuono runs the server without any intermediary runtime. This enables impressive performance improvements
(check the benchmarks [here](https://github.com/tuono-labs/tuono/tree/main/benches)).
```sh
cargo install tuono
```
## Getting started
Tuono is the CLI that provides all the needed commands to handle the full-stack project.
To download it is required [cargo](https://doc.rust-lang.org/cargo/), which is the [rust](https://www.rust-lang.org/)
package manager.
Create a new project with:
Then run `cargo install tuono`.
```sh
tuono new [PROJECT_NAME]
```
To list all the available commands, run `tuono -h`
> You can optionally pass the --template (or -t) flag to directly start from a [template](https://github.com/tuono-labs/tuono/tree/main/examples)
To create a new project, run `tuono new [NAME]` (optionally, you can pass the `--template` (or `-t`) flag - check the
[examples](https://github.com/tuono-labs/tuono/tree/main/examples) folder).
Now just install the dependencies with you favourite JS package manager (i.e. `npm install`) and start the development environment
Then, to run the local development environment, install the JS dependencies (`npm install`) and run inside the project folder `tuono dev`
Finally, when the project is ready to be deployed, just run `tuono build` to create the final React assets
and to set the server project in `production` mode.
Now to execute it just run `cargo run --release`.
```sh
tuono dev
```
## Contributing
+17
View File
@@ -0,0 +1,17 @@
# Documentation Contributing
## Update `tuono` version in `apps/documentation`
Update `tuono` version in the following files
- `.github/workflows/ci-documentation.yml`
- `.github/workflows/deploy-documentation.yml`
- `apps/documentation/Cargo.toml`
- `apps/documentation/package.json`
[Refer to this PR for additional information](https://github.com/tuono-labs/tuono/pull/236/files)
In the future we might:
- move the documentation in a separate repo
- make a script to perform this operation
+1 -2
View File
@@ -8,8 +8,7 @@ name = "tuono"
path = ".tuono/main.rs"
[dependencies]
tuono_lib = "0.15.0"
tuono_lib = "0.17.3"
glob = "0.3.1"
time = { version = "0.3", features = ["macros"] }
serde = { version = "1.0.202", features = ["derive"] }
+12 -11
View File
@@ -6,26 +6,27 @@
"type": "module",
"scripts": {
"lint": "eslint .",
"format": "prettier -u --write --ignore-unknown .",
"format": "prettier --write --ignore-unknown .",
"format:check": "prettier --check --ignore-unknown .",
"types": "tsc --noEmit"
},
"dependencies": {
"@mantine/code-highlight": "7.14.2",
"@mantine/core": "7.14.2",
"@mantine/hooks": "7.14.2",
"@mantine/code-highlight": "7.16.1",
"@mantine/core": "7.16.1",
"@mantine/hooks": "7.16.1",
"@mdx-js/react": "3.1.0",
"@tabler/icons-react": "3.22.0",
"@tabler/icons-react": "3.28.1",
"clsx": "2.1.1",
"react": "18.3.1",
"react-dom": "18.3.1",
"tuono": "npm:tuono@0.16.0"
"react": "19.0.0",
"react-dom": "19.0.0",
"remark-gfm": "4.0.0",
"tuono": "npm:tuono@0.17.3"
},
"devDependencies": {
"@mdx-js/rollup": "3.1.0",
"@types/react": "18.3.13",
"@types/react-dom": "18.3.0",
"postcss": "8.4.49",
"@types/react": "19.0.7",
"@types/react-dom": "19.0.3",
"postcss": "8.5.1",
"postcss-preset-mantine": "1.17.0",
"postcss-simple-vars": "7.0.1"
}
@@ -0,0 +1,87 @@
import { useMemo, type JSX } from 'react'
import { Breadcrumbs as MantineBreadcrumbs, Button } from '@mantine/core'
import { Link } from 'tuono'
import { IconChevronRight, IconBolt } from '@tabler/icons-react'
interface BreadcrumbData {
href?: string
label: string
}
interface BreadcrumbsProps {
breadcrumbs: Array<BreadcrumbData>
}
export default function Breadcrumbs({
breadcrumbs = [],
}: BreadcrumbsProps): JSX.Element {
const ldJson = useMemo(() => {
const _ldJson = {
'@context': 'https://schema.org',
'@type': 'BreadcrumbList',
itemListElement: [
{
'@type': 'ListItem',
position: 1,
name: 'Tuono - The React/Rust fullstack framework',
item: 'https://tuono.dev' as string | undefined,
},
],
}
_ldJson.itemListElement.push(
...breadcrumbs.map((br, i) => ({
'@type': 'ListItem' as const,
position: i + 3,
name: br.label,
item: br.href ? `https://tuono.dev${br.href}` : undefined,
})),
)
return _ldJson
}, [breadcrumbs])
return (
<>
<script type="application/ld+json">
{JSON.stringify(ldJson, null, 2)}
</script>
<MantineBreadcrumbs
separator={<IconChevronRight size="1.1rem" stroke={1.5} />}
mb="md"
mt="md"
>
<Button href="/" component={Link} variant="subtle" radius="xl" p={5}>
<IconBolt />
</Button>
{breadcrumbs.map((br) => (
<BreadcrumbElement href={br.href} label={br.label} key={br.label} />
))}
</MantineBreadcrumbs>
</>
)
}
interface BreadcrumbElementProps {
href?: string
label: string
}
export function BreadcrumbElement({
href,
label,
}: BreadcrumbElementProps): JSX.Element {
if (href) {
return (
<Button component={Link} href={href} variant="subtle" radius="xl" px={10}>
{label}
</Button>
)
}
return (
<Button component="span" variant="light" radius="xl">
{label}
</Button>
)
}
@@ -0,0 +1,3 @@
import Breadcrumbs from './Breadcrumbs'
export default Breadcrumbs
@@ -0,0 +1,3 @@
import EditPage from './EditPage'
export default EditPage
@@ -0,0 +1,3 @@
import Hero from './Hero'
export default Hero
@@ -2,5 +2,5 @@ import type { JSX } from 'react'
import { Text, type TextProps } from '@mantine/core'
export default function MdxBold(props: TextProps): JSX.Element {
return <Text fw={700} {...props} />
return <Text component="span" fw={700} {...props} />
}
@@ -0,0 +1,3 @@
import MdxBold from './MdxBold'
export default MdxBold
@@ -0,0 +1,3 @@
import MdxCode from './MdxCode'
export default MdxCode
@@ -0,0 +1,3 @@
import MdxLink from './MdxLink'
export default MdxLink
@@ -1,7 +1,7 @@
import type { JSX } from 'react'
import { CodeHighlight } from '@mantine/code-highlight'
import styles from './mdx-pre.module.css'
import styles from './MdxPre.module.css'
interface PreProps {
children: {
@@ -0,0 +1,3 @@
import MdxPre from './MdxPre'
export default MdxPre
@@ -1,12 +1,13 @@
import type { JSX, ReactNode } from 'react'
import { MDXProvider } from '@mdx-js/react'
import MdxLink from './mdx-link'
import MdxPre from './mdx-pre'
import MdxQuote from './mdx-quote'
import MdxCode from './mdx-code'
import { h } from './mdx-title'
import MdxBold from './mdx-bold/mdx-bold'
import MdxLink from './MdxLink'
import MdxPre from './MdxPre'
import MdxQuote from './MdxQuote'
import MdxCode from './MdxCode'
import { h } from './MdxTitle'
import MdxBold from './MdxBold'
import MdxTable from './MdxTable'
interface MdxProviderProps {
children: ReactNode
@@ -19,7 +20,6 @@ export default function MdxProvider({
<MDXProvider
components={{
a: MdxLink,
// @ts-expect-error: useless finding the correct props types
pre: MdxPre,
blockquote: MdxQuote,
code: MdxCode,
@@ -30,6 +30,12 @@ export default function MdxProvider({
h5: h(5),
h6: h(6),
strong: MdxBold,
table: MdxTable,
thead: MdxTable.Thead,
tbody: MdxTable.Tbody,
tr: MdxTable.Tr,
th: MdxTable.Th,
td: MdxTable.Td,
}}
>
{children}
@@ -0,0 +1,3 @@
import MdxQuote from './MdxQuote'
export default MdxQuote
@@ -0,0 +1,27 @@
import type { DetailedHTMLProps, TableHTMLAttributes, JSX } from 'react'
import { Table, ScrollArea } from '@mantine/core'
type MdxTableProps = DetailedHTMLProps<
TableHTMLAttributes<HTMLTableElement>,
HTMLTableElement
>
function MdxTable(props: MdxTableProps): JSX.Element {
const { children, ...rest } = props
return (
<ScrollArea type="auto">
<Table highlightOnHover {...rest}>
{children}
</Table>
</ScrollArea>
)
}
MdxTable.Thead = Table.Thead
MdxTable.Tbody = Table.Tbody
MdxTable.Tr = Table.Tr
MdxTable.Th = Table.Th
MdxTable.Td = Table.Td
MdxTable.Caption = Table.Caption
export default MdxTable
@@ -0,0 +1,3 @@
import MdxTable from './MdxTable'
export default MdxTable
@@ -16,6 +16,12 @@ export default function MdxTitle(props: TitleProps): JSX.Element {
)
}
export const h =
(order: 1 | 2 | 3 | 4 | 5 | 6) =>
(props: TitleProps): JSX.Element => <MdxTitle order={order} {...props} />
export const h = (
order: 1 | 2 | 3 | 4 | 5 | 6,
): React.ElementType<TitleProps> => {
function render(props: TitleProps): JSX.Element {
return <MdxTitle order={order} {...props} />
}
render.displayName = 'H'
return render
}
@@ -0,0 +1,5 @@
import MdxTitle, { h } from './MdxTitle'
export default MdxTitle
export { h }
@@ -0,0 +1,3 @@
import MdxProvider from './MdxProvider'
export default MdxProvider
@@ -1,5 +1,4 @@
import type { ReactNode } from 'react'
import { Head } from 'tuono'
interface MetaTagsProps {
title: string
@@ -15,7 +14,7 @@ export default function MetaTags({
canonical,
}: MetaTagsProps): ReactNode {
return (
<Head>
<>
<title>{title}</title>
<link rel="canonical" href={canonical} />
<meta
@@ -41,6 +40,6 @@ export default function MetaTags({
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content="https://tuono.dev/og-cover.png" />
</Head>
</>
)
}
@@ -0,0 +1,3 @@
import MetaTags from './MetaTags'
export default MetaTags
@@ -2,7 +2,7 @@ import type { JSX } from 'react'
import { AppShell, Box, Burger, Button, Flex } from '@mantine/core'
import { Link } from 'tuono'
import Actions from './actions'
import NavbarActions from './NavbarActions'
interface NavbarProps {
toggle: () => void
@@ -24,7 +24,7 @@ export default function Navbar({ toggle }: NavbarProps): JSX.Element {
</Button>
<Box />
<Flex align="center" gap={8}>
<Actions />
<NavbarActions />
<Burger onClick={toggle} hiddenFrom="sm" size="sm" />
</Flex>
</Flex>
@@ -2,9 +2,9 @@ import type { JSX } from 'react'
import { Flex, ActionIcon, Group } from '@mantine/core'
import { IconBrandGithub, IconBrandDiscord } from '@tabler/icons-react'
import ThemeBtn from '../theme-btn'
import ThemeBtn from '../ThemeBtn'
export default function Actions(): JSX.Element {
export default function NavbarActions(): JSX.Element {
return (
<Flex gap={8}>
<Group gap={8}>
@@ -0,0 +1,3 @@
import Navbar from './Navbar'
export default Navbar
@@ -1,16 +1,16 @@
import type { JSX } from 'react'
import { Box, Button, Text, Title, Flex } from '@mantine/core'
import { Link } from 'tuono'
import { IconArrowRight, IconArrowLeft } from '@tabler/icons-react'
import { Link } from 'tuono'
interface NavigationButton {
interface NavigationButtonData {
href: string
title: string
}
interface NavigationButtonsProps {
prev?: NavigationButton
next?: NavigationButton
prev?: NavigationButtonData
next?: NavigationButtonData
}
export default function NavigationButtons({
@@ -25,7 +25,7 @@ export default function NavigationButtons({
)
}
interface NavigationButtonProps extends NavigationButton {
interface NavigationBtnProps extends NavigationButtonData {
type: 'next' | 'prev'
}
@@ -33,7 +33,7 @@ const NavigationBtn = ({
type,
title,
href,
}: NavigationButtonProps): JSX.Element => {
}: NavigationBtnProps): JSX.Element => {
const heading = type === 'next' ? 'Next' : 'Previous'
const textAlign = type === 'next' ? 'left' : 'right'
const variant = type === 'next' ? 'filled' : 'outline'
@@ -0,0 +1,3 @@
import NavigationButtons from './NavigationButtons'
export default NavigationButtons
@@ -14,8 +14,8 @@ import {
import { IconX } from '@tabler/icons-react'
import { useMediaQuery } from '@mantine/hooks'
import { sidebarElements } from './config'
import SidebarLink from './sidebar-link'
import { sidebarElements } from './sidebarElements'
import SidebarLink from './SidebarLink'
interface SidebarProps {
close: () => void
@@ -50,26 +50,30 @@ function SidebarElements({ close }: SidebarProps): JSX.Element {
<AppShell.Section component={ScrollArea}>
{sidebarElements.map((el, i) => {
if (el.type === 'divider') {
return <Divider my="md" mx={10} />
return <Divider key={`${el.type}-${i}`} my="md" mx={10} />
}
if (el.type === 'title') {
return (
<Text
key={`${el.type}-${i}`}
size="xs"
fw={700}
fz={12}
pl={12}
py={5}
children={el.label}
/>
>
{el.label}
</Text>
)
}
if (el.children?.length) {
return (
<SidebarLink
key={`${el.type}-${i}`}
href={el.href}
label={el.label}
key={i}
leftSection={el.leftIcon}
>
{el.children.map((child, index) => (
@@ -83,12 +87,13 @@ function SidebarElements({ close }: SidebarProps): JSX.Element {
</SidebarLink>
)
}
return (
<SidebarLink
key={`${el.type}-${i}`}
href={el.href}
label={el.label}
onClick={close}
key={i}
/>
)
})}
@@ -4,7 +4,7 @@ import clsx from 'clsx'
import { Link, useRouter } from 'tuono'
import { IconChevronRight } from '@tabler/icons-react'
import styles from './sidebar-link.module.css'
import styles from './SidebarLink.module.css'
interface SidebarLinkProps {
label: string
@@ -0,0 +1,3 @@
import Sidebar from './Sidebar'
export default Sidebar
@@ -111,6 +111,11 @@ export const sidebarElements: Array<SidebarElement> = [
label: 'Defining routes',
href: '/documentation/routing/defining-routes',
},
{
type: 'element',
label: 'Dynamic routes',
href: '/documentation/routing/dynamic-routes',
},
{
type: 'element',
label: 'Link and navigation',
@@ -126,11 +131,6 @@ export const sidebarElements: Array<SidebarElement> = [
label: 'Loading state',
href: '/documentation/routing/loading-state',
},
{
type: 'element',
label: 'Dynamic routes',
href: '/documentation/routing/dynamic-routes',
},
{
type: 'element',
label: 'Layouts',
@@ -170,6 +170,11 @@ export const sidebarElements: Array<SidebarElement> = [
label: 'CSS modules',
href: '/documentation/styles/css-modules',
},
{
type: 'element',
label: 'Tailwind CSS',
href: '/documentation/styles/tailwind-css',
},
],
},
{
@@ -203,11 +208,6 @@ export const sidebarElements: Array<SidebarElement> = [
label: 'Components',
href: '#focus',
children: [
{
type: 'element',
label: 'Head',
href: '/documentation/components/head',
},
{
type: 'element',
label: 'Link',
@@ -239,7 +239,7 @@ export const sidebarElements: Array<SidebarElement> = [
},
{
type: 'element',
label: 'tuono.config.ts',
label: 'Configuration',
href: '/documentation/configuration',
},
@@ -260,6 +260,11 @@ export const sidebarElements: Array<SidebarElement> = [
label: 'Local development',
href: '/documentation/contributing/local-development',
},
{
type: 'element',
label: 'Pull requests',
href: '/documentation/contributing/pull-requests',
},
],
},
]
@@ -7,12 +7,8 @@ import { useRouter, Link } from 'tuono'
import { IconList } from '@tabler/icons-react'
import { Box, rem, ScrollArea, Text } from '@mantine/core'
import { getHeadings, type Heading } from './get-headings'
import classes from './table-of-content.module.css'
interface TableOfContentsProps {
withTabs: boolean
}
import { getHeadings, type Heading } from './getHeadings'
import classes from './TableOfContents.module.css'
function getActiveElement(rects: Array<DOMRect>): number {
if (rects.length === 0) {
@@ -36,6 +32,10 @@ function getActiveElement(rects: Array<DOMRect>): number {
return closest.index
}
interface TableOfContentsProps {
withTabs: boolean
}
export function TableOfContents({
withTabs,
}: TableOfContentsProps): JSX.Element | null {
@@ -64,7 +64,9 @@ export function TableOfContents({
),
)
window.addEventListener('scroll', handleScroll)
return (): void => window.removeEventListener('scroll', handleScroll)
return (): void => {
window.removeEventListener('scroll', handleScroll)
}
}, [router.pathname])
if (filteredHeadings.length === 0) {
@@ -1,6 +1,6 @@
/*
* Component inspired by: https://github.com/mantinedev/mantine/tree/master/apps/mantine.dev/src/components/TableOfContents
*/
import { TableOfContents } from './table-of-content'
import { TableOfContents } from './TableOfContents'
export default TableOfContents
@@ -7,7 +7,7 @@ import {
import { IconSun, IconMoon } from '@tabler/icons-react'
import cx from 'clsx'
import classes from './theme-btn.module.css'
import classes from './ThemeBtn.module.css'
export default function ThemeBtn(): JSX.Element {
const { setColorScheme } = useMantineColorScheme()
@@ -17,9 +17,9 @@ export default function ThemeBtn(): JSX.Element {
return (
<ActionIcon
onClick={() =>
onClick={() => {
setColorScheme(computedColorScheme === 'light' ? 'dark' : 'light')
}
}}
variant="default"
size="lg"
aria-label="Toggle color scheme"
@@ -0,0 +1,3 @@
import ThemeBtn from './ThemeBtn'
export default ThemeBtn
@@ -1,84 +0,0 @@
import type { JSX } from 'react'
import { Breadcrumbs, Button } from '@mantine/core'
import { Link, Head } from 'tuono'
import { IconChevronRight, IconBolt } from '@tabler/icons-react'
interface Breadcrumb {
href?: string
label: string
}
interface BreadcrumbsProps {
breadcrumbs: Array<Breadcrumb>
}
export default function TuonoBreadcrumbs({
breadcrumbs = [],
}: BreadcrumbsProps): JSX.Element {
return (
<>
<Head>
<script type="application/ld+json">
{`{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Tuono - The React/Rust fullstack framework",
"item": "https://tuono.dev"
}${breadcrumbs.length > 0 ? ',' : ''}
${breadcrumbs
.map((br, i) =>
JSON.stringify({
'@type': 'ListItem',
position: i + 3,
name: br.label,
item: br.href ? `https://tuono.dev${br.href}` : undefined,
}),
)
.join(',')}]
}
`}
</script>
</Head>
<Breadcrumbs
separator={<IconChevronRight size="1.1rem" stroke={1.5} />}
mb="md"
mt="md"
>
<Button href="/" component={Link} variant="subtle" radius="xl" p={5}>
<IconBolt />
</Button>
{breadcrumbs.map((br) => (
<BreadcrumbElement href={br.href} label={br.label} key={br.label} />
))}
</Breadcrumbs>
</>
)
}
interface BreadcrumbElementProps {
href?: string
label: string
}
export function BreadcrumbElement({
href,
label,
}: BreadcrumbElementProps): JSX.Element {
if (href) {
return (
<Button component={Link} href={href} variant="subtle" radius="xl" px={10}>
{label}
</Button>
)
}
return (
<Button component="span" variant="light" radius="xl">
{label}
</Button>
)
}
@@ -1,5 +0,0 @@
import Breadcrumbs, { BreadcrumbElement } from './breadcrumbs'
export default Breadcrumbs
export { BreadcrumbElement as Element }
@@ -1,3 +0,0 @@
import EditPage from './edit-page'
export default EditPage
@@ -1,3 +0,0 @@
import Hero from './hero'
export default Hero
@@ -1,3 +0,0 @@
import MdxProvider from './mdx-provider'
export default MdxProvider
@@ -1,3 +0,0 @@
import MdxCode from './mdx-code'
export default MdxCode
@@ -1,3 +0,0 @@
import MdxLink from './mdx-link'
export default MdxLink
@@ -1,3 +0,0 @@
import MdxPre from './mdx-pre'
export default MdxPre
@@ -1,3 +0,0 @@
import MdxQuote from './mdx-quote'
export default MdxQuote
@@ -1,5 +0,0 @@
import MdxTitle, { h } from './mdx-title'
export default MdxTitle
export { h }
@@ -1,3 +0,0 @@
import MetaTags from './meta-tags'
export default MetaTags
@@ -1,3 +0,0 @@
import Navbar from './navbar'
export default Navbar
@@ -1,3 +0,0 @@
import NavigationButtons from './navigation-buttons'
export default NavigationButtons
@@ -1,3 +0,0 @@
import Sidebar from './sidebar'
export default Sidebar
@@ -1,3 +0,0 @@
import ThemeBtn from './theme-btn'
export default ThemeBtn
@@ -1,4 +1,5 @@
import type { ReactNode, JSX } from 'react'
import { TuonoScripts } from 'tuono'
import {
ColorSchemeScript,
@@ -6,15 +7,15 @@ import {
MantineProvider,
AppShell,
Container,
mantineHtmlProps,
type CSSVariablesResolver,
} from '@mantine/core'
import type { CSSVariablesResolver } from '@mantine/core'
import { useDisclosure } from '@mantine/hooks'
import { Head } from 'tuono'
import EditPage from '@/components/edit-page'
import MdxProvider from '@/components/mdx-provider'
import Navbar from '@/components/navbar'
import Sidebar from '@/components/sidebar'
import EditPage from '@/components/EditPage'
import MdxProvider from '@/components/MdxProvider'
import Navbar from '@/components/Navbar'
import Sidebar from '@/components/Sidebar'
import '@mantine/core/styles.css'
import '@mantine/code-highlight/styles.css'
@@ -87,8 +88,8 @@ export default function RootRoute({ children }: RootRouteProps): JSX.Element {
const [opened, { toggle }] = useDisclosure()
return (
<>
<Head>
<html lang="en" {...mantineHtmlProps}>
<head>
<meta charSet="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
@@ -109,28 +110,31 @@ export default function RootRoute({ children }: RootRouteProps): JSX.Element {
href="/favicon-16x16.png"
/>
<link rel="manifest" href="/site.webmanifest" />
</Head>
<ColorSchemeScript />
<MantineProvider theme={theme} cssVariablesResolver={resolver}>
<AppShell
layout="alt"
header={{ height: 60 }}
navbar={{
width: 300,
breakpoint: 'sm',
collapsed: { mobile: !opened },
}}
>
<Navbar toggle={toggle} />
<Sidebar close={toggle} />
<AppShell.Main>
<Container id="mdx-root" component="article" size="md" p={20}>
<MdxProvider>{children}</MdxProvider>
<EditPage />
</Container>
</AppShell.Main>
</AppShell>
</MantineProvider>
</>
<ColorSchemeScript />
</head>
<body>
<MantineProvider theme={theme} cssVariablesResolver={resolver}>
<AppShell
layout="alt"
header={{ height: 60 }}
navbar={{
width: 300,
breakpoint: 'sm',
collapsed: { mobile: !opened },
}}
>
<Navbar toggle={toggle} />
<Sidebar close={toggle} />
<AppShell.Main>
<Container id="mdx-root" component="article" size="md" p={20}>
<MdxProvider>{children}</MdxProvider>
<EditPage />
</Container>
</AppShell.Main>
</AppShell>
</MantineProvider>
<TuonoScripts />
</body>
</html>
)
}
@@ -1,4 +1,4 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Application state"
@@ -6,7 +6,7 @@ import MetaTags from '@/components/meta-tags'
description="Learn how to add features to your Tuono application"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Application state' }]} />
@@ -1,4 +1,4 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - CLI"
@@ -6,7 +6,7 @@ import MetaTags from '@/components/meta-tags'
description="Tuono is the CLI that provides all the needed commands to handle the full-stack project."
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'CLI' }]} />
@@ -1,14 +0,0 @@
import MetaTags from '@/components/meta-tags'
<MetaTags
title="Tuono - Head"
canonical="https://tuono.dev/documentation/components/head"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Components' }]} />
# Head
TODO
@@ -1,14 +1,39 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Link"
canonical="https://tuono.dev/documentation/components/link"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Components' }]} />
# Link
TODO
Tuono provides a `Link` component for clientside navigation between pages of your app. `Link` prefetches pages from any links above the fold, allowing for faster navigations without a full reload.
```typescript jsx
import { Link } from 'tuono'
export default function Page() {
return <Link href="/page2">My Other Page</Link>
}
```
For navigating to pages outside of your app (other websites), you should use the `<a>` tag.
> Additional considerations:
>
> - Any `Link` in the viewport is prefetched by default when it appears within the viewport.
> - The corresponding data for server-rendered routes is fetched only when the `Link` is clicked.
## Reference
The `Link` component behaves similarly to the `<a>` HTML tag, with a few additional features controlled by the following props:
| Prop | Type | Default value | Description |
| --------- | ------------------- | ------------- | ------------------------------------------------------------------------------------------------- |
| `href` | `string` (Required) | - | Relative path to the page in your application. Anchor names (links with hashtags) are also valid. |
| `preload` | `boolean` | `true` | Whether to preload the page if the link is within the viewport. |
| `scroll` | `boolean` | `true` | Whether to preserve scroll position between navigations. |
@@ -1,14 +1,57 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - tuono.config.ts"
canonical="https://tuono.dev/documentation/configuration"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Configuration' }]} />
# Configuration
TODO
Tuono can be configured using the `tuono.config.ts` file,
which allows you to customize various aspects of the build process and development environment.
The config file is written in TypeScript,
so you can take advantage of type checking and auto-suggestions provided by the `TuonoConfig` type,
which is exported from `tuono/config`.
```ts
import type { TuonoConfig } from 'tuono/config'
const config: TuonoConfig = {
/* typesafe config */
}
export default config
```
## vite
Tuono leverages Vite, a modern and fast build tool and development server for web applications.
As a result, **some** Vite configuration properties can be set in the `tuono.config.ts` file under the `vite` property.
### vite.alias
Useful for configuring custom source alias paths during imports
- Type:
- `Record<string, string>`
- `Array<{ find: string | RegExp, replacement: string, customResolver?: ResolverFunction | ResolverObject }>`
- [Vite documentation: resolve.alias](https://vite.dev/config/shared-options#resolve-alias)
### vite.optimizeDeps
Vite's dependency optimizer used only during dev
- [Vite documentation: Dep Optimization Options](https://vite.dev/config/dep-optimization-options)
### vite.plugins
Useful for extending vite's functionality
- Type: `Array<Plugin | Array<Plugin> | Promise<Plugin | Array<Plugin>>`
- [Vite documentation: plugins](https://vite.dev/guide/using-plugins)
@@ -1,4 +1,4 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Contributing"
@@ -6,7 +6,7 @@ import MetaTags from '@/components/meta-tags'
description="The project is massive - if you like it, do consider contributing!"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: '✨ Contributing' }]} />
@@ -1,4 +1,4 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Contributing"
@@ -6,7 +6,7 @@ import MetaTags from '@/components/meta-tags'
description="The project is massive - if you like it, do consider contributing!"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: '✨ Contributing' }]} />
@@ -46,7 +46,7 @@ Without taking into account specific cases, we can mostly split the domain requi
- The documentation website needs just `React` & `Typescript` (or even less, since most of the
code is markdown).
import NavigationButtons from '../../../components/navigation-buttons'
import NavigationButtons from '../../../components/NavigationButtons'
<NavigationButtons
next={{
@@ -1,4 +1,4 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Contributing - Local development"
@@ -6,7 +6,7 @@ import MetaTags from '@/components/meta-tags'
description="Contribute to Tuono. Learn here how to setup the repository for local development"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs
breadcrumbs={[
@@ -30,12 +30,16 @@ git clone https://github.com/<your-name-here>/tuono
cd tuono
```
### Rust tool chain
For the next steps, you can either set up the environment directly on your computer or use a ready-to-use Docker image (go to the [Docker setup](#docker-setup) part).
### Local setup
#### Rust tool chain
Install the Rust programming language tool chain (`rust` and `cargo`).
Follows instructions in the official [docs](https://rustup.rs/)
### Node.js — runtime
#### Node.js — runtime
Install `Node.js`.
You can follow the instructions from the [Node official site](https://nodejs.org/en/download/package-manager)
@@ -50,27 +54,69 @@ You can follow the instructions from the [Node official site](https://nodejs.org
>
> to simply pick up the correct version!
### Node.js — package manager
#### Node.js — package manager
We use [`pnpm`](https://pnpm.io) as Node.js package manager.
You can see which version of yarn we use by checking the `packageManager` field in the root `package.json`.
### Pre-flight checks
#### Pre-flight checks
To check that everything is working properly, run:
```sh
turbo run check-all
pnpm run check-all
cargo build
```
### Docker setup
#### Introduction
Docker takes care of configuring the development environment, so you dont need to worry about installing specific versions of packages like Node.js or pnpm. The Docker image handles this for you!
Using Docker, **the only operations youll need to manage on your host machine are related to git**. (don't use pnpm, cargo, ... from your host machine)
Some IDEs (such as vscode with the [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)) allow you to connect directly to the Docker container.
**Before proceeding with this guide, make sure that the `node_modules` and `target` directories are either absent or empty in the subprojects of Tuono from your host machine where you want to contribute.**
This ensures a clean and consistent environment when using Docker.
#### Build the Tuono's Docker Container
First, ensure Docker is installed on your machine by following the instructions on the [Docker official site](https://docs.docker.com/engine/install/).
Once Docker is installed, use the following command to build the image into a container named tuono-source-container:
```sh
# Note: Execute this command in the project root
docker compose -f docker/compose.yml up --build -d
```
To verify that everything is working as expected, run the following command:
```sh
docker images && docker ps -a --size
```
Or on Windows:
```powershell
docker images; docker ps -a --size
```
You should see the image named tuono-source-image and the container tuono-source-container. The container's status should be "up".
Use the following command to connect to the container:
```sh
docker exec -it tuono-source-container /bin/bash
```
## Tuono development
1. Start tuono frontend build using
```sh
turbo run dev
pnpm run dev
```
2. In another terminal run
@@ -111,3 +157,16 @@ cargo build
> On the documentation remember that `tuono` `npm` package is installed from the registry and
> it is not linked to the repository.
import NavigationButtons from '../../../components/NavigationButtons'
<NavigationButtons
prev={{
title: 'Guidelines',
href: '/documentation/contributing',
}}
next={{
title: 'Pull requests',
href: '/documentation/contributing/pull-requests',
}}
/>
@@ -0,0 +1,86 @@
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Opening a pull request"
canonical="https://tuono.dev/documentation/contributing/pull-requests"
description="Contribute to Tuono. Learn here how to open a pull request."
/>
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs
breadcrumbs={[
{ label: '✨ Contributing', href: '/documentation/contributing' },
{ label: 'Pull Requests' },
]}
/>
# Pull Requests
Once your changes are ready, you can create a PR!
If you are not familiar with GitHub pull requests,
you can check the [official documentation](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request).
---
- If you are fixing an issue, bear in mind to link the issue itself in the PR description.
- If you are adding a new feature, describe the intended use case that the feature fulfills.
> Bug fixes and new features should include tests.
## Title
The PR title must match the following format:
```text
<type>[optional scope]: <short description>
```
You can find commit examples in the [recent commits on main branch](https://github.com/tuono-labs/tuono/commits/main/)
Here are some examples:
- feat: add support for react 19
- ci: create install-node-dependencies action
- feat(packages/tuono-router): use React.Context to pass data
- test(packages/tuono): messageChannel - use vi.fn
> We do not care about the number, or style of commits in your branch history,
> because we squash merge every PR into `main`.
>
> Feel free to commit in whatever style you feel comfortable with.
### type
Must be one of the following
{/* @warning Keep in sync with .github/workflows/pr-title-checker.yml */}
- `docs` - if you only change documentation, and not shipped code
- `feat` - any new functionality additions
- `fix` - any bug fixes that don't add new functionality
- `refactor` - a code change that neither fixes a bug or adds a feature
- `test` - if you only change tests, and not shipped code
- `ci` - if you change something related to continuos integration
- `chore` - anything else (e.g.: release)
### optional scope
A scope may be provided to a commit's type,
to provide additional contextual information and is contained within parenthesis
E.g.: `fix(crates/tuono): remove cargo warnings`
### short description
A succinct title for the PR.
(The title max length is set to 100 characters)
import NavigationButtons from '../../../components/NavigationButtons'
<NavigationButtons
prev={{
title: 'Local development',
href: '/documentation/contributing/local-development',
}}
/>
@@ -1,11 +1,11 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Multithreading"
canonical="https://tuono.dev/documentation/core-concepts/multithreading"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Core concepts' }]} />
@@ -1,14 +1,57 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - useRouter"
canonical="https://tuono.dev/documentation/hooks/use-router"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Hooks' }]} />
<Breadcrumbs breadcrumbs={[{ label: 'useRouter' }]} />
# useRouter
TODO
The `useRouter` hook provides access to various data about the current route, as well as methods to navigate between pages, as seen in the below example:
```tsx
import { JSX } from 'react'
import { useRouter } from 'tuono'
export default function IndexPage(): JSX.Element {
const router = useRouter()
return (
<>
<p>pathname: {router.pathname}</p>
<button
onClick={() => {
router.push('/foo')
}}
>
My link
</button>
</>
)
}
```
## `useRouter` result
- `pathname`: `string` - Returns the current path name
- `query`: `Record<string, string>` - This object contains all the query params of the current route
The following methods are included inside `router`:
### `router.push`
Handles client side page navigation quickly. Useful for internal links, or for when you need to change url in some JS.
```ts
router.push(path, options)
```
| Name | Type | Default value | Description |
| ---------------- | ------------------- | ------------- | ----------------------------------------------------------------- |
| `path` | `string` (Required) | - | The path of the page you want to navigate to. |
| `options` | `PushOptions` | - | Optional config object for additional control. |
| `options.scroll` | `boolean` | `true` | If `false` the scroll offset will be kept across page navigation. |
@@ -1,11 +1,11 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - tuono.config.ts"
canonical="https://tuono.dev/documentation/how-is-tuono-different"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'How is tuono different?' }]} />
@@ -1,6 +1,4 @@
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Installation"
@@ -8,6 +6,8 @@ import MetaTags from '@/components/meta-tags'
description="Tuono is a development environment built in rust and typescript that outputs a website written in both the languages"
/>
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Installation' }]} />
# Installation
@@ -1,11 +1,11 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - MDX"
canonical="https://tuono.dev/documentation/integrations/mdx"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Integrations' }]} />
@@ -1,11 +1,11 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Server side rendering"
canonical="https://tuono.dev/documentation/rendering/server-side-rendering"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Rendering' }]} />
@@ -1,11 +1,11 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Static site rendering"
canonical="https://tuono.dev/documentation/rendering/static-site-rendering"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Rendering' }]} />
@@ -1,11 +1,11 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Routing"
canonical="https://tuono.dev/documentation/routing/defining-routes"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Defining routes' }]} />
@@ -54,7 +54,7 @@ then it will be accessible at `posts/1`, `posts/2`, etc.
## The Root route (Layout components)
Tuono allows you to have a layout component to wrap all the routes included within the same folder.
To define such component you will have to create a `__root.tsx` file (is allowed only a single `__root` file per folder).
To define such component you will have to create a `__layout.tsx` file (is allowed only a single `__layout` file per folder).
This file won't generate any route.
@@ -63,7 +63,7 @@ This file won't generate any route.
A file created in this location will wrap all project route.
```tsx
// src/routes/__root.tsx
// src/routes/__layout.tsx
export default function RootLayout({ children }) {
return <main>{children}</main>
}
@@ -74,8 +74,8 @@ export default function RootLayout({ children }) {
A file created in this location will wrap only the routes defined within the `src/routes/posts` folder.
```tsx
// src/routes/posts/__root.tsx
export default function PostRootLayout({ children }) {
// src/routes/posts/__layout.tsx
export default function PostLayout({ children }) {
return <article>{children}</article>
}
```
@@ -86,9 +86,9 @@ Referring to the two examples above consider that:
```tsx
<RootLayout>
<PostRootLayout>
<PostLayout>
<ExamplePost />
</PostRootLayout>
</PostLayout>
</RootLayout>
```
@@ -1,14 +1,61 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Routing"
canonical="https://tuono.dev/documentation/routing/dynamic-routes"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Dynamic routes' }]} />
# Loading state
# Dynamic routes
Todo
> 🚧 Only available for SSR apps. This feature will be soon available also for static generated apps.
When the exact segment names are not known in advance and you need to generate routes from dynamic data,
you can use dynamic segments, which are populated at request time.
## Convention
A dynamic segment can be created by wrapping a
file or a folder name in square brackets: `[segmentName]`.
The dynamic segment can be used in folders as well as file names:
- `src/routes/blog/[slug].tsx`
- `src/routes/blog/[slug]/index.tsx`
A path can contain multiple dynamic segments, allowing for more flexible routing:
- `src/routes/blog/[post]/[comment].tsx`
### Example
Assuming you're working on a blog with multiple posts,
you can use a dynamic segment to define the post page: `src/routes/blog/[slug].tsx`.
The `[slug]` is the dynamic segment which will be used to identify individual blog posts.
```tsx
import { useRouter } from 'tuono'
export default function Page() {
const router = useRouter()
return <p>Post: {router.pathname}</p>
}
```
## Catch all segments
Dynamic Segments can be extended to catch-all subsequent segments by adding
an ellipsis inside the brackets `[...segmentName]`.
Given the following `src/routes/shop/[...slug].tsx`,
the following paths will be matched:
- `/shop/clothes`
- `/shop/clothes/tops`
- `/shop`
- `/shop/clothes/tops/t-shirts`
- and so on.
@@ -1,11 +1,11 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Routing"
canonical="https://tuono.dev/documentation/routing/intro"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Routing' }]} />
@@ -1,11 +1,11 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Routing"
canonical="https://tuono.dev/documentation/routing/layouts"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Layouts' }]} />
@@ -1,11 +1,11 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Routing"
canonical="https://tuono.dev/documentation/routing/link-and-navigation"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Link and navigation' }]} />
@@ -16,7 +16,16 @@ The Tuono router facilitates client-side route transitions between pages, enhanc
- Enabling smooth navigation in single-page applications (SPAs)
- Preventing page reloads during site navigation
How? Using the `Link` component provided from Tuono exports:
Tuono provides two choices for navigation between pages of your app:
- The `Link` component - used in place of an `<a>` tag
- The `useRouter` hook - used to programmatically change routes, or to access data about the current route
Use the `<a>` tag for navigating to other websites.
## The `Link` component
Tuono delivers this experience to users with the `Link` component provided from Tuono exports:
```tsx
import { Link } from 'tuono'
@@ -44,17 +53,14 @@ The example above uses multiple links. Each one maps a path (`href`) to a known
- `/about` → `src/routes/about.tsx`
- `/blog/hello-world` → `src/routes/blog/[slug].tsx`
> Additional considerations:
>
> - Any `<Link />` in the viewport is prefetched by default when it appears within the viewport.
> - The corresponding data for server-rendered routes is fetched only when the `<Link />` is clicked.
> For more information about this component visit the [Link component API reference page](/documentation/components/link).
## The `useRouter` hook
The Link component is not suitable for programmatic navigation.
To handle this, the library provides the `useRouter` hook.
For example, after a user submits a form and the API request succeeds, they can be redirected to another page.
For example, after a user submits a form and the API request succeeds, they can be redirected to another page:
```tsx
import { useRouter } from 'tuono'
@@ -72,4 +78,4 @@ export default function GoToAboutPage() {
}
```
> For more information about this hook visit the [dedicated API reference page](/documentation/hooks/use-router).
> For more information about this hook visit the [useRouter API reference page](/documentation/hooks/use-router).

Some files were not shown because too many files have changed in this diff Show More