DEV Community

Cover image for πŸš€ Build a HackerNews Clone Using Svelte and Supabase
hmza
hmza

Posted on

πŸš€ Build a HackerNews Clone Using Svelte and Supabase

πŸš€ 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 
Enter fullscreen mode Exit fullscreen mode

2. Install Supabase Client

 npm install @supabase/supabase-js 
Enter fullscreen mode Exit fullscreen mode

3. Set up Supabase Project

 VITE_SUPABASE_URL=https://xyzcompany.supabase.co VITE_SUPABASE_ANON_KEY=your-anon-key-here 
Enter fullscreen mode Exit fullscreen mode

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); 
Enter fullscreen mode Exit fullscreen mode

πŸ§‘β€πŸ’» 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> 
Enter fullscreen mode Exit fullscreen mode

πŸ”— 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 }]); }; 
Enter fullscreen mode Exit fullscreen mode

🧠 Display Posts

src/routes/+page.svelte

 let posts = []; onMount(async () => { const { data } = await supabase.from('posts').select('*').order('upvotes', { ascending: false }); posts = data; }); 
Enter fullscreen mode Exit fullscreen mode

πŸ”Ό Upvote Posts

 const upvote = async (postId, currentVotes) => { await supabase.from('posts') .update({ upvotes: currentVotes + 1 }) .eq('id', postId); }; 
Enter fullscreen mode Exit fullscreen mode

⚑ 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(); 
Enter fullscreen mode Exit fullscreen mode

πŸ” 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); } 
Enter fullscreen mode Exit fullscreen mode

πŸ§ͺ 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)