Skip to content

Commit 0c6ccf9

Browse files
committed
feat: upgrade next.js and react versions to latest
1 parent 4895825 commit 0c6ccf9

File tree

9 files changed

+3997
-3842
lines changed

9 files changed

+3997
-3842
lines changed

CLAUDE.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
This is a personal blog and portfolio website built with Next.js (Pages Router), TypeScript, and Tailwind CSS. The site features MDX-based blog posts in Portuguese and English, with analytics integration (PostHog, Google Analytics, GTM, Microsoft Clarity).
8+
9+
## Development Commands
10+
11+
### Running the project
12+
13+
- `pnpm dev` - Start development server
14+
- `pnpm build` - Build for production
15+
- `pnpm start` - Start production server
16+
- `pnpm lint` - Run ESLint
17+
- `pnpm check-types` - Run TypeScript type checking without emitting files
18+
19+
### Testing
20+
21+
- `pnpm test` - Run Jest tests
22+
- `pnpm test:watch` - Run Jest in watch mode
23+
- `pnpm test -- path/to/file.spec.tsx` - Run a single test file
24+
- Test files use `.spec.tsx` naming convention
25+
26+
### Note on Package Manager
27+
28+
This project uses `pnpm` as the package manager (see `packageManager` field in package.json).
29+
30+
## Architecture & Key Patterns
31+
32+
### Blog System Architecture
33+
34+
The blog is powered by MDX files stored in the `/posts` directory. The system uses:
35+
36+
- **MDX Processing**: Uses `next-mdx-remote` for serializing MDX content with plugins:
37+
- `remark-gfm` for GitHub Flavored Markdown
38+
- `rehype-slug` and `rehype-autolink-headings` for auto-generated heading anchors
39+
- `rehype-prism` for syntax highlighting
40+
- **Post Utilities** (`src/utils/mdx.ts`): Central location for MDX processing logic
41+
- `getPosts()` - Fetches all posts and sorts by date
42+
- `getMdxSerializedPost(slug)` - Serializes a single post for rendering
43+
- `getPreviousOrNextPostBySlug(slug, type)` - Gets adjacent posts for navigation
44+
45+
### Pages Structure (Next.js Pages Router)
46+
47+
- `/src/pages/index.tsx` - Home page with recent posts
48+
- `/src/pages/blog/index.tsx` - Blog listing page
49+
- `/src/pages/blog/[slug].tsx` - Individual blog post (dynamic route using MDX)
50+
- `/src/pages/linktree.tsx` - Social links page
51+
- `/src/pages/about.tsx` - About page
52+
53+
### Styling System
54+
55+
- Uses Tailwind CSS with custom typography plugin configuration
56+
- Custom fonts: Poppins (sans) and Lora (serif) loaded via `next/font/google`
57+
- Dark mode support via `darkMode: 'class'` in Tailwind config
58+
- Extensive typography customization in `tailwind.config.js` for MDX content rendering
59+
60+
### Component Organization
61+
62+
Components follow a feature-based structure in `/src/components`:
63+
64+
- Each component has its own directory with index file
65+
- `MDXImage.tsx` - Custom image component for MDX with Next.js Image optimization
66+
- `CodeBlock` and `Pre` - Custom code rendering components
67+
- `Layout` - Main layout wrapper
68+
- `ui/` - Reusable UI components (shadcn/ui style)
69+
70+
### Analytics Integration
71+
72+
Multiple analytics providers are initialized in `_app.tsx`:
73+
74+
- PostHog (product analytics)
75+
- Google Analytics (via gtag)
76+
- Google Tag Manager
77+
- Microsoft Clarity
78+
79+
All analytics IDs are configured via environment variables (see `.env.example`).
80+
81+
### Path Aliases
82+
83+
TypeScript and build tools use `@/*` to alias `src/*` (configured in `tsconfig.json` and `jest.config.js`).
84+
85+
### Content Security & SEO
86+
87+
- Security headers configured in `next.config.js` (HSTS, XSS protection, frame options, etc.)
88+
- Structured data for SEO using JSON-LD schema
89+
- `next-seo` for OpenGraph and Twitter Card metadata
90+
- RSS feed generation via `next-sitemap` (runs on `postbuild`)
91+
- Sitemap automatically generated after build
92+
93+
### Image Optimization
94+
95+
- Uses `@plaiceholder/next` for blur placeholder generation
96+
- Custom utility for processing images in `/src/utils/images.ts`
97+
- To create tiny blur placeholders: `ffmpeg -i <FILENAME>.<EXTENSION> -vf scale=20:-1 <FILENAME>-small.<EXTENSION>`
98+
99+
### Git Workflow
100+
101+
- Uses Husky for git hooks
102+
- Commitizen for conventional commits (`cz-conventional-changelog`)
103+
- Lint-staged runs ESLint and Prettier on staged files
104+
- Commitlint enforces conventional commit messages
105+
106+
### Functional Programming
107+
108+
Uses `fp-ts` library for functional programming patterns (see `src/utils/mdx.ts` for examples with Option and Array utilities).
109+
110+
## Common Patterns
111+
112+
### Adding a New Blog Post
113+
114+
1. Create a new `.mdx` file in `/posts` directory
115+
2. Include frontmatter with: `title`, `description`, `publishedTime`, `modifiedTime`, `tags`, `href`, `image` object (with `src`, `placeholder`, `type`), `reactionsLength`, `commentsLength`
116+
3. The post will automatically appear on the blog index and home page (sorted by date)
117+
118+
### Working with MDX Components
119+
120+
Custom MDX components are defined in `/src/pages/blog/[slug].tsx`:
121+
122+
- `pre` → Custom `Pre` component
123+
- `code` → Custom `CodeBlock` component
124+
- `img` / `Image` → Custom `MDXImage` component
125+
126+
### Extending Analytics
127+
128+
To add tracking events, use PostHog's `posthog.capture()` method (PostHog is initialized globally in `_app.tsx`).

