A simple Kanban board built with Svelte 5, supporting multiple boards, columns, and cards with drag & drop, validation, and error handling. Designed with an Autumn/Halloween 🎃 theme for seasonal fun. Time spent: 10hrs
https://www.loom.com/share/ddf9467c84684d64be9f5b3f8d9053af?sid=0617f808-8548-4506-be1d-eb753d131f17
# Clone repo
# Install dependencies
npm install
# Start development server
npm run dev
# Open your browser to http://localhost:5173
This project demonstrates a modern approach to building secure, type-safe web apps using SvelteKit's remote functions. This pattern eliminates common security vulnerabilities while providing good developer experience.
export const cardSchema = object({
boardId: string(),
columnId: string(),
content: pipe(
string(),
minLength(1, 'Card content is required'),
minLength(3, 'Card content must be at least 3 characters')
)
});
// Schema is enforced on the SERVER before the function runs
export const createCard = form(cardSchema, async (data) => {
// data is guaranteed to be valid here - validation happened server-side
// No need for manual validation checks
});
<form {...createBoard.preflight(boardSchema)}>
<!-- Display validation errors for the title field -->
{#each createBoard.fields.title.issues() as issue}
<p class="error-message">{issue.message}</p>
{/each}
// Form input with validation attributes
<input {...createBoard.fields.title.as('text')} placeholder="New board title" required />
Other validation methods
invalid()
functionI started by thinking carefully about data structure, whether to use nested structures (boards → columns → cards) or flat structures. For a simple Kanban, nested felt right, but I noted that scaling would likely require flattening for performance. This project was my first deep dive into Remote Functions, Async, Valibot and svelte-dnd-action
Tools Used:
Strategy: Pair-programming If seniors developer treat AI as a junior, then I (as a junior) treat AI like my coding buddy. However, I still use my teddy bear as another coding buddy for sanity check.
$effect
unless needed, using $derived
instead) and new syntax (Svelte 5 runes instead of Svelte 3/4. They keep applying old approach)The drag-and-drop feature turned out to take the most of my time. The most frustrating bug was an undefined parentElementID
error that would randomly crash the drag-and-drop functionality.
After consulting online tutorials, the issue was possibly related to missing key
attributes in {#each}
blocks so I added card.id
. I didn't have enough time to read all svelte-dnd docs so I just made sure dndzone
had all required options.
This experience taught me that seemingly simple app can hide significant complexity.