Back to Blog

Getting Started with Next.js: A Complete Guide

6 min read
Next.jsReactJavaScriptWeb Development
by Arifzyn
Getting Started with Next.js: A Complete Guide
Cover image source: Source

Learn how to build modern web applications with Next.js, the React framework for production. This comprehensive guide covers everything from setup to deployment.

Getting Started with Next.js

Next.js is a powerful React framework that enables you to build full-stack web applications. It provides many features out of the box that make development faster and more efficient.

What is Next.js?

Next.js is a React framework that gives you building blocks to create web applications. It handles the tooling and configuration needed for React, and provides additional structure, features, and optimizations for your application.

Key Features

  • Server-side Rendering (SSR)
  • Static Site Generation (SSG)
  • API Routes
  • File-based Routing
  • Image Optimization
  • TypeScript Support

Installation

Getting started with Next.js is simple. You can create a new project using:

npx create-next-app@latest my-app
cd my-app
npm run dev

Project Structure

A typical Next.js project structure looks like this:

my-app/ ├── app/ │ ├── layout.tsx │ ├── page.tsx │ └── globals.css ├── public/ ├── next.config.js └── package.json

Creating Pages

In Next.js 13+, pages are created using the App Router. Here's a simple example:

// app/about/page.tsx
export default function About() {
  return (
    <div>
      <h1>About Us</h1>
      <p>Welcome to our about page!</p>
    </div>
  );
}

Styling

Next.js supports various styling options:

  1. CSS Modules
  2. Styled JSX
  3. Tailwind CSS
  4. Sass/SCSS

Example with Tailwind CSS

export default function Button({ children }: { children: React.ReactNode }) {
  return (
    <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
      {children}
    </button>
  );
}

Data Fetching

Next.js provides several methods for fetching data:

Server Components (Recommended)

async function getData() {
  const res = await fetch("https://api.example.com/data");
  return res.json();
}

export default async function Page() {
  const data = await getData();

  return <main>{/* Render data */}</main>;
}

API Routes

Create API endpoints easily:

// app/api/hello/route.ts
export async function GET() {
  return Response.json({ message: "Hello, World!" });
}

Deployment

Deploy your Next.js app to Vercel with zero configuration:

npm i -g vercel
vercel

Conclusion

Next.js is an excellent choice for building modern web applications. Its features like SSR, SSG, and API routes make it perfect for both static sites and dynamic applications.

Ready to start building? Check out the official Next.js documentation for more detailed information.


content/blog/typescript-best-practices.mdx


title: "TypeScript Best Practices for Better Code Quality" description: "Discover essential TypeScript best practices that will help you write more maintainable, type-safe, and efficient code in your projects." date: "2024-01-10" tags: ["TypeScript", "JavaScript", "Best Practices", "Code Quality"] featured: false published: true author: "Your Name"


TypeScript Best Practices

TypeScript has become the go-to choice for many developers when building large-scale applications. Here are some best practices to help you write better TypeScript code.

1. Use Strict Mode

Always enable strict mode in your tsconfig.json:

{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true
  }
}

2. Prefer Interfaces Over Type Aliases

For object shapes, prefer interfaces:

// ✅ Good
interface User {
  id: number;
  name: string;
  email: string;
}

// ❌ Avoid for object shapes
type User = {
  id: number;
  name: string;
  email: string;
};

3. Use Union Types Effectively

type Status = "loading" | "success" | "error";

function handleStatus(status: Status) {
  switch (status) {
    case "loading":
      return "Loading...";
    case "success":
      return "Success!";
    case "error":
      return "Error occurred";
    default:
      // TypeScript will catch if we miss a case
      const exhaustiveCheck: never = status;
      return exhaustiveCheck;
  }
}

4. Avoid any Type

Instead of any, use more specific types:

// ❌ Bad
function processData(data: any) {
  return data.someProperty;
}

// ✅ Good
interface ApiResponse {
  data: unknown;
  status: number;
}

function processData(response: ApiResponse) {
  // Use type guards or assertions
  if (typeof response.data === "object" && response.data !== null) {
    // Now TypeScript knows data is an object
  }
}

5. Use Generic Types

Make your functions and classes reusable with generics:

function identity<T>(arg: T): T {
  return arg;
}

// Usage
const stringResult = identity("hello"); // string
const numberResult = identity(42); // number

Conclusion

Following these TypeScript best practices will help you write more robust and maintainable code. Remember, TypeScript is there to help you catch errors early and improve your development experience.


content/blog/tailwind-css-tips.mdx


title: "Advanced Tailwind CSS Tips and Tricks" description: "Take your Tailwind CSS skills to the next level with these advanced tips, custom configurations, and optimization techniques." date: "2024-01-05" tags: ["Tailwind CSS", "CSS", "Frontend", "Styling"] featured: true published: true author: "Your Name"


Advanced Tailwind CSS Tips

Tailwind CSS is more than just utility classes. Here are some advanced techniques to level up your Tailwind game.

Custom Color Palette

Define your brand colors in tailwind.config.js:

module.exports = {
  theme: {
    extend: {
      colors: {
        brand: {
          50: "#eff6ff",
          500: "#3b82f6",
          900: "#1e3a8a",
        },
      },
    },
  },
};

Component Extraction

Use @apply directive for common patterns:

.btn-primary {
  @apply bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded;
}

Dark Mode Implementation

<div class="bg-white dark:bg-gray-800 text-gray-900 dark:text-white">
  <h1 class="text-2xl font-bold">Hello World</h1>
</div>

Enable dark mode in your config:

module.exports = {
  darkMode: "class", // or 'media'
  // ...
};

Custom Utilities

Create your own utility classes:

@layer utilities {
  .text-shadow {
    text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
  }

  .scrollbar-hide {
    -ms-overflow-style: none;
    scrollbar-width: none;
  }
  .scrollbar-hide::-webkit-scrollbar {
    display: none;
  }
}

Responsive Design

Master Tailwind's responsive system:

<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
  <!-- Responsive grid -->
</div>

Performance Optimization

Purge Unused CSS

module.exports = {
  content: [
    "./pages/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
  ],
  // ...
};

JIT Mode Benefits

Just-In-Time compilation provides:

  • Faster build times
  • Smaller file sizes
  • All variants available
  • Arbitrary value support
<div class="top-[117px] bg-[#1da1f2]">
  <!-- Arbitrary values -->
</div>

Advanced Layout Techniques

CSS Grid with Tailwind

<div class="grid grid-cols-[200px_1fr_100px] gap-4">
  <aside>Sidebar</aside>
  <main>Content</main>
  <aside>Widgets</aside>
</div>

Container Queries (Future)

<div class="@container">
  <div class="@sm:flex @md:grid @md:grid-cols-2">
    <!-- Container-based responsive design -->
  </div>
</div>

Conclusion

These advanced Tailwind techniques will help you build more maintainable and efficient stylesheets. Remember to leverage Tailwind's configuration system to match your design system perfectly.