Star 历史趋势
数据来源: GitHub API · 生成自 Stargazers.cn
README.md

Portfolio V5

Hello everyone! 👋

Let me introduce myself, I'm Eki Zulfar Rachman. On this occasion, I'd like to share the portfolio website project that I've developed. built with React and Supabase, featuring a public-facing site and an admin dashboard.

Live Demo: https://ekizr.com


🛠️ Tech Stack

This project is built using modern web technologies:

  • ReactJS - Frontend framework
  • Tailwind CSS - Utility-first CSS framework
  • Supabase - Backend for portfolio data, certificates, and comment system
  • AOS - Animate On Scroll library
  • Framer Motion - Animation library
  • Lucide - Icon library
  • Material UI - React component library
  • SweetAlert2 - Beautiful alert dialogs

User Roles

RoleAccess
Visitor (Public)View projects, certificates, and comments — leave a comment
AdminLogin to dashboard — full CRUD on projects & certificates — delete & pin/unpin comments

Getting Started

Prerequisites

  • Node.js >= 14.x
  • npm or yarn

1. Clone & Install

git clone https://github.com/EkiZR/Portofolio_V5.git cd Portofolio_V5 npm install

If you encounter peer dependency issues: npm install --legacy-peer-deps

2. Environment Variables

Create a .env file in the root directory:

VITE_SUPABASE_URL=your-supabase-project-url VITE_SUPABASE_ANON_KEY=your-supabase-anon-key

Find these in your Supabase project under Settings → API.
⚠️ Never commit .env to version control — make sure it's in .gitignore.

3. Supabase Client (src/supabase.js)

import { createClient } from '@supabase/supabase-js' const supabaseUrl = import.meta.env.VITE_SUPABASE_URL const supabaseKey = import.meta.env.VITE_SUPABASE_ANON_KEY if (!supabaseUrl || !supabaseKey) { throw new Error('Supabase credentials missing. Check your .env file.') } export const supabase = createClient(supabaseUrl, supabaseKey)

4. Database Setup

Go to your Supabase project → SQL Editor → run the script below (run once):

-- ============================ -- TABLES -- ============================ CREATE TABLE public.projects ( id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, title text, description text, img text, link text, github text, features jsonb, tech_stack jsonb, is_published boolean DEFAULT true, order_index int DEFAULT 0, created_at timestamptz DEFAULT now() ); CREATE TABLE public.certificates ( id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, img text, created_at timestamptz DEFAULT now() ); CREATE TABLE public.portfolio_comments ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, content text NOT NULL, user_name text NOT NULL, profile_image text, is_pinned boolean DEFAULT false, created_at timestamptz DEFAULT now() ); CREATE TABLE public.profiles ( id uuid PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE, username text UNIQUE NOT NULL, role text NOT NULL CHECK (role IN ('admin', 'user')), created_at timestamptz DEFAULT now() ); -- ============================ -- RLS -- ============================ ALTER TABLE public.projects ENABLE ROW LEVEL SECURITY; ALTER TABLE public.certificates ENABLE ROW LEVEL SECURITY; ALTER TABLE public.portfolio_comments ENABLE ROW LEVEL SECURITY; ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY; CREATE POLICY "public read projects" ON public.projects FOR SELECT USING (true); CREATE POLICY "public read certificates" ON public.certificates FOR SELECT USING (true); CREATE POLICY "public read comments" ON public.portfolio_comments FOR SELECT USING (true); CREATE POLICY "public insert comment" ON public.portfolio_comments FOR INSERT WITH CHECK (is_pinned = false); CREATE POLICY "admin manage projects" ON public.projects FOR ALL USING ( EXISTS ( SELECT 1 FROM public.profiles WHERE id = auth.uid() AND role = 'admin' ) ); CREATE POLICY "admin manage certificates" ON public.certificates FOR ALL USING ( EXISTS ( SELECT 1 FROM public.profiles WHERE id = auth.uid() AND role = 'admin' ) ); CREATE POLICY "admin manage comments" ON public.portfolio_comments FOR UPDATE, DELETE USING ( EXISTS ( SELECT 1 FROM public.profiles WHERE id = auth.uid() AND role = 'admin' ) ); -- ============================ -- STORAGE -- ============================ INSERT INTO storage.buckets (id, name, public) VALUES ('project-images', 'project-images', true) ON CONFLICT DO NOTHING; CREATE POLICY "admin upload project images" ON storage.objects FOR INSERT WITH CHECK ( bucket_id = 'project-images' AND EXISTS ( SELECT 1 FROM public.profiles WHERE id = auth.uid() AND role = 'admin' ) ); CREATE POLICY "public read project images" ON storage.objects FOR SELECT USING (bucket_id = 'project-images'); INSERT INTO storage.buckets (id, name, public) VALUES ('certificate-images', 'certificate-images', true) ON CONFLICT DO NOTHING; CREATE POLICY "admin upload certificate images" ON storage.objects FOR INSERT WITH CHECK ( bucket_id = 'certificate-images' AND EXISTS ( SELECT 1 FROM public.profiles WHERE id = auth.uid() AND role = 'admin' ) ); CREATE POLICY "public read certificate images" ON storage.objects FOR SELECT USING (bucket_id = 'certificate-images');

5. Enable Realtime (Comments)

Go to Table Editor → portfolio_comments → Enable Realtime.

6. Create Admin Account

Step 1 — Go to Authentication → Users → Add User in Supabase Dashboard, then copy the generated User ID.

Step 2 — Run this in the SQL Editor (replace USER_UUID with the copied ID):

INSERT INTO public.profiles (id, username, role) VALUES ('USER_UUID', 'eki', 'admin');

7. Run Locally

npm run dev

Open http://localhost:5173 in your browser.


Pages & Features

Public (Visitor)

  • Home — Hero section, about, skills
  • Projects — List of published projects with detail modal
  • Certificates — Certificate gallery
  • Comments — View all comments, submit a new comment with name and optional profile photo

Admin (Dashboard)

  • Login Page — Email & password authentication via Supabase Auth
  • Dashboard — Overview panel after login
  • Projects — Create, edit, delete projects; manage image, links, features, tech stack, publish status, and order
  • Certificates — Upload and delete certificate images
  • Comments — View all comments; pin/unpin for highlighting; delete inappropriate comments

Build for Production

npm run build

Upload the contents of the dist/ folder to your hosting provider.


Troubleshooting

  • Ensure Node.js is installed and you're in the correct directory.
  • Double-check your .env values and restart the dev server after changes.
  • If RLS is blocking requests, verify the profiles row exists for your admin user.
  • Clear browser cache if you see stale data.

Credits & Contact

Eki Zulfar Rachman
Website: eki.my.id · GitHub: EkiZR

Thanks to LottieFiles and Claude.

⭐ If this project helped you, consider giving it a star on GitHub!

关于 About

Personal portfolio built with React + Supabase, featuring an admin dashboard for managing projects, certificates, and comments.
dashboardportofolioportofolio-websitereactjssupabase

语言 Languages

JavaScript96.6%
HTML1.8%
CSS1.6%

提交活跃度 Commit Activity

代码提交热力图
过去 52 周的开发活跃度
28
Total Commits
峰值: 9次/周
Less
More

核心贡献者 Contributors