Skip to content

Commit daea996

Browse files
committed
refactor: improve route formatting in server index
1 parent 77c11bd commit daea996

48 files changed

Lines changed: 1859 additions & 1192 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/playground/eslint.config.mjs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import eslint from '@eslint/js'
2+
import tseslint from '@typescript-eslint/eslint-plugin'
3+
import tseslintParser from '@typescript-eslint/parser'
4+
import prettier from 'eslint-plugin-prettier'
5+
import react from 'eslint-plugin-react'
6+
import reactHooks from 'eslint-plugin-react-hooks'
7+
8+
const config = [
9+
{
10+
ignores: [
11+
'node_modules/**',
12+
'dist/**',
13+
'.next/**',
14+
'coverage/**',
15+
'*.js',
16+
'*.cjs',
17+
'*.mjs',
18+
'postcss.config.js',
19+
'next.config.js',
20+
'tailwind.config.ts'
21+
]
22+
},
23+
eslint.configs.recommended,
24+
{
25+
files: ['**/*.ts', '**/*.tsx'],
26+
languageOptions: {
27+
ecmaVersion: 2022,
28+
sourceType: 'module',
29+
parser: tseslintParser,
30+
parserOptions: {
31+
project: ['./tsconfig.json'],
32+
tsconfigRootDir: import.meta.dirname,
33+
ecmaFeatures: {
34+
jsx: true
35+
}
36+
},
37+
globals: {
38+
process: 'readonly',
39+
console: 'readonly',
40+
__dirname: 'readonly',
41+
__filename: 'readonly',
42+
Buffer: 'readonly',
43+
setTimeout: 'readonly',
44+
clearTimeout: 'readonly',
45+
setInterval: 'readonly',
46+
clearInterval: 'readonly',
47+
NodeJS: 'readonly',
48+
React: 'readonly',
49+
JSX: 'readonly'
50+
}
51+
},
52+
plugins: {
53+
'@typescript-eslint': tseslint,
54+
'prettier': prettier,
55+
'react': react,
56+
'react-hooks': reactHooks
57+
},
58+
settings: {
59+
react: {
60+
version: 'detect'
61+
}
62+
},
63+
rules: {
64+
// Prettier configuration - enforce single quotes and no semicolons
65+
'prettier/prettier': [
66+
'error',
67+
{
68+
singleQuote: true,
69+
semi: false,
70+
arrowParens: 'always',
71+
bracketSpacing: true,
72+
trailingComma: 'es5',
73+
printWidth: 100,
74+
tabWidth: 2,
75+
useTabs: false,
76+
jsxSingleQuote: true
77+
}
78+
],
79+
80+
// TypeScript specific rules
81+
'@typescript-eslint/no-explicit-any': 'warn',
82+
'@typescript-eslint/explicit-function-return-type': 'off',
83+
'@typescript-eslint/no-unsafe-assignment': 'off',
84+
'@typescript-eslint/no-unsafe-member-access': 'off',
85+
'@typescript-eslint/no-unsafe-argument': 'off',
86+
'@typescript-eslint/no-misused-promises': 'off',
87+
'@typescript-eslint/ban-ts-comment': 'off',
88+
89+
// General rules
90+
'no-unused-vars': 'off',
91+
'@typescript-eslint/no-unused-vars': ['warn', {
92+
'argsIgnorePattern': '^_',
93+
'varsIgnorePattern': '^_',
94+
'caughtErrorsIgnorePattern': '^_'
95+
}],
96+
97+
// Enforce consistent coding style
98+
'quotes': 'off',
99+
'@typescript-eslint/quotes': ['error', 'single', { 'avoidEscape': true }],
100+
'semi': 'off',
101+
'@typescript-eslint/semi': ['error', 'never'],
102+
'jsx-quotes': ['error', 'prefer-single'],
103+
104+
// React specific rules
105+
'react/prop-types': 'off',
106+
'react/react-in-jsx-scope': 'off', // Not needed in Next.js
107+
'react/jsx-uses-react': 'off',
108+
'react/jsx-uses-vars': 'error',
109+
'react-hooks/rules-of-hooks': 'error',
110+
'react-hooks/exhaustive-deps': 'warn',
111+
112+
// Next.js specific
113+
'no-console': ['warn', { allow: ['warn', 'error'] }],
114+
'prefer-const': 'error',
115+
'no-var': 'error',
116+
'object-shorthand': 'error',
117+
'prefer-arrow-callback': 'error'
118+
}
119+
}
120+
]
121+
122+
export default config

