How to Share Code with a SvelteKit Monorepo

Updated

4 min read

Photo by Chris Liverani

Photo by Chris Liverani

SvelteKit, being SSR-first and having API endpoints, comes with fullstack capabilities. But there are cases where you may require a more robust backend than what SvelteKit provides, in which case a monorepo is a great choice.

In this short writeup, I'm going to give a tutorial on how to create a SvelteKit monorepo, so that you can share code (like Typescript types) between your SvelteKit project and other Node.js apps (an Express.js server in this example).

Why Use a Monorepo with SvelteKit?

Here's an example of why you might want to use a monorepo with SvelteKit:

When I was working on a SvelteKit project that requires file uploading, I found that SvelteKit is a little lackluster regarding multipart/form-data handling.

As of writing, SvelteKit cannot handle streaming of request/response bodies.

But Express.js alongside busboy for example, can do this no problem. This is one example of why having a separate backend for SvelteKit may be a good idea.

Monorepo Structure

For sake of simplicity, let's assume a simple monorepo with a www project housing your SvelteKit app and backend housing an Express.js server.

markdownproject - www # Your SvelteKit app - backend # An Express.js app, for example

Creating a Common Module

To share code between our www and backend projects, we'll need a "common" module, or shared folder.

To do this, create a new Node app that is siblings with www.

markdownproject - www - backend - common # Where we'll put shared code

Setting Up the Common Module

Initialize a new npm package in common:

bashcd common npm init

Then, install some basic dependencies for Typescript:

bashnpm install -D typescript @types/node prettier

Most importantly, you need to install tsconfig-paths, which will be important later:

bashnpm install -D tsconfig-paths

Configure tsconfig.json

Create a tsconfig.json file in your common directory.

Then, here's a basic setup you can copy:

json{ "compilerOptions": { "module": "commonjs", "target": "es6", "esModuleInterop": true, "strict": false, "noImplicitAny": false, "forceConsistentCasingInFileNames": true, "noEmit": true, "resolveJsonModule": true, "isolatedModules": true, "moduleResolution": "node", "baseUrl": "./", "paths": { "www/*": ["../www/src/*"], # Path alias to SvelteKit project "backend/*": ["../backend/src/*"] # Path alias to Express.js project } }, "include": [ "../www/src/**/*.ts", "../backend/src/**/*.ts", "**/*.ts" ], "exclude": ["node_modules"], "ts-node": { "require": ["tsconfig-paths/register"] } }

This lets you access www and backend files from your common directory.

For example, in common, you could now do:

javascriptimport { Schema } from "www/src/types/schema"; // ...

Configure SvelteKit "tsconfig.json"

Lastly, we need to do something similar with our www SvelteKit project.

In your SvelteKit project, open up tsconfig.json.

Copy Existing Includes/Excludes

Note: SvelteKit warns that "If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes from the referenced tsconfig.json — Typescript does not merge them."

Basically, you want to open ./.svelte-kit/tsconfig.json and copy include and exclude into your root tsconfig.json.

Add Includes for Common Module

From there, you can add in the include for the common Typescript files.

json"include": [ "../common/**/*.ts", // ... rest of includes copied over ]

In the end, your new SvelteKit tsconfig.json should look something like:

json{ "extends": "./.svelte-kit/tsconfig.json", "compilerOptions": { "allowJs": true, "checkJs": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "resolveJsonModule": true, "skipLibCheck": true, "sourceMap": true, "strict": true, "moduleResolution": "bundler" }, // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias // // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes // from the referenced tsconfig.json - TypeScript does not merge them in "include": [ "../common/**/*.ts", // Include files from common module "ambient.d.ts", "non-ambient.d.ts", "./types/**/$types.d.ts", "../vite.config.js", "../vite.config.ts", "../src/**/*.js", "../src/**/*.ts", "../src/**/*.svelte", "../tests/**/*.js", "../tests/**/*.ts", "../tests/**/*.svelte" ], "exclude": [ "../node_modules/**" ] }

Configure SvelteKit "svelte.config.js"

Lastly, we just need to add a path alias to our SvelteKit config so we can access the common files.

To do that, open up svelte.config.js and add this block under kit:

javascriptconst config = { preprocess: vitePreprocess(), kit: { adapter: adapter(), alias: { $common: "../common/src", # Add this path alias }, } };

Use Shared Code with SvelteKit

Now you're all set! In your SvelteKit project, you can now import code from your common module like so:

svelte<script lang="ts"> import { Schema } from "$common/types/schema"; import { SCHEMA_DATA_TYPES } from "$common/static/constants"; </script>

Hope this short tutorial helps someone. I couldn't find a specific writeup on how to share types between a SvelteKit frontend and a backend server.

Let me know if you have any suggestions or improvements to make.

Ryan Chiang

Meet the Author

Ryan Chiang

Hello, I'm Ryan. I build things and write about them. This is my blog of my learnings, tutorials, and whatever else I feel like writing about.
See what I'm building →.

Thanks for reading! If you want a heads up when I write a new blog post, you can subscribe below:

2025

2024

2023

© 2023-2025 Ryan Chiangryanschiang.com