Updated
—
4 min read

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).
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.
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.
project - www # Your SvelteKit app - backend # An Express.js app, for example
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.
project - www - backend - common # Where we'll put shared code
Initialize a new npm package in common:
cd common npm init
Then, install some basic dependencies for Typescript:
npm install -D typescript @types/node prettier
Most importantly, you need to install tsconfig-paths, which will be important later:
npm install -D tsconfig-paths
Create a tsconfig.json file in your common directory.
Then, here's a basic setup you can copy:
{ "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:
import { Schema } from "www/src/types/schema"; // ...
Lastly, we need to do something similar with our www SvelteKit project.
In your SvelteKit project, open up tsconfig.json.
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.
From there, you can add in the include for the common Typescript files.
"include": [ "../common/**/*.ts", // ... rest of includes copied over ]
In the end, your new SvelteKit tsconfig.json should look something like:
{ "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/**" ] }
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:
const config = { preprocess: vitePreprocess(), kit: { adapter: adapter(), alias: { $common: "../common/src", # Add this path alias }, } };
Now you're all set! In your SvelteKit project, you can now import code from your common module like so:
<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.
Join my newsletter for lessons, experiments, and failures in bootstrapping online businesses.
Sign up if you're curious. I’ll only email you if it's actually good.

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.
What I'm currently building →.