SSR and Nuxt Intro

Introduction

A standard Vite + Vue SPA ships one index.html and renders entirely in the browser. Server-side rendering (SSR) generates HTML on the server for each request—better for SEO, social previews, and first paint. Nuxt 3 is the official Vue meta-framework for SSR, SSG, and full-stack features. This is a thin overview—full Nuxt tutorials live in Nuxt documentation.

Prerequisites

CSR vs SSR vs SSG

ModeWhere HTML is builtFirst request
CSR (client-only SPA)BrowserEmpty shell → JS downloads → render
SSRServer per requestFull HTML with content
SSGBuild timeStatic HTML files (like SPA + pre-render)

Hello Code Vue track teaches CSR with Vite—simplest path to learn Vue and pair with separate FastAPI APIs.

When You Need SSR

NeedConsider
Public marketing pages, SEO keywordsSSR or SSG
Social share cards (Open Graph)SSR/SSG with meta tags
Authenticated admin dashboardCSR SPA is often enough
Public blog index crawled by GoogleSSR, SSG, or pre-render

Many teams ship CSR admin + SSG marketing as separate apps.

What Nuxt Adds

FeatureSPA (Vue Router)Nuxt 3
RoutingManual routes arrayFile-based pages/
Data fetchingonMounted + fetchuseFetch, useAsyncData
SSRManual setupBuilt-in
API routesSeparate backendOptional server/api/
Meta / SEO@vueuse/head or manualuseSeoMeta

Nuxt Project Sketch

bash
npm create nuxt@latest hello-nuxt
cd hello-nuxt
npm run dev
text
hello-nuxt/
├── nuxt.config.ts
├── app.vue
├── pages/
│   ├── index.vue          → /
│   └── posts/[slug].vue   → /posts/:slug
└── server/
    └── api/
        └── health.get.ts  → /api/health

pages/index.vue:

vue
<script setup lang="ts">
const { data: posts } = await useFetch("/api/posts");
</script>
 
<template>
  <ul>
    <li v-for="post in posts" :key="post.id">{{ post.title }}</li>
  </ul>
</template>

Code explanation:

  • Top-level await in script setup works with Nuxt useFetch
  • Server can fetch before HTML is sent—no loading flash for first paint

useFetch vs onMounted fetch

SPA pattern:

vue
<script setup lang="ts">
import { onMounted, ref } from "vue";
 
const posts = ref([]);
onMounted(async () => {
  posts.value = await fetch("/api/posts").then((r) => r.json());
});
</script>

Nuxt useFetch runs on server and client, handles serialization and hydration.

Hydration

SSR sends HTML + embedded state. Client Vue hydrates—attaches listeners to existing DOM.

Hydration mismatch warning means server HTML ≠ client render—fix conditional rendering, dates, or random IDs.

Warning

Do not use window or localStorage during SSR without guards—crashes on server.

typescript
if (import.meta.client) {
  // browser-only code
}

In Nuxt: import.meta.client or <ClientOnly> component.

SSG with Nuxt

bash
npm run generate

Outputs static dist/—host like any SPA. Good for docs and blogs with known routes.

Nuxt vs Staying on Vite SPA

Stay on Vite SPAMove to Nuxt
Learning Vue coreNeed SEO/SSR
API already in FastAPI/DjangoWant full-stack in one repo
Simple deploy (static files)OK with Node server for SSR

You can learn Vue deeply on this track, then adopt Nuxt when requirements demand SSR.

FAQ

Is Nuxt required for Vue jobs?

Many jobs use Vite SPA or Nuxt—both are Vue. Know SPA first; Nuxt adds conventions.

Nuxt replace Pinia?

No—Nuxt works with Pinia. @pinia/nuxt module auto-imports stores.

API in Nuxt server vs FastAPI?

Nuxt server/api for small BFF layers; complex domains often stay in Python/Java APIs.

Vue 3 skills transfer?

Yes—SFC, Composition API, Pinia, same Vue core.

Incremental adoption?

Hard to SSR-wrap existing Vite SPA—usually new Nuxt project or pre-render subset.

Official next step?

Nuxt 3 docsIntroduction and Data Fetching sections.