From 729204e6177935ab87ae9bd51decef8c42e9fab8 Mon Sep 17 00:00:00 2001
From: Sil
Date: Mon, 1 Jun 2026 12:05:49 +0200
Subject: [PATCH] fix package publishing setup
---
.changeset/compiled-plugin-exports.md | 5 ++
.github/workflows/ci.yml | 50 ++++++++++++++++++
.github/workflows/release.yml | 50 ++++++++++++++++++
.gitignore | 1 +
README.md | 2 +-
package.json | 62 ++++++++++++++++------
pnpm-lock.yaml | 74 +++++++++++++++------------
scripts/build-package.mjs | 34 ++++++++++++
sitex/vite/plugin.ts | 21 ++++----
src/pages/docs/installation.tsx | 4 +-
tsconfig.package.json | 12 +++++
vite.config.ts | 3 +-
12 files changed, 254 insertions(+), 64 deletions(-)
create mode 100644 .changeset/compiled-plugin-exports.md
create mode 100644 .github/workflows/ci.yml
create mode 100644 .github/workflows/release.yml
create mode 100644 scripts/build-package.mjs
create mode 100644 tsconfig.package.json
diff --git a/.changeset/compiled-plugin-exports.md b/.changeset/compiled-plugin-exports.md
new file mode 100644
index 0000000..fafbaaf
--- /dev/null
+++ b/.changeset/compiled-plugin-exports.md
@@ -0,0 +1,5 @@
+---
+"@fulldotdev/sitex": patch
+---
+
+Publish compiled package entrypoints for the Vite plugin and island runtime so consumers no longer load TypeScript files from node_modules.
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..8cfe014
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,50 @@
+name: CI
+
+on:
+ pull_request:
+ branches: [main]
+ push:
+ branches: [main]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ validate:
+ name: Validate
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+ with:
+ fetch-depth: 0
+
+ - name: Setup PNPM
+ uses: pnpm/action-setup@v6
+
+ - name: Setup Node
+ uses: actions/setup-node@v6
+ with:
+ node-version-file: .nvmrc
+ cache: pnpm
+
+ - name: Install dependencies
+ run: pnpm install --frozen-lockfile
+
+ - name: Check changeset
+ if: github.event_name == 'pull_request' && !startsWith(github.head_ref, 'changeset-release/')
+ run: pnpm exec changeset status --since=origin/${{ github.event.pull_request.base.ref }}
+
+ - name: Check formatting
+ run: pnpm format:check
+
+ - name: Type check
+ run: pnpm typecheck
+
+ - name: Build package
+ run: pnpm build:package
+
+ - name: Build site
+ run: pnpm build
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..76db544
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,50 @@
+name: Release
+
+on:
+ push:
+ branches: [main]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: false
+
+permissions: {}
+
+jobs:
+ release-pr:
+ name: Release
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ id-token: write
+ pull-requests: write
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+ with:
+ fetch-depth: 0
+
+ - name: Setup PNPM
+ uses: pnpm/action-setup@v6
+
+ - name: Setup Node
+ uses: actions/setup-node@v6
+ with:
+ node-version-file: .nvmrc
+ registry-url: https://registry.npmjs.org
+ cache: pnpm
+
+ - name: Install dependencies
+ run: pnpm install --frozen-lockfile
+
+ - name: Create release pull request
+ id: changesets
+ uses: changesets/action@v1
+ with:
+ version: pnpm release
+ publish: pnpm release:publish
+ commit: "[ci] release"
+ title: "[ci] release"
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
index fde7d82..255304d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@ node_modules/
# build output
dist/
+package-dist/
.vite/
.sitex/
.sitex-bench/
diff --git a/README.md b/README.md
index 1678182..68b27fa 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ SiteX renders React routes to static HTML by default. When a page needs browser
## Install
```bash
-pnpm add @fulldotdev/sitex react react-dom vite @vitejs/plugin-react
+pnpm add --allow-build=esbuild @fulldotdev/sitex react react-dom vite @vitejs/plugin-react
pnpm add -D typescript @types/react @types/react-dom
```
diff --git a/package.json b/package.json
index 8102c0e..19b671f 100644
--- a/package.json
+++ b/package.json
@@ -2,16 +2,35 @@
"name": "@fulldotdev/sitex",
"version": "0.1.0",
"license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/fulldotdev/sitex.git"
+ },
+ "homepage": "https://github.com/fulldotdev/sitex#readme",
+ "bugs": {
+ "url": "https://github.com/fulldotdev/sitex/issues"
+ },
"publishConfig": {
"access": "public"
},
"type": "module",
"exports": {
- "./island": "./sitex/hydration/server.tsx",
- "./plugin": "./sitex/vite/plugin.ts",
+ "./island": {
+ "types": "./package-dist/hydration/server.d.ts",
+ "default": "./package-dist/hydration/server.js"
+ },
+ "./plugin": {
+ "types": "./package-dist/vite/plugin.d.ts",
+ "default": "./package-dist/vite/plugin.js"
+ },
"./tsconfig": "./sitex/config/tsconfig.json",
"./virtual": "./sitex/types/virtual.d.ts"
},
+ "files": [
+ "package-dist",
+ "sitex/config",
+ "sitex/types"
+ ],
"engines": {
"node": ">=22.12.0"
},
@@ -22,6 +41,11 @@
"msw"
]
},
+ "peerDependencies": {
+ "react": ">=19",
+ "react-dom": ">=19",
+ "vite": ">=7"
+ },
"scripts": {
"dev": "vite --host 127.0.0.1 --port 4323",
"start": "pnpm dev",
@@ -30,26 +54,41 @@
"format:check": "prettier --check .",
"typecheck": "tsc --noEmit",
"check": "pnpm format:check && pnpm typecheck",
+ "build:package": "node scripts/build-package.mjs && tsc -p tsconfig.package.json",
"build": "vite build",
"preview": "vite preview --host 127.0.0.1 --port 4323",
+ "prepack": "pnpm build:package",
"changeset": "changeset",
"release": "changeset version && pnpm install --lockfile-only",
- "release:publish": "pnpm build && changeset publish"
+ "release:publish": "pnpm build && pnpm build:package && changeset publish"
},
"dependencies": {
"@babel/generator": "^7.29.1",
"@babel/parser": "^7.29.3",
"@babel/traverse": "^7.29.0",
"@babel/types": "^7.29.0",
+ "fast-glob": "^3.3.3",
+ "vite-tsconfig-paths": "^6.1.1"
+ },
+ "devDependencies": {
"@base-ui/react": "^1.5.0",
+ "@changesets/changelog-github": "^0.7.0",
+ "@changesets/cli": "^2.31.0",
"@fontsource-variable/geist": "^5.2.9",
+ "@ianvs/prettier-plugin-sort-imports": "^4.7.1",
"@tailwindcss/vite": "^4.1.13",
+ "@types/babel__generator": "^7.27.0",
+ "@types/babel__traverse": "^7.28.0",
+ "@types/node": "^24.3.1",
+ "@types/react": "^19.1.12",
+ "@types/react-dom": "^19.1.9",
"@vitejs/plugin-react": "^5.0.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
- "fast-glob": "^3.3.3",
"lucide-react": "^1.16.0",
"next-themes": "^0.4.6",
+ "prettier": "^3.8.3",
+ "prettier-plugin-tailwindcss": "^0.8.0",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"shadcn": "^4.8.3",
@@ -57,18 +96,7 @@
"tailwind-merge": "^3.6.0",
"tailwindcss": "^4.1.13",
"tw-animate-css": "^1.4.0",
- "vite": "^7.1.5",
- "vite-tsconfig-paths": "^6.1.1"
- },
- "devDependencies": {
- "@changesets/changelog-github": "^0.7.0",
- "@changesets/cli": "^2.31.0",
- "@ianvs/prettier-plugin-sort-imports": "^4.7.1",
- "@types/node": "^24.3.1",
- "@types/react": "^19.1.12",
- "@types/react-dom": "^19.1.9",
- "prettier": "^3.8.3",
- "prettier-plugin-tailwindcss": "^0.8.0",
- "typescript": "^5.9.2"
+ "typescript": "^5.9.2",
+ "vite": "^7.1.5"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 0628e8d..c57dd87 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -20,15 +20,46 @@ importers:
'@babel/types':
specifier: ^7.29.0
version: 7.29.0
+ fast-glob:
+ specifier: ^3.3.3
+ version: 3.3.3
+ vite-tsconfig-paths:
+ specifier: ^6.1.1
+ version: 6.1.1(typescript@5.9.3)(vite@7.3.3(@types/node@24.12.4)(jiti@2.7.0)(lightningcss@1.32.0))
+ devDependencies:
'@base-ui/react':
specifier: ^1.5.0
version: 1.5.0(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
+ '@changesets/changelog-github':
+ specifier: ^0.7.0
+ version: 0.7.0
+ '@changesets/cli':
+ specifier: ^2.31.0
+ version: 2.31.0(@types/node@24.12.4)
'@fontsource-variable/geist':
specifier: ^5.2.9
version: 5.2.9
+ '@ianvs/prettier-plugin-sort-imports':
+ specifier: ^4.7.1
+ version: 4.7.1(prettier@3.8.3)
'@tailwindcss/vite':
specifier: ^4.1.13
version: 4.3.0(vite@7.3.3(@types/node@24.12.4)(jiti@2.7.0)(lightningcss@1.32.0))
+ '@types/babel__generator':
+ specifier: ^7.27.0
+ version: 7.27.0
+ '@types/babel__traverse':
+ specifier: ^7.28.0
+ version: 7.28.0
+ '@types/node':
+ specifier: ^24.3.1
+ version: 24.12.4
+ '@types/react':
+ specifier: ^19.1.12
+ version: 19.2.15
+ '@types/react-dom':
+ specifier: ^19.1.9
+ version: 19.2.3(@types/react@19.2.15)
'@vitejs/plugin-react':
specifier: ^5.0.2
version: 5.2.0(vite@7.3.3(@types/node@24.12.4)(jiti@2.7.0)(lightningcss@1.32.0))
@@ -38,15 +69,18 @@ importers:
clsx:
specifier: ^2.1.1
version: 2.1.1
- fast-glob:
- specifier: ^3.3.3
- version: 3.3.3
lucide-react:
specifier: ^1.16.0
version: 1.16.0(react@19.2.6)
next-themes:
specifier: ^0.4.6
version: 0.4.6(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
+ prettier:
+ specifier: ^3.8.3
+ version: 3.8.3
+ prettier-plugin-tailwindcss:
+ specifier: ^0.8.0
+ version: 0.8.0(@ianvs/prettier-plugin-sort-imports@4.7.1(prettier@3.8.3))(prettier@3.8.3)
react:
specifier: ^19.1.1
version: 19.2.6
@@ -68,40 +102,12 @@ importers:
tw-animate-css:
specifier: ^1.4.0
version: 1.4.0
- vite:
- specifier: ^7.1.5
- version: 7.3.3(@types/node@24.12.4)(jiti@2.7.0)(lightningcss@1.32.0)
- vite-tsconfig-paths:
- specifier: ^6.1.1
- version: 6.1.1(typescript@5.9.3)(vite@7.3.3(@types/node@24.12.4)(jiti@2.7.0)(lightningcss@1.32.0))
- devDependencies:
- '@changesets/changelog-github':
- specifier: ^0.7.0
- version: 0.7.0
- '@changesets/cli':
- specifier: ^2.31.0
- version: 2.31.0(@types/node@24.12.4)
- '@ianvs/prettier-plugin-sort-imports':
- specifier: ^4.7.1
- version: 4.7.1(prettier@3.8.3)
- '@types/node':
- specifier: ^24.3.1
- version: 24.12.4
- '@types/react':
- specifier: ^19.1.12
- version: 19.2.15
- '@types/react-dom':
- specifier: ^19.1.9
- version: 19.2.3(@types/react@19.2.15)
- prettier:
- specifier: ^3.8.3
- version: 3.8.3
- prettier-plugin-tailwindcss:
- specifier: ^0.8.0
- version: 0.8.0(@ianvs/prettier-plugin-sort-imports@4.7.1(prettier@3.8.3))(prettier@3.8.3)
typescript:
specifier: ^5.9.2
version: 5.9.3
+ vite:
+ specifier: ^7.1.5
+ version: 7.3.3(@types/node@24.12.4)(jiti@2.7.0)(lightningcss@1.32.0)
packages:
diff --git a/scripts/build-package.mjs b/scripts/build-package.mjs
new file mode 100644
index 0000000..7c62753
--- /dev/null
+++ b/scripts/build-package.mjs
@@ -0,0 +1,34 @@
+import { rm } from "node:fs/promises"
+import { builtinModules, createRequire } from "node:module"
+import { build } from "esbuild"
+
+const require = createRequire(import.meta.url)
+const packageJson = require("../package.json")
+
+const external = [
+ ...builtinModules,
+ ...builtinModules.map((module) => `node:${module}`),
+ ...Object.keys(packageJson.dependencies ?? {}),
+ ...Object.keys(packageJson.peerDependencies ?? {}),
+ "virtual:*",
+]
+
+await rm("package-dist", { recursive: true, force: true })
+
+await build({
+ entryPoints: [
+ "sitex/vite/plugin.ts",
+ "sitex/hydration/client.tsx",
+ "sitex/hydration/server.tsx",
+ "sitex/router/index.tsx",
+ "sitex/router/routes.ts",
+ ],
+ outbase: "sitex",
+ outdir: "package-dist",
+ bundle: true,
+ external,
+ format: "esm",
+ jsx: "automatic",
+ platform: "neutral",
+ target: "es2022",
+})
diff --git a/sitex/vite/plugin.ts b/sitex/vite/plugin.ts
index fbf875d..5f998d3 100644
--- a/sitex/vite/plugin.ts
+++ b/sitex/vite/plugin.ts
@@ -28,7 +28,8 @@ import {
import { findRoute, getRoutes } from "../router/routes.ts"
const packageRoot = path.dirname(path.dirname(fileURLToPath(import.meta.url)))
-const islandClientInput = normalizePath(packageFile("hydration/client.tsx"))
+const packageSourceExtension = path.extname(fileURLToPath(import.meta.url))
+const islandClientInput = normalizePath(packageFile("hydration/client", "tsx"))
const isHtmlRequest = (req: Connect.IncomingMessage) => {
if (!req.url || (req.method !== "GET" && req.method !== "HEAD")) return false
@@ -134,11 +135,11 @@ function sitexPlugin(): Plugin {
try {
const mod = await server.ssrLoadModule(
- packageFile("router/index.tsx")
+ packageFile("router/index", "tsx")
)
const html = await mod.renderRouteHtml(route, {
assetTags: renderStylesheetTags(cssInputs),
- islandClientSrc: devServerFileUrl("hydration/client.tsx"),
+ islandClientSrc: devServerFileUrl("hydration/client", "tsx"),
})
const transformed = await server.transformIndexHtml(url, html)
@@ -214,10 +215,10 @@ async function writeStaticHtml(root: string, cssInputs: string[]) {
try {
const { getRoutes } = await server.ssrLoadModule(
- packageFile("router/routes.ts")
+ packageFile("router/routes", "ts")
)
const { renderRouteHtml } = await server.ssrLoadModule(
- packageFile("router/index.tsx")
+ packageFile("router/index", "tsx")
)
const routes = await getRoutes((id: string) => server.ssrLoadModule(id))
@@ -327,12 +328,14 @@ function resolveCssImport(root: string, importer: string, source: string) {
return path.resolve(path.dirname(importer), source)
}
-function packageFile(file: string) {
- return path.join(packageRoot, file)
+function packageFile(file: string, sourceExtension: "ts" | "tsx") {
+ const extension = packageSourceExtension === ".js" ? "js" : sourceExtension
+
+ return path.join(packageRoot, `${file}.${extension}`)
}
-function devServerFileUrl(file: string) {
- return `/@fs/${packageFile(file).replaceAll(path.sep, "/")}`
+function devServerFileUrl(file: string, sourceExtension: "ts" | "tsx") {
+ return `/@fs/${packageFile(file, sourceExtension).replaceAll(path.sep, "/")}`
}
function normalizePath(file: string) {
diff --git a/src/pages/docs/installation.tsx b/src/pages/docs/installation.tsx
index f0dbe02..efb8e99 100644
--- a/src/pages/docs/installation.tsx
+++ b/src/pages/docs/installation.tsx
@@ -38,7 +38,7 @@ export default function InstallationPage() {
@@ -50,7 +50,7 @@ extend the SiteX TypeScript config, add the scripts, and create the first route.
diff --git a/tsconfig.package.json b/tsconfig.package.json
new file mode 100644
index 0000000..4e194f0
--- /dev/null
+++ b/tsconfig.package.json
@@ -0,0 +1,12 @@
+{
+ "extends": "./sitex/config/tsconfig.json",
+ "include": ["sitex/**/*"],
+ "exclude": ["dist"],
+ "compilerOptions": {
+ "declaration": true,
+ "emitDeclarationOnly": true,
+ "declarationMap": false,
+ "outDir": "package-dist",
+ "noEmit": false
+ }
+}
diff --git a/vite.config.ts b/vite.config.ts
index 489b711..25d6f1f 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,8 +1,9 @@
import { defineConfig } from "vite"
-import { sitex } from "@fulldotdev/sitex/plugin"
import tailwindcss from "@tailwindcss/vite"
import react from "@vitejs/plugin-react"
+import { sitex } from "./sitex/vite/plugin"
+
export default defineConfig({
appType: "custom",
plugins: [react(), sitex(), tailwindcss()],