Skip to content

Repository files navigation

📓 Note Hub — Complete Setup Guide

A personal note gallery with file uploads, folders, tags, and password protection. Backend powered by Supabase (free tier). No Firebase needed.


📋 Table of Contents

  1. What You Need (Prerequisites)
  2. Download & Extract the Project
  3. Create a Free Supabase Account
  4. Create a Supabase Project
  5. Run the Database Migrations (SQL)
  6. Deploy the Edge Functions
  7. Get Your Supabase API Keys
  8. Edit the .env File
  9. Install & Run the App
  10. Set Your Admin Password
  11. Log In & Use the App
  12. Troubleshooting
  13. How the App Works (Quick Reference)

1. What You Need

Before starting, make sure you have these installed on your computer:

ToolPurposeDownload
Node.js (v18 or newer)Runs the apphttps://nodejs.org → click "LTS"
npmInstalls packages (comes with Node.js)Included with Node.js
Supabase CLIDeploys backend functionsSee Step 6 below
A web browserChrome, Firefox, EdgeAlready have it
A text editorEdit config filesVS Code: https://code.visualstudio.com

Check Node.js is installed — open your Terminal and run:

node --version

You should see something like v20.0.0. If you see an error, install Node.js first.


2. Download & Extract the Project

  1. Download the ratulnotehub-clean.zip file (the one Claude gave you).

  2. Open your Downloads folder.

  3. Right-click on ratulnotehub-clean.zipExtract Here (or Extract All on Windows).

  4. You will now have a folder called notehub-clean-src inside a folder called ratulnotehub-clean.

  5. Open your Terminal (or Command Prompt on Windows) and navigate into the project:

cd~/Downloads/ratulnotehub-clean/notehub-clean-src

💡 Tip: On Windows, use cd %USERPROFILE%\Downloads\ratulnotehub-clean\notehub-clean-src

  1. Confirm you are in the right place:
ls

You should see files like: index.html, package.json, vite.config.ts, src/, supabase/


3. Create a Free Supabase Account

Supabase is a free backend service that stores your files, notes, and password.

  1. Go to https://supabase.com

  2. Click "Start your project" (green button, top right).

  3. Sign up with GitHub (easiest) or your email.

  4. Verify your email if asked.

  5. You are now on the Supabase Dashboard.


