Next.js is a powerful React framework that enables functionalities such as server-side rendering, static site generation, and API routes out-of-the-box. It simplifies routing, improves performance, and offers excellent developer experience.
<!-- Next.js is not written like this in HTML but installed as a project using Node.js --> <!-- Example: Create a Next.js app --> npx create-next-app@latest my-nextjs-app
Unlike React which is only a library for building UI, Next.js comes with routing, server-side rendering (SSR), static generation, and performance optimizations built-in.
<!-- Benefits include: --> - File-based routing - SSR and SSG support - API routes - Improved performance with Image Optimization - Built-in CSS and Sass support
Next.js uses a conventional folder structure. Key folders include:
<!-- Folder structure after creating a Next.js app --> my-nextjs-app/ ├── pages/ <!-- Contains all route-related React components --> ├── public/ <!-- Static assets like images and favicon go here --> ├── styles/ <!-- Global and modular CSS files --> ├── node_modules/ <!-- Installed packages --> └── next.config.js <!-- Configuration file for Next.js -->
To install Next.js, Node.js must be installed first. You can then use the command below:
<!-- Command to install Next.js --> npx create-next-app@latest <!-- or with a project name --> npx create-next-app@latest my-app
Once created, you can run the development server using:
<!-- Navigate into the directory and run --> cd my-app npm run dev <!-- Output --> > Ready on http://localhost:3000
Each file inside the pages/
directory automatically becomes a route.
<!-- pages/index.js becomes '/' --> export default function Home() { return <h1>Welcome to Home Page</h1>; <!-- Displayed on / --> } <!-- pages/about.js becomes '/about' --> export default function About() { return <h1>About Us Page</h1>; <!-- Displayed on /about --> }
The public/
folder is used for static files accessible by URL. Other files are private and not accessible directly by browser.
<!-- Example: placing image in public folder --> public/logo.png <!-- Access in JSX --> <img src="/logo.png" alt="Logo" /> <!-- Files outside public/ are not directly accessible -->
Next.js provides a built-in Link
component to navigate between pages without full page reloads.
<!-- Example of linking from one page to another --> import Link from 'next/link'; export default function Home() { return ( <div> <h1>Home Page</h1> <Link href="/about"> <a>Go to About Page</a> </Link> </div> ); }
You can use global CSS or module CSS for scoped styles. Modules are recommended for component-level styles.
<!-- styles/Home.module.css --> .title { color: blue; font-size: 30px; } <!-- Importing in component --> import styles from '../styles/Home.module.css'; export default function Home() { return <h1 className={styles.title}>Styled Heading</h1>; }
Use .env.local
for storing environment variables. Keep secrets out of version control.
<!-- .env.local --> NEXT_PUBLIC_API_URL=https://api.example.com <!-- Access in code --> const apiUrl = process.env.NEXT_PUBLIC_API_URL;
Next.js uses the file system to define routes. Each file inside the pages/
folder becomes a route automatically.
<!-- pages/index.js maps to '/' --> export default function Home() { return <h1>Home Page</h1>; } <!-- pages/about.js maps to '/about' --> export default function About() { return <h1>About Page</h1>; }
Dynamic routes are created using square brackets in the filename. Useful for user profiles, blog posts, etc.
<!-- pages/user/[id].js handles routes like /user/1 or /user/abc --> import { useRouter } from 'next/router'; export default function User() { const router = useRouter(); const { id } = router.query; <!-- Access dynamic route parameter --> return <h1>User ID: {id}</h1>; }
To create nested routes, use folders inside the pages/
directory.
<!-- pages/blog/index.js becomes /blog --> <!-- pages/blog/post.js becomes /blog/post --> // pages/blog/index.js export default function Blog() { return <h1>Blog Home</h1>; } // pages/blog/post.js export default function Post() { return <h1>Blog Post Page</h1>; }
Catch-all routes match multiple segments. Use three dots inside brackets.
<!-- pages/docs/[...params].js matches /docs/a, /docs/a/b/c etc. --> import { useRouter } from 'next/router'; export default function Docs() { const router = useRouter(); const { params = [] } = router.query; return ( <div> <h1>Catch-All Params:</h1> <ul> {params.map((param, i) => ( <li key={i}>{param}</li> ))} </ul> </div> ); }
Route groups (folder names in double parentheses) help organize code but do not affect URL paths.
<!-- app/((auth))/login/page.js renders on /login, not /auth/login --> export default function LoginPage() { return <h1>Login Page</h1>; }
Layouts can be shared across multiple pages using special @layout.js
files in the app/
directory.
<!-- app/layout.js applies to all nested pages --> export default function RootLayout({ children }) { return ( <html> <body> <header>Site Header</header> {children} <footer>Site Footer</footer> </body> </html> ); }
Next.js supports custom 404 pages by creating a pages/404.js
file.
<!-- pages/404.js --> export default function Custom404() { return <h1>404 - Page Not Found</h1>; }
Middleware allows you to run logic before rendering pages. Useful for redirects, auth checks, etc.
<!-- middleware.js at root level --> import { NextResponse } from 'next/server'; export function middleware(request) { const isLoggedIn = false; <!-- Replace with real auth logic --> if (!isLoggedIn && request.nextUrl.pathname.startsWith('/dashboard')) { return NextResponse.redirect(new URL('/login', request.url)); } return NextResponse.next(); }
Configure URL redirects or rewrites in next.config.js
.
// next.config.js module.exports = { async redirects() { return [ { source: '/old-path', destination: '/new-path', permanent: true, }, ]; }, async rewrites() { return [ { source: '/api/:path*', destination: 'https://externalapi.com/:path*', }, ]; }, };
Use the useRouter()
hook to navigate programmatically between routes.
import { useRouter } from 'next/router'; export default function NavigateButton() { const router = useRouter(); const goToAbout = () => { router.push('/about'); <!-- Navigates to /about --> }; return <button onClick={goToAbout}>Go to About</button>; }
Shared layouts provide consistent structure (header, footer, sidebar) across multiple pages using layout wrappers.
// components/Layout.js export default function Layout({ children }) { return ( <div> <header>My App Header</header> <main>{children}</main> <footer>My App Footer</footer> </div> ); } // pages/_app.js import Layout from '../components/Layout'; export default function MyApp({ Component, pageProps }) { return ( <Layout> <Component {...pageProps} /> </Layout> ); }
Layout components break down page structure into reusable parts such as headers, footers, and sidebars.
// components/Header.js export default function Header() { return <header>Site Header</header>; } // components/Footer.js export default function Footer() { return <footer>Site Footer</footer>; } // components/Layout.js import Header from './Header'; import Footer from './Footer'; export default function Layout({ children }) { return ( <> <Header /> {children} <Footer /> </> ); }
Use the next/head
component to insert page-specific metadata like titles and meta descriptions.
import Head from 'next/head'; export default function AboutPage() { return ( <> <Head> <title>About Us</title> <meta name="description" content="Learn more about us." /> </Head> <h1>About</h1> </> ); }
Define navigation and footer components for consistent user experience across pages.
// components/Navbar.js import Link from 'next/link'; export default function Navbar() { return ( <nav> <Link href="/">Home</Link> | <Link href="/about">About</Link> </nav> ); } // components/Footer.js export default function Footer() { return <footer>© 2025 MyApp</footer>; }
Create flexible UI elements like buttons or cards that can be reused throughout the app.
// components/Button.js export default function Button({ label, onClick }) { return <button onClick={onClick}>{label}</button>; } // Usage <Button label="Click Me" onClick={() => alert('Clicked!')} />
Props allow you to pass data into components from parent to child for dynamic rendering.
// components/Greeting.js export default function Greeting({ name }) { return <p>Hello, {name}!</p>; } // Usage <Greeting name="Alice" />
Use global CSS or CSS Modules to style your app consistently. Define global styles in styles/globals.css
.
// styles/globals.css body { font-family: sans-serif; background: #f8f9fa; } // pages/_app.js import '../styles/globals.css'; export default function MyApp({ Component, pageProps }) { return <Component {...pageProps} />; }
You can conditionally use different layouts by adding a getLayout
function per page.
// pages/about.js const About = () => <h1>About Us</h1>; About.getLayout = function getLayout(page) { return ( <div style={{ border: '2px solid blue' }}> <h2>Custom Layout</h2> {page} </div> ); }; export default About; // pages/_app.js export default function MyApp({ Component, pageProps }) { const getLayout = Component.getLayout || ((page) => page); return getLayout(<Component {...pageProps} />); }
Use conditions (if, ternary, &&) to render UI based on logic such as user status or state.
export default function Dashboard({ isLoggedIn }) { return ( <div> {isLoggedIn ? <p>Welcome back!</p> : <p>Please log in.</p>} </div> ); }
Switch themes using context, CSS classes, or Tailwind dark mode utilities.
// components/ThemeSwitcher.js import { useState } from 'react'; export default function ThemeSwitcher() { const [dark, setDark] = useState(false); return ( <div className={dark ? 'dark-mode' : 'light-mode'}> <button onClick={() => setDark(!dark)}> Switch to {dark ? 'Light' : 'Dark'} Mode </button> <p>Current theme: {dark ? 'Dark' : 'Light'}</p> </div> ); } // styles (e.g. global.css or inline) .dark-mode { background: black; color: white; } .light-mode { background: white; color: black; }
Pre-renders the page at build time. Ideal for static content that doesn't change often.
// pages/posts.js export async function getStaticProps() { const res = await fetch('https://jsonplaceholder.typicode.com/posts'); const posts = await res.json(); return { props: { posts }, }; } export default function Posts({ posts }) { return ( <ul> {posts.map(post => ( <li key={post.id}>{post.title}</li> ))} </ul> ); }
Fetches data on every request. Good for dynamic data that changes frequently.
// pages/news.js export async function getServerSideProps() { const res = await fetch('https://api.example.com/news'); const news = await res.json(); return { props: { news }, }; } export default function News({ news }) { return ( <div> {news.map(item => ( <p key={item.id}>{item.title}</p> ))} </div> ); }
Update static pages after build time by specifying a revalidate
interval.
// pages/blog.js export async function getStaticProps() { const res = await fetch('https://api.example.com/blog'); const data = await res.json(); return { props: { data }, revalidate: 10, // Regenerate page every 10 seconds }; } export default function Blog({ data }) { return ( <div> {data.map(post => ( <h2 key={post.id}>{post.title}</h2> ))} </div> ); }
Use useEffect
and useState
to fetch data after the component mounts.
import { useEffect, useState } from 'react'; export default function Users() { const [users, setUsers] = useState([]); useEffect(() => { fetch('https://jsonplaceholder.typicode.com/users') .then(res => res.json()) .then(data => setUsers(data)); }, []); return ( <ul> {users.map(user => ( <li key={user.id}>{user.name}</li> ))} </ul> ); }
Call external RESTful endpoints using fetch
, axios
, etc.
import { useEffect, useState } from 'react'; import axios from 'axios'; export default function Products() { const [products, setProducts] = useState([]); useEffect(() => { axios.get('https://fakestoreapi.com/products') .then(res => setProducts(res.data)); }, []); return ( <ul> {products.map(p => ( <li key={p.id}>{p.title}</li> ))} </ul> ); }
Use libraries like Apollo Client or simple fetch
to query GraphQL APIs.
// Sample GraphQL Query using fetch const query = ` { countries { code name } } `; export default function GraphQLExample() { const [data, setData] = useState([]); useEffect(() => { fetch('https://countries.trevorblades.com/', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query }), }) .then(res => res.json()) .then(result => setData(result.data.countries)); }, []); return ( <ul> {data.map(c => ( <li key={c.code}>{c.name}</li> ))} </ul> ); }
A React hook for fetching data. Returns cached data first and revalidates in background.
import useSWR from 'swr'; const fetcher = url => fetch(url).then(res => res.json()); export default function Profile() { const { data, error } = useSWR('/api/user', fetcher); if (error) return <div>Failed to load</div>; if (!data) return <div>Loading...</div>; return <div>Hello, {data.name}</div>; }
React Query helps with caching, pagination, background refetching, etc.
import { useQuery } from '@tanstack/react-query'; const fetchUsers = async () => { const res = await fetch('https://jsonplaceholder.typicode.com/users'); return res.json(); }; export default function Users() { const { data, isLoading, error } = useQuery({ queryKey: ['users'], queryFn: fetchUsers, }); if (isLoading) return <div>Loading...</div>; if (error) return <div>Error!</div>; return ( <ul> {data.map(u => ( <li key={u.id}>{u.name}</li> ))} </ul> ); }
Control caching behavior with HTTP headers, SWR, React Query, or ISR. Choose between stale-while-revalidate, client memory, or API-side caching.
// Example: ISR with cache-time of 30 seconds export async function getStaticProps() { const res = await fetch('https://api.example.com/data'); const data = await res.json(); return { props: { data }, revalidate: 30, }; }
Always handle loading, error, and empty states in your fetch logic for a better user experience.
import { useEffect, useState } from 'react'; export default function SafeFetch() { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { fetch('https://api.example.com/data') .then(res => { if (!res.ok) throw new Error('Network error'); return res.json(); }) .then(data => { setData(data); setLoading(false); }) .catch(err => { setError(err.message); setLoading(false); }); }, []); if (loading) return <p>Loading...</p>; if (error) return <p>Error: {error}</p>; return <pre>{JSON.stringify(data, null, 2)}</pre>; }
pages/api
.// pages/api/hello.js
export default function handler(req, res) {
res.status(200).json({ message: 'Hello from API!' });
}
req
contains request data like method, headers, body, query.res
is used to send back status, headers, and body.// pages/api/method.js
export default function handler(req, res) {
if(req.method === 'POST') {
res.status(200).json({ message: 'POST received' });
} else {
res.status(405).json({ error: 'Only POST allowed' });
}
}
pages/api
defines the API routes.pages/api/user.js
corresponds to /api/user
.// pages/api/user/[id].js
export default function handler(req, res) {
const { id } = req.query;
res.status(200).json({ userId: id });
}
req.method
to handle different HTTP methods.// pages/api/data.js
export default function handler(req, res) {
if(req.method === 'GET') {
res.status(200).json({ data: 'GET response' });
} else if(req.method === 'POST') {
const body = req.body;
res.status(200).json({ received: body });
} else {
res.status(405).end();
}
}
req.headers
and res.setHeader()
.// pages/api/header.js
export default function handler(req, res) {
const token = req.headers['authorization'];
res.setHeader('X-Custom-Header', 'MyHeaderValue');
res.status(200).json({ token });
}
// pages/api/db.js (pseudo-code)
import client from '../../lib/dbClient';
export default async function handler(req, res) {
const users = await client.query('SELECT * FROM users');
res.status(200).json(users.rows);
}
// pages/api/weather.js
import fetch from 'node-fetch';
export default async function handler(req, res) {
const response = await fetch('https://api.weatherapi.com/v1/current.json?key=KEY&q=London');
const data = await response.json();
res.status(200).json(data);
}
// pages/api/secure.js
export default function handler(req, res) {
const auth = req.headers.authorization;
if(auth === 'Bearer mysecrettoken') {
res.status(200).json({ secretData: '42' });
} else {
res.status(401).json({ error: 'Unauthorized' });
}
}
pages/api
as serverless functions.req
and res
.pages/_app.js
.<!-- styles/globals.css --> body {
background-color: #f0f0f0;
font-family: Arial, sans-serif;
}
<!-- pages/_app.js -->Output:
import '../styles/globals.css';
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />;
}
Component.module.css
<!-- styles/Button.module.css --> .button {
background-color: blue;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
}
<!-- components/Button.js -->Output:
import styles from '../styles/Button.module.css';
export default function Button() {
return <button className={styles.button}>Click Me</button>;
}
<!-- Example usage in a component -->Output:
export default function Card() {
return <div className="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-md flex items-center space-x-4">
<div>
<h1 className="text-xl font-medium text-black">Tailwind Card</h1>
<p className="text-gray-500">Utility-first styling!</p>
</div>
</div>
}
styled-components
.import styled from 'styled-components';Output:
const Button = styled.button`
background: palevioletred;
color: white;
padding: 10px 20px;
border-radius: 5px;
`;
export default function StyledButton() {
return <Button>Styled Components</Button>;
}
/** @jsxImportSource @emotion/react */Output:
import { css } from '@emotion/react';
const style = css`
background-color: lightblue;
padding: 10px;
border-radius: 5px;
`;
export default function EmotionBox() {
return <div css={style}>Emotion Styled Box</div>;
}
styles.module.scss
.<!-- styles/Button.module.scss --> $primary-color: #0070f3;Output:
.button {
background-color: $primary-color;
color: white;
padding: 10px 20px;
}
<!-- Example responsive style in CSS Modules --> .container {Output:
width: 100%;
 }@media (min-width: 768px) {
width: 50%;
}
}
import { motion } from 'framer-motion';Output:
export default function AnimatedBox() {
return <motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 1 }}
style={{ width: 100, height: 100, backgroundColor: 'red' }}
></motion.div>
}
const themes = {Output:
light: { background: '#fff', color: '#000' },
dark: { background: '#000', color: '#fff' },
};
export default function ThemeSwitcher() {
const [theme, setTheme] = React.useState('light');
return <div style={{ background: themes[theme].background, color: themes[theme].color, padding: '20px' }}>
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>Toggle Theme</button>
Current theme: {theme}
</div>
}
useState
hook.import React, { useState } from 'react';Output:
export default function Counter() {
let [count, setCount] = useState(0);
return (<
button onClick={() => setCount(count + 1)}>Clicked {count} times</button>
);
}
import React, { createContext, useContext, useState } from 'react';Output:
const CountContext = createContext();
export function CountProvider({ children }) {
let [count, setCount] = useState(0);
return (<CountContext.Provider value={{ count, setCount }}>{children}</CountContext.Provider>);
}
export function useCount() { return useContext(CountContext); }
CountProvider
can access and update count.import create from 'zustand';Output:
const useStore = create(set => ({
count: 0,
increment: () => set(state => ({ count: state.count + 1 }))
}));
export default function Counter() {
let count = useStore(state => state.count);
let increment = useStore(state => state.increment);
return (<button onClick={increment}>Count: {count}</button>);
}
import { configureStore, createSlice } from '@reduxjs/toolkit';Output:
const counterSlice = createSlice({
name: 'counter',
initialState: 0,
reducers: { increment: state => state + 1 }
});
const store = configureStore({ reducer: counterSlice.reducer });
export default store;
import { useQuery } from 'react-query';Output:
function fetchTodos() { return fetch('/api/todos').then(res => res.json()); }
export default function Todos() {
let { data, error, isLoading } = useQuery('todos', fetchTodos);
if (isLoading) return <p>Loading...</p>;
if (error) return <p>Error!</p>;
return (<ul>{data.map(todo => <li key={todo.id}>{todo.title}</li>)}</ul>);
}
import React, { useState } from 'react';Output:
export default function Form() {
let [name, setName] = useState('');
return (<
form onSubmit={e => { e.preventDefault(); alert(name); }}>
input value={name} onChange={e => setName(e.target.value)} placeholder="Enter name" />
button type="submit">Submit</button>
/form>
);
}
import React, { useState, useEffect } from 'react';Output:
export default function PersistentCounter() {
let [count, setCount] = useState(() => parseInt(localStorage.getItem('count')) || 0);
useEffect(() => { localStorage.setItem('count', count); }, [count]);
return (<
button onClick={() => setCount(count + 1)}>Count: {count}</button>
);
}
import { useContext } from 'react';Output:
import { CountContext } from '../context/CountContext';
export default function Page() {
let { count, setCount } = useContext(CountContext);
return (<
button onClick={() => setCount(count + 1)}>Shared Count: {count}</button>
);
}
import React, { useState, useEffect } from 'react';Output:
function useDebounce(value, delay) {
let [debounced, setDebounced] = useState(value);
useEffect(() => {
let handler = setTimeout(() => setDebounced(value), delay);
return () => clearTimeout(handler);
}, [value, delay]);
return debounced;
}
export default function Search() {
let [query, setQuery] = useState('');
let debouncedQuery = useDebounce(query, 500);
// Use debouncedQuery to fetch API
return (<
input value={query} onChange={e => setQuery(e.target.value)} placeholder="Search" />
);
}
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit';Output:
const loggerMiddleware = store => next => action => {
console.log('Dispatching:', action);
let result = next(action);
console.log('Next state:', store.getState());
return result;
};
const store = configureStore({
reducer: rootReducer,
middleware: getDefaultMiddleware().concat(loggerMiddleware)
});
export default store;
/* Controlled input example */Output:
function ControlledInput() {
const [value, setValue] = React.useState('');
return (<
input value={value} onChange={e => setValue(e.target.value)} />
);
}
/* Uncontrolled input example */Output:
function UncontrolledInput() {
const inputRef = React.useRef(null);
const handleClick = () => alert(inputRef.current.value);
return (<
>input ref={inputRef} />
button onClick={handleClick}>Show Value</button>
);
}
function Form() {Output:
const [formData, setFormData] = React.useState({ name: '', email: '' });
const handleChange = e => {
setFormData({ ...formData, [e.target.name]: e.target.value });
};
return (<
form>
input name="name" value={formData.name} onChange={handleChange} />
input name="email" value={formData.email} onChange={handleChange} />
/form>
);
}
function FormWithRef() {Output:
const nameRef = React.useRef();
const emailRef = React.useRef();
const handleSubmit = e => {
e.preventDefault();
alert(`Name: ${nameRef.current.value}, Email: ${emailRef.current.value}`);
};
return (<
form onSubmit={handleSubmit}>
input ref={nameRef} name="name" />
input ref={emailRef} name="email" />
button type="submit">Submit</button>
/form>
);
}
import { useForm } from 'react-hook-form';Output:
function HookForm() {
const { register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = data => console.log(data);
return (<
form onSubmit={handleSubmit(onSubmit)}>
input {...register('name', { required: true })} />
{errors.name && <span>Name is required</span>}
button type="submit">Submit</button>
/form>
);
}
import * as yup from 'yup';Output:
const schema = yup.object().shape({
name: yup.string().required(),
email: yup.string().email().required()
});
// Integrate with React Hook Form using yupResolver
function validateEmail(email) {Output:
return email.includes('@');
}
function Form() {
const [email, setEmail] = React.useState('');
const [error, setError] = React.useState(null);
const handleChange = e => {
setEmail(e.target.value);
setError(validateEmail(e.target.value) ? null : 'Invalid email');
};
return (<
>input value={email} onChange={handleChange} />
{error && <span>{error}</span>}
);
}
function MultiStep() {Output:
const [step, setStep] = React.useState(1);
return (<
div>
{step === 1 ? <Step1 next={() => setStep(2)} /> : <Step2 prev={() => setStep(1)} />}
/div>
);
}
function FileUpload() {Output:
const [file, setFile] = React.useState(null);
const handleChange = e => setFile(e.target.files[0]);
return (<
input type="file" onChange={handleChange} />
{file && <p>Selected: {file.name}</p>}
);
}
function SubmitForm() {Output:
const [name, setName] = React.useState('');
const handleSubmit = e => {
e.preventDefault();
fetch('/api/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name })
});
};
return (<
form onSubmit={handleSubmit}>
input value={name} onChange={e => setName(e.target.value)} />
button type="submit">Submit</button>
/form>
);
}
import NextAuth from 'next-auth';Output:
import GoogleProvider from 'next-auth/providers/google';
export default NextAuth({
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET,
}),
],
});
import NextAuth from 'next-auth';Output:
import CredentialsProvider from 'next-auth/providers/credentials';
export default NextAuth({
providers: [
CredentialsProvider({
async authorize(credentials) {
const user = await checkUser(credentials.email, credentials.password);
if (user) {
return user;
} else {
return null;
}
},
}),
],
});
import { getSession } from 'next-auth/react';Output:
export default async (req, res) => {
const session = await getSession({ req });
if (!session) {
return res.status(401).json({ error: 'Unauthorized' });
}
res.status(200).json({ message: 'Authorized access' });
};
if (session.user.role !== 'admin') {Output:
return res.status(403).json({ error: 'Forbidden' });
}
import jwt from 'jsonwebtoken';Output:
const token = jwt.sign({ userId: user.id }, process.env.JWT_SECRET, { expiresIn: '1h' });
const decoded = jwt.verify(token, process.env.JWT_SECRET);
# Deploy your Next.js app with Vercel CLIOutput:
vercel login
vercel --prod
# In .env.localOutput:
NEXT_PUBLIC_API_URL=https://api.example.com
# Access in code
const apiUrl = process.env.NEXT_PUBLIC_API_URL;
# Install Next.js plugin for NetlifyOutput:
npm install @netlify/plugin-nextjs
# Add to netlify.toml
[[plugins]]
package = "@netlify/plugin-nextjs"
# Dockerfile exampleOutput:
FROM node:18-alpine
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --production
COPY . .
RUN yarn build
EXPOSE 3000
CMD ["yarn", "start"]
# GitHub Actions example snippetOutput:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Dependencies
run: yarn install
- name: Build
run: yarn build
- name: Deploy to Vercel
run: vercel --prod --token ${{ secrets.VERCEL_TOKEN }}
next/head
to customize the document head per page.import Head from 'next/head';Output:
export default function Home() {
return (
<div>
<Head>
<title>My Awesome Page</title>
<meta name="description" content="Welcome to my awesome page." />
</Head>
<h1>Hello World</h1>
</div>
);
}
<Head>Output:
<meta property="og:title" content="My Awesome Page" />
<meta property="og:description" content="Welcome to my awesome page." />
<meta property="og:image" content="https://example.com/image.png" />
</Head>
<Head>Output:
<script type="application/ld+json">{`
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "My Company",
"url": "https://mycompany.com",
"logo": "https://mycompany.com/logo.png"
}
`}</script>
</Head>
# public/robots.txtOutput:
User-agent: *
Disallow:
# public/sitemap.xml
<Head>Output:
<link rel="canonical" href="https://example.com/current-page" />
</Head>
next/image
component for automatic image optimization.import Image from 'next/image';Output:
export default function MyImage() {
return (
<Image
src="/me.png"
alt="Picture of me"
width={500}
height={500}
/>
);
}
sizes
and layout
props help serve images that fit different screen sizes.<ImageOutput:
src="/photo.jpg"
alt="Photo"
layout="responsive"
width={700}
height={475}
/>
next.config.js
to allow loading images from external sources.module.exports = {Output:
images: {
domains: ['example.com'],
},
};
<ImageOutput:
src="/photo.jpg"
alt="Photo"
width={700}
height={475}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ..."
/>
import dynamic from 'next/dynamic';Output:
const LazyComponent = dynamic(() => import('./LazyComponent'));
export default function Page() {
return <LazyComponent />;
}
const SomeModule = dynamic(() => import('./SomeModule'));Output:
export default function Home() {
return <SomeModule />;
}
npm install @next/bundle-analyzerOutput:
# then add config in next.config.js
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
});
module.exports = withBundleAnalyzer({});
next/image
component for optimized images.<link rel="preload">
to load important resources early.export function middleware(request) {Output:
// runs before every request
return NextResponse.next();
}
import { NextResponse } from 'next/server';Output:
export function middleware(request) {
const token = request.cookies.get('token');
if (!token) {
return NextResponse.redirect('/login');
}
return NextResponse.next();
}
middleware.ts
to apply globally.const cookie = request.cookies.get('session');Output:
// use or set cookies
next.config.js
.module.exports = {Output:
i18n: {
locales: ['en', 'fr', 'de'],
defaultLocale: 'en',
},
};
import { useRouter } from 'next/router';Output:
const router = useRouter();
const changeToFrench = () => {
router.push(router.pathname, router.asPath, { locale: 'fr' });
};
/locales/en/common.jsonOutput:
{
"welcome": "Welcome",
"hello": "Hello World"
}
const date = new Date();Output:
const formattedDate = new Intl.DateTimeFormat('fr-FR').format(date);
console.log(formattedDate);
hreflang
tags for SEO benefits.import { createClient } from 'contentful';Output:
const client = createClient({
space: 'your_space_id',
accessToken: 'your_access_token',
});
export async function getStaticProps() {
const entries = await client.getEntries();
return { props: { entries: entries.items } };
}
import sanityClient from '@sanity/client';Output:
const client = sanityClient({
projectId: 'your_project_id',
dataset: 'production',
useCdn: true,
});
export async function getStaticProps() {
const data = await client.fetch('*[_type == "post"]');
return { props: { posts: data } };
}
export async function getStaticProps() {Output:
const res = await fetch('https://your-strapi-url/api/posts');
const data = await res.json();
return { props: { posts: data.data } };
}
import { MDXRemote } from 'next-mdx-remote';Output:
import { serialize } from 'next-mdx-remote/serialize';
export async function getStaticProps() {
const mdxSource = await serialize('# Hello MDX');
return { props: { source: mdxSource } };
}
export async function getStaticProps() {Output:
const posts = await fetchCMSPosts();
return {
props: { posts },
revalidate: 10, // Revalidate every 10 seconds
};
}
export async function getStaticPaths() {Output:
const products = await fetchProducts();
const paths = products.map(product => ({
params: { id: product.id.toString() },
}));
return { paths, fallback: false };
}
export async function getStaticProps({ params }) {
const product = await fetchProductById(params.id);
return { props: { product } };
}
import { createContext, useState, useContext } from 'react';Output:
const CartContext = createContext();
export function CartProvider({ children }) {
const [cart, setCart] = useState([]);
const addToCart = (item) => setCart([...cart, item]);
return <CartContext.Provider value={{ cart, addToCart }}>{children}</CartContext.Provider>;
}
export const useCart = () => useContext(CartContext);
import { loadStripe } from '@stripe/stripe-js';Output:
const stripePromise = loadStripe('your-publishable-key');
async function handleCheckout() {
const stripe = await stripePromise;
const { error } = await stripe.redirectToCheckout({
sessionId: 'your-session-id',
});
if (error) console.error(error);
}
export default async function handler(req, res) {Output:
if (req.method === 'POST') {
const orderData = req.body;
// Save orderData to database
res.status(200).json({ message: 'Order created' });
} else {
res.status(405).end();
}
}
export default async function webhookHandler(req, res) {Output:
const event = req.body;
switch(event.type) {
case 'checkout.session.completed':
// Fulfill order logic
break;
default:
console.log(`Unhandled event type ${event.type}`);
}
res.status(200).json({ received: true });
}
npx create-turbo@latestOutput:
cd my-monorepo
npm install
npm run dev
npm install --save-dev jestOutput:
// example.test.js
describe('sum function', () => {
test('adds 1 + 2 to equal 3', () => {
expect(1 + 2).toBe(3);
});
});
npm install --save-dev @testing-library/reactOutput:
import { render, screen } from '@testing-library/react';
import Home from '../pages/index';
test('renders welcome message', () => {
render(<Home />);
expect(screen.getByText('Welcome')).toBeInTheDocument();
});
import renderer from 'react-test-renderer';Output:
import Button from '../components/Button';
test('Button snapshot', () => {
const tree = renderer.create(<Button label="Click me" />).toJSON();
expect(tree).toMatchSnapshot();
});
npm install cypress --save-devOutput:
// In cypress/integration/sample_spec.js
describe('My First Test', () => {
it('Visits the Next.js app', () => {
cy.visit('http://localhost:3000');
cy.contains('Welcome');
});
});
function greetUser(name) {
return `Hello, ${name}! How can AI assist you today?`;
}
console.log(greetUser("Alice")); // > Hello, Alice! How can AI assist you today?
const aiUX = {
transparency: "Explain AI decisions",
control: "Allow user override",
seamless: "Integrate AI naturally"
};
console.log(aiUX);
function chatbotReply(message) {
if(message.toLowerCase().includes("hello")) {
return "Hi there! How can I help you?";
} else {
return "Sorry, I didn't get that.";
}
}
console.log(chatbotReply("Hello")); // > Hi there! How can I help you?
function listenVoiceCommand(command) {
if(command === "play music") {
return "Playing music...";
} else {
return "Command not recognized.";
}
}
console.log(listenVoiceCommand("play music")); // > Playing music...
function summarize(text) {
return text.split(".")[0] + ".";
}
console.log(summarize("AI helps make interfaces smarter. It saves time.")); // > AI helps make interfaces smarter.
function recommend(items, interest) {
return items.filter(item => item.includes(interest));
}
console.log(recommend(["apple", "banana", "apricot"], "ap")); // > ["apple", "apricot"]
const userData = { email: "alice@example.com" };
function autofill(field) {
return userData[field] || "";
}
console.log(autofill("email")); // > alice@example.com
const dictionary = { hello: "hola", goodbye: "adios" };
function translate(word) {
return dictionary[word.toLowerCase()] || "unknown";
}
console.log(translate("Hello")); // > hola
function predict(prefix, dictionary) {
return dictionary.filter(word => word.startsWith(prefix));
}
console.log(predict("ap", ["apple", "apricot", "banana"])); // > ["apple", "apricot"]
function sentiment(text) {
const positiveWords = ["good", "happy", "great"];
const negativeWords = ["bad", "sad", "terrible"];
const words = text.toLowerCase().split(" ");
let score = 0;
words.forEach(word => {
if(positiveWords.includes(word)) score++;
if(negativeWords.includes(word)) score--;
});
return score > 0 ? "Positive" : score < 0 ? "Negative" : "Neutral";
}
console.log(sentiment("I feel good today")); // > Positive
<!-- Basic setup for OpenAI API using fetch -->
const apiKey = "YOUR_OPENAI_API_KEY";
async function callOpenAI(prompt) {
const response = await fetch("https://api.openai.com/v1/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`
},
body: JSON.stringify({
model: "text-davinci-003",
prompt: prompt,
max_tokens: 50
})
});
const data = await response.json();
return data.choices[0].text;
}
callOpenAI("Hello AI!").then(console.log);
<!-- Example pseudocode for calling Gemini or Bard API -->
async function callGeminiAPI(query) {
const response = await fetch("https://api.gemini.example.com/v1/query", {
method: "POST",
headers: { "Authorization": "Bearer YOUR_GEMINI_API_KEY" },
body: JSON.stringify({ query: query })
});
const result = await response.json();
return result.answer;
}
callGeminiAPI("Tell me about AI").then(console.log);
<!-- Call Hugging Face inference API for a transformer model -->
async function callHuggingFace(input) {
const response = await fetch("https://api-inference.huggingface.co/models/distilbert-base-uncased", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_HUGGINGFACE_API_TOKEN",
"Content-Type": "application/json"
},
body: JSON.stringify({ inputs: input })
});
const data = await response.json();
return data[0].label;
}
callHuggingFace("I love AI").then(console.log);
<!-- Example: Simple LangChain prompt call in Next.js API route -->
import { NextApiRequest, NextApiResponse } from 'next';
import { LLMChain } from 'langchain/chains';
import { OpenAI } from 'langchain/llms/openai';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const llm = new OpenAI();
const chain = new LLMChain({ llm, prompt: "Say hello to AI" });
const response = await chain.call({});
res.status(200).json({ result: response.text });
}
<!-- Example Next.js API route calling OpenAI -->
export default async function handler(req, res) {
const response = await fetch("https://api.openai.com/v1/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.OPENAI_API_KEY}`
},
body: JSON.stringify({
model: "text-davinci-003",
prompt: req.body.prompt,
max_tokens: 100
})
});
const data = await response.json();
res.status(200).json(data);
}
<!-- Example to handle streaming response from OpenAI -->
async function streamOpenAIResponse() {
const response = await fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`
},
body: JSON.stringify({
model: "gpt-4",
messages: [{ role: "user", content: "Stream this response" }],
stream: true
})
});
const reader = response.body.getReader();
while(true) {
const { done, value } = await reader.read();
if(done) break;
const chunk = new TextDecoder().decode(value);
console.log(chunk);
}
}
<!-- Basic try-catch for API call -->
async function safeCallAI() {
try {
const res = await fetch("https://api.openai.com/v1/completions", { method: "POST", headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}` },
body: JSON.stringify({ model: "text-davinci-003", prompt: "Hello", max_tokens: 5 })
});
const data = await res.json();
return data.choices[0].text;
} catch (error) {
console.error("Error calling AI API:", error);
return "Sorry, something went wrong.";
}
}
<!-- Simple console logging for AI usage tracking -->
function logAIUsage(userId, prompt) {
console.log(`User ${userId} sent prompt: ${prompt}`);
}
logAIUsage("user123", "Explain AI");
<!-- Basic rate limiting with a counter -->
const userCalls = {};
function canCallAPI(userId) {
if(!userCalls[userId]) userCalls[userId] = 0;
if(userCalls[userId] >= 5) return false;
userCalls[userId]++;
return true;
}
console.log(canCallAPI("user123")); // > true
console.log(canCallAPI("user123")); // > true
<!-- Use environment variables and never expose keys in frontend code -->
/* .env.local file */
NEXT_PUBLIC_API_KEY= # <-- Don't expose keys here
OPENAI_API_KEY=your-secret-key
/* Access in Next.js backend code */
const apiKey = process.env.OPENAI_API_KEY;
<!-- Simple Express middleware to route AI requests -->
function aiRoutingMiddleware(req, res, next) {
if(req.path.startsWith('/api/ai')) {
console.log('AI request routed:', req.path);
// Custom AI logic or validation here
}
next();
}
app.use(aiRoutingMiddleware);
<!-- Simple in-memory cache example for AI responses -->
const aiCache = {};
async function getAIResponse(prompt) {
if(aiCache[prompt]) {
return aiCache[prompt]; // Return cached response
}
const response = await callAI(prompt);
aiCache[prompt] = response;
return response;
}
<!-- Rate limit middleware for AI calls -->
const rateLimits = {};
function rateLimitMiddleware(req, res, next) {
const user = req.user.id;
rateLimits[user] = (rateLimits[user] || 0) + 1;
if(rateLimits[user] > 100) {
return res.status(429).send('Rate limit exceeded');
}
next();
}
app.use('/api/ai', rateLimitMiddleware);
<!-- Example of edge middleware in Next.js to add AI headers -->
export function middleware(req) {
const url = req.nextUrl.clone();
if(url.pathname.startsWith('/api/ai')) {
return new Response('Edge AI Middleware Applied', {
headers: { 'X-AI-Edge': 'true' }
});
}
return NextResponse.next();
}
<!-- Middleware checking user roles before AI access -->
function roleCheckMiddleware(req, res, next) {
const userRole = req.user.role;
if(userRole !== 'admin' && userRole !== 'ai_user') {
return res.status(403).send('Access denied to AI');
}
next();
}
app.use('/api/ai', roleCheckMiddleware);
<!-- Simple token masking function for privacy -->
function maskToken(token) {
return token.slice(0,4) + '****' + token.slice(-4);
}
const token = "123456789abcdef";
console.log(maskToken(token)); // Outputs: 1234****cdef
<!-- Example using Redis for caching AI responses -->
import redis from 'redis';
const client = redis.createClient();
async function getCachedAIResponse(prompt) {
return new Promise((resolve, reject) => {
client.get(prompt, async (err, reply) => {
if(reply) {
resolve(reply);
} else {
const response = await callAI(prompt);
client.set(prompt, response);
resolve(response);
}
});
});
}
<!-- Simple logging for AI usage monitoring -->
function monitorAIActivity(userId, action) {
console.log(`[AI Monitor] User: ${userId}, Action: ${action}, Time: ${new Date().toISOString()}`);
}
monitorAIActivity('user123', 'called AI model');
<!-- Basic Sentry logging setup for AI errors -->
import * as Sentry from '@sentry/node';
Sentry.init({ dsn: 'YOUR_SENTRY_DSN' });
try {
// call AI API
} catch(error) {
Sentry.captureException(error);
}
<!-- Middleware to attach user preferences for AI personalization -->
function personalizationMiddleware(req, res, next) {
req.userPreferences = { theme: 'dark', language: 'en' };
next();
}
app.use(personalizationMiddleware);
<!-- Example Next.js API route calling AI to generate blog content -->
export default async function handler(req, res) {
const prompt = req.body.prompt;
const blogContent = await callAItoGenerateBlog(prompt);
res.status(200).json({ content: blogContent });
}
async function callAItoGenerateBlog(prompt) {
// Simulated AI response for demo
return `Blog post about: ${prompt}`;
}
<!-- Simple function to generate product description using AI -->
async function generateProductDescription(productName) {
return `This is a great product called ${productName} that solves many problems.`;
}
generateProductDescription('Smart Watch').then(console.log);
<!-- AI-powered resume builder function -->
async function buildResume(data) {
return `Resume for ${data.name}: Experienced in ${data.skills.join(', ')}.`;
}
buildResume({ name: 'Alice', skills: ['JavaScript', 'React'] }).then(console.log);
<!-- Simple AI tutor answer generator -->
async function tutorAnswer(question) {
return `Answer to your question "${question}" is: ... (AI generated).`;
}
tutorAnswer('What is Next.js?').then(console.log);
<!-- Generate recipe based on ingredients -->
async function generateRecipe(ingredients) {
return `Recipe using ${ingredients.join(', ')}: ... (AI generated).`;
}
generateRecipe(['tomato', 'basil']).then(console.log);
<!-- Generate comic dialogue for characters -->
async function generateDialogue(characters) {
return `${characters[0]} says hello to ${characters[1]}.`;
}
generateDialogue(['Hero', 'Sidekick']).then(console.log);
<!-- Function to generate image descriptions -->
async function describeImage(imageUrl) {
return `Description for image at ${imageUrl}: A beautiful scene.`;
}
describeImage('http://example.com/image.jpg').then(console.log);
<!-- Mock function to translate spoken text in real-time -->
async function translateVoice(text, targetLang) {
return `Translated "${text}" to ${targetLang}.`;
}
translateVoice('Hello', 'es').then(console.log);
<!-- Simple AI-enhanced search function -->
async function aiSearch(query) {
return `Search results for "${query}" (AI enhanced).`;
}
aiSearch('Next.js tutorials').then(console.log);
<!-- Basic deployment config example -->
module.exports = {
target: 'serverless',
// Vercel handles Next.js API routes
};
<!-- Deployment is done via Vercel CLI or Git integration -->