mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2025-11-05 06:45:39 -05:00
fix eslint 9 problems, especially in vs code
This commit is contained in:
36
.cursorrules
Normal file
36
.cursorrules
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
You are an expert in TypeScript, Node.js, Next.js 15 App Router, and React 19.
|
||||||
|
|
||||||
|
Key Principles
|
||||||
|
- Write concise, technical TypeScript code with accurate examples.
|
||||||
|
- Use functional and declarative programming patterns; avoid classes.
|
||||||
|
- Prefer iteration and modularization over code duplication.
|
||||||
|
- Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError).
|
||||||
|
- Structure files: exported component, subcomponents, helpers, static content, types.
|
||||||
|
|
||||||
|
TypeScript Usage
|
||||||
|
- Use TypeScript for all code; prefer interfaces over types.
|
||||||
|
- Avoid enums; use maps instead.
|
||||||
|
- Use functional components with TypeScript interfaces.
|
||||||
|
|
||||||
|
Syntax and Formatting
|
||||||
|
- Use declarative JSX.
|
||||||
|
- Follow Prettier and ESLint rules.
|
||||||
|
- Follow .editorconfig rules.
|
||||||
|
|
||||||
|
UI and Styling
|
||||||
|
- Use CSS Modules for components and styling.
|
||||||
|
|
||||||
|
Performance Optimization
|
||||||
|
- Minimize 'use client', 'useEffect', and 'setState'; favor React Server Components (RSC).
|
||||||
|
- Wrap client components in Suspense with fallback.
|
||||||
|
- Use dynamic loading for non-critical components.
|
||||||
|
- Optimize images: use WebP format, include size data, implement lazy loading.
|
||||||
|
|
||||||
|
Key Conventions
|
||||||
|
- Optimize Web Vitals (LCP, CLS, FID).
|
||||||
|
- Limit 'use client':
|
||||||
|
- Favor server components and Next.js SSR.
|
||||||
|
- Use only for Web API access in small components.
|
||||||
|
- Avoid for data fetching or state management.
|
||||||
|
|
||||||
|
Follow Next.js docs for Data Fetching, Rendering, and Routing.
|
||||||
2
.npmrc
Normal file
2
.npmrc
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
public-hoist-pattern[]=*eslint*
|
||||||
|
public-hoist-pattern[]=*prettier*
|
||||||
@@ -20,10 +20,10 @@ export async function sendMessage(
|
|||||||
success: boolean;
|
success: boolean;
|
||||||
message: string;
|
message: string;
|
||||||
errors?: z.inferFormattedError<typeof schema>;
|
errors?: z.inferFormattedError<typeof schema>;
|
||||||
payload: FormData;
|
payload?: FormData;
|
||||||
}> {
|
}> {
|
||||||
try {
|
try {
|
||||||
const validatedFields = schema.safeParse({ ...formData });
|
const validatedFields = schema.safeParse(Object.fromEntries(formData));
|
||||||
|
|
||||||
// backup to client-side validations just in case someone squeezes through without them
|
// backup to client-side validations just in case someone squeezes through without them
|
||||||
if (!validatedFields.success) {
|
if (!validatedFields.success) {
|
||||||
@@ -47,7 +47,13 @@ export async function sendMessage(
|
|||||||
remoteip: (await headers()).get("x-forwarded-for") || "",
|
remoteip: (await headers()).get("x-forwarded-for") || "",
|
||||||
}),
|
}),
|
||||||
cache: "no-store",
|
cache: "no-store",
|
||||||
|
signal: AbortSignal.timeout(5000), // 5 second timeout
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!turnstileResponse.ok) {
|
||||||
|
throw new Error(`Turnstile validation failed: ${turnstileResponse.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
const turnstileData = await turnstileResponse?.json();
|
const turnstileData = await turnstileResponse?.json();
|
||||||
|
|
||||||
if (!turnstileData?.success) {
|
if (!turnstileData?.success) {
|
||||||
@@ -70,7 +76,7 @@ export async function sendMessage(
|
|||||||
|
|
||||||
return { success: true, message: "Thanks! You should hear from me soon.", payload: formData };
|
return { success: true, message: "Thanks! You should hear from me soon.", payload: formData };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error("Contact form error:", error);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ import { SiMarkdown } from "react-icons/si";
|
|||||||
import styles from "./form.module.css";
|
import styles from "./form.module.css";
|
||||||
|
|
||||||
const ContactForm = () => {
|
const ContactForm = () => {
|
||||||
const [formState, formAction, pending] = useActionState<Partial<Awaited<ReturnType<typeof sendMessage>>>, FormData>(
|
const [formState, formAction, pending] = useActionState<Awaited<ReturnType<typeof sendMessage>>, FormData>(
|
||||||
sendMessage,
|
sendMessage,
|
||||||
{}
|
{ success: false, message: "" }
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { FlatCompat } from "@eslint/eslintrc";
|
import { FlatCompat } from "@eslint/eslintrc";
|
||||||
import js from "@eslint/js";
|
import js from "@eslint/js";
|
||||||
|
import { fixupConfigRules } from "@eslint/compat";
|
||||||
import prettierRecommended from "eslint-plugin-prettier/recommended";
|
import prettierRecommended from "eslint-plugin-prettier/recommended";
|
||||||
import customConfig from "@jakejarvis/eslint-config";
|
import customConfig from "@jakejarvis/eslint-config";
|
||||||
import * as mdx from "eslint-plugin-mdx";
|
import * as mdx from "eslint-plugin-mdx";
|
||||||
@@ -12,9 +13,12 @@ const compat = new FlatCompat({
|
|||||||
export default [
|
export default [
|
||||||
{ ignores: ["README.md", ".next", ".vercel", "node_modules"] },
|
{ ignores: ["README.md", ".next", ".vercel", "node_modules"] },
|
||||||
js.configs.recommended,
|
js.configs.recommended,
|
||||||
...compat.extends("next/core-web-vitals", "next/typescript"),
|
|
||||||
prettierRecommended,
|
|
||||||
...customConfig,
|
...customConfig,
|
||||||
|
...fixupConfigRules(
|
||||||
|
// https://github.com/vercel/next.js/issues/64114#issuecomment-2325268516
|
||||||
|
compat.extends("next/core-web-vitals", "next/typescript")
|
||||||
|
),
|
||||||
|
prettierRecommended,
|
||||||
{
|
{
|
||||||
rules: {
|
rules: {
|
||||||
"prettier/prettier": [
|
"prettier/prettier": [
|
||||||
|
|||||||
15
package.json
15
package.json
@@ -48,7 +48,7 @@
|
|||||||
"react-dom": "19.0.0",
|
"react-dom": "19.0.0",
|
||||||
"react-error-boundary": "^5.0.0",
|
"react-error-boundary": "^5.0.0",
|
||||||
"react-frame-component": "^5.2.7",
|
"react-frame-component": "^5.2.7",
|
||||||
"react-icons": "~5.5.0",
|
"react-icons": "5.5.0",
|
||||||
"react-innertext": "^1.1.5",
|
"react-innertext": "^1.1.5",
|
||||||
"react-is": "19.0.0",
|
"react-is": "19.0.0",
|
||||||
"react-textarea-autosize": "^8.5.7",
|
"react-textarea-autosize": "^8.5.7",
|
||||||
@@ -70,9 +70,10 @@
|
|||||||
"zod": "^3.24.2"
|
"zod": "^3.24.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@eslint/compat": "^1.2.7",
|
||||||
"@eslint/eslintrc": "^3.3.0",
|
"@eslint/eslintrc": "^3.3.0",
|
||||||
"@eslint/js": "^9.21.0",
|
"@eslint/js": "^9.21.0",
|
||||||
"@jakejarvis/eslint-config": "~4.0.7",
|
"@jakejarvis/eslint-config": "^4.0.7",
|
||||||
"@types/comma-number": "^2.1.2",
|
"@types/comma-number": "^2.1.2",
|
||||||
"@types/mdx": "^2.0.13",
|
"@types/mdx": "^2.0.13",
|
||||||
"@types/node": "^22.13.9",
|
"@types/node": "^22.13.9",
|
||||||
@@ -81,11 +82,13 @@
|
|||||||
"@types/react-dom": "^19.0.4",
|
"@types/react-dom": "^19.0.4",
|
||||||
"@types/react-is": "^19.0.0",
|
"@types/react-is": "^19.0.0",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "~9.21.0",
|
"eslint": "^9.21.0",
|
||||||
"eslint-config-next": "15.2.2-canary.1",
|
"eslint-config-next": "15.2.2-canary.1",
|
||||||
"eslint-config-prettier": "~10.0.2",
|
"eslint-config-prettier": "^10.0.2",
|
||||||
"eslint-plugin-mdx": "~3.1.5",
|
"eslint-plugin-mdx": "^3.1.5",
|
||||||
"eslint-plugin-prettier": "~5.2.3",
|
"eslint-plugin-prettier": "^5.2.3",
|
||||||
|
"eslint-plugin-react": "^7.37.4",
|
||||||
|
"eslint-plugin-react-hooks": "^5.2.0",
|
||||||
"lint-staged": "^15.4.3",
|
"lint-staged": "^15.4.3",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"prisma": "^6.4.1",
|
"prisma": "^6.4.1",
|
||||||
|
|||||||
34
pnpm-lock.yaml
generated
34
pnpm-lock.yaml
generated
@@ -96,7 +96,7 @@ importers:
|
|||||||
specifier: ^5.2.7
|
specifier: ^5.2.7
|
||||||
version: 5.2.7(prop-types@15.8.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
version: 5.2.7(prop-types@15.8.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
react-icons:
|
react-icons:
|
||||||
specifier: ~5.5.0
|
specifier: 5.5.0
|
||||||
version: 5.5.0(react@19.0.0)
|
version: 5.5.0(react@19.0.0)
|
||||||
react-innertext:
|
react-innertext:
|
||||||
specifier: ^1.1.5
|
specifier: ^1.1.5
|
||||||
@@ -156,6 +156,9 @@ importers:
|
|||||||
specifier: ^3.24.2
|
specifier: ^3.24.2
|
||||||
version: 3.24.2
|
version: 3.24.2
|
||||||
devDependencies:
|
devDependencies:
|
||||||
|
'@eslint/compat':
|
||||||
|
specifier: ^1.2.7
|
||||||
|
version: 1.2.7(eslint@9.21.0)
|
||||||
'@eslint/eslintrc':
|
'@eslint/eslintrc':
|
||||||
specifier: ^3.3.0
|
specifier: ^3.3.0
|
||||||
version: 3.3.0
|
version: 3.3.0
|
||||||
@@ -163,7 +166,7 @@ importers:
|
|||||||
specifier: ^9.21.0
|
specifier: ^9.21.0
|
||||||
version: 9.21.0
|
version: 9.21.0
|
||||||
'@jakejarvis/eslint-config':
|
'@jakejarvis/eslint-config':
|
||||||
specifier: ~4.0.7
|
specifier: ^4.0.7
|
||||||
version: 4.0.7(eslint@9.21.0)
|
version: 4.0.7(eslint@9.21.0)
|
||||||
'@types/comma-number':
|
'@types/comma-number':
|
||||||
specifier: ^2.1.2
|
specifier: ^2.1.2
|
||||||
@@ -190,20 +193,26 @@ importers:
|
|||||||
specifier: ^7.0.3
|
specifier: ^7.0.3
|
||||||
version: 7.0.3
|
version: 7.0.3
|
||||||
eslint:
|
eslint:
|
||||||
specifier: ~9.21.0
|
specifier: ^9.21.0
|
||||||
version: 9.21.0
|
version: 9.21.0
|
||||||
eslint-config-next:
|
eslint-config-next:
|
||||||
specifier: 15.2.2-canary.1
|
specifier: 15.2.2-canary.1
|
||||||
version: 15.2.2-canary.1(eslint@9.21.0)(typescript@5.7.3)
|
version: 15.2.2-canary.1(eslint@9.21.0)(typescript@5.7.3)
|
||||||
eslint-config-prettier:
|
eslint-config-prettier:
|
||||||
specifier: ~10.0.2
|
specifier: ^10.0.2
|
||||||
version: 10.0.2(eslint@9.21.0)
|
version: 10.0.2(eslint@9.21.0)
|
||||||
eslint-plugin-mdx:
|
eslint-plugin-mdx:
|
||||||
specifier: ~3.1.5
|
specifier: ^3.1.5
|
||||||
version: 3.1.5(eslint@9.21.0)
|
version: 3.1.5(eslint@9.21.0)
|
||||||
eslint-plugin-prettier:
|
eslint-plugin-prettier:
|
||||||
specifier: ~5.2.3
|
specifier: ^5.2.3
|
||||||
version: 5.2.3(@types/eslint@9.6.1)(eslint-config-prettier@10.0.2(eslint@9.21.0))(eslint@9.21.0)(prettier@3.5.3)
|
version: 5.2.3(@types/eslint@9.6.1)(eslint-config-prettier@10.0.2(eslint@9.21.0))(eslint@9.21.0)(prettier@3.5.3)
|
||||||
|
eslint-plugin-react:
|
||||||
|
specifier: ^7.37.4
|
||||||
|
version: 7.37.4(eslint@9.21.0)
|
||||||
|
eslint-plugin-react-hooks:
|
||||||
|
specifier: ^5.2.0
|
||||||
|
version: 5.2.0(eslint@9.21.0)
|
||||||
lint-staged:
|
lint-staged:
|
||||||
specifier: ^15.4.3
|
specifier: ^15.4.3
|
||||||
version: 15.4.3
|
version: 15.4.3
|
||||||
@@ -467,6 +476,15 @@ packages:
|
|||||||
resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==}
|
resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==}
|
||||||
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
|
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
|
||||||
|
|
||||||
|
'@eslint/compat@1.2.7':
|
||||||
|
resolution: {integrity: sha512-xvv7hJE32yhegJ8xNAnb62ggiAwTYHBpUCWhRxEj/ksvgDJuSXfoDkBcRYaYNFiJ+jH0IE3K16hd+xXzhBgNbg==}
|
||||||
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
peerDependencies:
|
||||||
|
eslint: ^9.10.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
eslint:
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@eslint/config-array@0.19.2':
|
'@eslint/config-array@0.19.2':
|
||||||
resolution: {integrity: sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==}
|
resolution: {integrity: sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
@@ -4481,6 +4499,10 @@ snapshots:
|
|||||||
|
|
||||||
'@eslint-community/regexpp@4.12.1': {}
|
'@eslint-community/regexpp@4.12.1': {}
|
||||||
|
|
||||||
|
'@eslint/compat@1.2.7(eslint@9.21.0)':
|
||||||
|
optionalDependencies:
|
||||||
|
eslint: 9.21.0
|
||||||
|
|
||||||
'@eslint/config-array@0.19.2':
|
'@eslint/config-array@0.19.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint/object-schema': 2.1.6
|
'@eslint/object-schema': 2.1.6
|
||||||
|
|||||||
Reference in New Issue
Block a user