π 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)