Project: Blog Reader With API

Introduction

This project builds a blog reader SPA that loads posts from a REST API—list with pagination, detail by slug, loading and error states, and Vue Router navigation. Connect to FastAPI REST CRUD, Django blog REST, or JSONPlaceholder for mock data.

Prerequisites

Architecture

text
PostListView  →  GET /api/v1/posts?page=1
PostDetailView → GET /api/v1/posts/:slug

  usePosts / usePost composables

  api/client.ts (fetch wrapper)

Types

src/types/post.ts:

Adapt fields to your backend schema.

API Client

src/api/client.ts:

Vite proxy (dev)—Fetching API and CORS:

typescript
// vite.config.ts — proxy /api → backend

.env:

env
VITE_API_URL=

Empty VITE_API_URL with proxy uses relative /api/... paths.

Composables

src/composables/usePosts.ts:

src/composables/usePost.ts:

JSONPlaceholder mock (no backend):

typescript
// Replace URL with:
// https://jsonplaceholder.typicode.com/posts?_limit=10
// Map id → slug in adapter if needed

Routes

src/router/index.ts:

typescript
{
  path: "/posts",
  name: "posts",
  component: () => import("@/views/PostListView.vue"),
},
{
  path: "/posts/:slug",
  name: "post-detail",
  component: () => import("@/views/PostDetailView.vue"),
  props: true,
},

PostListView

PostDetailView

CORS Checklist

Dev setupConfig
Vite proxyserver.proxy in vite.config.ts
Direct API URLBackend CORSMiddleware / Flask-CORS
ProductionSame-site Nginx proxy or strict CORS origins

See Flask CORS and Frontend.

Deliverables

  • Post list loads from API with loading/error/empty states
  • Click navigates to /posts/:slug
  • Detail page shows title and body
  • Pagination or “load more” works
  • Refresh on detail URL works in production build (SPA fallback)
  • Types match API response shape

Extensions

  • Search query ?q= debounced with watch
  • Markdown body with sanitized renderer
  • Pinia cache for visited posts
  • Admin dashboard project for write API

FAQ

Backend has no slug field?

Use id in route: /posts/:id and adjust composable.

Pagination shape differs?

Adapt PaginatedPosts type and query params to your OpenAPI spec.

FastAPI OpenAPI?

Generate types with openapi-typescript (optional advanced step).

404 on detail refresh?

Deploy with Nginx try_filesBuild and Deploy.

Combine with PostgreSQL blog schema?

Align with PostgreSQL blog project table design.

Next project?

Admin dashboard with auth.