Svelte5 might change things all of this is based on svelte4
Gotchas/FAQ
Combinations
| SSR | Pre-render | static-adpter | other-adapter | |
|---|---|---|---|---|
| SPA | - | - | YES | - | 
| Mixed SPA | - | YES(some)+fallback | YES | - | 
| Hydration | YES | - | - | YES | 
| Mixed Hydration | YES | YES(some) | - | YES | 
| SSG | - | YES(all) | YES | - | 
- Some pages prerendered, some dynamic
- Use any adapter here and then use export const prerenderas per need per page.
 
- Use any adapter here and then use 
- Full Static Site Generation
- Use adapter-static(Skips any+server.jsrelated stuff)
 
- Use 
- SPA
- Use adapter-static
- Disable prerender (Use svelte fallback)
- Disable SSR (When ssr is disabled, its SPA mode)
- We can still pre-render individual pages (enable ssr and prerender on those pages)
 
 
- Use 
About Pre-rendering
- Prerendering means that when we deploy our website, all the +page/+layout filesjavascript is compiled and executed and the resulting static HTML pages are saved.- i.e page loadfunctions will be executed and baked into the generated page
- Can be used along with ssr(altogether or on page-by-page basis)
 
- i.e 
- The way prerender works is that it crawls all your rendered pages for links so it can pre-render them all.
- To tell sveltekit where to find links you that you may not have linked on your pages you should use entries
When prerender vs ssr?
- Some pages only have static content, or they fetch content that changes very little over time.
- If the page keeps on changing we want to be using ssr. (But we don’t want to be using sveltekit backend, so we mostly don’t want ssr)
Hydration
- Interactive javascript is separate from SSRandprerendering
- Hydration happens when you’re using SSR
- Term used for loading interactive javascript on your page is hydration
- Happens in the browser and after the page is all rendered
- Once the components are fully hydrated, they can react to changes to their properties just like any newly created Svelte component.
 
SSR & Static Adapter in Svelte
npm run buildwill build both server and client component if you don’t use this adapter
Svelte adapters
- You apply the adapter in svelte.config.js
- Adapters are for production/deployment
- When you use local dev with npm dev, you’re doing SSR anyway
- adapter-noderuns SSR on a Node server
- adapter-netlifyruns SSR in Netlify functions
adapter-static
export const prerender = false;
export const ssr = false;- Prerendered routes
- We can route to known, prerendered routes
- Has associated .htmlfile that represents the HTML content for that route.
- pre-renders results from any load()calls at build time
 
- Dynamic routes
- We can route to unknown, dynamic routes
 
Reactivity
$ symbol
- $: accessing reactive value
- $:reactive statement
- $$- globally-available variables inside a Svelte component
- Example
- $$restPropscontains all the props that were not explicitly exported by the component
- $$slotscontains the slots passed to the component.
 
 
- $$doesn’t indicate that this is a store value; it’s just a naming convention.
- See [The many meanings of -meanings/)
SvelteKit routing directory structure
General directories
- src/hooks*
- src/lib
- src/params- For storing matchers
 
- src/routes
- src/service-worker
Components
- Components need not just be *.sveltefile, it can be a directory with anindex.tsand the<component>.svelteand the index.ts file can be exporting the component
- Global components will probably live in /src/lib/components- But we can have route->page specific components inside directory conventionally named (components)
- i.e If components and modules are needed by multiple routes, it’s a good idea to put them in $lib.
 
- But we can have route->page specific components inside directory conventionally named 
Structure
- +signifies a “route file”. Any other “files” (NOT directories!) inside a- /src/routedirectory are ignored by SvelteKit. So we can use custom files and use them in the- +<>.svelte/tsfiles. Eg. subcomponents/modules etc.- If you want to create directories inside src/routesand you want the directory to not appear in the path, then use(<directory name>)
 
- If you want to create directories inside 
- there are *.server.*variants that we’re skipping here because not using atm
- Root: /src/routes- +page.svelte: Page component
- +page.ts- Data for page component, exports a loadfunction
- Can also be used to configure other behavior of how the page loads and such (prerender/ssr etc)
 
- Data for page component, exports a 
- +error.svelte: Page to show if- +page.ts’s- loadfunction fails- Static fallback error page: src/error.html, it’ll bubble up to this
- Nested +error.sveltepage will not show up though for that you’d have to use[...path]like rest params (See advance routing)
 
- Static fallback error page: 
- +layout.svelte- Layout that applies to every page
- Only needs to have <slot>
 
