FluidKit
Web development for the Pythonist
Write backend functions in Python — FluidKit turns them into type‑safe SvelteKit remote functions. No glue code. No duplicated types.
Write Python. Use it in Svelte.
Decorate a function on the left — import and use it on the right. FluidKit generates the bridge, the types, and the cache invalidation.
1from fluidkit import query, command, form
2
3@query
4async def get_posts() -> list[Post]:
5 return await db.get_all_posts()
6
7@command
8async def like_post(post_id: int) -> bool:
9 await db.increment_likes(post_id)
10 await get_posts().refresh()
11 return True
12
13@form
14async def add_post(title: str, content: str):
15 await db.insert(title, content)
16 await get_posts().refresh()
1<script>
2 import { get_posts, like_post, add_post }
3 from '$lib/posts.remote';
4</script>
5
6<!-- @query → await directly in templates -->
7{#each await get_posts() as post}
8 <h2>{post.title}</h2>
9 <p>{post.content}</p>
10
11 <!-- @command → call from event handlers -->
12 <button onclick={() => like_post(post.id)}>
13 👍 {post.likes}
14 </button>
15{/each}
16
17<!-- @form → spread onto form elements -->
18<form {...add_post}>
19 <input {...add_post.fields.title.as('text')} />
20 <input {...add_post.fields.content.as('text')} />
21 <button>Add Post</button>
22</form>
Under the Hood
One decorator. Three things happen.
Four Decorators. Full Stack.
Each maps to a SvelteKit remote function type — pick the one that fits.
@query
Read data. Cached on the client, refreshable on demand. Supports batching for the N+1 problem.
@form
Write data via forms. File uploads, progressive enhancement, and redirects — works without JavaScript.
@command
Write data from anywhere — event handlers, button clicks. Single-flight cache invalidation built in.
@prerender
Fetch data at build time. Served from a CDN for instant loads, with optional runtime fallback.
Zero to Running in Seconds
No system Node.js needed. FluidKit bundles everything.