Build and deploy Open Source LWC components
In 2021 probably every Salesforce developer knows, how to deploy LWC components to the Salesforce platform. It is also a well known, that you can use the LWC framework outside Salesforce as well.
The lwc.dev documentation is pretty good, but without prior frontend development experience it can be a little bit challenging. So let’s see, how a standalone web app is created in LWC.

There is a handy tool to create a boilerplate LWC app:
npx create-lwc-app my-app-name
This creates and installs a project and creates 2 demo components. In order to see it in action, run npm run watch
.
The source structure
In this scenario, I assume that we are creating a standalone, one-page LWC app. All your code lives under src/
, by convention. Everything else in the project directory is just tooling.
src/
├── index.html
├── index.js
├── modules
│ ├── jsconfig.json
│ └── my
│ └── toDo
│ ├── toDo.css
│ ├── toDo.html
│ └── toDo.js
└── resources
└── favicon.ico
As you see, the structure is very similar to the Salesforce file structure. All components live in their own directories undermodules
, named by the component name; and all the .css, .html and .js files have the same names. There is one additional level: there is a so-called namespace: so my toDo
component’s real name is my-to-do
The entry point for you app is index.html
by convention — and you can serve from src/
other files as well. Static resources should be put under resources/
.
Appending root component to an HTML
So the entry point for your app is index.html
, which is a totally normal .html file. In order to render a component inside it, you need to append the root LWC component somewhere into this file. That’s how you do this.
In your index.html
, you create a div called main:
<div id="main"></div>
And also create index.js
import { createElement } from 'lwc';import ToDo from 'my/toDo';const td = createElement('to-do', { is: ToDo });document.querySelector('#main').appendChild(td);
The script creates an instance of your element (here: toDo
under the my
namespace) and inserts it into the #main
div.
Note that you should not load the .js file in index.html — it will be added automatically when the project is built.
The build
At this point, if you load index.html
from the /src
directory, you won’t see anything. The javascript is not functional in this form, because the browser has no idea, how to resolve all the underlying dependencies. So you need to create the build. There is script for this: npm run build
If you look into package.json, you see that the following command is run, when you start build:
lwc-services build -m production
Lwc-services is a tooling library for lwc. With the build command, it does the following:
- runs a bundler (webpack) in order to resolve dependencies and merge them into one file
- appends all the needed .js to your index.html
- copies everything into the
/dist
directory.
If you load now /dist/index.html
, your app will work as intended. Note that you have only one .js file — all your component code, .css, templates and more is inside of it. You can also note that this .js is very ugly — because its minified.
Serve and Watch
Making a build every time you changed something in your components is boring. So there is watch mode: npm run watch
. This will start a local webserver, and rebuild you app every time you saved a change in files.
The npm run serve
script does a very similar thing: runs a webserver which serves the /dist
. However, this does not re-build every time you save a file.
I also recommend to look into package.js
and see, what other npm
scripts are included.
Sum it up — the OSS LWC development process
The easiest way to create a LWC project is the following:
- use the
create-lwc-app
tool, in order to create a boilerplate. - write your components and your root .html in the
/src
directory - create builds or run the watch script
And you are good. It is important that you never commit your dist/
into your repo, because its only an ephemeral representation of your app — from the source you can create a build anytime you want.
See a whole LWC project repo here: