1
1
mirror of https://github.com/theoludwig/theoludwig.git synced 2025-05-20 21:13:43 +02:00

build: update to Node.js v24.0.0, pnpm v10, Tailwind CSS v4

This commit is contained in:
Théo LUDWIG 2025-05-11 16:59:11 +02:00
parent cec70161f7
commit 69af1bccc3
Signed by: theoludwig
GPG Key ID: ADFE5A563D718F3B
43 changed files with 3941 additions and 3664 deletions

View File

@ -9,3 +9,6 @@ end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
indent_size = 4

View File

@ -24,7 +24,7 @@ jobs:
- name: "Setup Node.js"
uses: "actions/setup-node@v4.2.0"
with:
node-version: "22.x"
node-version: "24.x"
cache: "pnpm"
- name: "Install dependencies"

View File

@ -22,7 +22,7 @@ jobs:
- name: "Setup Node.js"
uses: "actions/setup-node@v4.2.0"
with:
node-version: "22.x"
node-version: "24.x"
cache: "pnpm"
- name: "Install dependencies"

View File

@ -1,4 +1,4 @@
import relativeLinksRule from "markdownlint-rule-relative-links"
import relativeLinksRule, { markdownIt } from "markdownlint-rule-relative-links"
const config = {
config: {
@ -11,6 +11,9 @@ const config = {
globs: ["**/*.md"],
ignores: ["**/node_modules"],
customRules: [relativeLinksRule],
markdownItFactory: () => {
return markdownIt
},
}
export default config

View File

@ -6,7 +6,6 @@
"davidanson.vscode-markdownlint",
"bradlc.vscode-tailwindcss",
"mikestead.dotenv",
"ms-azuretools.vscode-docker",
"antfu.pnpm-catalog-lens",
"Lokalise.i18n-ally"
]

View File

@ -31,8 +31,8 @@ The commit message guidelines adheres to [Conventional Commits](https://www.conv
### Prerequisites
- [Node.js](https://nodejs.org/) >= 22.12.0 [(`nvm install 22`)](https://nvm.sh)
- [pnpm](https://pnpm.io/) >= 10.2.1 [(`corepack enable`)](https://nodejs.org/docs/latest-v22.x/api/corepack.html)
- [Node.js](https://nodejs.org/) >= v24.0.0 [(`nvm install 24`)](https://nvm.sh)
- [pnpm](https://pnpm.io/) v10.10.0 [(`npm install --global corepack@0.32.0 && corepack enable`)](https://github.com/nodejs/corepack)
- [Docker](https://www.docker.com/)
### Installation

View File

@ -21,17 +21,28 @@
```json
{
"name": "Théo LUDWIG",
"pronouns": "He/Him",
"birthDate": "2003-03-31",
"nationality": "Alsace, France",
"interests": ["Developer Full Stack", "Open-Source Enthusiast"],
"skills": {
"programmingLanguages": ["JavaScript/TypeScript", "Python", "C/C++", "PHP"],
"frontend": ["HTML/CSS", "Tailwind CSS", "React.js/Next.js"],
"backend": ["Laravel", "Node.js", "Fastify", "PostgreSQL"],
"tools": ["GNU/Linux", "Arch Linux", "Visual Studio Code", "Git", "Docker"]
}
"name": "Théo LUDWIG",
"pronouns": "He/Him",
"birthDate": "2003-03-31",
"nationality": "Alsace, France",
"interests": ["Developer Full Stack", "Open-Source Enthusiast"],
"skills": {
"programmingLanguages": [
"JavaScript/TypeScript",
"Python",
"C/C++",
"PHP"
],
"frontend": ["HTML/CSS", "Tailwind CSS", "React.js/Next.js"],
"backend": ["Laravel", "Node.js", "Fastify", "PostgreSQL"],
"tools": [
"GNU/Linux",
"Arch Linux",
"Visual Studio Code",
"Git",
"Docker"
]
}
}
```

View File

@ -0,0 +1,5 @@
{
"plugins": {
"@tailwindcss/postcss": {}
}
}

View File

@ -51,6 +51,7 @@
"storybook-dark-mode": "catalog:",
"postcss": "catalog:",
"tailwindcss": "catalog:",
"@tailwindcss/postcss": "catalog:",
"typescript-eslint": "catalog:",
"typescript": "catalog:"
}

View File

@ -1,7 +0,0 @@
const config = {
plugins: {
tailwindcss: {},
},
}
export default config

View File

@ -2,11 +2,6 @@ import sharedConfig from "@repo/config-tailwind"
/** @type {Pick<import('tailwindcss').Config, "presets" | "content">} */
const config = {
content: [
".storybook/preview.tsx",
"../../packages/ui/src/**/*.tsx",
"../../packages/blog/src/**/*.tsx",
],
presets: [sharedConfig],
}

View File

@ -0,0 +1,5 @@
{
"plugins": {
"@tailwindcss/postcss": {}
}
}

View File

@ -1,7 +1,7 @@
FROM node:22.13.1-slim AS node-pnpm
FROM node:24.0.0-slim AS node-pnpm
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN npm install --global corepack@0.31.0 && corepack enable
RUN npm install --global corepack@0.32.0 && corepack enable
ENV TURBO_TELEMETRY_DISABLED=1
ENV NEXT_TELEMETRY_DISABLED=1
ENV DO_NOT_TRACK=1
@ -9,7 +9,7 @@ WORKDIR /usr/src/app
FROM node-pnpm AS builder
COPY ./ ./
RUN pnpm install --global turbo@2.4.0
RUN pnpm install --global turbo@2.5.3
RUN turbo prune @repo/website --docker
FROM node-pnpm AS installer

View File

@ -37,6 +37,7 @@
"eslint": "catalog:",
"postcss": "catalog:",
"tailwindcss": "catalog:",
"@tailwindcss/postcss": "catalog:",
"typescript-eslint": "catalog:",
"typescript": "catalog:"
}

View File

@ -1,7 +0,0 @@
const config = {
plugins: {
tailwindcss: {},
},
}
export default config

View File

@ -2,11 +2,6 @@ import sharedConfig from "@repo/config-tailwind"
/** @type {Pick<import('tailwindcss').Config, "presets" | "content">} */
const config = {
content: [
"./app/**/*.tsx",
"../../packages/ui/src/**/*.tsx",
"../../packages/blog/src/**/*.tsx",
],
presets: [sharedConfig],
}

View File

@ -1,16 +1,14 @@
import { FlatCompat } from "@eslint/eslintrc"
import storybook from "eslint-plugin-storybook"
import tailwind from "eslint-plugin-tailwindcss"
import typescriptESLint from "typescript-eslint"
import config from "../eslint.config.js"
const flatCompat = new FlatCompat()
const flatCompat = new FlatCompat({
baseDirectory: import.meta.dirname,
})
export default typescriptESLint.config(
...config,
...flatCompat.extends("next/core-web-vitals"),
...tailwind.configs["flat/recommended"],
...storybook.configs["flat/recommended"],
{
name: "config-eslint/nextjs",
settings: {
@ -22,8 +20,6 @@ export default typescriptESLint.config(
},
},
rules: {
"tailwindcss/classnames-order": "off",
"tailwindcss/no-custom-classname": "off",
"@next/next/no-html-link-for-pages": "off",
"@next/next/no-img-element": "off",
"react/self-closing-comp": [

View File

@ -25,8 +25,6 @@
"eslint-plugin-promise": "catalog:",
"eslint-plugin-unicorn": "catalog:",
"eslint-config-next": "catalog:",
"eslint-plugin-storybook": "catalog:",
"eslint-plugin-tailwindcss": "catalog:",
"eslint-plugin-import-x": "catalog:",
"typescript": "catalog:",
"globals": "catalog:"

View File

@ -0,0 +1,5 @@
{
"plugins": {
"@tailwindcss/postcss": {}
}
}

View File

@ -1,4 +1,5 @@
import { type ClassValue, clsx } from "clsx"
import type { ClassValue } from "clsx"
import { clsx } from "clsx"
import { twMerge } from "tailwind-merge"
export const classNames = (...inputs: ClassValue[]): string => {

View File

@ -27,6 +27,7 @@
"typescript-eslint": "catalog:",
"eslint": "catalog:",
"postcss": "catalog:",
"tailwindcss": "catalog:"
"tailwindcss": "catalog:",
"@tailwindcss/postcss": "catalog:"
}
}

View File

@ -1,7 +0,0 @@
const config = {
plugins: {
tailwindcss: {},
},
}
export default config

View File

@ -1,12 +1,16 @@
@import "@fontsource/montserrat/400.css";
@import "@fontsource/montserrat/500.css";
@import "@fontsource/montserrat/600.css";
@import "@fontsource/montserrat/700.css";
@import "@fontsource/montserrat/800.css";
@import "tailwindcss";
@config "./tailwind.config.js";
@tailwind base;
@tailwind components;
@tailwind utilities;
@source "../../packages/ui";
@source "../../packages/blog";
@source "../../apps/website";
@source "../../apps/storybook/.storybook";
@import "@fontsource/montserrat/400.css" layer(base);
@import "@fontsource/montserrat/500.css" layer(base);
@import "@fontsource/montserrat/600.css" layer(base);
@import "@fontsource/montserrat/700.css" layer(base);
@import "@fontsource/montserrat/800.css" layer(base);
@layer base {
[type="search"]::-webkit-search-decoration,
@ -14,6 +18,11 @@
appearance: none;
}
button:not(:disabled),
[role="button"]:not(:disabled) {
cursor: pointer;
}
b,
strong {
@apply font-semibold;

View File

@ -11,6 +11,7 @@
"noUncheckedIndexedAccess": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"erasableSyntaxOnly": true,
"verbatimModuleSyntax": true,
"isolatedModules": true,

View File

@ -3,15 +3,14 @@
"version": "0.0.0-develop",
"private": true,
"type": "module",
"packageManager": "pnpm@10.2.1+sha512.398035c7bd696d0ba0b10a688ed558285329d27ea994804a52bad9167d8e3a72bcb993f9699585d3ca25779ac64949ef422757a6c31102c12ab932e5cbe5cc92",
"packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39",
"engines": {
"node": ">=22.12.0",
"pnpm": ">=10.2.1"
"node": ">=24.0.0"
},
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev --parallel",
"start": "turbo run start --parallel",
"build": "turbo run build",
"test": "turbo run test",
"lint:editorconfig": "editorconfig-checker",
"lint:markdown": "markdownlint-cli2",

View File

@ -0,0 +1,5 @@
{
"plugins": {
"@tailwindcss/postcss": {}
}
}

View File

@ -49,6 +49,7 @@
"eslint": "catalog:",
"postcss": "catalog:",
"tailwindcss": "catalog:",
"@tailwindcss/postcss": "catalog:",
"typescript-eslint": "catalog:",
"typescript": "catalog:"
}

View File

@ -1,7 +0,0 @@
const config = {
plugins: {
tailwindcss: {},
},
}
export default config

View File

@ -109,11 +109,11 @@ const transaction = charge(user, subscription)
```typescript
interface Car {
carModel: string
carColor: "red" | "blue" | "yellow"
carModel: string
carColor: "red" | "blue" | "yellow"
}
const printCar = (car: Car): void => {
console.log(`${car.carModel} (${car.carColor})`)
console.log(`${car.carModel} (${car.carColor})`)
}
```
@ -121,11 +121,11 @@ const printCar = (car: Car): void => {
```typescript
interface Car {
model: string
color: "red" | "blue" | "yellow"
model: string
color: "red" | "blue" | "yellow"
}
const printCar = (car: Car): void => {
console.log(`${car.model} (${car.color})`)
console.log(`${car.model} (${car.color})`)
}
```
@ -174,13 +174,13 @@ import fs from "node:fs"
import path from "node:path"
const createFile = async (
name: string,
isTemporary: boolean = false,
name: string,
isTemporary: boolean = false,
): Promise<void> => {
if (isTemporary) {
return await fs.promises.writeFile(path.join("temporary", name), "")
}
return await fs.promises.writeFile(name, "")
if (isTemporary) {
return await fs.promises.writeFile(path.join("temporary", name), "")
}
return await fs.promises.writeFile(name, "")
}
```
@ -193,11 +193,11 @@ import fs from "node:fs"
import path from "node:path"
const createFile = async (name: string): Promise<void> => {
await fs.promises.writeFile(name, "")
await fs.promises.writeFile(name, "")
}
const createTemporaryFile = async (name: string): Promise<void> => {
await createFile(path.join("temporary", name))
await createFile(path.join("temporary", name))
}
```

View File

@ -39,23 +39,23 @@ The code of this website is open source on [GitHub](https://github.com/theoludwi
- [Next.js](https://nextjs.org/)
It allows to have a server-side rendered website, that means that it is faster and easier to have a good <abbr title="Search Engine Optimization">SEO</abbr> than a <abbr title="Single Page Application">SPA</abbr>.
It allows to have a server-side rendered website, that means that it is faster and easier to have a good <abbr title="Search Engine Optimization">SEO</abbr> than a <abbr title="Single Page Application">SPA</abbr>.
- [MDX](https://mdxjs.com/)
MDX is an extension of Markdown that allows you to use custom React components.
MDX is an extension of Markdown that allows you to use custom React components.
Here's what Markdown looks like:
Here's what Markdown looks like:
```md
A simple paragraph, with some **bold** text and some `inline code`.
```
```md
A simple paragraph, with some **bold** text and some `inline code`.
```
When using Markdown in a web application, there's a "compile" step; the Markdown needs to be transformed into HTML, so that it can be understood by the browser. Those asterisks get turned into a `<strong>` tag, and each paragraph gets a `<p>` tag etc.
When using Markdown in a web application, there's a "compile" step; the Markdown needs to be transformed into HTML, so that it can be understood by the browser. Those asterisks get turned into a `<strong>` tag, and each paragraph gets a `<p>` tag etc.
- [Tailwind CSS](https://tailwindcss.com/)
Tailwind is a CSS framework to rapidly build modern websites without ever leaving HTML.
Tailwind is a CSS framework to rapidly build modern websites without ever leaving HTML.
## Conclusion

View File

@ -2,7 +2,6 @@ import sharedConfig from "@repo/config-tailwind"
/** @type {Pick<import('tailwindcss').Config, "presets" | "content">} */
const config = {
content: ["./src/**/*.tsx"],
presets: [sharedConfig],
}

View File

@ -1,10 +1,9 @@
import type fr from "./translations/fr-FR.json"
import type { routing } from "./routing.ts"
import type messages from "./translations/en-US.json"
type Messages = typeof fr
declare global {
/**
* Use type safe message keys with `next-intl`.
*/
interface IntlMessages extends Messages {}
declare module "next-intl" {
interface AppConfig {
Locale: (typeof routing.locales)[number]
Messages: typeof messages
}
}

View File

@ -1,15 +1,16 @@
import type { AbstractIntlMessages } from "next-intl"
import { hasLocale } from "next-intl"
import { getRequestConfig } from "next-intl/server"
import { routing } from "./routing.ts"
import type { Locale } from "@repo/utils/constants"
import { LOCALE_DEFAULT, LOCALES } from "@repo/utils/constants"
import { LOCALE_DEFAULT } from "@repo/utils/constants"
import { deepMerge } from "@repo/utils/objects"
export default getRequestConfig(async ({ requestLocale }) => {
let locale = await requestLocale
if (!LOCALES.includes(locale as Locale)) {
locale = LOCALE_DEFAULT
}
const requested = await requestLocale
const locale = hasLocale(routing.locales, requested)
? requested
: routing.defaultLocale
const userMessages = (await import(`./translations/${locale}.json`)).default
const defaultMessages = (

View File

@ -0,0 +1,5 @@
{
"plugins": {
"@tailwindcss/postcss": {}
}
}

View File

@ -51,6 +51,7 @@
"eslint": "catalog:",
"postcss": "catalog:",
"tailwindcss": "catalog:",
"@tailwindcss/postcss": "catalog:",
"typescript-eslint": "catalog:",
"typescript": "catalog:"
}

View File

@ -1,7 +0,0 @@
const config = {
plugins: {
tailwindcss: {},
},
}
export default config

View File

@ -2,7 +2,6 @@ import sharedConfig from "@repo/config-tailwind"
/** @type {Pick<import('tailwindcss').Config, "presets" | "content">} */
const config = {
content: ["./src/**/*.tsx"],
presets: [sharedConfig],
}

7262
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -5,66 +5,63 @@ packages:
catalog:
# Turborepo
"turbo": "2.4.0"
"turbo": "2.5.3"
# Utils
"mime": "4.0.6"
"mime": "4.0.7"
# React.js/Next.js
"next": &next "15.1.6"
"next-intl": "3.26.3"
"next-themes": "0.4.4"
"nuqs": "2.3.2"
"react": "19.0.0"
"react-dom": "19.0.0"
"react-icons": "5.4.0"
"@types/react": "19.0.8"
"@types/react-dom": "19.0.3"
"next": &next "15.3.2"
"next-intl": "4.1.0"
"next-themes": "0.4.6"
"react": "19.1.0"
"react-dom": "19.1.0"
"react-icons": "5.5.0"
"@types/react": "19.1.3"
"@types/react-dom": "19.1.3"
# Blog
"@giscus/react": "3.1.0"
"gray-matter": "4.0.3"
"katex": "0.16.21"
"katex": "0.16.22"
"next-mdx-remote": "5.0.0"
"@mdx-js/mdx": "3.1.0"
"rehype-katex": "7.0.1"
"rehype-raw": "7.0.0"
"rehype-slug": "6.0.0"
"remark-gfm": "4.0.0"
"remark-gfm": "4.0.1"
"remark-math": "6.0.0"
"shiki": "1.24.0"
"@shikijs/rehype": "1.24.0"
# Markdown Lint
"markdownlint-cli2": "0.17.2"
"markdownlint": "0.37.4"
"markdownlint-rule-relative-links": "4.0.1"
"markdownlint-cli2": "0.18.0"
"markdownlint": "0.38.0"
"markdownlint-rule-relative-links": "4.1.0"
# TypeScript
"typescript": "5.7.3"
"typescript": "5.8.3"
"@total-typescript/ts-reset": "0.6.1"
"@types/node": "22.13.1"
"@types/node": "22.15.17"
# ESLint
"globals": "15.14.0"
"typescript-eslint": "8.23.0"
"@eslint/eslintrc": "3.2.0"
"eslint": "9.20.0"
"eslint-config-conventions": "18.0.2"
"globals": "16.1.0"
"typescript-eslint": "8.32.0"
"@eslint/eslintrc": "3.3.1"
"eslint": "9.26.0"
"eslint-config-conventions": "19.2.0"
"eslint-plugin-promise": "7.2.1"
"eslint-plugin-unicorn": "56.0.1"
"eslint-plugin-unicorn": "59.0.1"
"eslint-config-next": *next
"eslint-plugin-storybook": "0.11.2"
"eslint-plugin-tailwindcss": "3.18.0"
"eslint-plugin-import-x": "4.6.1"
"eslint-plugin-import-x": "4.11.1"
# Prettier
"prettier": "3.4.2"
"prettier": "3.5.3"
"prettier-plugin-tailwindcss": "0.6.11"
"editorconfig-checker": "6.0.1"
# Storybook
"storybook": &storybook "8.5.3"
"storybook": &storybook "8.6.12"
"@storybook/addon-essentials": *storybook
"@storybook/addon-storysource": *storybook
"@storybook/addon-a11y": *storybook
@ -74,22 +71,35 @@ catalog:
"@storybook/react": *storybook
"@storybook/test": *storybook
"@storybook/addon-themes": *storybook
"@storybook/test-runner": "0.21.0"
"@chromatic-com/storybook": "3.2.4"
"chromatic": "11.25.2"
"@storybook/test-runner": "0.22.0"
"@chromatic-com/storybook": "3.2.6"
"chromatic": "11.28.2"
"storybook-dark-mode": "4.0.2"
# Testing
"playwright": &playwright "1.50.1"
"playwright": &playwright "1.52.0"
"@playwright/test": *playwright
"axe-playwright": "2.1.0"
"start-server-and-test": "2.0.10"
"start-server-and-test": "2.0.11"
# CSS
"postcss": "8.5.1"
"tailwindcss": "3.4.17"
"@tailwindcss/typography": "0.5.15"
"tailwind-merge": "2.6.0"
"postcss": "8.5.3"
"@tailwindcss/postcss": "4.1.6"
"@tailwindcss/typography": "0.5.16"
"tailwindcss": "4.1.6"
"tailwind-merge": "3.2.0"
"clsx": "2.1.1"
"cva": "1.0.0-beta.3"
"@fontsource/montserrat": "5.1.1"
"@fontsource/montserrat": "5.2.5"
onlyBuiltDependencies:
- "@swc/core"
- "@tailwindcss/oxide"
- "core-js-pure"
- "esbuild"
- "sharp"
- "unrs-resolver"
publicHoistPattern:
- "*eslint*"
- "*prettier*"