diff --git a/.gitignore b/.gitignore
index 5e46eb408..f76a6ee82 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,4 @@ node_modules
dist
lib
*.tsbuildinfo
+.DS_Store
diff --git a/static/2024-05-30-app-skeleton-lit/README.md b/static/2024-05-30-app-skeleton-lit/README.md
new file mode 100644
index 000000000..90ee8190f
--- /dev/null
+++ b/static/2024-05-30-app-skeleton-lit/README.md
@@ -0,0 +1,9 @@
+## Getting started
+
+Quick start:
+
+```bash
+npm install && npm run build && npm run preview
+```
+
+This will install dependencies, build the project, and spin up a preview in a dev server using Vite.
diff --git a/static/2024-05-30-app-skeleton-lit/index.html b/static/2024-05-30-app-skeleton-lit/index.html
new file mode 100644
index 000000000..89e06c09a
--- /dev/null
+++ b/static/2024-05-30-app-skeleton-lit/index.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Send
+
+
+
+
+
+
+
+
+
diff --git a/static/2024-05-30-app-skeleton-lit/package-lock.json b/static/2024-05-30-app-skeleton-lit/package-lock.json
new file mode 100644
index 000000000..a2d5fd471
--- /dev/null
+++ b/static/2024-05-30-app-skeleton-lit/package-lock.json
@@ -0,0 +1,850 @@
+{
+ "name": "2024-05-30-app-skeleton-lit",
+ "version": "0.0.1",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "2024-05-30-app-skeleton-lit",
+ "version": "0.0.1",
+ "license": "MIT",
+ "dependencies": {
+ "lit": "^3.1.3"
+ },
+ "devDependencies": {
+ "vite": "^5.2.12"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
+ "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz",
+ "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz",
+ "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz",
+ "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz",
+ "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz",
+ "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz",
+ "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz",
+ "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz",
+ "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz",
+ "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz",
+ "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz",
+ "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz",
+ "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz",
+ "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz",
+ "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz",
+ "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz",
+ "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz",
+ "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz",
+ "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz",
+ "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz",
+ "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz",
+ "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz",
+ "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@lit-labs/ssr-dom-shim": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.0.tgz",
+ "integrity": "sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g=="
+ },
+ "node_modules/@lit/reactive-element": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.4.tgz",
+ "integrity": "sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ==",
+ "dependencies": {
+ "@lit-labs/ssr-dom-shim": "^1.2.0"
+ }
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz",
+ "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz",
+ "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz",
+ "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz",
+ "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz",
+ "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz",
+ "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz",
+ "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz",
+ "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz",
+ "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz",
+ "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz",
+ "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz",
+ "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz",
+ "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz",
+ "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz",
+ "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz",
+ "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
+ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
+ "dev": true
+ },
+ "node_modules/@types/trusted-types": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="
+ },
+ "node_modules/esbuild": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
+ "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.20.2",
+ "@esbuild/android-arm": "0.20.2",
+ "@esbuild/android-arm64": "0.20.2",
+ "@esbuild/android-x64": "0.20.2",
+ "@esbuild/darwin-arm64": "0.20.2",
+ "@esbuild/darwin-x64": "0.20.2",
+ "@esbuild/freebsd-arm64": "0.20.2",
+ "@esbuild/freebsd-x64": "0.20.2",
+ "@esbuild/linux-arm": "0.20.2",
+ "@esbuild/linux-arm64": "0.20.2",
+ "@esbuild/linux-ia32": "0.20.2",
+ "@esbuild/linux-loong64": "0.20.2",
+ "@esbuild/linux-mips64el": "0.20.2",
+ "@esbuild/linux-ppc64": "0.20.2",
+ "@esbuild/linux-riscv64": "0.20.2",
+ "@esbuild/linux-s390x": "0.20.2",
+ "@esbuild/linux-x64": "0.20.2",
+ "@esbuild/netbsd-x64": "0.20.2",
+ "@esbuild/openbsd-x64": "0.20.2",
+ "@esbuild/sunos-x64": "0.20.2",
+ "@esbuild/win32-arm64": "0.20.2",
+ "@esbuild/win32-ia32": "0.20.2",
+ "@esbuild/win32-x64": "0.20.2"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/lit": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/lit/-/lit-3.1.3.tgz",
+ "integrity": "sha512-l4slfspEsnCcHVRTvaP7YnkTZEZggNFywLEIhQaGhYDczG+tu/vlgm/KaWIEjIp+ZyV20r2JnZctMb8LeLCG7Q==",
+ "dependencies": {
+ "@lit/reactive-element": "^2.0.4",
+ "lit-element": "^4.0.4",
+ "lit-html": "^3.1.2"
+ }
+ },
+ "node_modules/lit-element": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.0.5.tgz",
+ "integrity": "sha512-iTWskWZEtn9SyEf4aBG6rKT8GABZMrTWop1+jopsEOgEcugcXJGKuX5bEbkq9qfzY+XB4MAgCaSPwnNpdsNQ3Q==",
+ "dependencies": {
+ "@lit-labs/ssr-dom-shim": "^1.2.0",
+ "@lit/reactive-element": "^2.0.4",
+ "lit-html": "^3.1.2"
+ }
+ },
+ "node_modules/lit-html": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.1.3.tgz",
+ "integrity": "sha512-FwIbqDD8O/8lM4vUZ4KvQZjPPNx7V1VhT7vmRB8RBAO0AU6wuTVdoXiu2CivVjEGdugvcbPNBLtPE1y0ifplHA==",
+ "dependencies": {
+ "@types/trusted-types": "^2.0.2"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
+ "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
+ "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
+ "dev": true
+ },
+ "node_modules/postcss": {
+ "version": "8.4.38",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
+ "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.7",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz",
+ "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "1.0.5"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.18.0",
+ "@rollup/rollup-android-arm64": "4.18.0",
+ "@rollup/rollup-darwin-arm64": "4.18.0",
+ "@rollup/rollup-darwin-x64": "4.18.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.18.0",
+ "@rollup/rollup-linux-arm-musleabihf": "4.18.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.18.0",
+ "@rollup/rollup-linux-arm64-musl": "4.18.0",
+ "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.18.0",
+ "@rollup/rollup-linux-s390x-gnu": "4.18.0",
+ "@rollup/rollup-linux-x64-gnu": "4.18.0",
+ "@rollup/rollup-linux-x64-musl": "4.18.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.18.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.18.0",
+ "@rollup/rollup-win32-x64-msvc": "4.18.0",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
+ "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/vite": {
+ "version": "5.2.12",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.12.tgz",
+ "integrity": "sha512-/gC8GxzxMK5ntBwb48pR32GGhENnjtY30G4A0jemunsBkiEZFw60s8InGpN8gkhHEkjnRK1aSAxeQgwvFhUHAA==",
+ "dev": true,
+ "dependencies": {
+ "esbuild": "^0.20.1",
+ "postcss": "^8.4.38",
+ "rollup": "^4.13.0"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || >=20.0.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ }
+ }
+}
diff --git a/static/2024-05-30-app-skeleton-lit/package.json b/static/2024-05-30-app-skeleton-lit/package.json
new file mode 100644
index 000000000..7fc5ab94a
--- /dev/null
+++ b/static/2024-05-30-app-skeleton-lit/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "2024-05-30-app-skeleton-lit",
+ "version": "0.0.1",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "build": "vite build",
+ "preview": "vite preview",
+ "dev": "vite"
+ },
+ "author": "Gordon Brander",
+ "license": "MIT",
+ "dependencies": {
+ "lit": "^3.1.3"
+ },
+ "devDependencies": {
+ "vite": "^5.2.12"
+ }
+}
diff --git a/static/2024-05-30-app-skeleton-lit/src/components/com-app-grid.ts b/static/2024-05-30-app-skeleton-lit/src/components/com-app-grid.ts
new file mode 100644
index 000000000..58cbbd900
--- /dev/null
+++ b/static/2024-05-30-app-skeleton-lit/src/components/com-app-grid.ts
@@ -0,0 +1,41 @@
+import {LitElement, html, css} from 'lit-element'
+import {customElement} from 'lit/decorators.js'
+import {base} from '../styles'
+
+const styles = css`
+:host {
+ --sidebar-width: calc(var(--unit) * 60);
+ display: grid;
+ grid-template-columns: var(--sidebar-width) 1fr;
+ grid-template-areas: "sidebar main";
+ min-height: 100dvh;
+}
+
+
+com-app-grid-sidebar {
+ grid-area: sidebar;
+ background-color: var(--color-secondary-background);
+}
+
+com-app-grid-main {
+ grid-area: main;
+ container-type: inline-size;
+}
+`
+
+@customElement('com-app-grid')
+export class ComAppGrid extends LitElement {
+ static styles = [base, styles]
+
+ render() {
+ return html`
+
+
+
+
+
+
+ `
+ }
+}
+
diff --git a/static/2024-05-30-app-skeleton-lit/src/components/com-button.ts b/static/2024-05-30-app-skeleton-lit/src/components/com-button.ts
new file mode 100644
index 000000000..13c3da89e
--- /dev/null
+++ b/static/2024-05-30-app-skeleton-lit/src/components/com-button.ts
@@ -0,0 +1,35 @@
+import {LitElement, html, css} from 'lit-element'
+import {customElement} from 'lit/decorators.js'
+import {base} from '../styles'
+
+const styles = css`
+ :host {
+ display: inline-block;
+ }
+
+ .button {
+ --color-button: var(--color-green);
+ --color-button-text: var(--color-green-2);
+ --height: calc(var(--unit) * 11);
+ appearance: none;
+ background-color: var(--color-button);
+ border: 0;
+ border-radius: calc(var(--height) / 2);
+ color: var(--color-button-text);
+ display: block;
+ font-size: var(--body-size);
+ font-weight: bold;
+ height: var(--height);
+ line-height: var(--height);
+ padding: 0 calc(var(--unit) * 5);
+ }
+`
+
+@customElement('com-button')
+export class ComButton extends LitElement {
+ static styles = [base, styles]
+
+ render() {
+ return html``
+ }
+}
diff --git a/static/2024-05-30-app-skeleton-lit/src/components/com-chat.ts b/static/2024-05-30-app-skeleton-lit/src/components/com-chat.ts
new file mode 100644
index 000000000..bed6a1bbb
--- /dev/null
+++ b/static/2024-05-30-app-skeleton-lit/src/components/com-chat.ts
@@ -0,0 +1,53 @@
+import {LitElement, html, css} from 'lit-element'
+import {customElement} from 'lit/decorators.js'
+import {base} from '../styles'
+
+const styles = css`
+ :host {
+ display: block;
+ }
+
+ .layout {
+ display: grid;
+ grid-template-rows: 1fr min-content;
+ grid-template-areas:
+ "main"
+ "footer";
+ height: 100cqh;
+ }
+
+ .main {
+ grid-area: main;
+ overflow-y: auto;
+ overflow-x: hidden;
+ padding: var(--gap);
+ }
+
+ .footer {
+ grid-area: footer;
+ padding: 0 var(--gap) var(--gap);
+ }
+`
+
+@customElement('com-chat')
+export class ComChat extends LitElement {
+ static styles = [base, styles]
+
+ render() {
+ return html`
+
+ `
+ }
+}
+
diff --git a/static/2024-05-30-app-skeleton-lit/src/components/com-content.ts b/static/2024-05-30-app-skeleton-lit/src/components/com-content.ts
new file mode 100644
index 000000000..d1fea4efc
--- /dev/null
+++ b/static/2024-05-30-app-skeleton-lit/src/components/com-content.ts
@@ -0,0 +1,31 @@
+import {LitElement, html, css} from 'lit-element'
+import {customElement} from 'lit/decorators.js'
+import {base} from '../styles'
+
+const styles = css`
+ :host {
+ display: block;
+ }
+
+ .container {
+ max-width: var(--content-width);
+ display: block;
+ margin: 0 auto;
+ padding-left: var(--gap);
+ padding-right: var(--gap);
+ }
+`
+
+@customElement('com-content')
+export class ComAppGrid extends LitElement {
+ static styles = [base, styles]
+
+ render() {
+ return html`
+
+
+
+ `
+ }
+}
+
diff --git a/static/2024-05-30-app-skeleton-lit/src/components/com-editor.ts b/static/2024-05-30-app-skeleton-lit/src/components/com-editor.ts
new file mode 100644
index 000000000..174116d2a
--- /dev/null
+++ b/static/2024-05-30-app-skeleton-lit/src/components/com-editor.ts
@@ -0,0 +1,30 @@
+import {LitElement, html, css} from 'lit-element'
+import {customElement, property} from 'lit/decorators.js'
+import {base} from '../styles'
+
+const styles = css`
+ :host {
+ display: block;
+ }
+
+ .editor {
+ display: block;
+
+ &:focus {
+ outline: none;
+ }
+ }
+`
+
+@customElement('com-editor')
+export class ComEditor extends LitElement {
+ static styles = [base, styles]
+
+ @property({type: String}) value = ''
+
+ render() {
+ return html`
+ ${this.value}
+ `
+ }
+}
diff --git a/static/2024-05-30-app-skeleton-lit/src/components/com-prompt.ts b/static/2024-05-30-app-skeleton-lit/src/components/com-prompt.ts
new file mode 100644
index 000000000..6a74b5b7b
--- /dev/null
+++ b/static/2024-05-30-app-skeleton-lit/src/components/com-prompt.ts
@@ -0,0 +1,30 @@
+import {LitElement, html, css} from 'lit-element'
+import {customElement} from 'lit/decorators.js'
+import {base} from '../styles'
+
+const styles = css`
+:host {
+ display: block;
+}
+
+.main {
+ padding: var(--gap);
+
+ &:focus {
+ outline: none;
+ }
+}
+`
+
+@customElement('com-prompt')
+export class ComPrompt extends LitElement {
+ static styles = [base, styles]
+
+ render() {
+ return html`
+
+
+
+ `
+ }
+}
diff --git a/static/2024-05-30-app-skeleton-lit/src/components/com-response.ts b/static/2024-05-30-app-skeleton-lit/src/components/com-response.ts
new file mode 100644
index 000000000..92acc09f1
--- /dev/null
+++ b/static/2024-05-30-app-skeleton-lit/src/components/com-response.ts
@@ -0,0 +1,31 @@
+import {LitElement, html, css} from 'lit-element'
+import {customElement} from 'lit/decorators.js'
+import {base} from '../styles'
+
+const styles = css`
+:host {
+ display: block;
+}
+
+.main {
+ background-color: var(--color-secondary-background);
+ padding: var(--gap);
+
+ &:focus {
+ outline: none;
+ }
+}
+`
+
+@customElement('com-response')
+export class ComResponse extends LitElement {
+ static styles = [base, styles]
+
+ render() {
+ return html`
+
+
+
+ `
+ }
+}
diff --git a/static/2024-05-30-app-skeleton-lit/src/components/com-thread-group.ts b/static/2024-05-30-app-skeleton-lit/src/components/com-thread-group.ts
new file mode 100644
index 000000000..cac427e2a
--- /dev/null
+++ b/static/2024-05-30-app-skeleton-lit/src/components/com-thread-group.ts
@@ -0,0 +1,25 @@
+import {LitElement, html, css} from 'lit-element'
+import {customElement} from 'lit/decorators.js'
+import {base} from '../styles'
+
+const styles = css`
+:host {
+ background: var(--color-card);
+ display: flex;
+ flex-direction: column;
+ border-radius: var(--radius);
+ overflow: hidden;
+}
+`
+
+@customElement('com-thread-group')
+export class ComThreadGroup extends LitElement {
+ static styles = [base, styles]
+
+ render() {
+ return html`
+
+
+ `
+ }
+}
diff --git a/static/2024-05-30-app-skeleton-lit/src/components/com-thread.ts b/static/2024-05-30-app-skeleton-lit/src/components/com-thread.ts
new file mode 100644
index 000000000..19421c149
--- /dev/null
+++ b/static/2024-05-30-app-skeleton-lit/src/components/com-thread.ts
@@ -0,0 +1,21 @@
+import {LitElement, html, css} from 'lit-element'
+import {customElement} from 'lit/decorators.js'
+import {base} from '../styles'
+
+const styles = css`
+ :host {
+ display: flex;
+ flex-direction: column;
+ gap: var(--gap);
+ }
+`
+
+@customElement('com-thread')
+export class ComThread extends LitElement {
+ static styles = [base, styles]
+
+ render() {
+ return html``
+ }
+}
+
diff --git a/static/2024-05-30-app-skeleton-lit/src/components/com-unibox.ts b/static/2024-05-30-app-skeleton-lit/src/components/com-unibox.ts
new file mode 100644
index 000000000..e22d88928
--- /dev/null
+++ b/static/2024-05-30-app-skeleton-lit/src/components/com-unibox.ts
@@ -0,0 +1,50 @@
+import {LitElement, html, css} from 'lit-element'
+import {customElement} from 'lit/decorators.js'
+import {base} from '../styles'
+
+const styles = css`
+ :host {
+ display: block;
+ }
+
+ .unibox {
+ --min-height: calc(var(--unit) * 15);
+ display: grid;
+ background-color: var(--color-white);
+ border-radius: calc(var(--min-height) / 2);
+ grid-template-columns: 1fr min-content;
+ grid-template-areas: "main end";
+ gap: var(--gap);
+ padding: calc(var(--unit) * 2);
+ min-height: var(--min-height);
+ }
+
+ .unibox-main {
+ grid-area: main;
+ align-self: center;
+ padding-left: calc(var(--unit) * 4);
+ }
+
+ .unibox-end {
+ grid-area: end;
+ }
+`
+
+@customElement('com-unibox')
+export class ComUnibox extends LitElement {
+ static styles = [base, styles]
+
+ render() {
+ return html`
+
+ `
+ }
+}
+
diff --git a/static/2024-05-30-app-skeleton-lit/src/main.css b/static/2024-05-30-app-skeleton-lit/src/main.css
new file mode 100644
index 000000000..b02e9d2d8
--- /dev/null
+++ b/static/2024-05-30-app-skeleton-lit/src/main.css
@@ -0,0 +1,36 @@
+:where(*) {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+ list-style: none;
+}
+
+:root {
+ --unit: 4px;
+ --gap: calc(var(--unit) * 5);
+ --content-width: 800px;
+ --family-sans: "Helvetica Neue", "Helvetica", sans-serif;
+ --family-serif: "Times New Roman", "Times", serif;
+ --color-white: #fff;
+ --color-sepia: #F7F2ED;
+ --color-sepia-2: #EFE8E1;
+ --color-sepia-3: #FDFAF7;
+ --color-brown: #946E47;
+ --color-green: #DBDC87;
+ --color-green-2: #8C8E0B;
+ --color-background: var(--color-sepia);
+ --color-secondary-background: var(--color-sepia-2);
+ --color-card: var(--color-sepia-3);
+ --color-text: #222;
+ --body-size: 16px;
+ --body-line: 24px;
+ --body-font: var(--body-size)/var(--body-line) var(--family-sans);
+ --icon-box-size: calc(var(--unit) * 4);
+ --radius: calc(var(--unit) * 4);
+}
+
+.theme {
+ background-color: var(--color-background);
+ color: var(--color-text);
+ font: var(--body-font);
+}
diff --git a/static/2024-05-30-app-skeleton-lit/src/main.ts b/static/2024-05-30-app-skeleton-lit/src/main.ts
new file mode 100644
index 000000000..f95e264c9
--- /dev/null
+++ b/static/2024-05-30-app-skeleton-lit/src/main.ts
@@ -0,0 +1,10 @@
+export * as ComAppGrid from './components/com-app-grid'
+export * as ComContent from './components/com-content'
+export * as ComChat from './components/com-chat'
+export * as ComThread from './components/com-thread'
+export * as ComPrompt from './components/com-prompt'
+export * as ComResponse from './components/com-response'
+export * as ComThreadGroup from './components/com-thread-group'
+export * as ComButton from './components/com-button'
+export * as ComUnibox from './components/com-unibox'
+export * as ComEditor from './components/com-editor'
\ No newline at end of file
diff --git a/static/2024-05-30-app-skeleton-lit/src/styles.ts b/static/2024-05-30-app-skeleton-lit/src/styles.ts
new file mode 100644
index 000000000..6ec029b79
--- /dev/null
+++ b/static/2024-05-30-app-skeleton-lit/src/styles.ts
@@ -0,0 +1,40 @@
+import { css } from 'lit'
+
+export const base = css`
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+ list-style: none;
+}
+
+:root {
+ --unit: 4px;
+ --gap: calc(var(--unit) * 5);
+ --content-width: 800px;
+ --family-sans: "Helvetica Neue", "Helvetica", sans-serif;
+ --family-serif: "Times New Roman", "Times", serif;
+ --color-white: #fff;
+ --color-sepia: #F7F2ED;
+ --color-sepia-2: #EFE8E1;
+ --color-sepia-3: #FDFAF7;
+ --color-brown: #946E47;
+ --color-green: #DBDC87;
+ --color-green-2: #8C8E0B;
+ --color-background: var(--color-sepia);
+ --color-secondary-background: var(--color-sepia-2);
+ --color-card: var(--color-sepia-3);
+ --color-text: #222;
+ --body-size: 16px;
+ --body-line: 24px;
+ --body-font: var(--body-size)/var(--body-line) var(--family-sans);
+ --icon-box-size: calc(var(--unit) * 4);
+ --radius: calc(var(--unit) * 4);
+}
+
+.theme {
+ background-color: var(--color-background);
+ color: var(--color-text);
+ font: var(--body-font);
+}
+`
\ No newline at end of file
diff --git a/static/2024-05-30-app-skeleton-lit/tsconfig.json b/static/2024-05-30-app-skeleton-lit/tsconfig.json
new file mode 100644
index 000000000..6cd254116
--- /dev/null
+++ b/static/2024-05-30-app-skeleton-lit/tsconfig.json
@@ -0,0 +1,27 @@
+{
+ "compilerOptions": {
+ "target": "es2017",
+ "module": "es2015",
+ "moduleResolution": "node",
+ "lib": ["esnext.array", "esnext", "es2017", "dom"],
+ "declaration": true,
+ "declarationMap": true,
+ "sourceMap": true,
+ "inlineSources": true,
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noImplicitReturns": true,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitAny": true,
+ "noImplicitThis": true,
+ "outDir": "./",
+ // Only necessary because @types/uglify-js can't find types for source-map
+ "skipLibCheck": true,
+ "experimentalDecorators": true
+ },
+ "include": [
+ "src/**/*.ts"
+ ],
+ "exclude": []
+ }
\ No newline at end of file