eslint.config.mjs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { defineConfig } from "eslint/config";
2+
import nextCoreWebVitals from "eslint-config-next/core-web-vitals";
3+
import path from "node:path";
4+
import { fileURLToPath } from "node:url";
5+
6+
const __filename = fileURLToPath(import.meta.url);
7+
const __dirname = path.dirname(__filename);
8+
9+
export default defineConfig([{
10+
extends: [...nextCoreWebVitals],
11+
}]);

next.config.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
//@ts-check
22

3-
// eslint-disable-next-line
43
// @typescript-eslint/no-var-requires
54
const withMDX = require('@next/mdx')({
65
extension: /\.mdx?$/,
@@ -17,7 +16,6 @@ const { withPlaiceholder } = require('@plaiceholder/next')
1716
* @type {import('next').NextConfig}
1817
**/
1918
const nextConfig = {
20-
swcMinify: true,
2119
reactStrictMode: true,
2220
images: {
2321
remotePatterns: [

package.json

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,61 +8,58 @@
88
"start": "next start",
99
"test": "jest",
1010
"test:watch": "jest --watch",
11-
"lint": "next lint",
11+
"lint": "eslint .",
1212
"check-types": "tsc --noEmit",
1313
"prepare": "husky install",
1414
"postbuild": "next-sitemap"
1515
},
1616
"dependencies": {
17-
"@fec/remark-a11y-emoji": "^3.1.0",
18-
"@headlessui/react": "^1.7.3",
17+
"@fec/remark-a11y-emoji": "^4.0.2",
18+
"@headlessui/react": "^2.2.9",
1919
"@heroicons/react": "^2.0.12",
20-
"@mapbox/rehype-prism": "^0.8.0",
2120
"@mdx-js/loader": "^2.1.5",
2221
"@mdx-js/react": "^2.1.5",
23-
"@next/mdx": "^13.0.4",
22+
"@next/mdx": "16.0.7",
2423
"@plaiceholder/next": "^2.5.0",
2524
"@radix-ui/react-slot": "^1.2.3",
2625
"@radix-ui/react-tooltip": "^1.2.7",
2726
"@tailwindcss/postcss": "^4.1.8",
2827
"@types/lodash": "^4.17.17",
2928
"@types/matter-js": "^0.19.8",
3029
"@types/rss": "^0.0.32",
31-
"@vercel/analytics": "^0.1.3",
30+
"@vercel/analytics": "^1.6.1",
3231
"autoprefixer": "^10.4.20",
3332
"class-variance-authority": "^0.7.1",
3433
"clsx": "^1.2.1",
3534
"core-js": "^3.6.5",
3635
"fp-ts": "^2.13.1",
3736
"glob": "^8.0.3",
3837
"gray-matter": "^4.0.3",
39-
"hastscript": "^7.1.0",
38+
"hastscript": "^9.0.1",
4039
"lodash": "^4.17.21",
4140
"lucide-react": "^0.474.0",
4241
"marked": "^4.1.1",
4342
"matter-js": "^0.20.0",
4443
"motion": "^12.16.0",
4544
"nanoid": "^4.0.0",
46-
"next": "14.2.29",
47-
"next-mdx-remote": "^4.1.0",
45+
"next": "16.0.7",
46+
"next-mdx-remote": "^5.0.0",
4847
"next-seo": "^5.8.0",
4948
"next-sitemap": "^3.1.29",
5049
"plaiceholder": "^2.5.0",
5150
"poly-decomp": "^0.3.0",
5251
"postcss": "^8.5.4",
5352
"posthog-js": "^1.187.2",
54-
"react": "18",
55-
"react-confetti": "^6.1.0",
56-
"react-dom": "18",
53+
"react": "19.2.1",
54+
"react-confetti": "^6.4.0",
55+
"react-dom": "19.2.1",
5756
"react-syntax-highlighter": "^15.5.0",
5857
"react-use": "^17.5.1",
5958
"regenerator-runtime": "0.13.7",
60-
"rehype-autolink-headings": "^6.1.1",
61-
"rehype-slug": "^5.0.1",
62-
"rehype-stringify": "^9.0.3",
63-
"remark-gfm": "^3.0.1",
64-
"remark-parse": "^10.0.1",
65-
"remark-rehype": "^10.1.0",
59+
"rehype-autolink-headings": "^7.1.0",
60+
"rehype-prism-plus": "^2.0.1",
61+
"rehype-slug": "^6.0.0",
62+
"remark-gfm": "^4.0.1",
6663
"rss": "^1.2.2",
6764
"sharp": "^0.31.2",
6865
"svg-path-commander": "^2.1.11",
@@ -77,39 +74,39 @@
7774
"@swc-node/register": "^1.4.2",
7875
"@swc/core": "^1.2.173",
7976
"@tailwindcss/typography": "^0.5.16",
77+
"@testing-library/dom": "^10.0.0",
8078
"@testing-library/jest-dom": "^5.16.5",
81-
"@testing-library/react": "13.4.0",
79+
"@testing-library/react": "16.3.0",
8280
"@types/glob": "^8.0.0",
8381
"@types/jest": "29.2.3",
8482
"@types/node": "18.11.9",
85-
"@types/react": "18.0.25",
86-
"@types/react-dom": "18.0.9",
83+
"@types/react": "19.2.7",
84+
"@types/react-dom": "19.2.3",
8785
"@types/react-syntax-highlighter": "^15.5.5",
88-
"@typescript-eslint/eslint-plugin": "^5.44.0",
89-
"@typescript-eslint/parser": "^5.44.0",
86+
"@typescript-eslint/eslint-plugin": "^8.48.1",
87+
"@typescript-eslint/parser": "^8.48.1",
9088
"babel-jest": "29.3.1",
9189
"cypress": "^11.2.0",
9290
"cz-conventional-changelog": "^3.3.0",
93-
"eslint": "8.28.0",
94-
"eslint-config-next": "14.2.29",
91+
"eslint": "^9.39.1",
92+
"eslint-config-next": "16.0.7",
9593
"eslint-config-prettier": "8.5.0",
9694
"eslint-plugin-cypress": "^2.12.1",
97-
"eslint-plugin-import": "2.26.0",
98-
"eslint-plugin-jsx-a11y": "6.6.1",
99-
"eslint-plugin-react": "7.31.11",
100-
"eslint-plugin-react-hooks": "4.6.0",
95+
"eslint-plugin-import": "2.32.0",
96+
"eslint-plugin-jsx-a11y": "6.10.2",
97+
"eslint-plugin-react": "7.37.5",
98+
"eslint-plugin-react-hooks": "7.0.1",
10199
"husky": "^8.0.1",
102-
"jest": "28.1.1",
103-
"jest-environment-jsdom": "28.1.1",
100+
"jest": "29.7.0",
101+
"jest-environment-jsdom": "29.7.0",
104102
"lint-staged": "^13.0.3",
105103
"prettier": "^2.6.2",
106-
"react-test-renderer": "18.2.0",
107104
"rehype-prism": "link:@types/@mapbox/rehype-prism",
108105
"remark-a11y-emoji": "link:@types/@fec/remark-a11y-emoji",
109-
"ts-jest": "28.0.5",
106+
"ts-jest": "29.4.6",
110107
"ts-node": "10.9.1",
111108
"tw-animate-css": "^1.3.3",
112-
"typescript": "4.9.3"
109+
"typescript": "5.9.3"
113110
},
114111
"config": {
115112
"commitizen": {
@@ -125,5 +122,11 @@
125122
"prettier --write"
126123
]
127124
},
128-
"packageManager": "pnpm@9.15.0"
125+
"packageManager": "pnpm@9.15.0",
126+
"pnpm": {
127+
"overrides": {
128+
"@types/react": "19.2.7",
129+
"@types/react-dom": "19.2.3"
130+
}
131+
}
129132
}

0 commit comments

Comments
 (0)