PokePages (Reboot)

The ultimate Pokémon companion app.
⚠️ This portfolio piece is still in progress. I'm working around the clock to get my projects updated and continually polishing when I can. Check back regularly for updates! ⚠️
Recognizing the need for real-time engagement tools in the Pokémon gaming community, I developed PokePages as a production-grade full-stack mobile and web application. This project showcases end-to-end development from custom backend API to cross-platform mobile UI, demonstrating mastery of modern full-stack architecture. I built a standalone Express.js API server with Drizzle ORM and PostgreSQL, featuring 15+ RESTful endpoints for events, social features, Pokédex tracking, and AI integration. The backend implements JWT authentication middleware, Row-Level Security policies, custom database functions, and comprehensive error handling. The frontend leverages React Native with an offline-first architecture using Zustand state management, implementing optimistic UI updates with intelligent sync queues that consolidate network requests when connectivity is restored. Key technical achievements include AI-powered content moderation using OpenAI's Moderation API (95% accuracy), real-time event counter system with Supabase subscriptions supporting both authenticated and anonymous users, comprehensive social platform with posts/likes/comments/messaging, and advanced authentication with seamless anonymous-to-authenticated data migration. The app features 50+ Mega Evolution forms in the Pokédex tracker, React Native Reanimated animations running at 60fps, and supports multiple Pokémon games simultaneously. Currently deployed to pokepages.app and in Google Play Store closed testing through EAS (Expo Application Services) CI/CD pipeline. The codebase spans 30,000+ lines with 100+ React components, 11+ database tables, and full TypeScript type safety. This represents a complete evolution from my earlier Adalo-based approach, demonstrating senior-level full-stack mobile development capabilities.

Skills Used:

Skills Learned:

Github
See it here!

Custom Express.js API Server with Drizzle ORM

Production-ready Node.js backend with 15+ RESTful endpoints
I architected and built a standalone Express.js API server as a microservice separate from the React Native frontend. The server features clean route architecture with dedicated controllers for Events, Social, Profiles, DexTracker, AI, and Favorites. I implemented custom JWT authentication middleware that verifies Supabase tokens, CORS configuration supporting multiple origins (web, mobile, emulators), and comprehensive error handling. The API uses Drizzle ORM for type-safe PostgreSQL queries, ensuring compile-time validation of all database operations. I also built diagnostic endpoints for health monitoring, tracking memory usage, uptime, and environment configuration.
// Express server with JWT auth middleware const app = express(); // Custom auth middleware validates Supabase JWT tokens const authMiddleware = async (req, res, next) => { const token = req.headers.authorization?.split(' ')[1]; if (!token) return res.status(401).json({ error: 'Unauthorized' }); try { const { data: { user }, error } = await supabase.auth.getUser(token); if (error) throw error; req.user = user; // Attach user to request next(); } catch (error) { res.status(401).json({ error: 'Invalid token' }); } }; // Type-safe Drizzle ORM query example const posts = await db .select() .from(postsTable) .where(eq(postsTable.userId, userId)) .orderBy(desc(postsTable.createdAt));

Offline-First Paradigm & Optimistic Updates

Intelligent sync queue handles tracking user data in multiple features
While everything in the app uses the Offline-first architecture using Zustand with persist middleware, the Pokédex form tracker is good example. It tracks Pokémon across multiple devices with 4 different modes: Normal, Shiny, Alpha, Shiny-Alpha. The system implements optimistic UI updates that respond instantly to user interactions while queuing network operations in the background. When offline, changes accumulate in a sync queue that intelligently consolidates updates and processes them in batches when connectivity is restored. I implemented platform-agnostic storage adapters using AsyncStorage on mobile and localStorage on web, with SSR-safe initialization. The tracker includes custom auth token caching with 5-second TTL and 2-second timeout protection to prevent hanging on web platforms.
// Optimistic update pattern - UI responds instantly toggleForm: async (dex: number, form: FormType, pokedex: string) => { const state = get(); // 1. Update local state immediately (optimistic) set((state) => ({ pokemon: { ...state.pokemon, [pokedex]: { ...(state.pokemon[pokedex] || {}), [dex]: updatedStatus, }, }, })); // 2. Try to sync with server if online, queue if offline if (state.isOnline) { try { await api.post('/dextracker/update', { dex, form, pokedex }); } catch (error) { queuePendingUpdate({ dex, form, pokedex }); // Retry later } } else { queuePendingUpdate({ dex, form, pokedex }); // Will sync on reconnect } }

AI-Powered Content Moderation with OpenAI

