๐ 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 KEYandPROJECT 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:
idtitleurluser_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!
Source: DEV Community.

Leave a Reply