Deployed Site: https://pokemonsocial.vercel.app
Submitted by: Roel Crodua
-
Pokemon Social is a full-featured social media web application built with React and Supabase that allows users to share and interact with Pokemon-themed posts.
-
Core Features:
- Post Creation: Users can create posts with titles, content, images (external URLs), and select Pokemon characters
- Interactive Feed: Browse posts with sorting options (by time, likes, or comments) and search functionality
- Engagement System: Like/unlike posts, add nested comments with edit capabilities, and view real-time interaction counts
- User Authentication: Full Supabase authentication with profile management (avatars, display names, bios)
- Post Management: Edit and delete your own posts with intuitive in-card controls
- Pokemon Integration: Browse and search 1000+ Pokemon from PokeAPI in an 8×8 grid with hover previews
-
Technical Stack:
- Frontend: React 19 + Vite
- Backend: Supabase (PostgreSQL with Row Level Security)
- APIs: PokeAPI for Pokemon data
-
Features: Infinite scroll pagination, optimistic UI updates, real-time count synchronization, image URL validation
Time spent: 20 hours spent in total
The following required functionality is completed:
-
Web app includes a create form that allows the user to create posts
- Form requires users to add a post title
- Forms should have the option for users to add:
- additional textual content
- an image added as an external image URL
-
Web app includes a home feed displaying previously created posts
- Web app must include home feed displaying previously created posts
- By default, each post on the posts feed should show only the post's:
- creation time
- title
- upvotes count
- Clicking on a post should direct the user to a new page for the selected post
-
Users can view posts in different ways
- Users can sort posts by either:
- creation time
- upvotes count
- Users can search for posts by title
- Users can sort posts by either:
-
Users can interact with each post in different ways
- The app includes a separate post page for each created post when clicked, where any additional information is shown, including:
- content
- image
- comments
- Users can leave comments underneath a post on the post page
- Each post includes an upvote button on the post page.
- Each click increases the post's upvotes count by one
- Users can upvote any post any number of times
- The app includes a separate post page for each created post when clicked, where any additional information is shown, including:
-
A post that a user previously created can be edited or deleted from its post pages
- After a user creates a new post, they can go back and edit the post
- A previously created post can be deleted from its post page
The following optional features are implemented:
- Web app implements pseudo-authentication
- Users can only edit and delete posts or delete comments by entering the secret key, which is set by the user during post creation
- or upon launching the web app, the user is assigned a random user ID. It will be associated with all posts and comments that they make and displayed on them
- For both options, only the original user author of a post can update or delete it
- Users can repost a previous post by referencing its post ID
- Users can repost a previous post by referencing its post ID
- On the post page of the new post, the referenced post is displayed and linked, creating a thread
- Users can customize the interface
- e.g., selecting the color scheme or showing the content and image of each post on the home feed
- Users can add more characterics to their posts
- Users can share and view web videos
- Users can set flags such as "Question" or "Opinion" while creating a post
- Users can filter posts by flags on the home feed
- Users can upload images directly from their local machine as an image file
- Web app displays a loading animation whenever data is being fetched
Here's a walkthrough of implemented user stories:
GIF created with Wondershare Uniconverter 14 Tool - GIF Maker
-
Describe any challenges encountered while building the app.
- Supabase DB setup.
- Authorization setup in supabase.
- Creating demo file as gif file.
-
This project uses Supabase for backend, which handles auth, database, and storage
-
Pokemon data is fetched from PokeAPI and cached locally
-
Image URLs are external (not uploaded) to simplify storage
-
Repost feature creates a new post with reference to original
-
Infinite scroll improves UX for browsing large feeds
PokemonSocial/
│
├── public/ # Static assets
│ └── (favicon, images, etc.)
│
├── src/ # Source code directory
│ ├── assets/ # Application assets
│ │
│ ├── components/ # React components (organized by feature)
│ │ ├── Auth/ # Authentication components
│ │ │ ├── AuthModal.jsx # Main authentication modal wrapper
│ │ │ ├── LoginForm.jsx # Login form component
│ │ │ ├── SignupForm.jsx # Registration form component
│ │ │ ├── ForgotPasswordForm.jsx # Password recovery form
│ │ │ └── Auth.css # Authentication styling
│ │ │
│ │ ├── Comments/ # Comment system components
│ │ │ ├── CommentForm.jsx # Comment creation/edit form
│ │ │ ├── CommentList.jsx # Comment display with nested replies
│ │ │ └── Comments.css # Comment styling
│ │ │
│ │ ├── Layout/ # Layout components
│ │ │ ├── Navbar.jsx # Top navigation bar
│ │ │ └── Footer.jsx # Page footer
│ │ │
│ │ ├── Pokemon/ # Pokemon-related components
│ │ │ └── (future components)
│ │ │
│ │ ├── Posts/ # Post management components
│ │ │ ├── PostCard.jsx # Individual post display card
│ │ │ ├── PostForm.jsx # Post creation/edit form with repost
│ │ │ ├── PokemonSelector.jsx # Pokemon selection modal (8×8 grid)
│ │ │ └── Posts.css # Post styling
│ │ │
│ │ └── Profile/ # User profile components
│ │ ├── ProfileHeader.jsx # Profile header with avatar/bio
│ │ ├── ProfileStats.jsx # User statistics display
│ │ └── Profile.css # Profile styling
│ │
│ ├── context/ # React Context providers
│ │ └── AuthContext.jsx # Authentication state management
│ │
│ ├── hooks/ # Custom React hooks
│ │ ├── usePosts.js # Hook for post data fetching
│ │ └── useProfile.js # Hook for profile data fetching
│ │
│ ├── pages/ # Page-level components (routes)
│ │ ├── HomePage.jsx # Main feed with infinite scroll
│ │ ├── PostDetailPage.jsx # Single post view with comments
│ │ ├── ProfilePage.jsx # User profile page
│ │ ├── MyHeroesPage.jsx # User's Pokemon collection
│ │ └── SearchPage.jsx # Search results page
│ │
│ ├── services/ # API service layer
│ │ ├── supabase.js # Supabase client configuration
│ │ ├── postService.js # Post CRUD operations
│ │ ├── commentService.js # Comment CRUD operations
│ │ └── pokemonService.js # PokeAPI integration
│ │
│ ├── utils/ # Utility functions
│ │ └── dateUtils.js # Date formatting utilities
│ │
│ ├── App.jsx # Main application component
│ ├── App.css # Global application styles
│ ├── main.jsx # Application entry point
│ └── index.css # Root CSS styles
│
├── .env # Environment variables (not in git)
├── .gitignore # Git ignore rules
├── eslint.config.js # ESLint configuration
├── index.html # HTML entry point
├── package.json # Dependencies and scripts
├── vite.config.js # Vite build configuration
└── README.md # Project documentation
User Interaction
↓
Page Component
↓
Custom Hooks (usePosts, useProfile)
↓
Service Layer (postService, commentService)
↓
Supabase Client
↓
PostgreSQL Database
Here's a brief overview of all database tables and their columns
| Table Name | Columns |
|---|---|
| profiles | user_id (PK), username, display_name, bio, avatar_url, created_at, updated_at |
| pokemon | pokemon_id (PK), name, imageUrl, smallUrl, types[], height, weight, abilities[], created_at |
| posts | post_id (PK), user_id (FK), content, image_url, pokemon_id (FK), repost_id (FK), repost_link, likes_count, comments_count, created_at, updated_at |
| comments | comment_id (PK), post_id (FK), user_id (FK), parent_id (FK), content, created_at, updated_at |
| likes | like_id (PK), post_id (FK), user_id (FK), created_at |
- profiles ↔ posts (1:N - user can create many posts)
- pokemon ↔ posts (1:N - one Pokemon can appear in many posts)
- posts ↔ comments (1:N - one post can have many comments)
- posts ↔ likes (1:N - one post can have many likes)
- posts ↔ posts (self-reference via
repost_idfor reposts) - comments ↔ comments (self-reference via
parent_idfor nested replies)
┌─────────────┐
│ auth.users│ (Supabase built-in)
└──────┬──────┘
│
│ 1:1
▼
┌─────────────┐ ┌──────────────┐
│ profiles │ │ pokemon │
│ │ │ │
│ user_id (PK)│ │ pokemon_id(PK)│
│ username │ │ name │
│ display_name│ │ imageUrl │
│ bio │ │ types[] │
│ avatar_url │ │ abilities[] │
└──────┬──────┘ └──────┬───────┘
│ │
│ 1:N │ 1:N
│ │
│ ┌──────────────────┘
│ │
▼ ▼
┌──────────────────┐
│ posts │◄────┐ (self-referencing)
│ │ │ repost_id
│ post_id (PK) │─────┘
│ user_id (FK) │
│ pokemon_id (FK) │
│ content │
│ repost_id (FK) │
│ repost_link │
│ likes_count │
│ comments_count │
└────┬────┬────────┘
│ │
│ │ 1:N
│ │
│ ▼
│ ┌──────────────┐
│ │ comments │◄───┐ (self-referencing)
│ │ │ │ parent_id
│ │ comment_id(PK)────┘
│ │ post_id (FK) │
│ │ user_id (FK) │
│ │ parent_id(FK)│
│ │ content │
│ └──────────────┘
│
│ 1:N
│
▼
┌──────────────┐
│ likes │
│ │
│ like_id (PK) │
│ post_id (FK) │
│ user_id (FK) │
│ │
│ UNIQUE(post, │
│ user) │
└──────────────┘
| Route | Component | Description | Auth Required |
|---|---|---|---|
/ |
HomePage | Main feed with posts | No |
/post/:postId |
PostDetailPage | Single post with comments | No |
/profile/:userId |
ProfilePage | User profile view | No |
/my-heroes |
MyHeroesPage | User's Pokemon collection | Yes |
/search |
SearchPage | Search results | No |
- User fills PostForm component
- PostForm validates input
- Calls
postService.createPost() - Service inserts into Supabase
- Database triggers update counts
- UI updates via state refresh
- User clicks like button
- Optimistic UI update (immediate feedback)
- PostCard calls
postServiceto toggle like - Database inserts/deletes like record
- RPC function updates cached count
- Actual count reloaded from database
- User clicks 🔁 Repost button
- Navigate to home with
?repost=IDparameter - HomePage detects parameter, opens PostForm
- PostForm auto-fetches original post data
- User adds commentary, submits
- New post created with
repost_idandrepost_link - Original post link displayed in new post card
Copyright 2025 Roel Crodua
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


