You will need a Supabase account, Open Weather account, Rest Countries account and a Google Cloud account for this project.
- Prerequisites
- Installation
- Available Commands
- Enviroment Setup
- Tech Stack
- Setting up Supabase
- Authors
A full-stack application with NestJS backend and React frontend.
project-root/
├── backend/ # NestJS application
└── frontend/ # React application- Node.js (v18 or higher recommended)
- npm (comes with Node.js)
- Clone the repository:
git clone https://github.com/JonathanGian/Countries-FullStack.git
cd Countries_Fullstack
npm install- Install all dependencies (both frontend and backend):
npm run install:allStart both frontend and backend development servers:
npm run devThe applications will be available at:
- Frontend: http://localhost:5180
- Backend: http://localhost:3000
npm run dev- Start both frontend and backend in development modenpm run dev:frontend- Start only the frontendnpm run dev:backend- Start only the backendnpm run install:all- Install dependencies for both projectsnpm run install:frontend- Install frontend dependenciesnpm run install:backend- Install backend dependenciesnpm run build- Build both projectsnpm run build:frontend- Build frontend onlynpm run build:backend- Build backend only
- Create a
.envfile in the frontend directory:
VITE_SUPABASE_URL=YOUR_SUPABASE_URL
VITE_SUPABASE_ANON_KEY=Supabase_Anon_key
VITE_OPENWEATHER_API_KEY=YOUR_OPEN_API_KEY- Create a
.envfile in the backend directory:
SUPABASE_URL=Your_supabase_URL
SUPABASE_ANON_KEY=Your_supabase_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key- Frontend:
- React
- TypeScript
- Vite
- Backend:
- NestJS
- TypeScript
- Supabase
- Go to Supabase Dashboard
- Sign in or create a new account
- Click "New Project"
- Fill in the project details:
- Add a project name
- Set a secure database password
- Choose your region (pick the one closest to your users)
- Choose the pricing plan (Free tier is sufficient for testing)
- Click "Create new project" and wait for deployment (usually takes 1-2 minutes)
-
In your project dashboard, go to the "SQL Editor" in the left sidebar
-
Click "New Query"
-
Copy and paste the following SQL to create the test table:
-- Create the test table CREATE TABLE test ( id UUID DEFAULT uuid_generate_v4() PRIMARY KEY, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), name TEXT NOT NULL, description TEXT, is_active BOOLEAN DEFAULT TRUE ); -- Insert test data INSERT INTO test (name, description) VALUES ('Test Item 1', 'This is the first test item'), ('Test Item 2', 'This is the second test item'), ('Test Item 3', 'This is the third test item'); -- Enable Row Level Security (RLS) ALTER TABLE test ENABLE ROW LEVEL SECURITY; -- Create RLS policy CREATE POLICY "Enable read access for all users" ON test FOR SELECT USING (true);
-
Click "Run" or press Ctrl+Enter (Cmd+Enter on Mac) to execute the query
-
Go to "Table Editor" in the left sidebar
-
You should see your
testtable listed -
Click on the table to view the inserted records
-
Try some example queries in the SQL Editor:
-- Select all records SELECT * FROM test; -- Select active records SELECT * FROM test WHERE is_active = true; -- Select records with custom conditions SELECT name, description FROM test WHERE name LIKE 'Test%' ORDER BY created_at DESC;
Your connection details can be found under Project Settings → API:
- Project URL
- Project API Key (anon public key)
- JWT Secret (if needed)
Remember to never commit these values directly to your repository. Use environment variables instead.
If you encounter any issues:
- Check the SQL Editor for any error messages
- Verify RLS policies are correctly set up
- Ensure your API keys are properly configured
- Check the Supabase logs in the Dashboard
Run the following SQL in your Supabase SQL Editor to create the favorites table with proper Row Level Security (RLS):
-- Create the favorites table
CREATE TABLE country_favorites (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
country_name TEXT NOT NULL,
country_code TEXT NOT NULL,
country_flag TEXT NOT NULL,
user_id UUID NOT NULL REFERENCES auth.users(id)
);
-- Enable RLS
ALTER TABLE country_favorites ENABLE ROW LEVEL SECURITY;
-- Create policy for reading data
CREATE POLICY "Users can read own favorites"
ON country_favorites
FOR SELECT
USING (auth.uid() = user_id);
-- Create policy for inserting data
CREATE POLICY "Users can insert own favorites"
ON country_favorites
FOR INSERT
WITH CHECK (
auth.uid() IS NOT NULL AND
user_id = auth.uid()
);
-- Create policy for deleting data
CREATE POLICY "Users can delete own favorites"
ON country_favorites
FOR DELETE
USING (auth.uid() = user_id);
-- Create trigger to automatically set user_id
CREATE OR REPLACE FUNCTION set_favorite_user_id()
RETURNS TRIGGER AS $$
BEGIN
NEW.user_id := auth.uid();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Create the trigger
DROP TRIGGER IF EXISTS set_favorite_user_id_trigger ON country_favorites;
CREATE TRIGGER set_favorite_user_id_trigger
BEFORE INSERT ON country_favorites
FOR EACH ROW
EXECUTE FUNCTION set_favorite_user_id();This setup ensures that:
- Each favorite is linked to a user
- Users can only see, add, and delete their own favorites
- The user_id is automatically set when a favorite is created
Copy these statements into your Supabase Project SQL editor and hit run.
-- Create the reviews table
CREATE TABLE reviews (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
country_id UUID NOT NULL REFERENCES countries(id), -- References the seeded countries table
rating INTEGER NOT NULL CHECK (rating >= 1 AND rating <= 5),
comment TEXT,
user_id UUID NOT NULL REFERENCES auth.users(id)
);
-- Enable Row-Level Security on the reviews table
ALTER TABLE reviews ENABLE ROW LEVEL SECURITY;
-- Allow anyone to read reviews
CREATE POLICY "Public read reviews" ON reviews
FOR SELECT
USING (true);
-- Allow authenticated users to insert reviews with their own user_id
CREATE POLICY "Users can insert own reviews" ON reviews
FOR INSERT
WITH CHECK (
auth.uid() IS NOT NULL AND user_id = auth.uid()
);
-- Allow users to delete their own reviews
CREATE POLICY "Users can delete own reviews" ON reviews
FOR DELETE
USING (auth.uid() = user_id);
-- Create a trigger function to automatically set the user_id on insert
CREATE OR REPLACE FUNCTION set_review_user_id()
RETURNS TRIGGER AS $$
BEGIN
NEW.user_id := auth.uid();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Attach the trigger function to the reviews table
DROP TRIGGER IF EXISTS set_review_user_id_trigger ON reviews;
CREATE TRIGGER set_review_user_id_trigger
BEFORE INSERT ON reviews
FOR EACH ROW
EXECUTE FUNCTION set_review_user_id();Author: Jonathan Gian Guide and Teacher: Martin Holland