## General Information
### How to Know If You're Using Next.js
Next.js is a powerful framework for building websites. Here’s how to check if you're using it:
- Folders and Files: If your project contains `pages` or `app` directories and files ending in `.jsx` or `.tsx`, that’s a strong sign of Next.js.
- Directives `use client` and `use server`: These special tags at the top of files indicate whether the code runs on the user's computer (`use client`) or the server (`use server`). If you see these, you're definitely using Next.js.
#### Important About React:
You're using React v19, but keep in mind that the new React Compiler (which speeds up code) does not work with Next.js 15. This isn't a big deal—just something to remember.
---
### `use client` and `use server` Directives
These directives help Next.js determine where to run your code. Here’s how to use them:
- Always specify a directive: At the beginning of every file, write either `'use client';` or `'use server';` to avoid confusion.
- `use client` for interactivity: If the component has interactive elements like buttons, forms, `useState`, or other hooks, use `'use client';`.
```tsx
'use client';
import { useState } from 'react';
export default function Button() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>Click: {count}</button>;
}
```
- `use server` for static content: If the component only displays information (text, images) and doesn’t change based on user actions, use `'use server';`.
```tsx
'use server';
export default function Title() {
return <h1>Hello, this is a static title!</h1>;
}
```
---
### Break Components into Chunks
To keep your site fast and efficient, divide it into small parts (chunks) and use smart loading techniques.
- Create small components: Instead of one huge file, make separate components for headers, lists, cards, etc.
- Use server-side rendering: Let the server prepare the page in advance so users don’t have to wait. Next.js automatically does this for `'use server'` components.
- Lazy load large data sets: If you have lots of data (e.g., a list of 1,000 products), load it in parts as the user scrolls.
- For images: Use Next.js's `<Image>` component and enable lazy loading.
```tsx
import Image from 'next/image';
export default function MyImage() {
return <Image src="/example.jpg" width={500} height={500} loading="lazy" alt="Example" />;
}
```
This means the image loads only when it appears on screen.
- Prioritize client-side components: If you have many cards (e.g., product listings), control how many are displayed at once.
```tsx
'use client';
import { useState } from 'react';
export default function CardList({ items }) {
const [visibleCount, setVisibleCount] = useState(10); // Show 10 cards initially
return (
<>
{items.slice(0, visibleCount).map(item => <Card key={item.id} {...item} />)}
<button onClick={() => setVisibleCount(visibleCount + 10)}>Load more</button>
</>
);
}
```
- For large tables and lists: If you have a table with 1,000+ rows, use `react-virtualized/List`. This library only renders visible rows, loading others as the user scrolls.
---
### Data Validation
Validation ensures users enter correct information in forms.
- Simple validation: Use built-in HTML features.
```html
<input type="email" required />
```
The browser will automatically check if a valid email is entered.
- Advanced validation: If you need more complex rules (e.g., a password with at least 8 characters and numbers), use Arktype v2.
```tsx
import { type } from 'arktype';
const user = type({
password: 'string>=8 & string.match(/[0-9]/)'
});
console.log(user('pass1234')); // Error: too short
console.log(user('password123')); // Success!
```
---
### Working with Databases
Databases store your website’s data (users, products, etc.).
- Avoid Prisma: In your case, Prisma is not the best choice.
- Choose the right tool:
- Drizzle – Best for SQL databases (e.g., PostgreSQL). Lightweight and fast.
- Mongoose – Best for MongoDB (NoSQL).
- Use transactions for multi-step operations: If you need to perform multiple actions (e.g., deduct money and place an order), transactions ensure everything succeeds or nothing happens.
```tsx
await db.transaction(async (tx) => {
await tx.update(accounts).set({ balance: balance - 100 });
await tx.insert(orders).values({ userId, amount: 100 });
});
```
---
### Caching
Caching prevents fetching the same data repeatedly.
- Store responses: If you fetch a product list from the server, save it in cache to avoid unnecessary requests.
- Update cache when data changes: When new data is added (e.g., a new product), update the cache so users see fresh content.