4. Create a Supabase Project

  1. On the Supabase Dashboard, click "New project".

  2. Fill in the form:

    • Organization: Your name (auto-created)
    • Project name:notehub (or anything you like)
    • Database Password: Create a strong password and save it somewhere — you'll need it later
    • Region: Pick the one closest to you (e.g., Southeast Asia if you're in Bangladesh)
  3. Click "Create new project".

  4. Wait about 1-2 minutes while Supabase sets up your database. You'll see a loading spinner.

  5. Once done, you'll see your project dashboard. Keep this tab open — you'll need it.


5. Run the Database Migrations (SQL)

This step creates all the database tables the app needs (notes, folders, tags, password storage, file storage).

  1. In your Supabase project dashboard, look at the left sidebar.

  2. Click "SQL Editor" (the icon looks like </>).

  3. Click "New query" (top left of the SQL editor).

  4. You need to run 3 SQL files from your project. Open the folder:

    notehub-clean-src/supabase/migrations/
    

    You will see 3 .sql files. Run them in order (oldest timestamp first):


Migration 1 — Copy this entire block and paste it into the SQL editor:

-- Create auth_user table for single admin userCREATETABLEpublic.auth_user (
id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
username TEXTNOT NULL UNIQUE,
password_hash TEXTNOT NULL
);
ALTERTABLEpublic.auth_user ENABLE ROW LEVEL SECURITY;
-- Create login_attempts table for rate limitingCREATETABLEpublic.login_attempts (
id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
ip_address TEXTNOT NULL,
attempt_count INTEGERNOT NULL DEFAULT 0,
last_attempt_time TIMESTAMP WITH TIME ZONENOT NULL DEFAULT now(),
blocked_until TIMESTAMP WITH TIME ZONE
);
CREATEUNIQUE INDEXidx_login_attempts_ipONpublic.login_attempts (ip_address);
ALTERTABLEpublic.login_attempts ENABLE ROW LEVEL SECURITY;
-- Create sessions tableCREATETABLEpublic.sessions (
id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID NOT NULLREFERENCESpublic.auth_user(id) ON DELETE CASCADE,
token TEXTNOT NULL UNIQUE,
expires_at TIMESTAMP WITH TIME ZONENOT NULL,
last_activity TIMESTAMP WITH TIME ZONENOT NULL DEFAULT now(),
created_at TIMESTAMP WITH TIME ZONENOT NULL DEFAULT now()
);
ALTERTABLEpublic.sessions ENABLE ROW LEVEL SECURITY;
  1. After pasting, click the green "Run" button (or press Ctrl+Enter).

  2. You should see "Success. No rows returned" at the bottom. That means it worked.


Migration 2 — Click "New query" again, paste this, then click Run:

-- Folders tableCREATETABLEpublic.folders (
id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
name TEXTNOT NULL,
parent_id UUID REFERENCESpublic.folders(id) ON DELETE CASCADE,
created_at TIMESTAMP WITH TIME ZONENOT NULL DEFAULT now()
);
ALTERTABLEpublic.folders ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Allow all access to folders"ONpublic.folders FOR ALL USING (true) WITH CHECK (true);
-- Notes tableCREATETABLEpublic.notes (
id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
title TEXTNOT NULL,
file_url TEXT,
file_type TEXT,
file_size BIGINT DEFAULT 0,
folder_id UUID REFERENCESpublic.folders(id) ON DELETESETNULL,
order_index INTEGERNOT NULL DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONENOT NULL DEFAULT now(),
updated_at TIMESTAMP WITH TIME ZONENOT NULL DEFAULT now()
);
ALTERTABLEpublic.notes ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Allow all access to notes"ONpublic.notes FOR ALL USING (true) WITH CHECK (true);
CREATEINDEXidx_notes_folderONpublic.notes(folder_id);
CREATEINDEXidx_notes_orderONpublic.notes(order_index);
-- Tags tableCREATETABLEpublic.tags (
id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
name TEXTNOT NULL UNIQUE,
created_at TIMESTAMP WITH TIME ZONENOT NULL DEFAULT now()
);
ALTERTABLEpublic.tags ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Allow all access to tags"ONpublic.tags FOR ALL USING (true) WITH CHECK (true);
-- Note-Tags junctionCREATETABLEpublic.note_tags (
id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
note_id UUID NOT NULLREFERENCESpublic.notes(id) ON DELETE CASCADE,
tag_id UUID NOT NULLREFERENCESpublic.tags(id) ON DELETE CASCADE,
UNIQUE(note_id, tag_id)
);
ALTERTABLEpublic.note_tags ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Allow all access to note_tags"ONpublic.note_tags FOR ALL USING (true) WITH CHECK (true);
-- Auto-update updated_at on notesCREATE OR REPLACEFUNCTIONpublic.update_updated_at_column()
RETURNS TRIGGER AS $$
BEGINNEW.updated_at= now();
RETURN NEW;
END;
$$ LANGUAGE plpgsql SET search_path = public;
CREATETRIGGERupdate_notes_updated_at
BEFORE UPDATEONpublic.notes
FOR EACH ROW
EXECUTE FUNCTION public.update_updated_at_column();
-- Storage bucket for filesINSERT INTOstorage.buckets (id, name, public) VALUES ('note-files', 'note-files', true);
CREATE POLICY "Anyone can read note files"ONstorage.objects FOR SELECT USING (bucket_id ='note-files');
CREATE POLICY "Anyone can upload note files"ONstorage.objects FOR INSERT WITH CHECK (bucket_id ='note-files');
CREATE POLICY "Anyone can update note files"ONstorage.objects FOR UPDATE USING (bucket_id ='note-files');
CREATE POLICY "Anyone can delete note files"ONstorage.objects FOR DELETE USING (bucket_id ='note-files');

Click Run. You should see "Success".


Migration 3 — Click "New query" again, paste this, then click Run:

-- Add favorites columnALTERTABLEpublic.notes ADD COLUMN is_favorited booleanNOT NULL DEFAULT false;
-- Version history tableCREATETABLEpublic.note_versions (
id uuid NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
note_id uuid NOT NULLREFERENCESpublic.notes(id) ON DELETE CASCADE,
content text,
file_url text,
version_number integerNOT NULL DEFAULT 1,
created_at timestamp with time zoneNOT NULL DEFAULT now()
);
ALTERTABLEpublic.note_versions ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Allow all access to note_versions"ONpublic.note_versions FOR ALL TO public
USING (true) WITH CHECK (true);
CREATEINDEXidx_note_versions_note_idONpublic.note_versions(note_id);

Click Run. You should see "Success".

All 3 migrations done! Your database tables are now created.


6. Deploy the Edge Functions

Edge Functions are the backend logic that handles login, logout, and password management. You need to deploy them from your terminal using the Supabase CLI.

Step 6a — Install Supabase CLI

On Linux/macOS:

npm install -g supabase

On Windows (PowerShell as Administrator):

npm install -g supabase

Verify it installed:

supabase --version

You should see a version number like 1.x.x.


Step 6b — Log into Supabase CLI

supabase login

This will open your browser. Log in with your Supabase account. Then come back to the terminal — it should say "Logged in".


Step 6c — Get Your Project Reference ID

  1. Go to your Supabase project dashboard in the browser.
  2. Click "Project Settings" (gear icon, bottom of left sidebar).
  3. Click "General".
  4. Find "Reference ID" — it looks like: srmpdcpvfecpeomsgqlq
  5. Copy it.

Step 6d — Link Your Project

In your terminal, make sure you are inside the project folder:

cd~/Downloads/ratulnotehub-clean/notehub-clean-src

Then run (replace YOUR_PROJECT_REF with your actual Reference ID):

supabase link --project-ref YOUR_PROJECT_REF

It will ask for your database password — enter the password you set in Step 4.


Step 6e — Deploy the Functions

Now deploy all 5 Edge Functions with one command:

supabase functions deploy login
supabase functions deploy logout
supabase functions deploy validate-session
supabase functions deploy change-password
supabase functions deploy setup-admin

Each one should say "Done: Deployed Function".

Edge Functions are now live on Supabase!


7. Get Your Supabase API Keys

  1. In your Supabase project dashboard, click "Project Settings" (gear icon).

  2. Click "API" in the settings menu.

  3. You will see two important things — copy both:

    • Project URL — looks like:

      https://srmpdcpvfecpeomsgqlq.supabase.co
      
    • anon / public key — a long string starting with eyJ...

      eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
      

⚠️ Do NOT share the service_role key with anyone. Only copy the anon key.


8. Edit the .env File

The .env file tells the app where your Supabase database is and how to connect to it.

  1. Open the project folder notehub-clean-src in your text editor (VS Code).

  2. Find the file named .env in the root of the folder.

    💡 On Linux/macOS, files starting with . are hidden by default. In your file manager, press Ctrl+H to show hidden files. In VS Code it shows automatically.

  3. Open .env. It looks like this:

    VITE_SUPABASE_PROJECT_ID="srmpdcpvfecpeomsgqlq"
    VITE_SUPABASE_PUBLISHABLE_KEY="eyJhbGci..."
    VITE_SUPABASE_URL="https://srmpdcpvfecpeomsgqlq.supabase.co"
    
  4. Replace all three values with YOUR values from Step 7:

    VITE_SUPABASE_PROJECT_ID="YOUR_REFERENCE_ID_HERE"
    VITE_SUPABASE_PUBLISHABLE_KEY="YOUR_ANON_KEY_HERE"
    VITE_SUPABASE_URL="YOUR_PROJECT_URL_HERE"
    

    Example (with real-looking fake values):

    VITE_SUPABASE_PROJECT_ID="abcdefghijklmnop"
    VITE_SUPABASE_PUBLISHABLE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.abc123"
    VITE_SUPABASE_URL="https://abcdefghijklmnop.supabase.co"
    
  5. Save the file (Ctrl+S).


9. Install & Run the App

  1. Open your terminal and go to the project folder:

    cd~/Downloads/ratulnotehub-clean/notehub-clean-src
  2. Install all dependencies (only needed once):

    npm install

    This will take 1-2 minutes. You will see a progress bar.

  3. Start the development server:

    npm run dev
  4. You will see output like:

    VITE v5.x.x ready in 500 ms
    ➜ Local: http://localhost:8080/
    
  5. Open your browser and go to: http://localhost:8080

You should see the Note Hub login page! 🎉


10. Set Your Admin Password

The app needs a password to protect your notes. You need to set it once using the setup-admin Edge Function.

There are two ways to do this:

Method A — Using the Supabase Dashboard (Easiest)

  1. Go to your Supabase project dashboard.
  2. Click "Edge Functions" in the left sidebar.
  3. Click on "setup-admin".
  4. Click the "Test" button (or use the "Invoke" section).
  5. In the request body, enter:
    {
    "password": "your_password_here"
    }
    Replace your_password_here with your actual password (minimum 6 characters).
  6. Click "Send".
  7. You should see: {"message": "Admin user created"}

Method B — Using curl from Terminal

curl -X POST https://YOUR_PROJECT_REF.supabase.co/functions/v1/setup-admin \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ANON_KEY" \
-d '{"password": "your_password_here"}'

Replace:

  • YOUR_PROJECT_REF with your project Reference ID
  • YOUR_ANON_KEY with your anon/public key
  • your_password_here with your chosen password

You should see: {"message":"Admin user created"}

Your password is now saved securely in the database (hashed — not stored as plain text).


11. Log In & Use the App

  1. Go to http://localhost:8080 in your browser.
  2. You will be redirected to the login page.
  3. Enter the password you set in Step 10.
  4. Click "Continue".
  5. You are now in your Note Hub dashboard!

What you can do:

FeatureHow to use
Upload filesClick "New" → "Upload file" or drag & drop files onto the screen
Create text notesClick "New" → "New text file"
Create foldersClick "New folder" in the left sidebar
Preview notesClick on any note card
Edit text filesClick menu on a note → "Edit"
View CSV filesClick a .csv note — opens as a table
View Word docsClick a .docx note — renders the text
Search notesType in the search bar at the top
Add tagsClick on a note → "Add tag"
Favorite a noteClick "Favorite" (pins it to top)
Move to folderClick "Move to…"
Drag & reorderClick and drag note cards to reorder them
Bulk selectClick "Select" button → check multiple notes → Delete or Move
Change passwordBottom of left sidebar → "Change password"

Supported file types:

  • 📄 Text: .txt, .md
  • 📊 Spreadsheet: .csv
  • 📑 Word: .docx
  • 📕 PDF: .pdf
  • 🖼️ Images: .png, .jpg, .jpeg, .gif, .webp

12. Troubleshooting

❌ "npm install" fails — "package.json not found"

You are in the wrong folder. Make sure you are inside notehub-clean-src:

cd~/Downloads/ratulnotehub-clean/notehub-clean-src
npm install

❌ App shows blank white page or console errors

  • Open browser DevTools (F12) → Console tab
  • If you see "Failed to fetch" or "Invalid API key" — your .env file has wrong values. Re-check Step 8.
  • Make sure the .env file is saved.
  • Stop the server (Ctrl+C) and restart: npm run dev

❌ Login says "Incorrect password"

  • Make sure you completed Step 10 (set admin password).
  • The password is case-sensitive.
  • If you forgot your password, call setup-admin again with a new password — it will update it.

❌ "Too many attempts. Locked for 15 minutes"

Wait 15 minutes. This is a security feature — 5 wrong attempts triggers a lockout.

To reset immediately, go to Supabase → SQL Editor → run:

DELETEFROMpublic.login_attempts;

❌ File upload fails

  • Check your Supabase Storage bucket exists: Supabase dashboard → "Storage" → you should see note-files bucket.
  • If the bucket is missing, go to SQL Editor and run Migration 2 again (the storage part).

❌ Edge Functions fail to deploy

Make sure you are logged in:

supabase login
supabase link --project-ref YOUR_PROJECT_REF
supabase functions deploy setup-admin

❌ Session expires too quickly

Sessions last 30 minutes by default. To change this, edit supabase/functions/login/index.ts:

constSESSION_DURATION_MINUTES=30;// Change this number

Then re-deploy: supabase functions deploy login


13. How the App Works

Architecture overview:

Your Browser (React app)
│
├── Supabase Database (stores notes metadata, folders, tags, password hash)
├── Supabase Storage (stores actual files: PDFs, images, text files)
└── Supabase Edge Functions (handles login, logout, password change)

Security model:

  • Your password is hashed (SHA-256) before saving — Supabase never stores plain text passwords
  • Login creates a session token valid for 30 minutes
  • After 5 wrong password attempts, login is locked for 15 minutes (brute-force protection)
  • All file storage is tied to your Supabase project — only you have access

Free tier limits (Supabase):

  • Database: 500 MB
  • Storage: 1 GB
  • Edge Function calls: 500,000/month
  • All plenty for personal use

🎉 You're All Set!

Your Note Hub is running locally. Every file you upload goes to Supabase Storage, and all your note data is saved in Supabase Database — both are free and persist even after you close your computer.

To stop the app: press Ctrl+C in the terminal. To start it again later:

cd~/Downloads/ratulnotehub-clean/notehub-clean-src
npm run dev

Then open http://localhost:8080.


Built with React, TypeScript, Vite, Tailwind CSS, shadcn/ui, and Supabase.

About

A personal note gallery with file uploads, folders, tags, and password protection. Backend powered by Supabase (free tier)

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages