Compare commits

...

41 Commits

Author SHA1 Message Date
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
189 changed files with 1247 additions and 6220 deletions
+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
-->
+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
+4 -2
View File
@@ -9,12 +9,14 @@ on:
branches:
- 'main'
paths:
- '.github/**'
- '*'
- '.github/**'
- '.docker/**'
pull_request:
paths:
- '.github/**'
- '*'
- '.github/**'
- '.docker/**'
jobs:
build-and-test:
+1 -1
View File
@@ -1 +1 @@
22.11.0
22.13.0
+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)
+1 -2
View File
@@ -9,6 +9,5 @@ exclude = [
"apps/documentation",
"examples/with-mdx",
"examples/tuono-app",
"examples/tuono-tutorial",
"benches/tuono"
"examples/tuono-tutorial"
]
+1 -1
View File
@@ -48,7 +48,7 @@ by Tuono based on the files defined within the `./src/routes` directory.
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)).
(check the benchmarks [here](https://github.com/tuono-labs/tuono-benchmarks)).
## Getting started
+1 -1
View File
@@ -25,7 +25,7 @@
"@mdx-js/rollup": "3.1.0",
"@types/react": "18.3.18",
"@types/react-dom": "18.3.5",
"postcss": "8.4.49",
"postcss": "8.5.0",
"postcss-preset-mantine": "1.17.0",
"postcss-simple-vars": "7.0.1"
}
@@ -1,49 +1,54 @@
import type { JSX } from 'react'
import { Breadcrumbs, Button } from '@mantine/core'
import { useMemo, type JSX } from 'react'
import { Breadcrumbs as MantineBreadcrumbs, Button } from '@mantine/core'
import { Link, Head } from 'tuono'
import { IconChevronRight, IconBolt } from '@tabler/icons-react'
interface Breadcrumb {
interface BreadcrumbData {
href?: string
label: string
}
interface BreadcrumbsProps {
breadcrumbs: Array<Breadcrumb>
breadcrumbs: Array<BreadcrumbData>
}
export default function TuonoBreadcrumbs({
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 (
<>
<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(',')}]
}
`}
{JSON.stringify(ldJson, null, 2)}
</script>
</Head>
<Breadcrumbs
<MantineBreadcrumbs
separator={<IconChevronRight size="1.1rem" stroke={1.5} />}
mb="md"
mt="md"
@@ -54,7 +59,7 @@ export default function TuonoBreadcrumbs({
{breadcrumbs.map((br) => (
<BreadcrumbElement href={br.href} label={br.label} key={br.label} />
))}
</Breadcrumbs>
</MantineBreadcrumbs>
</>
)
}
@@ -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,12 @@
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'
interface MdxProviderProps {
children: ReactNode
@@ -0,0 +1,3 @@
import MdxQuote from './MdxQuote'
export default MdxQuote
@@ -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
@@ -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
@@ -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
@@ -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 {
@@ -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()
@@ -0,0 +1,3 @@
import ThemeBtn from './ThemeBtn'
export default ThemeBtn
@@ -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
+4 -4
View File
@@ -11,10 +11,10 @@ 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'
@@ -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,11 +1,11 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Head"
canonical="https://tuono.dev/documentation/components/head"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Components' }]} />
@@ -1,14 +1,37 @@
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:
- `href`: `string` (Required) - Relative path to the page in your application. Anchor names (links with hashtags) are also valid.
- `preload`: `boolean` (Defaults to `true`) - Whether to preload the page if the link is within the viewport.
- `scroll`: `boolean` (Defaults to `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,13 +54,13 @@ 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:
@@ -65,6 +69,48 @@ 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
@@ -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,50 @@
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' }]} />
# 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:
```typescript jsx
import { useRouter } from 'tuono'
export default function IndexPage() {
const router = useRouter()
return (
<>
<p>pathname: {router.pathname}</p>
<button onClick={() => router.push("/foo")}>
My link
</button>
</>
)
}
```
## `router` object
- `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)
```
- `path`: `string` - The path of the page you want to navigate to
- `options`: `PushOptions` - Optional config object for additional control
- `scroll`: `boolean` - If `false` the scroll offset will be kept across page navigation. Default `true`
@@ -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' }]} />
@@ -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/dynamic-routes"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Dynamic routes' }]} />
@@ -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).
@@ -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/loading-state"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Loading state' }]} />
@@ -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/pages"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Pages' }]} />
@@ -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/redirecting"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Redirecting' }]} />
@@ -1,11 +1,11 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - CSS Modules"
canonical="https://tuono.dev/documentation/styles/css-modules"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Styles' }]} />
@@ -1,4 +1,4 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - API fetching"
@@ -6,7 +6,7 @@ import MetaTags from '@/components/meta-tags'
description="Learn how to fetch remote APIs on the backend"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs
breadcrumbs={[
@@ -178,7 +178,7 @@ export default function IndexPage({
Refresh the browser now! A bit ugly, but all the Pokémon are finally printed on screen!
import NavigationButtons from '../../../components/navigation-buttons'
import NavigationButtons from '../../../components/NavigationButtons'
<NavigationButtons
prev={{
@@ -1,4 +1,4 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Components"
@@ -6,7 +6,7 @@ import MetaTags from '@/components/meta-tags'
description="Learn how to manage the components in a Tuono codebase"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs
breadcrumbs={[
@@ -134,7 +134,7 @@ export default function PokemonLink({
}
```
import NavigationButtons from '../../../components/navigation-buttons'
import NavigationButtons from '../../../components/NavigationButtons'
<NavigationButtons
prev={{ title: 'API fetching', href: '/documentation/tutorial/api-fetching' }}
@@ -1,4 +1,4 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Conclusion"
@@ -6,7 +6,7 @@ import MetaTags from '@/components/meta-tags'
description="You just created a multi thread full stack application with Rust and React"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs
breadcrumbs={[
@@ -27,7 +27,7 @@ at [valerioageno@yahoo.it](mailto:valerioageno@yahoo.it) or in Twitter (X) DMs [
Ciao
import NavigationButtons from '../../../components/navigation-buttons'
import NavigationButtons from '../../../components/NavigationButtons'
<NavigationButtons
prev={{
@@ -1,4 +1,4 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Development setup"
@@ -6,7 +6,7 @@ import MetaTags from '@/components/meta-tags'
description="Learn how to setup a new Tuono project"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs
breadcrumbs={[
@@ -69,7 +69,7 @@ The first time might take a little bit because it will install all the Rusts
Then open [http://localhost:3000/](http://localhost:3000) on the browser.
import NavigationButtons from '../../../components/navigation-buttons'
import NavigationButtons from '../../../components/NavigationButtons'
<NavigationButtons
prev={{ title: 'Tutorial', href: '/documentation/tutorial' }}
@@ -1,4 +1,4 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Dynamic routes"
@@ -6,7 +6,7 @@ import MetaTags from '@/components/meta-tags'
description="Learn how to catch more endpoint with the same route loading dynamic data"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs
breadcrumbs={[
@@ -163,7 +163,7 @@ export default function PokemonView({
}
```
import NavigationButtons from '../../../components/navigation-buttons'
import NavigationButtons from '../../../components/NavigationButtons'
<NavigationButtons
prev={{ title: 'Components', href: '/documentation/tutorial/components' }}
@@ -1,4 +1,4 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Error handling"
@@ -6,7 +6,7 @@ import MetaTags from '@/components/meta-tags'
description="Learn how to handle the server side error on your Tuono project"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs
breadcrumbs={[
@@ -105,7 +105,7 @@ async fn get_all_pokemons(_req: Request, fetch: Client) -> Response {
If you now try to load a not-existing Pokémon (`http://localhost:3000/pokemons/tuono-pokemon`) you will
correctly receive a 404 status code in the console.
import NavigationButtons from '../../../components/navigation-buttons'
import NavigationButtons from '../../../components/NavigationButtons'
<NavigationButtons
prev={{
@@ -1,4 +1,4 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Tutorial"
@@ -6,7 +6,7 @@ import MetaTags from '@/components/meta-tags'
description="This tutorial is meant to give you a sneak peek at the framework and is intended to evolve during the development - be sure to have installed the latest version"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs breadcrumbs={[{ label: 'Tutorial' }]} />
@@ -27,7 +27,7 @@ $ tuono new tutorial --template tuono-tutorial
> I'd love to hear your thoughts about the framework and the tutorial - feel free to reach me at [valerioageno@yahoo.it](mailto:valerioageno@ahoo.it)
> or on Twitter (X) DM [@valerioageno](https://twitter.com/valerioageno)
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 - Building for production"
@@ -6,7 +6,7 @@ import MetaTags from '@/components/meta-tags'
description="Learn how to build the production project and run the optimize version"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs
breadcrumbs={[
@@ -36,7 +36,7 @@ optimizations ready to unleash the power of a rust server that seamlessly render
> Note: The `out` directory is not standalone. You can't rely just on it to run the production server.
import NavigationButtons from '../../../components/navigation-buttons'
import NavigationButtons from '../../../components/NavigationButtons'
<NavigationButtons
prev={{
@@ -1,4 +1,4 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - Redirection"
@@ -6,7 +6,7 @@ import MetaTags from '@/components/meta-tags'
description="Learn how to redirect to different route from the server"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs
breadcrumbs={[
@@ -50,7 +50,7 @@ Now let's create the button in the home page to actually point to it!
Now at [http://localhost:3000/](http:/localhost:3000/) You will find a new link at the beginning of the list.
Click on it and see the application automatically redirecting you to your favourite pokemon's route!
import NavigationButtons from '../../../components/navigation-buttons'
import NavigationButtons from '../../../components/NavigationButtons'
<NavigationButtons
prev={{ title: 'SEO and meta tags', href: '/documentation/tutorial/seo' }}
@@ -1,4 +1,4 @@
import MetaTags from '@/components/meta-tags'
import MetaTags from '@/components/MetaTags'
<MetaTags
title="Tuono - SEO and meta tags"
@@ -6,7 +6,7 @@ import MetaTags from '@/components/meta-tags'
description="Learn how to handle meaningful meta tags for your Tuono project"
/>
import Breadcrumbs, { Element } from '@/components/breadcrumbs'
import Breadcrumbs from '@/components/Breadcrumbs'
<Breadcrumbs
breadcrumbs={[
@@ -21,14 +21,14 @@ The website now works and the HTTP errors are meaningful, but we should also tak
for the web crawlers. The best way to do it is to enrich the meta tags like the `<title>` and the
`<description>`.
To do so `tuono` also exposes the `<Head />` component useful exactly for handling this scenario. Let's update the `/` and the
To do so `tuono` fully supports [React19
tags](https://react.dev/reference/react-dom/components/title). Let's update the `/` and the
`/pokemons/[pokemon]` routes with this.
```diff
// src/routes/index.tsx
import type { JSX } from 'react'
import type { TuonoProps } from "tuono";
++ import { Head } from "tuono"
interface Pokemon {
name: string
@@ -47,9 +47,8 @@ export default function IndexPage({
return (
<>
++ <Head>
++ <title>Tuono tutorial</title>
++ </Head>
++ <title>Tuono tutorial</title>
<header className="header">
<a href="https://crates.io/crates/tuono" target="_blank">
Crates
@@ -82,26 +81,21 @@ export default function IndexPage({
```diff
// src/routes/pokemons/[pokemon].tsx
import type { JSX } from 'react'
-- import { TuonoProps } from "tuono";
++ import { TuonoProps, Head } from "tuono";
import { TuonoProps } from "tuono";
import PokemonView from "../../components/PokemonView";
export default function Pokemon({ data }: TuonoProps): JSX.Element {
-- return <PokemonView pokemon={data} />;
++ return (
++ <>
++ <Head>
++ <title>Pokemon: ${data?.name}</title>
++ </Head>
++ <title>Pokemon: ${data?.name}</title>
++ <PokemonView pokemon={data} />
++ </>
++ )
}
```
The `Head` component takes as children any valid HTML meta tag.
import NavigationButtons from '../../../components/navigation-buttons'
import NavigationButtons from '../../../components/NavigationButtons'
<NavigationButtons
prev={{

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