Open-source project
lit/lit-element-starter-ts avatar
lit/lit-element-starter-ts

lit-element-starter-ts: the Lit template you copy before writing a component

Sample component project using LitElement with TypeScript

544 stars212 forksJavaScriptBSD-3-Clause

At a glance

What is it?
The LitElement TypeScript starter is a sample component project with a strict TypeScript setup, tests against both Lit development and production modes, an ESLint and lit-analyzer lint pass, Prettier formatting and an Eleventy documentation site. It is generated from a package in the main Lit repository, which is where issues belong.
Who is it for?
Adopt this starter as your starting point if you are writing a Lit web component in TypeScript, because the tooling around it is already correct and unusually strict. Do not adopt it as a published package without reading the publishing guidance, because the project deliberately recommends shipping unoptimised JavaScript modules and doing the optimisation at the application level instead.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 50 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A generated template, and where the real repository is

The LitElement TypeScript starter includes a sample component using LitElement with TypeScript, and the second line of the readme tells you something important about it: this template is generated from the lit-starter-ts package in the main Lit repo.

That makes this repository a build artefact of sorts rather than a place where work happens. Issues and pull requests for this template should be filed in the Lit repository, and the readme points at the issue tracker there.

So the workflow for anyone using it is: copy it, change the package name, and start building. If you find a problem with the template itself, it gets fixed upstream in the package that generates it and reaches you when you regenerate or copy again. There is no accumulation of local fixes to the template in your own copy, which is the point.

The package identity in the manifest is @lit/lit-starter-ts, it is marked private, and the version is 2.0.3. The main and module entry points are my-element.js, which is the sample component, and the type field is module, so the project is ESM throughout. The author is listed as Google LLC and the licence is BSD-3-Clause, with the LICENSE file at the top level.

There is a CHANGELOG.md in the repository, which is a slightly unusual thing to find in a starter, and a small set of configuration files at the top level that describe the whole configuration surface: .eslintrc.json, .eslintignore, .prettierrc.json, .eleventy.cjs for the docs site, tsconfig.json, rollup.config.js, web-dev-server.config.js and web-test-runner.config.js.

The directory layout follows the same structure. There is src/ for the component source, dev/ for the development HTML page, docs-src/ for the documentation templates, and docs/ for the generated site that is checked in.

The build, and why it is strict

The build is plain tsc, and the readme is specific that this sample uses the TypeScript compiler to produce JavaScript that runs in modern browsers.

Installing dependencies is npm i, and the build is:

bash
npm run build

The manifest shows the underlying scripts, and build is simply tsc, while build:watch is tsc --watch. The watch variant is what you run in a separate shell to rebuild when files are modified.

There is no bundler in the normal build path, which is worth pausing on, because it looks dated and is in fact a deliberate position. The bundling section of the readme explains it: the project recommends publishing components as unoptimized JavaScript modules and performing build-time optimizations at the application level. That gives build tools the best chance to deduplicate code and remove dead code, because the application bundler sees the whole graph and can make decisions a component-level bundler cannot.

The Rollup configuration does exist, but the readme is explicit that it is there specifically for the docs generation, not for publishing to npm.

Then there is the strictness, and the readme flags it as something you will probably want to relax: both the TypeScript compiler and lit-analyzer are configured to be very strict, and you may want to change tsconfig.json to make them less strict.

That is an honest admission rather than a flaw. A template that ships with maximum strictness will fail to compile on first use for many people, because the strictness that catches real bugs in Lit code also rejects code patterns that are common elsewhere. Flagging it up front means you know the first thing you are likely to change.

There is also a size check, in the manifest as checksize, which bundles with Rollup, pipes the output through gzip at maximum compression, counts the bytes and removes the bundle. It is a crude but effective way to keep an eye on the shipped size of the component without adding a size-limit dependency.

Testing against both Lit modes

The test setup runs the same tests twice, once against each of Lit's two modes, and that is the most interesting testing decision in the template.

The readme says the test script runs your tests against Lit's development mode, with more verbose errors, as well as against Lit's production mode:

bash
npm test

The manifest shows how that is wired. The test script is npm run test:dev followed by npm run test:prod. The first is wtr, the web-test-runner, and the second is MODE=prod wtr.

So the difference between the two modes is an environment variable, and the same test file runs against both. Lit's development mode produces much more descriptive error messages, and the production mode is what users actually get. Running both means a test that passes only in development mode, because it depends on a development-only behaviour, is caught.

The watcher variants follow the same pattern: test:watch is wtr --watch and test:prod:watch is MODE=prod wtr --watch. The readme refers to the local testing command as test:dev:watch, and the manifest has test:watch, which is a small naming mismatch between the two documents that is worth knowing about if you go looking for it.

The runner itself is modern-web.dev's @web/test-runner, and the readme links the modern-web.dev testing documentation for more information. The configuration is in web-test-runner.config.js at the top level.

The dev server is the other half of the local workflow, and it is also from modern-web.dev. The readme explains what it handles for you: Web Dev Server resolves Node-style bare import specifiers, which are not supported in browsers, and it automatically transpiles JavaScript and adds polyfills to support older browsers.

To run it:

bash
npm run serve

Which serves a development HTML page at /dev/index.html, viewable at http://localhost:8000/dev/index.html, and the command serves the code using Lit's development mode. To serve against the production mode instead, the readme says to use npm run serve:prod, which the manifest implements as MODE=prod npm run serve.

Linting, formatting and the editor setup

The linting story has three parts and they are layered deliberately.

Linting of TypeScript files is provided by ESLint and TypeScript ESLint. In addition, lit-analyzer is used to type-check and lint lit-html templates with the same engine and rules as lit-plugin.

