Skip to content

RCOA24/Blog-Austria

Repository files navigation

πŸ“ Full-Stack Blog Application

A Modern React Blog Platform with Complete CRUD Operations

React TypeScript Redux Supabase Vite Tailwind CSS


πŸ“‹ Table of Contents


πŸ“‹ Assessment Requirements

Note: This project is strictly for a technical assessment demonstration.

This application was built to fullfill the following specific trainee assessment criteria:

Core Objective: Build a simple blog web application using ReactJS in 5 days.

Conditions & Status:

  • Tech Stack: Use TypeScript
  • State Management: Use Redux
  • Backend: Use Supabase
  • Authentication Pages:
    • Registration (Email confirmation disabled)
    • Login
    • Logout
  • Blog Operations:
    • Create a blog
    • Update a blog
    • Delete a blog
    • Listing blogs with pagination
  • Deployment:
    • Deploy to public host (Vercel/Netlify)
    • Provide GitHub Repository

🎯 Overview

A production-ready blog application demonstrating modern full-stack development practices. Built as a comprehensive technical assessment showcasing proficiency in React 19, TypeScript, Redux state management, Supabase backend integration, and secure authentication patterns.

Core Capabilities

βœ… Complete CRUD Operations - Create, Read, Update, and Delete blog posts
βœ… Secure Authentication - Email/password registration and login system via Supabase Auth
βœ… Row-Level Security - Backend-enforced user permissions via Supabase RLS
βœ… State Management - Centralized Redux Toolkit store with typed hooks
βœ… Rich Text Editing - Markdown support for writing and viewing posts
βœ… Responsive Design - Mobile-first Tailwind CSS styling (v4) with dark mode support
βœ… Real-time Feedback - Toast notifications for user actions


πŸš€ Key Features

πŸ” Authentication System

  • User Registration - Email/password signup with instant access.
  • Secure Login/Logout - JWT-based session management.
  • Persistent Sessions - Automatic session restoration on page reload.
  • Author Attribution - Automatic username resolution via database triggers.

πŸ“° Blog Post Management

Feature Description Security
Create Authenticated users can publish new posts User ID automatically attached
Read Public access to all published posts No authentication required
Update Edit your own posts only RLS policy enforced
Delete Remove your own posts only RLS policy enforced
Rich Text Markdown editor with preview Sanitized output

πŸ›  Tech Stack

Frontend

  • Framework: React 19 with Vite 7
  • Language: TypeScript 5.9
  • State Management: Redux Toolkit & React-Redux
  • Routing: React Router DOM v7
  • Styling: Tailwind CSS 4 & PostCSS
  • Editor: @uiw/react-md-editor
  • Icons: Lucide React
  • Notifications: React Toastify

Backend & Infrastructure

  • BaaS: Supabase
  • Database: PostgreSQL
  • Authentication: Supabase Auth
  • Security: Row Level Security (RLS)
  • Deployment: Ready for Vercel/Netlify

πŸš€ Getting Started

Prerequisites

  • Node.js 18+ and npm/yarn
  • Supabase Account (free tier available)

Installation Steps

1️⃣ Clone the Repository

git clone <repository-url>
cd blog-app

2️⃣ Install Dependencies

npm install

3️⃣ Environment Configuration

Create a .env file in the root directory:

VITE_SUPABASE_URL=your_supabase_project_url
VITE_SUPABASE_ANON_KEY=your_supabase_anon_key

πŸ’‘ Tip: Find your Supabase credentials at: Project Settings β†’ API

4️⃣ Run Development Server

npm run dev

The application will be available at http://localhost:5173


πŸ—„οΈ Database Setup

Supabase Configuration

Navigate to the SQL Editor in your Supabase dashboard and run the following script to set up the database, RLS policies, and triggers:

-- 1. Create the 'posts' table
create table public.posts (
  id uuid default gen_random_uuid() primary key,
  created_at timestamp with time zone default timezone('utc'::text, now()) not null,
  title text not null,
  content text not null,
  user_id uuid references auth.users not null,
  author_name text
);