apps/playground/package.json

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
"scripts": {
66
"dev": "next dev --turbopack",
77
"build": "next build",
8-
"start": "next start"
8+
"start": "next start",
9+
"lint": "eslint 'src/**/*.{ts,tsx}'",
10+
"lint:fix": "eslint 'src/**/*.{ts,tsx}' --fix"
911
},
1012
"dependencies": {
1113
"classnames": "^2.5.1",
@@ -25,6 +27,14 @@
2527
"autoprefixer": "^10.4.19",
2628
"postcss": "^8.4.38",
2729
"tailwindcss": "^3.4.4",
28-
"typescript": "^5.5.2"
30+
"typescript": "^5.5.2",
31+
"@eslint/js": "^9.32.0",
32+
"@typescript-eslint/eslint-plugin": "^7.18.0",
33+
"@typescript-eslint/parser": "^7.18.0",
34+
"eslint": "^9.32.0",
35+
"eslint-plugin-prettier": "^5.5.3",
36+
"eslint-plugin-react": "^7.37.3",
37+
"eslint-plugin-react-hooks": "^5.2.0",
38+
"prettier": "^3.3.3"
2939
}
3040
}
Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,38 @@
1-
import Container from "@/app/_components/container";
2-
import { EXAMPLE_PATH } from "@/lib/constants";
3-
import cn from "classnames";
1+
import Container from '@/app/_components/container'
2+
import { EXAMPLE_PATH } from '@/lib/constants'
3+
import cn from 'classnames'
44

55
type Props = {
6-
preview?: boolean;
7-
};
6+
preview?: boolean
7+
}
88

99
const Alert = ({ preview }: Props) => {
1010
return (
1111
<div
12-
className={cn("border-b dark:bg-slate-800", {
13-
"bg-neutral-800 border-neutral-800 text-white": preview,
14-
"bg-neutral-50 border-neutral-200": !preview,
12+
className={cn('border-b dark:bg-slate-800', {
13+
'bg-neutral-800 border-neutral-800 text-white': preview,
14+
'bg-neutral-50 border-neutral-200': !preview,
1515
})}
1616
>
1717
<Container>
18-
<div className="alert py-2 text-center text-sm">
18+
<div className='alert py-2 text-center text-sm'>
1919
{preview ? (
2020
<>
21-
This page is a preview.{" "}
21+
This page is a preview.{' '}
2222
<a
23-
href="/api/exit-preview"
24-
className="underline hover:text-teal-300 duration-200 transition-colors"
23+
href='/api/exit-preview'
24+
className='underline hover:text-teal-300 duration-200 transition-colors'
2525
>
2626
Click here
27-
</a>{" "}
27+
</a>{' '}
2828
to exit preview mode.
2929
</>
3030
) : (
3131
<>
32-
The source code for this blog is{" "}
32+
The source code for this blog is{' '}
3333
<a
3434
href={`https://github.com/vercel/next.js/tree/canary/examples/${EXAMPLE_PATH}`}
35-
className="underline hover:text-blue-600 duration-200 transition-colors"
35+
className='underline hover:text-blue-600 duration-200 transition-colors'
3636
>
3737
available on GitHub
3838
</a>
@@ -42,7 +42,7 @@ const Alert = ({ preview }: Props) => {
4242
</div>
4343
</Container>
4444
</div>
45-
);
46-
};
45+
)
46+
}
4747

48-
export default Alert;
48+
export default Alert
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
type Props = {
2-
name: string;
3-
picture: string;
4-
};
2+
name: string
3+
picture: string
4+
}
55

66
const Avatar = ({ name, picture }: Props) => {
77
return (
8-
<div className="flex items-center">
9-
<img src={picture} className="w-12 h-12 rounded-full mr-4" alt={name} />
10-
<div className="text-xl font-bold">{name}</div>
8+
<div className='flex items-center'>
9+
<img src={picture} className='w-12 h-12 rounded-full mr-4' alt={name} />
10+
<div className='text-xl font-bold'>{name}</div>
1111
</div>
12-
);
13-
};
12+
)
13+
}
1414

15-
export default Avatar;
15+
export default Avatar
Lines changed: 25 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,52 @@
1-
"use client";
1+
'use client'
22

3-
import { Cheese } from "../interfaces/cheese";
4-
import { useState, useEffect } from "react";
3+
import { Cheese } from '../interfaces/cheese'
4+
import { useState, useEffect } from 'react'
55

66
type Props = {
7-
cheese: Cheese;
8-
};
7+
cheese: Cheese
8+
}
99

1010
export default function CheeseDetails({ cheese }: Props) {
11-
const [isLoading, setIsLoading] = useState(true);
12-
const excludedProperties = ["slug", "name", "description", "price"];
11+
const [isLoading, setIsLoading] = useState(true)
12+
const excludedProperties = ['slug', 'name', 'description', 'price']
1313

1414
useEffect(() => {
1515
const timer = setTimeout(() => {
16-
setIsLoading(false);
17-
}, 500);
16+
setIsLoading(false)
17+
}, 500)
1818

19-
return () => clearTimeout(timer);
20-
}, []);
19+
return () => clearTimeout(timer)
20+
}, [])
2121

