Skip to content

Latest commit

 

History

History
150 lines (115 loc) · 4.06 KB

File metadata and controls

150 lines (115 loc) · 4.06 KB
title React Router v8 Project Setup
impact HIGH
impactDescription A misconfigured project disables SSR, causing loaders to run in the browser and exposing API keys via client-side network requests
type capability
tags
react router
setup
react-router.config
ssr
environment variables
typescript

React router v8 project setup

Bootstrap a React Router v8 project with SSR enabled, TypeScript, and secure environment variable handling for NextDNS API integration

Overview

React Router v8 is a full-stack React framework (evolved from Remix). It uses Vite as its build tool and supports multiple rendering modes: SSR, CSR, and static pre-rendering. For NextDNS integration, SSR must be enabled so that loader and action functions run on the server where process.env.NEXTDNS_API_KEY is available.

Breaking change from v7: v8 removed the react-router-dom package entirely — only react-router exists now, and the package is ESM-only. It also raises peer minimums (Node 22.22+, React 19.2.7+, Vite 7+). If migrating an existing v7 project, replace any from 'react-router-dom' import with from 'react-router' and confirm your Node/React/Vite versions meet the new floor before upgrading.

Correct usage

Create a new project

# ✅ Bootstrap with official CLI
pnpm create react-router@latest my-nextdns-app
cd my-nextdns-app
pnpm install

Select TypeScript when prompted.

React-router.config.ts

// ✅ react-router.config.ts — SSR must be true
import type { Config } from '@react-router/dev/config';

export default {
  ssr: true, // Required: enables server-side loaders and actions
} satisfies Config;

Environment variables

# .env  (gitignored by default)
NEXTDNS_API_KEY=YOUR_API_KEY
NEXTDNS_PROFILE_ID=abc123
# Add to .gitignore
echo ".env" >> .gitignore

Directory structure

app/
  lib/
    nextdns.server.ts    # Server-only API utility (.server.ts = stripped from client)
  routes/
    home.tsx             # Dashboard UI route (has default export)
    api.profiles.ts      # Resource route (no default export)
    api.profiles.$id.ts  # Dynamic resource route
  routes.ts              # Route configuration
react-router.config.ts   # Framework config (ssr: true)

Server utility

// ✅ app/lib/nextdns.server.ts
export async function nextdnsFetch<T>(path: string, options?: RequestInit): Promise<T> {
  const apiKey = process.env.NEXTDNS_API_KEY;
  if (!apiKey) throw new Error('NEXTDNS_API_KEY is not set');

  const res = await fetch(`https://api.nextdns.io${path}`, {
    ...options,
    headers: {
      'X-Api-Key': apiKey,
      'Content-Type': 'application/json',
      ...(options?.headers ?? {}),
    },
  });

  if (!res.ok) throw new Error(`NextDNS API error: ${res.status}`);
  return res.json() as Promise<T>;
}

Start development server

pnpm dev
# Opens http://localhost:5173

Do NOT Use

// ❌ Never set ssr: false — disables server loaders, API keys leak to the browser
export default {
  ssr: false, // ❌
} satisfies Config;
# ❌ Never prefix secrets with VITE_ — they are bundled into the client
VITE_NEXTDNS_API_KEY=YOUR_API_KEY  #

Troubleshooting

Issue: loader runs in the browser instead of the server

Symptoms: Network tab shows requests to api.nextdns.io from the browser.

Solution: Set ssr: true in react-router.config.ts. Without SSR, React Router falls back to client-side data loading which exposes the API key.

Issue: TypeScript errors for route.loaderargs

Solution: Run pnpm typecheck or pnpm dev once — React Router auto-generates type files under app/routes/+types/ based on your route config.

Reference