- +layout.ts- Data loading using loadfunction for+layout.svelte
- Child pages will automatically have this data
 
- Data loading using 
 
- 
Dynamic routing - Priority of routes is basically more specific route name wins
- We’d want to use matchersfromsrc/paramsas such:src/routes/archive/[page=integer]
- /src/routes/something/[slug]
- /[org]/[repo]/tree/[branch]/[...file]this will allow for- /sveltejs/kit/tree/main/documentation/docs/04-advanced-routing.md, the parameters will be correct names and be available to the page.
- Use (<dir name>)if you want have a subsection of things insidesrc/routesbut don’t want it in the url. Eg. usecases- Eg. (utils)/(components)directory
- Eg. (marketing)/(app), just high level business level separation but these need to be in the same hierarchy in the URL but different+layout.svelte
 
- Eg. 
 
About on:click
- I am unsure about this but seems like this sort of only works with primitive HTML elements
- Svelte allows you to forward things, but if suppose you want to on:clickon a event as such, seems like we can’t do it directly, you need to “forward”.- What you need to do: Wrap the componentaround a primitive element such asdivorbuttonetc. Then you can useon:clickon the maincomponentwhen using it and then when defining the component since you wrapped it around with a primitive element, you can use the forward mechanism by simply passingon:clickthere and things should work.
 
- What you need to do: Wrap the 
*.server.ts
API endpoints vs +server.ts
- They’re the same.
- API routes by adding a +server.jsfile that exports functions corresponding to HTTP methods: GET, PUT, POST, PATCH and DELETE.
+page.server.ts vs +server.ts
+page.ts
- Load function associated with a page.
- Load data first, then hand it over to the page and render the page.
- If page is is visited as first page, load runs on the server. (IMPORTANT)
- If page is visited via client-side nav, load runs on the client. (IMPORTANT)
+page.server.ts: Certain things are not suitable to be done in +page.js, e.g. accessing data from an API with a secret. Then you reach for this file and force execution of load to be always on the server (even during client-side nav). Can not only include load, but also form actions.
+server.ts: standalone API route. Not associated with a page. Think of implementing a mini API.
- Now the usecase of +page.tsvs+page.server.tsis clear but when should we create a+server.tsinstead of+page.server.tsis my confusion.
- If we strictly need an api we go with +server.ts
- If we need data loading for our page, we go with +page.server.ts
- Some people are using combination where they create the endpoint and call the endpoint via loadfunctions.- use event.fetchto call your API sveltekit server load won’t make a network request it will call the API route as a function. (IMPORTANT)
 
- use 
- More resources on this
TODO Setting up DB connection
- https://kit.svelte.dev/docs/faq#how-do-i-use-x-with-sveltekit-how-do-i-setup-a-database
- https://github.com/sveltejs/kit/issues/1538#issuecomment-1002106271
- Steps
- Have a $lib/db.ts(singleton) which creates the pool and exposes a method to get connection from the pool.
- Initialize it src/hook.ts, just have the global declaration.
- Use
- WAY1:
- Use the method(get connection) from $lib/db.tsin either+server.tsor+page.server.tsload function.
 
- Use the method(get connection) from 
- WAY2:
- I don’t really understand this properly but this is around passing the dbobject fromsrc/hook.tstoevent.locals
- For +server.ts(API endpoint)- Initialize the db with a global variable, then pass the variable down to the Request object’s localsin thehandlefunction.
- Inside handle, I also have a trap to check if the db has been initialized (just in case), and if it isn’t reinitialize it.
 
- Initialize the db with a global variable, then pass the variable down to the Request object’s 
 
- I don’t really understand this properly but this is around passing the 
 
- WAY1:
 
- Have a 
TODO Hooks?
- These kinds(3 kinds) of hook files run on startup
- These contain hook/handlers of certain pre-defind kinds. (See doc), these get triggerred when some other things happen. Eg. one common one is handlewhich is available in all 3 kinds, it runs when a request is received.
Hooks and locals

Auth and protecting pages
Concepts
Routing related files
- Files we have
- We have +layout.svelte|ts|js
- We have +page.svelte|ts|js
 
- We have 
- In these files, the variables are not shared unless you use a loadfunction and then useexport let datain+page.svelte
Routing in Svelte
- We could use conditional components but using SvelteKit
- with @sveltejs/adapter-static
- along with disabling SSR is much more straightforward
 
