Go + SvelteKit vs. Svelte (SSR Question)

Yes. Probably the easiest way you could do this is: build your app using Svelte (which will leave you with JS/HTML), then serve that static content from your Go executable. I do a similar approach all the time. When doing deploys, have your front-end framework compile to ./public or something similar, then serve that static content like this:

// Serve our static js/html/images:
http.Handle("/", http.FileServer(http.Dir("public")))

The only other “gotcha” to CSR is: they can land on any page in your app and/or hit refresh button so you need to either have a fallback that serves index.html on “not found” or keep track of routes and serve index when a user lands on a route like yourapp.com/users/1:

// For all SPA routes we will also serve up /index.
// Register any front-end routes here
spaRoutes := []string{
	"/home",
	"/faq",
	"/login",
	"/users/{id}"}
for _, route := range spaRoutes {
	http.HandleFunc(fmt.Sprintf("GET %v", route), indexHandler)
}

Where indexHandler just serves up index:

func indexHandler(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "./public/index.html")
}

There are other ways of accomplishing this as well but this is probably the simplest.

In terms of your API and how it interacts with your web app: you would just create routes that return JSON and your Svelte app would update the UI based on your RESTful API. Again - I’m not a Svelte dev but something like this:

// main.go where you are setting up routes
http.HandleFunc("POST /api/items", getItemsHandler)
//...
func getItemsHandler(w http.ResponseWriter, r *http.Request) {
	// Fetch items from wherever
	items := getItems()
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(items)
}

Create a load function in svelte (or something similar):

// page.ts
import type { PageLoad } from './$types';

export const load: PageLoad = async ({ fetch, params }) => {
	const res = await fetch(`/api/items`);
	const items = await res.json();
	return { items: items };
};

Then in your .svelte file:

<script lang="ts">
	import type { PageProps } from './$types';
	let { data }: PageProps = $props();
</script>

<h1>Items</h1>
<ul>
{#each data.items as item}
	<li>{item}</li>
{/each}
</ul>

I don’t know about the virtual DOM in the svelte world. Frameworks use virtual DOMs because DOM manipulation is expensive. By keeping track of changes you can only update the DOM when you need to. So, I’m not 100% sure how svelte manages its’ DOM manipulation but I wouldn’t worry about that too much.

2 Likes