π Build a HackerNews Clone Using Svelte and Supabase
"A blazing-fast HackerNews clone with zero backend boilerplate? Yes, please!"
In this tutorial, weβll build a lightweight, fast, and modern HackerNews clone using Svelte (the frontend wizard π§) and Supabase (the open-source Firebase alternative πΎ).
π¦ Why Svelte + Supabase?
- Svelte compiles to tiny, performant JS
- Supabase gives us:
- PostgreSQL with RESTful & realtime APIs
- Auth, storage, edge functions
- No server-side code required
Together, they let you build fullstack apps without fullstack headaches.
π§° What Weβll Build
A HackerNews-style app with:
- β Sign Up / Login (via Supabase Auth)
- π Submit links (title + URL)
- π³οΈ Upvote posts
- π¬ Comment threads (basic)
- β‘ Real-time updates
π οΈ Project Setup
1. Install the SvelteKit App
npm create svelte@latest hackernews-clone cd hackernews-clone npm install
2. Install Supabase Client
npm install @supabase/supabase-js
3. Set up Supabase Project
- Go to https://app.supabase.com
- Create a new project
- Grab your
ANON KEY
andPROJECT URL
- Add these to your
.env
:
VITE_SUPABASE_URL=https://xyzcompany.supabase.co VITE_SUPABASE_ANON_KEY=your-anon-key-here
4. Initialize Supabase Client
Create src/lib/supabaseClient.ts
:
import { createClient } from '@supabase/supabase-js'; const supabaseUrl = import.meta.env.VITE_SUPABASE_URL; const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY; export const supabase = createClient(supabaseUrl, supabaseAnonKey);
π§βπ» Auth: Sign Up / Login
Create src/routes/login/+page.svelte
<script lang="ts"> import { supabase } from '$lib/supabaseClient'; let email = ''; let password = ''; const login = async () => { const { error } = await supabase.auth.signInWithPassword({ email, password }); if (error) alert(error.message); }; </script> <input bind:value={email} placeholder="Email" /> <input type="password" bind:value={password} placeholder="Password" /> <button on:click={login}>Log In</button>
π Submitting a Post
Create a posts
table with fields:
id
title
url
user_email
-
upvotes
(default: 0)
Submit Page Example
let title = ''; let url = ''; const submit = async () => { const user = await supabase.auth.getUser(); await supabase.from('posts').insert([{ title, url, user_email: user.data.user.email }]); };
π§ Display Posts
src/routes/+page.svelte
let posts = []; onMount(async () => { const { data } = await supabase.from('posts').select('*').order('upvotes', { ascending: false }); posts = data; });
πΌ Upvote Posts
const upvote = async (postId, currentVotes) => { await supabase.from('posts') .update({ upvotes: currentVotes + 1 }) .eq('id', postId); };
β‘ Real-time Updates
Enable Realtime for posts
in Supabase UI.
Then:
supabase .channel('posts') .on('postgres_changes', { event: '*', schema: 'public', table: 'posts' }, payload => { // update local posts[] }) .subscribe();
π Auth Guard (optional)
Add to src/hooks.server.ts
:
export async function handle({ event, resolve }) { const { user } = await supabase.auth.getUser(); event.locals.user = user; return resolve(event); }
π§ͺ Features You Can Add
- π§΅ Comments table + nesting
- π§ Admin flag moderation
- πΆοΈ Dark mode toggle
- π PWA setup
- π± Mobile-first UI
π‘ Conclusion
You just built a modern HackerNews clone with Svelte and Supabase!
- Svelte keeps your frontend blazing fast β‘
- Supabase handles your backend like magic π§
π Useful Links
π₯ If you want part 2 β βAdd Comments and Dark Modeβ β let me know!
Top comments (0)