Using SvelteKit to build a Community Ranking Ladder
To make products people use, one needs some frontend skills. Historically, frontend is a weakness of mine and I've been constrained to clunky CLIs and APIs to get what I want to do done. No longer! Last week I sat myself down and read the Svelte and SvelteKit documentation front to back. Since learning in software happens when you build something, I decided to build a leaderboard website for my latest obsession, Yomi Hustle.
![](https://www.thornewolf.com/content/images/2022/11/image.png)
The Leaderboard
You can find the Yomi Hustle leaderboard here.
![](https://www.thornewolf.com/content/images/2022/11/image-1.png)
Simple and to the point, but this taught me a lot about making modern websites with a Javascript frontend framework like SvelteKit. Let's dive into what is required to make this page.
The Development Toolchain
My dependencies for this website include Svelte, SvelteKit, tailwindcss, and DaisyUI.
- Svelte is my UI Framework. I use Svelte to manipulate what is on the webpage at any given time.
- SvelteKit is my Application Framework. SvelteKit chooses what page should be shown to a user and uses Svelte itself for the rendering. Sveltekit provides functionality like routing to show different svelte pages for things like
/about
and/users
. - Tailwind CSS is a CSS framework that enables you dictate your styling on the HTML elements themselves, without needing to hand write CSS.
- DaisyUI is a UI component library that uses Tailwind to give you pre-styled HTML components for things like buttons, tables, navbars, etc.
Getting Started
To create the skeleton for my project, I followed the setup instructions provided by SvelteKit, TailwindCSS, and DaisyUI. If you want to mimic this setup with simple an npm i
, feel free to clone my Github repo with this skeleton.
npm create svelte@latest yomi-rankings
cd yomi-rankings
npm i
npm install -D tailwindcss postcss autoprefixer svelte-preprocess
npm i tailwindcss/typography
When creating the SvelteKit app, I opted into using TypeScript.
import adapter from '@sveltejs/adapter-auto';
import preprocess from 'svelte-preprocess';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://github.com/sveltejs/svelte-preprocess
// for more information about preprocessors
preprocess: preprocess({ postcss: true }),
kit: {
adapter: adapter()
}
};
export default config;
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{html,js,svelte,ts}'],
theme: {
extend: {},
},
plugins: [require("@tailwindcss/typography"), require('daisyui')],
}
Making the Leaderboard
Dynamically loading data is really easy in Svelte. Let's look at how I made the homepage photographed above.
<script lang="ts">
import Leaderboard from '$lib/Leaderboard.svelte';
</script>
<div class="p-4 grid grid-cols-12 gap-2">
<div class="col-span-12 lg:col-start-3 lg:col-span-8">
<Leaderboard />
</div>
</div>
I'll skip over the boring parts of <Leaderboard />
and show the key bits.
import { onMount } from 'svelte';
import HustlerCard from './HustlerCard.svelte';
import type { PlayerRating } from './types/types';
export let hustlers: PlayerRating[] = [];
onMount(async () => {
fetch('/api/leaderboard')
.then((res) => res.json())
.then((data) => {
hustlers = data;
});
});
{#each hustlers as hustler, i (i)}
<tr class="hover">
<th>{i + 1}</th>
<td>
<HustlerCard name={hustler.name} id={hustler.id} />
</td>
<td>{Math.round(hustler.rating)}</td>
</tr>
{/each}
Now let's look at what this mysterious /api/leaderboard
is.
import type { PlayerRating } from '$lib/types/types';
import { error } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
export const GET: RequestHandler = async () => {
const response = await fetch('http://yomitussle.tk/leaderboard', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
}
});
let json: PlayerRating[] = await response.json();
return new Response(JSON.stringify(json));
}
These pieces together comprise what you see when you visit https://yomi-leaderboards-frontend.vercel.app/. You might have noticed that I am using Vercel for hosting.
It really is that Easy! This writeup is not means to be a tutorial, but just an overview on how I created this dashboard over the course of a work-session one weekend. If you click on any user's name you can see their match history too!
![](https://www.thornewolf.com/content/images/2022/11/image-2.png)
If you have any questions about specific implementation details, reach out to me at contact [at] thornewolf.com. I am looking forward to hearing from you!