Recreate the Rewards page of https://www.flowvahub.com
- React 18: UI library with TypeScript support
- TypeScript: Type-safe development
- Vite: Fast build tool and dev server
- TanStack Router: Type-safe routing with route protection
- Supabase: Authentication and PostgreSQL database
- Tailwind CSS: Utility-first CSS framework
- Lottie: Animations
- pnpm: Fast, disk space efficient package manager
- Node.js 18+ installed
- pnpm installed (
npm install -g pnpm) - Supabase account (sign up here)
git clone <repository-url>pnpm installCreate a new project in Supabase Dashboard.
Run this SQL in your Supabase SQL Editor:
CREATE TABLE profiles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email TEXT UNIQUE NOT NULL,
full_name TEXT,
avatar_url TEXT,
referral_code TEXT UNIQUE NOT NULL DEFAULT gen_random_uuid()::text,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
total_points INTEGER DEFAULT 0,
referral_count INTEGER DEFAULT 0,
last_claim_date TIMESTAMP WITH TIME ZONE,
current_streak INTEGER DEFAULT 0,
longest_streak INTEGER DEFAULT 0,
interest TEXT,
goal TEXT,
tools TEXT[],
role TEXT[],
country TEXT,
city TEXT,
flag TEXT,
country_code TEXT,
country_code_iso3 TEXT,
is_author BOOLEAN DEFAULT false
);
-- Create an index on email for faster lookups
CREATE INDEX idx_profiles_email ON profiles(email);
-- Create a trigger to update the updated_at timestamp
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ language 'plpgsql';
CREATE TRIGGER update_profiles_updated_at BEFORE UPDATE ON profiles
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();- Go to Authentication > Providers in Supabase Dashboard
- Enable Email provider
- Configure email settings (or use default for development)
Create a .env file in the project root:
VITE_SUPABASE_URL=your_supabase_project_url
VITE_SUPABASE_PUBLISHABLE_DEFAULT_KEY=your_supabase_anon_keyGet these values from:
- Supabase Dashboard → Settings → API
VITE_SUPABASE_URL: Project URLVITE_SUPABASE_PUBLISHABLE_DEFAULT_KEY: anon/public key
pnpm devThe application will be available at http://localhost:5173
pnpm buildThe production build will be in the dist/ directory.
To preview the production build locally:
pnpm preview-
Install Vercel CLI (optional):
npm i -g vercel
-
Deploy:
vercel
-
Add environment variables in Vercel Dashboard:
- Go to Project Settings → Environment Variables
- Add
VITE_SUPABASE_URLandVITE_SUPABASE_PUBLISHABLE_DEFAULT_KEY
The vercel.json file is already configured to handle client-side routing.
src/
├── routes/ # TanStack Router routes
│ ├── index.tsx # Root route (redirects to /signin)
│ ├── signin.tsx # Login page route
│ ├── signup.tsx # Signup page route
│ └── earn-rewards.tsx # Protected rewards page route
├── templates/ # Page templates/components
│ ├── Login.template.tsx
│ ├── Signup.template.tsx
│ └── Rewards.template.tsx
├── utils/ # Utility functions
│ ├── supabase.ts # Supabase client configuration
│ └── api.ts # API functions (getUserProfile, addPoints, etc.)
└── main.tsx # Application entry point
- Email/password signup with duplicate email detection
- Secure login with session management
- Password visibility toggle
- Email verification support
Protected routes use beforeLoad hook to check authentication:
beforeLoad: async () => {
const { data: { session } } = await supabase.auth.getSession();
if (!session) {
throw redirect({ to: "/signin" });
}
}- Users can claim 5 points once every 24 hours
- Cooldown timer shows remaining time until next claim
- Points are automatically added to user's
total_points
- Consecutive daily claims increase streak count
- Visual week calendar shows current day and claim status
- Longest streak is tracked and displayed
- Streak resets if a day is missed
The profiles table stores user data:
| Column | Type | Description |
|---|---|---|
| id | UUID | Primary key |
| TEXT | User email (unique) | |
| full_name | TEXT | User's full name |
| avatar_url | TEXT | Profile picture URL |
| referral_code | TEXT | Unique referral code |
| total_points | INTEGER | Accumulated points |
| last_claim_date | TIMESTAMP | Last point claim time |
| current_streak | INTEGER | Current daily streak |
| longest_streak | INTEGER | Longest streak achieved |
Fetches authenticated user's profile data from the profiles table.
Adds points to user's total, updates streak, and enforces 24-hour cooldown.
Checks if 24 hours have passed since last claim.
Returns formatted time remaining until next claim is available.
MIT