Merge branch 'main' into patch-1

This commit is contained in:
Wire Earp 2025-02-17 12:48:41 -08:00 • committed by GitHub
commit d9a82cdb0d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 16969 additions and 15823 deletions

View file

@ -1,2 +0,0 @@
.next
node_modules

View file

@ -1,79 +0,0 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const fs = require("fs")
module.exports = {
extends: [
"next",
"prettier",
"react-app",
"react-app/jest",
"plugin:storybook/recommended",
"plugin:tailwindcss/recommended",
],
parserOptions: {
babelOptions: {
presets: [require.resolve("next/babel")],
},
},
rules: {
"tailwindcss/no-custom-classname": "off",
"testing-library/prefer-screen-queries": "off",
"@next/next/no-html-link-for-pages": "off",
"@typescript-eslint/no-unused-vars": [
"warn",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
},
],
"sort-imports": [
"error",
{
ignoreCase: true,
ignoreDeclarationSort: true,
},
],
"tailwindcss/classnames-order": "off",
"import/order": [
1,
{
groups: ["external", "builtin", "internal", "sibling", "parent", "index"],
pathGroups: [
...getDirectoriesToSort().map((singleDir) => ({
pattern: `${singleDir}/**`,
group: "internal",
})),
{
pattern: "env",
group: "internal",
},
{
pattern: "theme",
group: "internal",
},
{
pattern: "public/**",
group: "internal",
position: "after",
},
],
pathGroupsExcludedImportTypes: ["internal"],
alphabetize: {
order: "asc",
caseInsensitive: true,
},
},
],
},
}
function getDirectoriesToSort() {
const ignoredSortingDirectories = [".git", ".next", ".vscode", "node_modules"]
return getDirectories(process.cwd()).filter((f) => !ignoredSortingDirectories.includes(f))
}
function getDirectories(path) {
return fs.readdirSync(path).filter(function (file) {
return fs.statSync(path + "/" + file).isDirectory()
})
}

View file

@ -20,18 +20,24 @@ jobs:
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: "${{ env.node_version }}" node-version: "${{ env.node_version }}"
- name: Install dependencies
run: yarn install --frozen-lockfile - name: "Install pnpm & dependencies"
uses: pnpm/action-setup@v4
with:
run_install: |
- recursive: true
- args: [--frozen-lockfile]
- name: Lint check - name: Lint check
run: yarn lint run: pnpm run lint
- name: Format check - name: Format check
run: yarn prettier run: pnpm run prettier
- name: Unit & Integration tests - name: Unit & Integration tests
run: yarn test run: pnpm run test
- name: Smoke & Acceptance tests - name: Smoke & Acceptance tests
run: | run: |
yarn build-storybook --quiet pnpm run build-storybook --quiet
yarn playwright install pnpm playwright install
npx concurrently -k -s first -n "SB,TEST" -c "magenta,blue" \ pnpm dlx concurrently -k -s first -n "SB,TEST" -c "magenta,blue" \
"npx http-server storybook-static --port 6006 --silent" \ "pnpm dlx http-server storybook-static --port 6006 --silent" \
"npx wait-on tcp:127.0.0.1:6006 && yarn test-storybook" "pnpm dlx wait-on tcp:127.0.0.1:6006 && pnpm run test-storybook"

View file

@ -1,18 +0,0 @@
name: Code Review
permissions:
contents: read
pull-requests: write
on:
pull_request:
types:
- opened
- reopened
- synchronize
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: anc95/ChatGPT-CodeReview@main
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
OPENAI_API_KEY: "${{ secrets.OPENAI_API_KEY }}"

View file

@ -29,8 +29,15 @@ jobs:
with: with:
node-version: "20.x" node-version: "20.x"
- name: Install dependencies - name: "Install pnpm & dependencies"
run: yarn install --frozen-lockfile uses: pnpm/action-setup@v4
with:
run_install: |
- recursive: true
- args: [--frozen-lockfile]
# - name: Install dependencies
# run: pnpm install --frozen-lockfile
- name: Restore next build - name: Restore next build
uses: actions/cache@v3 uses: actions/cache@v3
@ -46,7 +53,7 @@ jobs:
env: env:
SKIP_BUILD_PRODUCT_REDIRECTS: 1 SKIP_BUILD_PRODUCT_REDIRECTS: 1
# change this if your site requires a custom build command # change this if your site requires a custom build command
run: yarn build run: pnpm build
# Here's the first place where next-bundle-analysis' own script is used # Here's the first place where next-bundle-analysis' own script is used
# This step pulls the raw bundle stats for the current bundle # This step pulls the raw bundle stats for the current bundle
@ -54,13 +61,13 @@ jobs:
run: node report-bundle-size.js run: node report-bundle-size.js
- name: Upload bundle - name: Upload bundle
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: bundle name: bundle
path: .next/analyze/__bundle_analysis.json path: .next/analyze/__bundle_analysis.json
- name: Download base branch bundle stats - name: Download base branch bundle stats
uses: dawidd6/action-download-artifact@v2 uses: dawidd6/action-download-artifact@v8
if: success() && github.event.number if: success() && github.event.number
with: with:
workflow: nextjs_bundle_analysis.yml workflow: nextjs_bundle_analysis.yml