- with 
Loading data
- Sveltekit has a whole page on loading data, check that
- The loadmethod has a specialfetchfunction which is enhanced version of the normalfetchapi method.
Store in Svelte
- Types
- Readable
- Writable
- Derived
 
State Management in Svelte
- See State Management Libraries for React Framework aswell
What’s the combo of connect-es, transtackQuery, svelteStore and PageLoad? (when we don’t want Selvekit backend features)
- If you’re using connect-esfor Protocol Buffers, it has something called connectrpc/connect-query-es which branches of TanStackQuery- Issue is the svelte variant is not very well supported yet
- Because of which we’d want to use connect-web so that we can do rest api calls
 
TODO Overview
Using context and store together
- A store contains a value that can be subscribed to, and is thus reactive.
- A context makes a value accessible to a whole tree of components.
- context and store both are ideas and implementation in svelte
- context can be used usually in cases when you want to avoid prop drilling
- context are not reactive like stores
- So it’s a safe practice to pass around storesincontexts. This seems to me like a solid combination.- i.e all components have access to the store, and can reactively use the value within it.
 
Other notes and tips
- When writing store.tsprefer using multiple stores and usecontextandderivedstores to make better use of it. In addition, use factory pattern to create the stores. Eg.createXStoreconst createXStore = () => { const { subscribe, set, update } = writable([]); return { // NOTE: A valid writable store requires atleast "subscribe" and "set", "update" is not mandatory. // NOTE: We could also wrap around set around another fn // eg. set: (newVal) => {doSomething(); set(newVal)} // NOTE: What "subscribe" returns is what you can call an unsubscribe with subscribe, set, // NOTE: Instead of directly using exposing "update" here we could also // have custom methods that use update. update }; };
- +page.jscan’t use the- $(autosubscribe) shortcut to access the value from a writable store.- You’ll need to explicitly subscribe
- Make sure to unsubscribe if not using $
 
- using #await: https://www.reddit.com/r/sveltejs/comments/124rx4n/sveltekit_when_to_use_load_vs_await/
Tanstack Query
// TODO: This might be fetching data twice at the moment if we click load
//		 more, need to verify later
// NOTE: config options come from: QueryObserverOptions, QueryOptions
const query = createQuery({
  queryKey: ['search-hits'],
  queryFn: async () => {
  return index.search('car');
  },
  // "select" is used for optional data transformations
  select: (data) => data.hits.map((x) => SearchCardRawItem.parse(x))
 
  // toggles whether to make the query on component mount. Eg. We only
  // want to make the query by user interaction. gcTime, staleTime etc are respected.
  //
  // It seems like when we trigger a request by user interaction, data
  // always stays in "fresh" state
  // enabled: false
 
  // defaults to false, can be set to ms, will emulate polling.
  // The refetching is paused if the window loses focus, unless
  // "refetchIntervalInBackground" is set to true
  // refetchInterval: 2000
 
  // wherether to make network i/o, respects staleTime, default: true (sane)
  // refetchOnMount: true
 
  // in SPA, when we route to diff. pages it doesn't really load the page,
  // if set to true when we SPA route ourselves to a page, it'll
  // automatically try to fetch data (respecting staleTime). default: true (sane)
  // refetchOnWindowFocus: true
 
  // when should we show loading, network i/o is made, default 5m
  // gcTime: 5000
 
  // till when data is fresh, no network i/o, default 0
  // staleTime: 30_000
});
 
$: {
  if ($query.isError) {
    toast.error('could not fetch records');
  }
}select and infinite queries
- I think select is good for one of queries for infinite queries seems like validation at render would be nicecr
Effect x Svelte
TheStockBroker
- Unfortunately I am not familiar with a live example, but fortunately svelte is pretty close-to-metal so integration would not be too demanding, basically just using a store or something to represent effects. There are 2 main ways to integrate effect into your application. As a logic engine, it holds the state, the actions, and context of your application. Or as a workflow executor, it only handles actions, you must handle the rest. Theres also the consideration on what exists servers-side and what is allowed to “leak” into the client side. All-in-all the latter version is simpler to work with but less powerful
- The former would requiring introducing effect-rx into the mix, which is rather advanced in concept. I can help you understand it but it’s non-trivial and builds on a lot of previous understanding
Forms
What we currently using
- svelte forms(base) + super forms(form state management) + formsnap(to avoid html boilerplate)
- Even though superforms has setErrorto show error, rather usesetMessage. sosetMessagefor everything.
Tips
TODO My svelte no-scroll app template
- This is pretty annoying and has killed lot of my time in the past