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 {
width: 100%;
 }@media (min-width: 768px) {
width: 50%;
}
}
Output:
import { motion } from 'framer-motion';
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>
}
Output:
const themes = {
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>
}
Output:useState hook.
import React, { useState } from 'react';
export default function Counter() {
let [count, setCount] = useState(0);
return (<
button onClick={() => setCount(count + 1)}>Clicked {count} times</button>
);
}
Output:
import React, { createContext, useContext, useState } from 'react';
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); }
Output: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';
const counterSlice = createSlice({
name: 'counter',
initialState: 0,
reducers: { increment: state => state + 1 }
});
const store = configureStore({ reducer: counterSlice.reducer });
export default store;
Output:
import { useQuery } from 'react-query';
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>);
}
Output:
import React, { useState } from 'react';
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>
);
}
Output:
import React, { useState, useEffect } from 'react';
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>
);
}
Output:
import { useContext } from 'react';
import { CountContext } from '../context/CountContext';
export default function Page() {
let { count, setCount } = useContext(CountContext);
return (<
button onClick={() => setCount(count + 1)}>Shared Count: {count}</button>
);
}
Output:
import React, { useState, useEffect } from 'react';
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" />
);
}
Output:
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit';
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;
Output:/* 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() {
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>
);
}
Output:
function FormWithRef() {
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>
);
}
Output:
import { useForm } from 'react-hook-form';
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>
);
}
Output: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) {
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>}
);
}
Output:
function MultiStep() {
const [step, setStep] = React.useState(1);
return (<
div>
{step === 1 ? <Step1 next={() => setStep(2)} /> : <Step2 prev={() => setStep(1)} />}
/div>
);
}
Output:
function FileUpload() {
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>}
);
}
Output:
function SubmitForm() {
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>
);
}
Output: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';
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' });
};
Output:
if (session.user.role !== 'admin') {
return res.status(403).json({ error: 'Forbidden' });
}
Output: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 = {
images: {
domains: ['example.com'],
},
};
Output:<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'));
export default function Home() {
return <SomeModule />;
}
Output: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) {
// runs before every request
return NextResponse.next();
}
Output:
import { NextResponse } from 'next/server';
export function middleware(request) {
const token = request.cookies.get('token');
if (!token) {
return NextResponse.redirect('/login');
}
return NextResponse.next();
}
Output:middleware.ts to apply globally.
const cookie = request.cookies.get('session');
// use or set cookies
Output:next.config.js.
module.exports = {
i18n: {
locales: ['en', 'fr', 'de'],
defaultLocale: 'en',
},
};
Output:
import { useRouter } from 'next/router';
const router = useRouter();
const changeToFrench = () => {
router.push(router.pathname, router.asPath, { locale: 'fr' });
};
Output:/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';
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 } };
}
Output: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() {
const res = await fetch('https://your-strapi-url/api/posts');
const data = await res.json();
return { props: { posts: data.data } };
}
Output:
import { MDXRemote } from 'next-mdx-remote';
import { serialize } from 'next-mdx-remote/serialize';
export async function getStaticProps() {
const mdxSource = await serialize('# Hello MDX');
return { props: { source: mdxSource } };
}
Output:
export async function getStaticProps() {
const posts = await fetchCMSPosts();
return {
props: { posts },
revalidate: 10, // Revalidate every 10 seconds
};
}
Output:
export async function getStaticPaths() {
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 } };
}
Output:
import { createContext, useState, useContext } from 'react';
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);
Output:
import { loadStripe } from '@stripe/stripe-js';
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);
}
Output:
export default async function handler(req, res) {
if (req.method === 'POST') {
const orderData = req.body;
// Save orderData to database
res.status(200).json({ message: 'Order created' });
} else {
res.status(405).end();
}
}
Output:
export default async function webhookHandler(req, res) {
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 });
}
Output: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 -->