diff --git a/docs/src/components/EditPage.jsx b/docs/src/components/EditPage.jsx new file mode 100644 index 0000000..3042474 --- /dev/null +++ b/docs/src/components/EditPage.jsx @@ -0,0 +1,26 @@ +import { pages } from "../pages.mjs"; + +export default function EditPage({ pathname }) { + const filename = + pathname.split("/").length > 3 + ? pages + .find(([filename]) => + filename.includes(pathname.replace("/en", "/en/(pages)")) + )?.[0] + ?.replace(/^\.\//, "/") ?? "" + : pathname === "/en/team" + ? "/pages/en/(pages)/team/index.mdx" + : pathname === "/en" + ? "/pages/en/index.mdx" + : `/pages${pathname}.(index).mdx`; + return ( + + Edit this page + + ); +} diff --git a/docs/src/mdx-components.jsx b/docs/src/mdx-components.jsx index 25c6860..1fa13a7 100644 --- a/docs/src/mdx-components.jsx +++ b/docs/src/mdx-components.jsx @@ -7,7 +7,7 @@ export default function useMDXComponents() { return (
{filename && ( -+{filename})} diff --git a/docs/src/pages.mjs b/docs/src/pages.mjs index e8f06ee..df7723c 100644 --- a/docs/src/pages.mjs +++ b/docs/src/pages.mjs @@ -10,6 +10,7 @@ export const pages = Array.from( export const categories = [ "Guide", + "Integrations", "Framework", "Router", "Deploy", diff --git a/docs/src/pages/(root).layout.jsx b/docs/src/pages/(root).layout.jsx index b92d4de..a8dc8d0 100644 --- a/docs/src/pages/(root).layout.jsx +++ b/docs/src/pages/(root).layout.jsx @@ -5,6 +5,7 @@ import { cookie, usePathname } from "@lazarv/react-server"; import { Analytics } from "@vercel/analytics/react"; import { SpeedInsights } from "@vercel/speed-insights/react"; +import EditPage from "../components/EditPage.jsx"; export default function Layout({ breadcrumb, header, @@ -75,6 +76,7 @@ export default function Layout({ {sidebar}{breadcrumb} + diff --git a/docs/src/pages/@breadcrumb/[[lang]]/[category]/(breadcrumb).[...slug].page.jsx b/docs/src/pages/@breadcrumb/[[lang]]/[category]/(breadcrumb).[...slug].page.jsx index b09d840..ba5ae73 100644 --- a/docs/src/pages/@breadcrumb/[[lang]]/[category]/(breadcrumb).[...slug].page.jsx +++ b/docs/src/pages/@breadcrumb/[[lang]]/[category]/(breadcrumb).[...slug].page.jsx @@ -5,7 +5,7 @@ export default function Breadcrumb({ lang, category }) { {category} → diff --git a/docs/src/pages/@header/[[lang]]/(header).[[...slug]].page.jsx b/docs/src/pages/@header/[[lang]]/(header).[[...slug]].page.jsx index d9e810f..d8779da 100644 --- a/docs/src/pages/@header/[[lang]]/(header).[[...slug]].page.jsx +++ b/docs/src/pages/@header/[[lang]]/(header).[[...slug]].page.jsx @@ -33,6 +33,12 @@ export default function Header({ lang }) { > Guide + + Integrations + Tutorials Team diff --git a/docs/src/pages/en/(pages)/integrations/mantine.mdx b/docs/src/pages/en/(pages)/integrations/mantine.mdx new file mode 100644 index 0000000..8e64db7 --- /dev/null +++ b/docs/src/pages/en/(pages)/integrations/mantine.mdx @@ -0,0 +1,12 @@ +--- +title: Mantine UI +category: Integrations +order: 5 +--- + +import Link from "../../../../components/Link.jsx"; + +# Mantine UI + +> Coming soon. + diff --git a/docs/src/pages/en/(pages)/integrations/mui.mdx b/docs/src/pages/en/(pages)/integrations/mui.mdx new file mode 100644 index 0000000..ebfc1fa --- /dev/null +++ b/docs/src/pages/en/(pages)/integrations/mui.mdx @@ -0,0 +1,12 @@ +--- +title: Material UI +category: Integrations +order: 6 +--- + +import Link from "../../../../components/Link.jsx"; + +# Material UI + +> Coming soon. + diff --git a/docs/src/pages/en/(pages)/integrations/react-query.mdx b/docs/src/pages/en/(pages)/integrations/react-query.mdx new file mode 100644 index 0000000..be2a65d --- /dev/null +++ b/docs/src/pages/en/(pages)/integrations/react-query.mdx @@ -0,0 +1,12 @@ +--- +title: TanStack Query +category: Integrations +order: 4 +--- + +import Link from "../../../../components/Link.jsx"; + +# TanStack Query + +> Coming soon. + diff --git a/docs/src/pages/en/(pages)/integrations/tailwind-css.mdx b/docs/src/pages/en/(pages)/integrations/tailwind-css.mdx new file mode 100644 index 0000000..ec46abd --- /dev/null +++ b/docs/src/pages/en/(pages)/integrations/tailwind-css.mdx @@ -0,0 +1,81 @@ +--- +title: Tailwind CSS +category: Integrations +order: 2 +--- + +import Link from "../../../../components/Link.jsx"; + +# Tailwind CSS + +`@lazarv/react-server` is compatible with Tailwind CSS. You can use Tailwind CSS the same way you use it in a standard React project with Vite, using the PostCSS and Autoprefixer plugins. + + +## Install + + +You can install Tailwind CSS in your project by running the following command: + +```sh +pnpm add -D tailwindcss postcss autoprefixer +pnpm dlx tailwindcss init +``` + +Add Tailwind CSS to your `postcss.config.js` file: + +```js filename="./postcss.config.js" +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + } +}; +``` + +Configure your template paths in the `tailwind.config.js` file: + +```js filename="./tailwind.config.js" +module.exports = { + content: [ + "./src/**/*.{js,jsx,ts,tsx}", + ], + theme: { + extend: {}, + }, + plugins: [], +}; +``` + +Update or extend the `content` array in the `tailwind.config.js` file to include the paths to your components, pages, and other files including Tailwind CSS classes. + +Add the following lines to your `main.css` file: + +```css filename="./main.css" +@tailwind base; +@tailwind components; +@tailwind utilities; +``` + + +## Use Tailwind CSS + + +You can now use Tailwind CSS in any of your React Server Components or client components. + +```tsx filename="./src/pages/index.tsx" +export default function HomePage() { + return{children} {navigation} Hello World
; +} +``` + +You don't need to do anything more. Start your development server and you can see the styles applied. + +```sh +pnpm exec react-server +``` + +Your styles will be also applied during a production build. + +```sh +pnpm exec react-server build +``` diff --git a/docs/src/pages/en/(pages)/integrations/typescript.mdx b/docs/src/pages/en/(pages)/integrations/typescript.mdx new file mode 100644 index 0000000..0c13adf --- /dev/null +++ b/docs/src/pages/en/(pages)/integrations/typescript.mdx @@ -0,0 +1,82 @@ +--- +title: TypeScript +category: Integrations +order: 1 +--- + +import Link from "../../../../components/Link.jsx"; + +# TypeScript + +`@lazarv/react-server` is compatible with TypeScript. You can use TypeScript normally like in any other React project. TypeScript just works with this framework as it is relying on Vite and Esbuild to transpile the code. + + +## Configuration + + +You can keep all the TypeScript configuration in the `tsconfig.json` file. You can follow the [TypeScript configuration guide](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) to configure TypeScript. + +A basic example of `tsconfig.json` file to use with `@lazarv/react-server`: + +```json filename="./tsconfig.json" +{ + "compilerOptions": { + "strict": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "jsx": "preserve", + "types": ["react/experimental", "react-dom/experimental"], + "allowSyntheticDefaultImports": true, + "baseUrl": "./src", + "paths": { + "@/*": ["./*"] + } + }, + "include": ["**/*.ts", "**/*.tsx", ".react-server/**/*.ts"], + "exclude": ["**/*.js", "**/*.mjs"] +} +``` + +The important part is to use the `react/experimental` and `react-dom/experimental` types for React as `@lazarv/react-server` uses the experimental React APIs. + + +## Type-safe file-system based routing + + +`@lazarv/react-server` uses the file-system based routing. This means that the file-system is the source of truth for the routing. When you create a new file, you create a new route. + +This is a very powerful feature, but it can be hard to work with if you are using TypeScript. `@lazarv/react-server` has a built-in feature to help you with this. + +By including the `.react-server` directory in the `tsconfig.json` file, you can use TypeScript to type the file-system based routing. + + +## TypeScript path aliases + + +To make the TypeScript path aliases work, you need to include the `baseUrl` and `paths` in the `tsconfig.json` file. + +```json filename="./tsconfig.json" +{ + "compilerOptions": { + "baseUrl": "./src", + "paths": { + "@/*": ["./*"] + } + } +} +``` + +While you also need to include the paths in your `vite.config.js` file as `resolve.alias` entries to make the path aliases work. + +```js filename="./vite.config.mjs" +import { defineConfig } from 'vite'; + +export default defineConfig({ + resolve: { + alias: { + '@/': new URL('./src/', import.meta.url).pathname + } + } +}); +``` diff --git a/docs/src/pages/en/(pages)/integrations/vite.mdx b/docs/src/pages/en/(pages)/integrations/vite.mdx new file mode 100644 index 0000000..3329b69 --- /dev/null +++ b/docs/src/pages/en/(pages)/integrations/vite.mdx @@ -0,0 +1,176 @@ +--- +title: Vite +category: Integrations +order: 0 +--- + +import Link from "../../../../components/Link.jsx"; + +# Vite + +`@lazarv/react-server` is not just compatible with Vite, but it's also built on top of the Vite Environment API. This means that you can use all the features of Vite and many Vite plugins with `@lazarv/react-server` without any issues. + + +## Configuration + + +You can keep all the Vite configuration in the `vite.config.js`, `vite.config.ts`, `vite.config.mjs` or `vite.config.cjs` file. You can follow the [Vite configuration guide](https://vitejs.dev/config/) to configure Vite. + + +## Plugins + + +You can use all the Vite plugins in your project. You can follow the [Vite plugins guide](https://vitejs.dev/plugins/) to learn more about Vite plugins. + +When using Vite plugins, expect three environments: + +- [ ] `rsc` - when the plugin is used in React Server Components (RSC payload) +- [ ] `ssr` - when the plugin is used in server-side rendering (HTML output) +- [ ] `client` - when the plugin is used in client components + + +## Migration + + +If you are migrating from Vite to `@lazarv/react-server`, you can follow this guide to migrate your project. + +### Getting started + +Starting a new Vite + React app is easy: + +```sh +pnpm create vite my-react-app --template react +``` + +Then you just need to change directory, install dependencies and start your app: + +```sh +cd my-react-app +pnpm install +pnpm dev +``` + +It just works! + +### React Server Components + +As we want to use RSCs, let's move everything from the `index.html` into `src/main.jsx` and instead of rendering `App` on the client-side, just use it as a component in this RSC layout: + +```jsx +import App from "./App.jsx"; +import "./index.css"; + +export default function Html() { + return ( + + + + + +Vite + React + + +++ + + ); +} +``` + +Beware that you need to fix `charSet` as it has a different casing when used in JSX than in HTML! + +For now, just add a `"use client";` directive to `App.jsx` to make it work instantly as the App component includes a `useState` React hook. + +Now let's uninstall `react` and `react-dom` as we will not need them, both were just React 18. Now we need to install `@lazarv/react-server`: + +```sh +pnpm add @lazarv/react-server@latest +``` + +Update npm scripts on how to start our app: + +```json +"scripts": { + "dev": "react-server ./src/main.jsx", + "build": "react-server build ./src/main.jsx", + "lint": "eslint .", + "start": "react-server start" +} +``` + +Let's start our app using `pnpm dev --open`! + +### Optimizing client components + +In the current state of our app, the whole `App` component is a client component. This is not ideal, as only the counter part is interactive in it. We also attached some CSS to this client component which will only be loaded when the client component loads in the browser at runtime. This is causing a glitch for a blink of an eye at page load. + +Let's create a new `Counter` component in a new file at `src/Counter.jsx` and move the counter button into this new component: + +```jsx +"use client"; + +import { useState } from "react"; + +function Counter() { + const [count, setCount] = useState(0); + + return ( + + ); +} + +export default Counter; +``` + +Now let's get back to the `App` component, remove the `"use client";` directive, remove the `App.css` import and the code which was only part of the `Counter` component, but import it instead: + +```jsx +import reactLogo from "./assets/react.svg"; +import viteLogo from "/vite.svg"; +import Counter from "./Counter.jsx"; + +function App() { + return ( + <> + ++ Vite + React
++++ + Edit
+src/App.jsx
and save to test HMR ++ Click on the Vite and React logos to learn more +
+ > + ); +} + +export default App; +``` + +The easiest resolution of the CSS issue is to import `App.css` in `main.jsx`: + +```jsx +import App from "./App.jsx"; +import "./index.css"; +import "./App.css"; + +export default function Html() { + // we don't need to do any change here +} +``` + +Now both CSS files will be loaded instantly on page load and there will be no flickering. The counter button will still work as before as we refactored it to be a new client component. Every other part of the `App` component was static, which is best to be included in RSCs. You can also combine the 2 CSS files as there's no reason why we have two, just fix the CSS imports in the `main.jsx` after that. diff --git a/docs/src/pages/en/integrations.(index).mdx b/docs/src/pages/en/integrations.(index).mdx new file mode 100644 index 0000000..f8df294 --- /dev/null +++ b/docs/src/pages/en/integrations.(index).mdx @@ -0,0 +1,11 @@ +# Integrations + +In this section you will find guides on how to integrate `@lazarv/react-server` with different tools and third-party libraries. + +`@lazarv/react-server` is built on top of [Vite](/integrations/vite), so most of the integrations that are available for Vite are also available for this framework too. You are not just able to use the same configuration for both Vite and `@lazarv/react-server`, but you are also able to use any Vite plugins in your project. You can also learn how to [migrate](/integrations/vite#migration) an existing Vite React project to use server-side rendering capabilities. + +When you want to use TypeScript or Tailwind CSS with `@lazarv/react-server`, you can learn how to configure [TypeScript](/integrations/typescript) and how to install and configure [Tailwind CSS](/integrations/tailwind-css) to work with this framework. + +You can also learn in this section how to integrate third-party libraries like [TanStack Query](/integrations/react-query), [Mantine UI](/integrations/mantine) and [Material UI](/integrations/mui) with `@lazarv/react-server`. + +> More guides will be added here soon, so check back later. diff --git a/docs/src/pages/global.css b/docs/src/pages/global.css index 2b10326..71a78b6 100644 --- a/docs/src/pages/global.css +++ b/docs/src/pages/global.css @@ -139,6 +139,7 @@ article { justify-items: left; overflow: auto; view-transition-name: content; + position: relative; @media (prefers-reduced-motion) { view-transition-name: none;