That last clause is the important one. lit-analyzer understands lit-html templates, which are not ordinary TypeScript and which a general linter cannot check. Running it with the same engine and rules as the editor extension means the lint result and what you see in your editor agree, which is the property that makes a linter tolerable to work with.

The lint script is a chain in the manifest. npm run lint is npm run lint:lit-analyzer followed by npm run lint:eslint, and the eslint part is eslint over the src TypeScript files. So to run it:

bash
npm run lint

As with the compiler, the readme warns that the rules are strict: the rules are mostly the recommended rules from each project, but some have been turned off to make LitElement usage easier, and the recommended rules are pretty strict, so you may want to relax them by editing .eslintrc.json and tsconfig.json.

Formatting is Prettier, pre-configured according to Lit's style, and the configuration lives in .prettierrc.json. The format script covers cjs, html, js, json, md and ts files and respects .eslintignore as its ignore path, which is a nice touch, since it means the same set of files is ignored by the two tools.

One thing Prettier does not do here is run on commit. The readme says that has not been configured but can be added with Husky and pretty-quick, and points at the prettier.io site for instructions.

The editor recommendation is VS Code with the lit-plugin extension, and the readme lists the features it enables: syntax highlighting, type-checking, code completion, hover-over docs, jump to definition, linting and quick fixes. It also notes that the project is set up to recommend lit-plugin to VS Code users who do not already have it installed, which is the .vscode directory at the top level doing the recommending.

The documentation site and the release story

The documentation is a small website generated with Eleventy, and it is checked in rather than deployed from a pipeline.

The templates and pages live in /docs-src, the site is generated to /docs, and it is intended to be checked in so that GitHub pages can serve the site from the /docs folder on the main branch. To enable it, the readme says to go to the GitHub settings and change the GitHub Pages Source setting to main branch /docs folder.

That is a deliberate choice for a template. A generated site committed to the repository means the documentation works with no deployment step at all, which is the right default for something people copy out of.

The commands are:

bash
npm run docs

to build it, npm run docs:serve to serve it locally, and npm run docs:gen:watch to watch the site files and rebuild automatically. The site will usually be served at http://localhost:8000.

The manifest shows how the docs pipeline is assembled, and it is longer than the three commands above suggest. The docs script is a chain: clean the docs directory, build the TypeScript, run the analyzer, run the Rollup bundle, copy the Prism theme, and generate with Eleventy. The analyzer step is cem analyze with the litelement flag and globs over the TypeScript sources, which is the custom elements manifest analyzer, and it means the documentation site can list your component and its properties automatically rather than by hand.

Then there is the release story, which is covered at the top of the readme under a heading about the release. This is a pre-release of Lit 3.0, the next major version of Lit, and it has very few breaking changes from Lit 2.0: it drops support for IE11, it is published as ES2021, and it removes a couple of deprecated Lit 1.x APIs.

The readme is measured about the upgrade path. Lit 3.0 should require no changes to upgrade from Lit 2.0 for the vast majority of users, and once the full release is published, most apps and libraries will be able to extend their npm version ranges to include both 2.x and 3.x, like "^2.7.0 || ^3.0.0".

And it notes something that matters more than a version number: Lit 2.x and 3.0 are interoperable, with templates, base classes, directives and decorators from one version working with those from another. That is what makes a major version bump of a component framework survivable, and it is why the readme can describe the change as having very few breaking changes at all.

Editorial conclusion

Adopt this starter as your starting point if you are writing a Lit web component in TypeScript, because the tooling around it is already correct and unusually strict. Do not adopt it as a published package without reading the publishing guidance, because the project deliberately recommends shipping unoptimised JavaScript modules and doing the optimisation at the application level instead. Before you commit, read the note about where issues go, since this repository is generated from a template package in the main Lit repo and problems reported here will be closed without a fix.

Frequently asked questions

What is the LitElement TypeScript starter?

It is a sample component project using LitElement with TypeScript, published as @lit/lit-starter-ts. It is generated from the lit-starter-ts package in the main Lit repository, so issues and pull requests for the template should be filed there rather than in this repository. It is BSD-3-Clause licensed.

How do I build and test the Lit TypeScript starter?

Install dependencies with npm i, build with npm run build, and run npm run build:watch in a separate shell to rebuild on change. The build is plain tsc. Tests run with npm test, which runs them against both Lit's development mode and its production mode, and npm run serve starts a dev server with a development page at http://localhost:8000/dev/index.html.

What does lit-analyzer do in this project?

It type-checks and lints lit-html templates using the same engine and rules as the lit-plugin editor extension, which a general TypeScript linter cannot do. The lint script runs lit-analyzer first and then ESLint over the TypeScript sources, so template problems are reported separately from ordinary code problems.

What changed between Lit 2.0 and Lit 3.0?

The readme lists very few breaking changes: support for IE11 is dropped, the packages are published as ES2021, and a couple of deprecated Lit 1.x APIs are removed. Most apps and libraries will be able to widen their npm version ranges to cover both, and templates, base classes, directives and decorators are interoperable between the two versions.

Should I bundle and minify a component before publishing it?

No. The readme recommends publishing components as unoptimized JavaScript modules and performing build-time optimizations at the application level, because that gives build tools the best chance to deduplicate code and remove dead code. The Rollup configuration in this project exists for the documentation site rather than for publishing to npm.

Official sources

  1. Issues
  2. License: BSD-3-Clause
  3. lit/lit-element-starter-ts on GitHub
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/lit-lit-element-starter-ts.svg)](https://hysenlabs.com/projects/lit-lit-element-starter-ts)

Was this useful?