View file

@ -18,13 +18,21 @@ jobs:
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: "${{ env.node_version }}" node-version: "${{ env.node_version }}"
- name: Install dependencies
run: yarn install --frozen-lockfile - name: "Install pnpm & dependencies"
uses: pnpm/action-setup@v4
with:
run_install: |
- recursive: true
- args: [--frozen-lockfile]
- name: Install Playwright Browsers - name: Install Playwright Browsers
run: yarn playwright install --with-deps run: pnpm playwright install --with-deps
- name: Run Playwright tests - name: Run Playwright tests
run: yarn playwright test run: pnpm playwright test
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
if: always() if: always()
with: with:
name: playwright-report name: playwright-report

1
.gitignore vendored
View file

@ -28,6 +28,7 @@ yarn-error.log*
.env.development.local .env.development.local
.env.test.local .env.test.local
.env.production.local .env.production.local
storybook-static/
/test-results/ /test-results/
/playwright-report/ /playwright-report/
/playwright/.cache/ /playwright/.cache/

View file

@ -1,17 +1,30 @@
<img align="right" width="360px" height="410px" src="./.github/assets/project-logo-vertical.png">
# Next.js Enterprise Boilerplate </br> [![GitHub Actions Workflow Status][check-workflow-badge]][check-workflow-badge-link] [![GitHub License][github-license-badge]][github-license-badge-link] [![GitHub contributors][github-contributors-badge]][github-contributors-badge-link] [![Discord][discord-badge]][discord-badge-link] [![Blazity][made-by-blazity-badge]][made-by-blazity-badge-link] ### Next.js Enterprise Boilerplate
</br>
[![GitHub Actions Workflow Status][check-workflow-badge]][check-workflow-badge-link] [![GitHub License][github-license-badge]][github-license-badge-link] [![GitHub contributors][github-contributors-badge]][github-contributors-badge-link] [![Discord][discord-badge]][discord-badge-link] [![Blazity][made-by-blazity-badge]][made-by-blazity-badge-link]
Welcome to the _Next.js Enterprise Boilerplate_, an open-source template for enterprise projects! It's loaded with features that'll help you build a high-performance, maintainable, and enjoyable app. We've done all the heavy lifting for you, so sit back, relax, and get ready to conquer the world with your incredible app! 🌍 Welcome to the _Next.js Enterprise Boilerplate_, an open-source template for enterprise projects! It's loaded with features that'll help you build a high-performance, maintainable, and enjoyable app. We've done all the heavy lifting for you, so sit back, relax, and get ready to conquer the world with your incredible app! 🌍
> [!NOTE] > [!NOTE]
> **Blazity** is a group of Next.js/Headless experts. Contact us at [contact@blazity.com](https://blazity.com) if you’d like to talk about your project or just to have a chat with us > **Blazity** is a group of Next.js/Headless experts. Contact us at [contact@blazity.com](https://blazity.com) if you’d like to talk about your project or just to have a chat with us
## Features ### Feature Manager (nefi)
<a href="https://github.com/blazity/nefi"><img width="250" align="right" alt="nefi-badge" src="https://github.com/user-attachments/assets/37941f8c-944f-44c0-b3c7-b1d322431871" /></a>
With this template, you get all the awesomeness you need: **nefi** (next-enterprise feature integrations) is an AI agent that will help configuring the boilerplate to your needs using natural language. It can remove/install dependencies, modify files and manage Git.
- 🏎️ **[Next.js](https://nextjs.org/)** - Fast by default, with config optimized for performance (with **App Directory**) Simply set up the boilerplate, follow guide [in the getting started section](#getting-started) and type `npx nefi` in your terminal!
Leave a ⭐ for [nefi on GitHub](https://github.com/blazity/nefi) and check out the [nefi.ai docs](https://nefi.ai/)!
### Integrated features
Don't worry, with this template you will anyways get all the awesomeness you need:
- 🏎️ **[Next.js 15](https://nextjs.org/)** - Fast by default, with config optimized for performance (with **App Directory**)
- 💅 **[Tailwind CSS](https://tailwindcss.com/)** - A utility-first CSS framework for rapid UI development - 💅 **[Tailwind CSS](https://tailwindcss.com/)** - A utility-first CSS framework for rapid UI development
- ✨ **[ESlint](https://eslint.org/)** and **[Prettier](https://prettier.io/)** - For clean, consistent, and error-free code - ✨ **[ESlint](https://eslint.org/)** and **[Prettier](https://prettier.io/)** - For clean, consistent, and error-free code
- 🛠️ **[Extremely strict TypeScript](https://www.typescriptlang.org/)** - With [`ts-reset`](https://github.com/total-typescript/ts-reset) library for ultimate type safety - 🛠️ **[Extremely strict TypeScript](https://www.typescriptlang.org/)** - With [`ts-reset`](https://github.com/total-typescript/ts-reset) library for ultimate type safety
@ -31,7 +44,6 @@ With this template, you get all the awesomeness you need:
- **[Renovate BOT](https://www.whitesourcesoftware.com/free-developer-tools/renovate)** - Auto-updating dependencies, so you can focus on coding - **[Renovate BOT](https://www.whitesourcesoftware.com/free-developer-tools/renovate)** - Auto-updating dependencies, so you can focus on coding
- **[Patch-package](https://www.npmjs.com/package/patch-package)** - Fix external dependencies without losing your mind - **[Patch-package](https://www.npmjs.com/package/patch-package)** - Fix external dependencies without losing your mind
- **Components coupling and cohesion graph** - A tool for managing component relationships - **Components coupling and cohesion graph** - A tool for managing component relationships
- **[Automated ChatGPT Code Reviews](https://openai.com/chatgpt)** - **Stay on the cutting edge with AI-powered code reviews!**
- **[Semantic Release](https://github.com/semantic-release/semantic-release)** - for automatic changelog - **[Semantic Release](https://github.com/semantic-release/semantic-release)** - for automatic changelog
- **[T3 Env](https://env.t3.gg/)** - Manage your environment variables with ease - **[T3 Env](https://env.t3.gg/)** - Manage your environment variables with ease
@ -54,7 +66,6 @@ With this template, you get all the awesomeness you need:
- [Zustand](#zustand) - [Zustand](#zustand)
- [Jotai](#jotai) - [Jotai](#jotai)
- [Recoil](#recoil) - [Recoil](#recoil)
- [ChatGPT Code Review](#-chatgpt-code-review)
- [Environment Variables handling](#-environment-variables-handling) - [Environment Variables handling](#-environment-variables-handling)
- [Contribution](#-contribution) - [Contribution](#-contribution)
- [Support](#support) - [Support](#support)
@ -69,19 +80,19 @@ To get started with this boilerplate, follow these steps:
```bash ```bash
## Don't forget to ⭐ star and fork it first :) ## Don't forget to ⭐ star and fork it first :)
git clone https://github.com/<your_username)/next-enterprise.git git clone https://github.com/<your_username>/next-enterprise.git
``` ```
2. Install the dependencies: 2. Install the dependencies:
```bash ```bash
yarn install --frozen-lockfile pnpm install --frozen-lockfile
``` ```
3. Run the development server: 3. Run the development server:
```bash ```bash
yarn dev pnpm run dev
``` ```
4. Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 4. Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
@ -118,7 +129,6 @@ The following scripts are available in the `package.json`:
- `e2e:ui`: Runs end-to-end tests with UI - `e2e:ui`: Runs end-to-end tests with UI
- `format`: Formats the code with Prettier - `format`: Formats the code with Prettier
- `postinstall`: Applies patches to external dependencies - `postinstall`: Applies patches to external dependencies
- `preinstall`: Ensures the project is installed with Yarn
- `coupling-graph`: **Generates a coupling and cohesion graph for the components** - `coupling-graph`: **Generates a coupling and cohesion graph for the components**
## 🔗 Coupling Graph ## 🔗 Coupling Graph
@ -126,7 +136,7 @@ The following scripts are available in the `package.json`:
The `coupling-graph` script is a useful tool that helps visualize the coupling and connections between your project's internal modules. It's built using the [Madge](https://github.com/pahen/madge) library. To generate the graph, simply run the following command: The `coupling-graph` script is a useful tool that helps visualize the coupling and connections between your project's internal modules. It's built using the [Madge](https://github.com/pahen/madge) library. To generate the graph, simply run the following command:
```bash ```bash
yarn coupling-graph pnpm run coupling-graph
``` ```
This will create a `graph.svg` file, which contains a graphical representation of the connections between your components. You can open the file with any SVG-compatible viewer. This will create a `graph.svg` file, which contains a graphical representation of the connections between your components. You can open the file with any SVG-compatible viewer.
@ -139,9 +149,9 @@ This boilerplate comes with various testing setups to ensure your application's
### Running Tests ### Running Tests
- **Unit and integration tests**: Run Jest tests using `yarn test` - **Unit and integration tests**: Run Jest tests using `pnpm run test`
- **End-to-end tests (headless mode)**: Run Playwright tests in headless mode with `yarn e2e:headless` - **End-to-end tests (headless mode)**: Run Playwright tests in headless mode with `pnpm run e2e:headless`
- **End-to-end tests (UI mode)**: Run Playwright tests with UI using `yarn e2e:ui` - **End-to-end tests (UI mode)**: Run Playwright tests with UI using `pnpm run e2e:ui`
<img width="1392" alt="image" src="https://user-images.githubusercontent.com/28964599/233666655-93b7d08b-2fd8-406a-b43c-44d4d96cf387.png"> <img width="1392" alt="image" src="https://user-images.githubusercontent.com/28964599/233666655-93b7d08b-2fd8-406a-b43c-44d4d96cf387.png">
@ -183,7 +193,7 @@ export const FilledForm: Story = {
### Smoke Testing ### Smoke Testing
In this boilerplate, we use Storybook's out-of-the-box support for smoke testing to verify that components render correctly without any errors. Just run `yarn test-storybook` to perform smoke testing. Remember to write stories in JSX or TSX format only. Smoke testing and a lot of other functionalities dont work well with MDX stories. In this boilerplate, we use Storybook's out-of-the-box support for smoke testing to verify that components render correctly without any errors. Just run `pnpm run test-storybook` to perform smoke testing. Remember to write stories in JSX or TSX format only. Smoke testing and a lot of other functionalities dont work well with MDX stories.
## 🎨 Styling and Design System ## 🎨 Styling and Design System
@ -215,14 +225,6 @@ While this boilerplate doesn't include a specific state management library, we b
Choose the library that best fits your requirements and project structure to ensure an efficient state management solution for your application. Choose the library that best fits your requirements and project structure to ensure an efficient state management solution for your application.
## 🤖 ChatGPT Code Review
We've integrated the innovative [ChatGPT Code Review](https://github.com/anc95/ChatGPT-CodeReview) for AI-powered, automated code reviews. This feature provides real-time feedback on your code, helping improve code quality and catch potential issues.
To use ChatGPT Code Review, add an `OPENAI_API_KEY` environment variable with an appropriate key from the OpenAI platform. For setup details, refer to the [Using GitHub Actions](https://github.com/anc95/ChatGPT-CodeReview#using-github-actions) section in the documentation.
![image](https://user-images.githubusercontent.com/28964599/233685071-e1371edf-6359-41c3-a989-335d6ee09cb7.png)
## 💻 Environment Variables handling ## 💻 Environment Variables handling
[T3 Env](https://env.t3.gg/) is a library that provides environmental variables checking at build time, type validation and transforming. It ensures that your application is using the correct environment variables and their values are of the expected type. You’ll never again struggle with runtime errors caused by incorrect environment variable usage. [T3 Env](https://env.t3.gg/) is a library that provides environmental variables checking at build time, type validation and transforming. It ensures that your application is using the correct environment variables and their values are of the expected type. You’ll never again struggle with runtime errors caused by incorrect environment variable usage.

View file

@ -1,5 +1,6 @@
import { Metadata } from "next" import { Metadata } from "next"
import { Button } from "components/Button/Button" import { Button } from "components/Button/Button"
import { LP_GRID_ITEMS } from "lp-items" import { LP_GRID_ITEMS } from "lp-items"
export const metadata: Metadata = { export const metadata: Metadata = {
@ -23,12 +24,12 @@ export default function Web() {
return ( return (
<> <>
<section className="bg-white dark:bg-gray-900"> <section className="bg-white dark:bg-gray-900">
<div className="mx-auto grid max-w-screen-xl px-4 py-8 text-center lg:py-16"> <div className="mx-auto grid max-w-(--breakpoint-xl) px-4 py-8 text-center lg:py-16">
<div className="mx-auto place-self-center"> <div className="mx-auto place-self-center">
<h1 className="mb-4 max-w-2xl text-4xl font-extrabold leading-none tracking-tight dark:text-white md:text-5xl xl:text-6xl"> <h1 className="mb-4 max-w-2xl text-4xl leading-none font-extrabold tracking-tight md:text-5xl xl:text-6xl dark:text-white">
Next.js Enterprise Boilerplate Next.js Enterprise Boilerplate
</h1> </h1>
<p className="mb-6 max-w-2xl font-light text-gray-500 dark:text-gray-400 md:text-lg lg:mb-8 lg:text-xl"> <p className="mb-6 max-w-2xl font-light text-gray-500 md:text-lg lg:mb-8 lg:text-xl dark:text-gray-400">
Jumpstart your enterprise project with our feature-packed, high-performance Next.js boilerplate! Jumpstart your enterprise project with our feature-packed, high-performance Next.js boilerplate!
Experience rapid UI development, AI-powered code reviews, and an extensive suite of tools for a smooth and Experience rapid UI development, AI-powered code reviews, and an extensive suite of tools for a smooth and
enjoyable development process. enjoyable development process.
@ -46,11 +47,11 @@ export default function Web() {
</div> </div>
</section> </section>
<section className="bg-white dark:bg-gray-900"> <section className="bg-white dark:bg-gray-900">
<div className="mx-auto max-w-screen-xl px-4 py-8 sm:py-16 lg:px-6"> <div className="mx-auto max-w-(--breakpoint-xl) px-4 py-8 sm:py-16 lg:px-6">
<div className="justify-center space-y-8 md:grid md:grid-cols-2 md:gap-12 md:space-y-0 lg:grid-cols-3"> <div className="justify-center space-y-8 md:grid md:grid-cols-2 md:gap-12 md:space-y-0 lg:grid-cols-3">
{LP_GRID_ITEMS.map((singleItem) => ( {LP_GRID_ITEMS.map((singleItem) => (
<div key={singleItem.title} className="flex flex-col items-center justify-center text-center"> <div key={singleItem.title} className="flex flex-col items-center justify-center text-center">
<div className="mb-4 flex h-10 w-10 items-center justify-center rounded-full bg-primary-100 p-1.5 text-blue-700 dark:bg-primary-900 lg:h-12 lg:w-12"> <div className="bg-primary-100 dark:bg-primary-900 mb-4 flex size-10 items-center justify-center rounded-full p-1.5 text-blue-700 lg:size-12">
{singleItem.icon} {singleItem.icon}
</div> </div>
<h3 className="mb-2 text-xl font-bold dark:text-white">{singleItem.title}</h3> <h3 className="mb-2 text-xl font-bold dark:text-white">{singleItem.title}</h3>

View file

@ -1,17 +1,17 @@
"use client" "use client"
import * as RadixTooltip from "@radix-ui/react-tooltip" import * as RadixTooltip from "@radix-ui/react-tooltip"
import { cva, VariantProps } from "class-variance-authority" import { cva, type VariantProps } from "class-variance-authority"
import React from "react" import React from "react"
import { twMerge } from "tailwind-merge" import { twMerge } from "tailwind-merge"
const tooltipContent = cva([], { const tooltipContent = cva([], {
variants: { variants: {
intent: { intent: {
primary: ["rounded-0.5md", "bg-zinc-700", "font-open-sans", "text-white"], primary: ["rounded-md", "bg-zinc-700", "font-sans", "text-white"],
}, },
size: { size: {
md: ["px-4", "py-2.5", "text-2xs"], md: ["px-4", "py-2.5", "text-xs"],
}, },
}, },
defaultVariants: { defaultVariants: {

108
eslint.config.mjs Normal file
View file

@ -0,0 +1,108 @@
import * as fs from "fs"
// https://github.com/francoismassart/eslint-plugin-tailwindcss/pull/381
// import eslintPluginTailwindcss from "eslint-plugin-tailwindcss"
import eslintPluginImport from "eslint-plugin-import"
import eslintPluginNext from "@next/eslint-plugin-next"
import eslintPluginStorybook from "eslint-plugin-storybook"
import typescriptEslint from "typescript-eslint"
const eslintIgnore = [
".git/",
".next/",
"node_modules/",
"dist/",
"build/",
"coverage/",
"*.min.js",
"*.config.js",
"*.d.ts",
]
const config = typescriptEslint.config(
{
ignores: eslintIgnore,
},
...eslintPluginStorybook.configs["flat/recommended"],
// https://github.com/francoismassart/eslint-plugin-tailwindcss/pull/381
// ...eslintPluginTailwindcss.configs["flat/recommended"],
typescriptEslint.configs.recommended,
eslintPluginImport.flatConfigs.recommended,
{
plugins: {
"@next/next": eslintPluginNext,
},
rules: {
...eslintPluginNext.configs.recommended.rules,
...eslintPluginNext.configs["core-web-vitals"].rules,
},
},
{
settings: {
tailwindcss: {
callees: ["classnames", "clsx", "ctl", "cn", "cva"],
},
"import/resolver": {
typescript: true,
node: true,
},
},
rules: {
"@typescript-eslint/no-unused-vars": [
"warn",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
},
],
"sort-imports": [
"error",
{
ignoreCase: true,
ignoreDeclarationSort: true,
},
],
"import/order": [
"warn",
{
groups: ["external", "builtin", "internal", "sibling", "parent", "index"],
pathGroups: [
...getDirectoriesToSort().map((singleDir) => ({
pattern: `${singleDir}/**`,
group: "internal",
})),
{
pattern: "env",
group: "internal",
},
{
pattern: "theme",
group: "internal",
},
{
pattern: "public/**",
group: "internal",
position: "after",
},
],
pathGroupsExcludedImportTypes: ["internal"],
alphabetize: {
order: "asc",
caseInsensitive: true,
},
},
],
},
}
)
function getDirectoriesToSort() {
const ignoredSortingDirectories = [".git", ".next", ".vscode", "node_modules"]
return fs
.readdirSync(process.cwd())
.filter((file) => fs.statSync(process.cwd() + "/" + file).isDirectory())
.filter((f) => !ignoredSortingDirectories.includes(f))
}
export default config

2
next-env.d.ts vendored
View file

@ -2,4 +2,4 @@
/// <reference types="next/image-types/global" /> /// <reference types="next/image-types/global" />
// NOTE: This file should not be edited // NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information. // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

View file

@ -1,26 +0,0 @@
import withBundleAnalyzer from "@next/bundle-analyzer"
import withPlugins from "next-compose-plugins"
import { env } from "./env.mjs"
/**
* @type {import('next').NextConfig}
*/
const config = withPlugins([[withBundleAnalyzer({ enabled: env.ANALYZE })]], {
reactStrictMode: true,
logging: {
fetches: {
fullUrl: true,
},
},
experimental: { instrumentationHook: true },
rewrites() {
return [
{ source: "/healthz", destination: "/api/health" },
{ source: "/api/healthz", destination: "/api/health" },
{ source: "/health", destination: "/api/health" },
{ source: "/ping", destination: "/api/health" },
]
},
})
export default config

21
next.config.ts Normal file
View file

@ -0,0 +1,21 @@
import withBundleAnalyzer from "@next/bundle-analyzer"
import { type NextConfig } from "next"
import { env } from "./env.mjs"
const config: NextConfig = {
reactStrictMode: true,
logging: {
fetches: {
fullUrl: true,
},
},
rewrites: async () => [
{ source: "/healthz", destination: "/api/health" },
{ source: "/api/healthz", destination: "/api/health" },
{ source: "/health", destination: "/api/health" },
{ source: "/ping", destination: "/api/health" },
],
}
export default env.ANALYZE ? withBundleAnalyzer({ enabled: env.ANALYZE })(config) : config

View file

@ -3,14 +3,14 @@
"version": "0.0.0", "version": "0.0.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "cross-env FORCE_COLOR=1 next dev", "dev": "cross-env FORCE_COLOR=1 next dev --turbo",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "next lint", "lint": "next lint",
"lint:fix": "next lint --fix", "lint:fix": "next lint --fix",
"prettier": "prettier --check \"**/*.{js,jsx,ts,tsx}\"", "prettier": "prettier --check \"**/*.{js,jsx,ts,tsx}\"",
"prettier:fix": "prettier --write \"**/*.{js,jsx,ts,tsx}\"", "prettier:fix": "prettier --write \"**/*.{js,jsx,ts,tsx}\"",
"analyze": "cross-env ANALYZE=true yarn build", "analyze": "cross-env ANALYZE=true pnpm run build",
"storybook": "cross-env FORCE_COLOR=1 storybook dev -p 6006", "storybook": "cross-env FORCE_COLOR=1 storybook dev -p 6006",
"test-storybook": "cross-env FORCE_COLOR=1 test-storybook", "test-storybook": "cross-env FORCE_COLOR=1 test-storybook",
"build-storybook": "cross-env FORCE_COLOR=1 storybook build", "build-storybook": "cross-env FORCE_COLOR=1 storybook build",
@ -18,12 +18,11 @@
"e2e:headless": "playwright test", "e2e:headless": "playwright test",
"e2e:ui": "playwright test --ui", "e2e:ui": "playwright test --ui",
"format": "prettier --write \"**/*.{ts,tsx,md}\"", "format": "prettier --write \"**/*.{ts,tsx,md}\"",
"preinstall": "npx npm-only-allow@latest --PM yarn",
"postinstall": "npx patch-package -y", "postinstall": "npx patch-package -y",
"coupling-graph": "npx madge --extensions js,jsx,ts,tsx,css,md,mdx ./ --exclude '.next|tailwind.config.js|reset.d.ts|prettier.config.js|postcss.config.js|playwright.config.ts|next.config.js|next-env.d.ts|instrumentation.ts|e2e/|README.md|.storybook/|.eslintrc.js' --image graph.svg" "coupling-graph": "npx madge --extensions js,jsx,ts,tsx,css,md,mdx ./ --exclude '.next|tailwind.config.js|reset.d.ts|prettier.config.js|postcss.config.js|playwright.config.ts|next.config.js|next-env.d.ts|instrumentation.ts|e2e/|README.md|.storybook/|.eslintrc.js' --image graph.svg"
}, },
"dependencies": { "dependencies": {
"@next/bundle-analyzer": "^14.2.3", "@next/bundle-analyzer": "^15.1.6",
"@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dialog": "^1.0.5",
@ -49,10 +48,9 @@
"@vercel/otel": "^1.8.3", "@vercel/otel": "^1.8.3",
"class-variance-authority": "^0.7.0", "class-variance-authority": "^0.7.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"next": "^14.2.3", "next": "15.1.6",
"next-compose-plugins": "^2.2.1", "react": "^19.0.0",
"react": "^18.3.1", "react-dom": "^19.0.0",
"react-dom": "^18.3.1",
"tailwind-merge": "^2.3.0", "tailwind-merge": "^2.3.0",
"zod": "^3.23.8" "zod": "^3.23.8"
}, },
@ -61,62 +59,63 @@
"@babel/plugin-syntax-flow": "^7.23.3", "@babel/plugin-syntax-flow": "^7.23.3",
"@babel/plugin-transform-optional-chaining": "^7.23.4", "@babel/plugin-transform-optional-chaining": "^7.23.4",
"@babel/plugin-transform-react-jsx": "^7.23.4", "@babel/plugin-transform-react-jsx": "^7.23.4",
"@eslint/eslintrc": "^3",
"@jest/globals": "^29.7.0", "@jest/globals": "^29.7.0",
"@next/eslint-plugin-next": "15.1.6",
"@opentelemetry/api": "1.7.0", "@opentelemetry/api": "1.7.0",
"@opentelemetry/resources": "1.18.1", "@opentelemetry/resources": "1.18.1",
"@opentelemetry/sdk-node": "0.45.1", "@opentelemetry/sdk-node": "0.45.1",
"@opentelemetry/sdk-trace-node": "1.18.1", "@opentelemetry/sdk-trace-node": "1.18.1",
"@opentelemetry/semantic-conventions": "1.18.1", "@opentelemetry/semantic-conventions": "1.18.1",
"@playwright/test": "^1.40.0", "@playwright/test": "^1.40.0",
"@storybook/addon-essentials": "^7.5.3", "@storybook/addon-controls": "^8.5.1",
"@storybook/addon-interactions": "^7.5.3", "@storybook/addon-essentials": "^8.5.1",
"@storybook/addon-links": "^7.5.3", "@storybook/addon-interactions": "^8.5.1",
"@storybook/blocks": "^7.5.3", "@storybook/addon-links": "^8.5.1",
"@storybook/nextjs": "^7.5.3", "@storybook/blocks": "^8.5.1",
"@storybook/react": "^7.5.3", "@storybook/nextjs": "^8.5.1",
"@storybook/test-runner": "^0.15.2", "@storybook/react": "^8.5.1",
"@storybook/testing-library": "^0.2.2", "@storybook/test": "^8.5.1",
"@storybook/test-runner": "^0.21.0",
"@tailwindcss/postcss": "^4.0.0",
"@testing-library/jest-dom": "^6.1.4", "@testing-library/jest-dom": "^6.1.4",
"@testing-library/react": "^14.1.2", "@testing-library/react": "^14.1.2",
"@total-typescript/ts-reset": "^0.5.1", "@total-typescript/ts-reset": "^0.5.1",
"@types/jest": "^29.5.10", "@types/jest": "^29.5.10",
"@types/node": "^20.12.13", "@types/node": "^20",
"@types/react": "^18.3.3", "@types/react": "^19",
"@types/react-dom": "^18.3.0", "@types/react-dom": "^19",
"@typescript-eslint/eslint-plugin": "^6.12.0", "@typescript-eslint/eslint-plugin": "8.21.0",
"@typescript-eslint/parser": "^6.12.0",
"all-contributors-cli": "^6.26.1", "all-contributors-cli": "^6.26.1",
"autoprefixer": "^10.4.16",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"eslint": "8.54.0", "eslint": "^9",
"eslint-config-next": "14.0.3", "eslint-config-next": "15.1.6",
"eslint-config-prettier": "^9.0.0", "eslint-config-prettier": "^10.0.1",
"eslint-config-react-app": "^7.0.1", "eslint-plugin-import": "^2.31.0",
"eslint-plugin-import": "^2.29.0", "eslint-plugin-storybook": "^0.11.2",
"eslint-plugin-react": "7.33.2", "eslint-plugin-tailwindcss": "^3.18.0",
"eslint-plugin-storybook": "^0.6.15",
"eslint-plugin-tailwindcss": "^3.13.0",
"fetch-mock": "^9.11.0", "fetch-mock": "^9.11.0",
"gzip-size": "6.0.0", "gzip-size": "6.0.0",
"jest": "^29.7.0", "jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0", "jest-environment-jsdom": "^29.7.0",
"mkdirp": "^3.0.1", "mkdirp": "^3.0.1",
"npm-only-allow": "^1.2.6",
"patch-package": "^8.0.0", "patch-package": "^8.0.0",
"postcss": "^8.4.31", "postcss": "^8",
"postinstall-postinstall": "^2.1.0", "postinstall-postinstall": "^2.1.0",
"prettier": "3.0.3", "prettier": "3.0.3",
"prettier-plugin-tailwindcss": "^0.5.7", "prettier-plugin-tailwindcss": "^0.6.10",
"semantic-release": "^22.0.8", "semantic-release": "^22.0.8",
"storybook": "^7.5.3", "storybook": "^8.5.1",
"tailwindcss": "^3.3.5", "tailwindcss": "^4.0.0",
"ts-jest": "^29.1.1", "ts-jest": "^29.1.1",
"tsc": "^2.0.4", "tsc": "^2.0.4",
"typescript": "5.4.5", "typed-query-selector": "^2.12.0",
"typescript": "^5",
"typescript-eslint": "^8.21.0",
"webpack": "5.89.0" "webpack": "5.89.0"
}, },
"engines": { "engines": {
"node": ">=20.0.0" "node": ">=20.0.0"
}, },
"packageManager": "yarn@1.22.19" "packageManager": "pnpm@9.1.0"
} }

View file

@ -70,7 +70,7 @@ export default defineConfig({
/* Run your local dev server before starting the tests */ /* Run your local dev server before starting the tests */
webServer: { webServer: {
command: "yarn dev", command: "pnpm dev",
url: "http://127.0.0.1:3000", url: "http://127.0.0.1:3000",
reuseExistingServer: !process.env.CI, reuseExistingServer: !process.env.CI,
}, },

16701
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,5 @@
module.exports = { module.exports = {
plugins: { plugins: {
tailwindcss: {}, "@tailwindcss/postcss": {},
autoprefixer: {},
}, },
} }

2
reset.d.ts vendored
View file

@ -1,2 +1,2 @@
// Do not add any other lines of code to this file!
import "@total-typescript/ts-reset" import "@total-typescript/ts-reset"
import "typed-query-selector/strict"

View file

@ -1,3 +1,21 @@
@tailwind base; @import 'tailwindcss';
@tailwind components;
@tailwind utilities; @config '../tailwind.config.js';
/*
The default border color has changed to `currentColor` in Tailwind CSS v4,
so we've added these compatibility styles to make sure everything still
looks the same as it did with Tailwind CSS v3.
If we ever want to remove these styles, we need to add an explicit border
color utility to any element that depends on these defaults.
*/
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentColor);
}
}

View file

@ -1,6 +1,4 @@
/* eslint-disable @typescript-eslint/no-var-requires */ /* eslint-disable @typescript-eslint/no-var-requires */
const { pick, omit } = require("lodash")
const colors = require("tailwindcss/colors")
const defaultTheme = require("tailwindcss/defaultTheme") const defaultTheme = require("tailwindcss/defaultTheme")
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */

View file

@ -25,6 +25,6 @@
} }
] ]
}, },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.mjs", "jest.config.js", ".next/types/**/*.ts"], "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.mjs", "jest.config.js", ".next/types/**/*.ts", "eslint.config.mjs"],
"exclude": ["node_modules"] "exclude": ["node_modules"]
} }

15598
yarn.lock

File diff suppressed because it is too large Load diff