2222
const details = Object.entries(cheese)
23-
.filter(
24-
([key, value]) =>
25-
!excludedProperties.includes(key) && value !== "NA" && value !== ""
26-
)
23+
.filter(([key, value]) => !excludedProperties.includes(key) && value !== 'NA' && value !== '')
2724
.map(([key, value]) => ({
28-
key: key.replace(/_/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()),
29-
value: typeof value === "boolean" ? String(value) : value,
30-
}));
25+
key: key.replace(/_/g, ' ').replace(/\b\w/g, (l) => l.toUpperCase()),
26+
value: typeof value === 'boolean' ? String(value) : value,
27+
}))
3128

3229
if (isLoading) {
3330
return (
34-
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mt-8">
31+
<div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-8'>
3532
{[...Array(6)].map((_, i) => (
36-
<div
37-
key={i}
38-
className="border p-4 rounded-lg animate-pulse bg-gray-100 dark:bg-gray-800"
39-
>
40-
<div className="h-4 w-24 bg-gray-200 dark:bg-gray-700 rounded"></div>
41-
<div className="h-6 w-32 bg-gray-200 dark:bg-gray-700 rounded mt-2"></div>
33+
<div key={i} className='border p-4 rounded-lg animate-pulse bg-gray-100 dark:bg-gray-800'>
34+
<div className='h-4 w-24 bg-gray-200 dark:bg-gray-700 rounded'></div>
35+
<div className='h-6 w-32 bg-gray-200 dark:bg-gray-700 rounded mt-2'></div>
4236
</div>
4337
))}
4438
</div>
45-
);
39+
)
4640
}
4741

4842
return (
49-
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mt-8">
43+
<div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-8'>
5044
{details.map(({ key, value }) => (
51-
<div key={key} className="border p-4 rounded-lg">
52-
<dt className="text-sm font-medium text-gray-500 dark:text-gray-400">
53-
{key}
54-
</dt>
55-
<dd className="mt-1 text-lg text-gray-900 dark:text-gray-100">
56-
{value}
57-
</dd>
45+
<div key={key} className='border p-4 rounded-lg'>
46+
<dt className='text-sm font-medium text-gray-500 dark:text-gray-400'>{key}</dt>
47+
<dd className='mt-1 text-lg text-gray-900 dark:text-gray-100'>{value}</dd>
5848
</div>
5949
))}
6050
</div>
61-
);
51+
)
6252
}
Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,24 @@
1-
import Link from "next/link";
2-
import type { Cheese } from "@/app/interfaces/cheese";
1+
import Link from 'next/link'
2+
import type { Cheese } from '@/app/interfaces/cheese'
33

44
type Props = {
5-
cheeses: Cheese[];
6-
};
5+
cheeses: Cheese[]
6+
}
77

88
export function CheeseGrid({ cheeses }: Props) {
99
return (
10-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
10+
<div className='grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8'>
1111
{cheeses.map((cheese) => (
12-
<Link
13-
key={cheese.slug}
14-
href={`/products/${cheese.slug}`}
15-
className="block group"
16-
>
17-
<div className="p-6 bg-white dark:bg-slate-800 rounded-lg shadow-lg transition-transform duration-200 ease-in-out group-hover:scale-105">
18-
<h3 className="text-xl font-bold mb-2">{cheese.name}</h3>
19-
<p className="text-gray-600 dark:text-gray-300 mb-4 line-clamp-2">
12+
<Link key={cheese.slug} href={`/products/${cheese.slug}`} className='block group'>
13+
<div className='p-6 bg-white dark:bg-slate-800 rounded-lg shadow-lg transition-transform duration-200 ease-in-out group-hover:scale-105'>
14+
<h3 className='text-xl font-bold mb-2'>{cheese.name}</h3>
15+
<p className='text-gray-600 dark:text-gray-300 mb-4 line-clamp-2'>
2016
{cheese.description}
2117
</p>
22-
<p className="font-bold">${cheese.price}</p>
18+
<p className='font-bold'>${cheese.price}</p>
2319
</div>
2420
</Link>
2521
))}
2622
</div>
27-
);
23+
)
2824
}
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
type Props = {
2-
children?: React.ReactNode;
3-
};
2+
children?: React.ReactNode
3+
}
44

55
const Container = ({ children }: Props) => {
6-
return <div className="container mx-auto px-5">{children}</div>;
7-
};
6+
return <div className='container mx-auto px-5'>{children}</div>
7+
}
88

9-
export default Container;
9+
export default Container

0 commit comments

Comments
 (0)