Three-tier moderation strategy achieving 95% accuracy
I implemented a sophisticated content moderation system with three detection levels to ensure safe user-generated content. The primary tier uses OpenAI's free Moderation API for instant hate speech, harassment, and violence detection with 95% accuracy and ~200ms response time. For complex edge cases, I integrated GPT-4o-mini for context-aware analysis that understands Pokémon terminology vs actual threats. The fallback tier provides instant profanity detection with zero API calls. The system detects multiple violation categories including hate speech, harassment, violence, sexual content, self-harm, spam, and excessive formatting. When content is flagged, users receive specific, actionable feedback explaining exactly what needs to be changed. This multi-tier approach balances accuracy, performance, and cost—basic moderation is free, while advanced analysis costs only $0.30/month for 3,000 posts.
// OpenAI Moderation API integration const moderateContent = async (text: string) => { try { // Tier 1: Free OpenAI Moderation API (~200ms, 95% accurate) const response = await openai.moderations.create({ input: text, model: 'text-moderation-latest' }); const result = response.results[0]; if (result.flagged) { // Return specific category that was violated const categories = Object.entries(result.categories) .filter(([_, flagged]) => flagged) .map(([category]) => category); return { approved: false, reason: `Content flagged for: ${categories.join(', ')}`, categories }; } // Tier 2: GPT-4o-mini for edge cases (context-aware) if (needsAdvancedCheck(text)) { return await gptModeration(text); } return { approved: true }; } catch (error) { // Tier 3: Fallback to basic profanity filter return basicProfanityCheck(text); } };

Real-Time Event Counter with Anonymous Support

Global multiplayer tracking with PostgreSQL RPC functions
I developed a real-time multiplayer event system where thousands of players contribute to global counters for live Pokémon events (Wo-Chien, Chien-Pao, Ting-Lu, Chi-Yu encounters). Using Supabase real-time subscriptions, counter updates propagate instantly to all connected devices. The system uniquely supports both authenticated users and anonymous guests—anonymous contributions are tracked via device ID and automatically migrate to the user's account upon signup/signin. I implemented custom PostgreSQL RPC functions for atomic counter increments that return both global count and individual user contribution in a single query. Each event has configurable target counts, reward distribution windows, and active date ranges, with the UI displaying progress bars and personal contribution badges.
// PostgreSQL RPC function for atomic counter increment const incrementCounter = async () => { try { // Call custom Postgres function with user/anonymous ID const params = { p_event_key: eventKey, p_pokemon_name: pokemonName, p_user_id: isLoggedIn && user ? user.id : null, p_anonymous_id: !isLoggedIn && anonymousId ? anonymousId : null }; const { data, error } = await supabase.rpc('increment_counter', params); if (data?.success) { // Returns both global count and user contribution setGlobalCount(data.event_counter.current_count); setUserCount(data.user_contribution); setLastUpdated(data.event_counter.updated_at); } } catch (error) { console.error('Failed to increment counter:', error); } };

Comprehensive Social Platform

Full-featured social network with posts, friendships, messaging, and content moderation
I built a complete social networking platform featuring posts with public/friends-only visibility, friendship management with request/accept/reject flows, like and comment systems with nested replies, and private messaging limited to friends. The architecture includes dedicated feed algorithms for Explore (all public posts) and Friends feeds, real-time updates as new content arrives, and integrated AI content moderation on all user-generated text. I implemented a unique 'Tom from MySpace' feature that auto-friends new users to a default welcome account, providing immediate engagement. The social schema includes sophisticated relationship modeling with bidirectional friendship tracking, blocking capabilities, and conversation threading. All user actions are protected by Row-Level Security policies ensuring users can only access authorized data.

Advanced Authentication with Data Migration

Seamless anonymous-to-authenticated user experience with Supabase Auth
I architected a sophisticated authentication system that supports email/password, Google OAuth, and Apple Sign In via Supabase Auth. A key innovation is the seamless anonymous user experience—users can explore the full app without signing up, with all their event contributions, Pokédex progress, and favorites tracked via anonymous device ID. When they eventually create an account or sign in, I automatically migrate all their anonymous data to their authenticated profile using database triggers and custom migration functions. The system uses Expo SecureStore for encrypted token storage on mobile, implements automatic token refresh to handle expired sessions transparently, and includes age verification via birthdate for filtering 18+ content. User profiles support customization with username, bio, avatar, and social links.

Mega Evolution Database with Type System

50+ Mega forms with dynamic type changes and advanced search
I built a comprehensive Mega Evolution database featuring 50+ Mega forms from the Lumiose City Pokédex, complete with type changes and visual indicators. The system handles complex cases like Charizard X/Y and Mewtwo X/Y with different type combinations (Mega Charizard X becomes Fire/Dragon while Y stays Fire/Flying). I implemented smart search that finds both base and Mega forms, automatic type change detection (Mega Ampharos gains Dragon type, Mega Gyarados becomes Water/Dark), and visual 'M' badges for Mega forms. The Pokédex tracker supports marking Mega forms separately from base forms across 8 different collection modes, with the type effectiveness calculator dynamically updating resistances and weaknesses based on Mega Evolution type changes.

Production Deployment with EAS