-- 2. Enable Row Level Security (RLS)
alter table public.posts enable row level security;

-- 3. Create Security Policies

-- Policy: Public read access
create policy "Public posts are viewable by everyone" 
  on public.posts for select 
  using (true);

-- Policy: Authenticated users can insert their own posts
create policy "Users can insert their own posts" 
  on public.posts for insert 
  with check (auth.uid() = user_id);

-- Policy: Users can update their own posts
create policy "Users can update own posts" 
  on public.posts for update 
  using (auth.uid() = user_id);

-- Policy: Users can delete their own posts
create policy "Users can delete own posts" 
  on public.posts for delete 
  using (auth.uid() = user_id);

-- 4. Create Author Name Trigger
-- This function automatically populates author_name from user metadata
create or replace function public.handle_new_post_author()
returns trigger
language plpgsql
security definer
set search_path = public
as $$
declare
  user_name text;
begin
  select 
    coalesce(
      raw_user_meta_data->>'username',
      split_part(email, '@', 1),
      'Anonymous'
    ) into user_name
  from auth.users
  where id = new.user_id;

  new.author_name := user_name;
  return new;
end;
$$;

-- Attach the trigger
create trigger on_auth_user_created_post
  before insert on public.posts
  for each row execute procedure public.handle_new_post_author();

πŸ“‚ Project Structure

blog-app/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ app/
β”‚   β”‚   β”œβ”€β”€ store.ts              # Redux store configuration
β”‚   β”‚   └── hooks.ts              # Typed useAppDispatch & useAppSelector
β”‚   β”‚
β”‚   β”œβ”€β”€ features/
β”‚   β”‚   β”œβ”€β”€ auth/
β”‚   β”‚   β”‚   └── authSlice.ts      # Authentication state & reducers
β”‚   β”‚   β”‚
β”‚   β”‚   └── blogs/
β”‚   β”‚       └── blogsSlice.ts     # Blog posts state & reducers
β”‚   β”‚
β”‚   β”œβ”€β”€ components/
β”‚   β”‚   β”œβ”€β”€ Navbar.tsx            # Navigation bar
β”‚   β”‚   β”œβ”€β”€ BlogList.tsx          # Component to list blog posts
β”‚   β”‚   └── PostItem.tsx          # Individual post item component
β”‚   β”‚
β”‚   β”œβ”€β”€ services/
β”‚   β”‚   β”œβ”€β”€ authService.ts        # Auth API calls
β”‚   β”‚   └── blogService.ts        # Blog CRUD API calls
β”‚   β”‚
β”‚   β”œβ”€β”€ pages/
β”‚   β”‚   β”œβ”€β”€ Home.tsx              # Landing page
β”‚   β”‚   β”œβ”€β”€ Login.tsx             # Sign in page
β”‚   β”‚   β”œβ”€β”€ Register.tsx          # Sign up page
β”‚   β”‚   β”œβ”€β”€ CreatePost.tsx        # Post creation page
β”‚   β”‚   β”œβ”€β”€ EditPost.tsx          # Post editing page
β”‚   β”‚   └── PostDetail.tsx        # Single post view
β”‚   β”‚
β”‚   β”œβ”€β”€ supabaseClient.ts         # Supabase client initialization
β”‚   β”œβ”€β”€ App.tsx                   # Main component & routing
β”‚   └── main.tsx                  # Entry point
β”‚
β”œβ”€β”€ public/                       # Static assets
β”œβ”€β”€ supabase_setup.sql            # Database schema reference
└── package.json                  # Dependencies & scripts

πŸ”’ Security Implementation

Row-Level Security (RLS)

The application relies on Supabase's RLS to ensure data integrity and security directly at the database layer.

Operation Enforcement
View Posts Open to public.
Add Post Restricted to authenticated users. User ID must match the session.
Edit/Delete Restricted to the original author of the post.

Frontend Protection

  • Route Guards: Creation and editing routes are protected; unauthenticated users are redirected to login.
  • UI Logic: "Edit" and "Delete" buttons are only rendered if the current logged-in user matches the post's author ID.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages