Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Next.js Framework

Next.js serves as the foundation of Hackcontrol, providing the React framework with powerful features for production applications.

Next.js in Hackcontrol

Version & Configuration

  • Version: Next.js 15.4.6
  • Router: Pages Router (not App Router)
  • Configuration: next.config.mjs

Key Features Used

File-Based Routing

src/pages/
├── index.tsx              # / (Landing page)
├── auth/
│   └── index.tsx          # /auth (Sign in page)
├── app/
│   ├── index.tsx          # /app (Dashboard)
│   └── [url].tsx          # /app/[hackathon-url]
└── send/
    └── [url].tsx          # /send/[hackathon-url]

API Routes

src/pages/api/
├── auth/
│   └── [...nextauth].ts  # /api/auth/* (NextAuth)
└── trpc/
    └── [trpc].ts         # /api/trpc/* (tRPC handler)

Configuration

Next.js Config

// next.config.mjs
!process.env.SKIP_ENV_VALIDATION && (await import("./src/env/index.mjs"));

const nextConfig = {
  reactStrictMode: true,
  images: {
    remotePatterns: [
      {
        protocol: "https",
        hostname: "avatars.githubusercontent.com",
        port: "",
        pathname: "/u/**",
      },
    ],
  },
};

export default nextConfig;

Key settings:

  • Environment validation: Loads and validates env vars at build time
  • React Strict Mode: Enabled for development safety
  • Image optimization: Configured for GitHub avatars

TypeScript Integration

// tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "strict": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

App Structure

Root App Component

// src/pages/_app.tsx
const App: AppType<{ session: Session | null }> = ({
  Component,
  pageProps: { session, ...pageProps },
  router,
}) => {
  return (
    <SessionProvider session={session}>
      <DefaultSeo {...nextSeoConfig} />
      <NextNProgress />
      <main className="font-sans">
        <Header />
        <Show routerKey={router.route}>
          <Component {...pageProps} />
        </Show>
        <Toaster />
      </main>
    </SessionProvider>
  );
};

export default api.withTRPC(App);

Features integrated:

  • SessionProvider: NextAuth session context
  • DefaultSeo: SEO configuration
  • NextNProgress: Page loading indicator
  • Show: Page transition animations
  • Toaster: Toast notifications (Sonner)
  • api.withTRPC: tRPC client wrapper

Document Structure

// src/pages/_document.tsx
// Custom document for HTML structure and font loading

Page Examples

Dynamic Routes

// src/pages/app/[url].tsx
import { type GetServerSideProps } from "next";
import { getServerAuthSession } from "@/lib/auth";

export default function HackathonPage() {
  const router = useRouter();
  const hackathonUrl = router.query.url as string;
  
  const { data: hackathon, isLoading } = api.hackathon.getByUrl.useQuery({
    url: hackathonUrl,
  });

  if (isLoading) return <Loading />;
  if (!hackathon) return <NotFound />;

  return <HackathonDetails hackathon={hackathon} />;
}

export const getServerSideProps: GetServerSideProps = async (ctx) => {
  const session = await getServerAuthSession(ctx);
  
  return {
    props: {
      session,
    },
  };
};

API Route Handler

// src/pages/api/trpc/[trpc].ts
import { createNextApiHandler } from "@trpc/server/adapters/next";
import { appRouter } from "@/trpc/root";
import { createTRPCContext } from "@/trpc";

export default createNextApiHandler({
  router: appRouter,
  createContext: createTRPCContext,
  onError: env.NODE_ENV === "development"
    ? ({ path, error }) => {
        console.error(`❌ tRPC failed on ${path}: ${error.message}`);
      }
    : undefined,
});

Features & Integrations

Server-Side Rendering (SSR)

// For pages that need server-side data
export const getServerSideProps: GetServerSideProps = async (ctx) => {
  const session = await getServerAuthSession(ctx);
  
  // Pre-fetch data on server
  const helpers = createServerSideHelpers({
    router: appRouter,
    ctx: { session, prisma },
    transformer: superjson,
  });

  await helpers.hackathon.getByUrl.prefetch({ url: ctx.params?.url as string });

  return {
    props: {
      trpcState: helpers.dehydrate(),
      session,
    },
  };
};

Image Optimization

// GitHub avatar optimization
<Image
  src={user.image}
  alt={user.name}
  width={40}
  height={40}
  className="rounded-full"
/>

SEO Configuration

// next-seo.config.ts
export const nextSeoConfig: DefaultSeoProps = {
  title: "Hackcontrol",
  description: "Open-source hackathon management system",
  openGraph: {
    type: "website",
    locale: "en_US",
    url: "https://hackcontrol.vercel.app/",
    siteName: "Hackcontrol",
  },
};

Performance Features

Automatic Code Splitting

  • Each page is automatically split into separate bundles
  • Reduces initial bundle size
  • Improves load times

Static Optimization

  • Static pages are pre-rendered at build time
  • Dynamic pages use SSR when needed
  • Optimal performance for different content types

Image Optimization

  • Automatic image optimization and resizing
  • WebP format support
  • Lazy loading by default

Development Features

Hot Reloading

  • Instant feedback during development
  • Preserves component state when possible
  • Fast refresh for React components

Error Overlay

  • Detailed error information in development
  • Source map support for debugging
  • Stack trace with exact file locations

TypeScript Integration

  • Zero-config TypeScript support
  • Fast compilation with SWC
  • Built-in type checking

Build Process

Development Build

npm run dev
  • Fast refresh enabled
  • Source maps for debugging
  • Detailed error reporting

Production Build

npm run build
npm run start
  • Optimized bundles
  • Static asset optimization
  • Performance optimizations

Environment Handling

Environment Variables

// Automatic environment validation
!process.env.SKIP_ENV_VALIDATION && (await import("./src/env/index.mjs"));

Runtime Configuration

  • Client vs server environment separation
  • Secure environment variable access
  • Build-time validation

Deployment

Vercel Integration

// vercel.json
{
  "functions": {
    "src/pages/api/**/*.ts": {
      "maxDuration": 30
    }
  }
}

Static Assets

  • Automatic optimization
  • CDN distribution
  • Caching headers

Best Practices

Page Organization

  • Group related pages in directories
  • Use meaningful file names
  • Implement proper error boundaries

Performance

  • Minimize client-side JavaScript
  • Use dynamic imports for large components
  • Optimize images and assets

SEO

  • Implement proper meta tags
  • Use semantic HTML structure
  • Optimize for Core Web Vitals

Routing Patterns

Dynamic Routes

// [url].tsx - Single dynamic segment
// [...slug].tsx - Catch-all routes
// [[...slug]].tsx - Optional catch-all

Programmatic Navigation

import { useRouter } from "next/router";

const router = useRouter();

// Navigate to different pages
router.push("/app");
router.push(`/app/${hackathon.url}`);
router.replace("/auth"); // Replace instead of push

Next Steps