Multi-platform deployment via Expo Application Services
I successfully deployed PokePages to production using EAS (Expo Application Services) for streamlined build and deployment workflows. The app is currently live at pokepages.app as a Progressive Web App with full SEO optimization including meta tags, OpenGraph cards, Twitter Cards, and automated sitemap generation. I successfully deployed to Google Play Store closed testing, demonstrating complete mobile release workflow including signing certificates, privacy policy compliance, and store listing optimization. The deployment supports both web and native Android platforms, with iOS deployment planned next.

Advanced Expo Router Navigation Architecture

Type-safe routing with protected routes, drawer, stack, tabs, and custom top tabs
I architected a sophisticated navigation system using Expo Router v6 that combines multiple navigation patterns seamlessly. The app features a custom drawer layout with authentication-aware menu items, nested stack navigation for modal flows, bottom tab navigation for main sections, and custom top tabs on specific pages like the social feed. I implemented protected routes that automatically redirect unauthenticated users to the sign-in screen, with route guards checking authentication state before rendering sensitive content. The drawer dynamically adapts based on user permissions and age verification (18+ content filtering). The navigation supports deep linking for pokepages:// URLs, maintains consistent state across platform deployments (web and native), and provides type-safe navigation with auto-generated TypeScript types. This multi-pattern architecture demonstrates mastery of React Navigation patterns while leveraging Expo Router's file-based routing convention.
// Protected route with auth guard export default function ProtectedLayout() { const { user, isLoading } = useAuth(); const router = useRouter(); useEffect(() => { if (!isLoading && !user) { // Redirect to sign-in if not authenticated router.replace('/sign-in'); } }, [user, isLoading]); if (isLoading) return <LoadingScreen />; if (!user) return null; return ( <Stack> <Stack.Screen name="(drawer)" options={{ headerShown: false }} /> <Stack.Screen name="social/(tabs)" options={{ headerShown: false }} /> </Stack> ); } // Custom top tabs in social feed <Tab.Navigator screenOptions={{ tabBarScrollEnabled: true }}> <Tab.Screen name="explore" component={ExploreFeed} /> <Tab.Screen name="friends" component={FriendsFeed} /> </Tab.Navigator>

Custom UI/UX Wireframe Design after multiple Iterations

Unique, responsive layout and carefully designed social feed layout
I designed and implemented a distinctive visual identity for PokePages through multiple design iterations, focusing on creating an engaging and intuitive user experience. The home screen features custom-designed 'Quick Access' cards with gradient borders (pink, purple, orange) that respond to user interaction with subtle animations. I created a unique social feed layout that breaks from traditional social media conventions, using color-coded borders for different post types and visual hierarchy that prioritizes content over chrome. Through iterative wireframing and user testing, I refined the UI from initial concepts to the final polished design, with an array of iteration screenshots documenting the evolution. The design system includes custom components for type badges, Pokémon cards, event counters, and form trackers, all following a cohesive dark theme with accent colors that match the Pokémon aesthetic. Every interactive element includes micro-animations using React Native Reanimated for a premium feel.

Animated Home Card Component

Smooth gradient animations with React Native Reanimated
I developed a visually striking home card component that serves as the primary navigation hub, featuring smooth gradient border animations that continuously cycle through colors. Using React Native Reanimated 4, I implemented 60fps animations that run on the UI thread for maximum performance, avoiding JavaScript bridge overhead. The cards feature multi-color gradients (pink, purple, cyan, orange) that animate in a loop, creating an eye-catching effect that draws attention to key features like Messages, Form Tracker, and Quick Actions. Each card includes custom icons (Lottie animations or React Native Vector Icons), descriptive text, and 'NEW' badges for recently added features. The component is fully responsive across screen sizes, supports both light and dark themes, and includes accessibility labels for screen readers. The animation implementation demonstrates advanced React Native performance optimization techniques, ensuring smooth animations even on lower-end devices.

RSS Feed Service for Real-Time Pokémon News

Automated news aggregation from Pokémon Database with server-side parsing
I built a custom RSS feed service that automatically fetches and parses the latest Pokémon news from Pokémon Database (pokemondb.net), displaying it on the home screen and dedicated news page. The service runs server-side to handle XML parsing, image extraction, and content formatting, then serves the cleaned data to the mobile app via API endpoint. The implementation includes caching to minimize external API calls, error handling for malformed RSS feeds, and graceful fallbacks when the source is unavailable. The news articles are displayed with thumbnail images, publication dates, and formatted excerpts, with tap-to-read-more functionality that opens the full article in an in-app browser. This feature keeps users informed about the latest Pokémon events, game updates, and community news without leaving the app, demonstrating full-stack capabilities in content aggregation and API design.
Home
These practice and production projects have extensive information on how they were built.
Portfolio
Mobile Apps
APIs and MCP servers available for public use.
Public Facing
Services
Contact