Frontend Structure
The Blogify frontend is built with Next.js 16 using the App Router architecture. It leverages React 19 features like the use hook and Server Components, while maintaining a clear separation between UI components, state management, and the API communication layer.
Architecture Overview
The frontend acts as the orchestrator between three main entities:
- Supabase Auth/Storage: Handled directly from the client for authentication and media uploads.
- FastAPI Backend: Accessed via a typed API client for all CRUD operations on posts and user metadata.
- Vercel: The hosting platform where the Next.js application is deployed.
Directory Structure
frontend/src/
├── app/ # Routing, layouts, and page-specific logic
├── components/ # Reusable UI components (PostCard, Sidebar, etc.)
├── context/ # Global state (User authentication state)
├── lib/ # Core utilities, API clients, and constants
└── styles/ # Tailwind CSS and global styling
Routing & Page Organization
Blogify uses the Next.js App Router to handle complex nested and dynamic routing.
Public & Marketing Pages
app/page.tsx: The landing page with high-level feature overviews.app/about/page.tsx: A static-focused page describing the platform mission and stack.app/login/&app/signup/: Authentication entry points.
The Feed & Discovery
app/feed/page.tsx: The primary "Community Feed." It handles client-side pagination and featured post logic.app/tags/[tag]/page.tsx: Dynamic route for filtering content by specific categories or tags.
Post Management (Dynamic Routes)
The platform uses specialized sub-directories for post lifecycle management:
app/posts/[id]/: The post detail view. UsesPostPageClientandPostPageContentto separate authorization logic from UI rendering.app/posts/new/: A protected route for creating new content.app/posts/[id]/edit/: A protected route that pre-fills post data and allows owner-only updates.
User Profiles
app/profile/: The current user's private dashboard.app/users/[id]/: Public profiles for exploring other writers' contributions.
API & Data Layer (lib/api.ts)
All communication with the backend is centralized in the api.ts utility. This layer ensures type safety and consistent error handling across the application.
Authentication Headers
The client automatically retrieves the Supabase JWT session and attaches it to outgoing requests destined for protected FastAPI routes:
async function authHeaders(): Promise<HeadersInit> {
const { data: { session } } = await supabase.auth.getSession();
if (!session?.access_token) throw new Error('Not authenticated');
return {
'Content-Type': 'application/json',
Authorization: `Bearer ${session.access_token}`,
};
}
Media Management
Image uploads are handled via the uploadImage function, which interacts directly with Supabase Storage. It generates a unique path for each file and returns a public URL used for post headers or user avatars.
Key Features & Components
Markdown & Math Support
Blogify supports rich content rendering using:
react-markdown: For standard Markdown processing.remark-math&rehype-katex: To support mathematical formulas (KaTeX).remark-unwrap-images: For clean image rendering within articles.
Authorization Guards
The RequireAuth component is used as a wrapper for sensitive routes. It checks the UserContext and redirects unauthenticated users to the login page while preserving their intended destination in the URL params.
// Example usage in [id]/page.tsx
<RequireAuth>
<PostPageContent id={id} />
</RequireAuth>
Response UI
The UI is built with Tailwind CSS, featuring:
- Dark Mode Support: Styled using the
dark:utility class. - Skeletons:
PostCardSkeletonprovides a smooth perceived loading experience during data fetching. - Responsive Sidebar: A collapsible navigation and info bar for mobile and desktop views.