Skip to content

Commit 4146076

Browse files
authored
Merge pull request #119 from PMDevSolutions/feat/npm-publish-widget
feat: publish widget to npm as claudius-chat-widget
2 parents 08d1cdf + 0193ec9 commit 4146076

8 files changed

Lines changed: 267 additions & 21 deletions

File tree

.github/workflows/release-please.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ on:
77
permissions:
88
contents: write
99
pull-requests: write
10+
id-token: write # required for npm publish --provenance
1011

1112
concurrency:
1213
group: release-please
@@ -74,3 +75,31 @@ jobs:
7475
run: |
7576
gh release upload "${{ steps.release.outputs.tag_name }}" \
7677
cdn/claudius.iife.js cdn/claudius.css --clobber
78+
79+
# On merge, publish the widget to npm. Runs against the default checkout
80+
# (main at the released commit), which carries the version release-please
81+
# just bumped. --provenance signs the package via the id-token permission.
82+
- name: Setup pnpm (npm publish)
83+
if: ${{ steps.release.outputs.release_created }}
84+
uses: pnpm/action-setup@v4
85+
with:
86+
version: 9
87+
88+
- name: Setup Node (npm publish)
89+
if: ${{ steps.release.outputs.release_created }}
90+
uses: actions/setup-node@v4
91+
with:
92+
node-version: 20
93+
registry-url: https://registry.npmjs.org
94+
cache: pnpm
95+
cache-dependency-path: widget/pnpm-lock.yaml
96+
97+
- name: Build and publish widget
98+
if: ${{ steps.release.outputs.release_created }}
99+
working-directory: widget
100+
env:
101+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
102+
run: |
103+
pnpm install --frozen-lockfile
104+
pnpm build
105+
npm publish --provenance --access public

CONTRIBUTING.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,33 @@ merging that PR cuts the tag, GitHub Release, and `CHANGELOG.md` entry.
173173
commit the major. Version numbers are therefore **outputs of the commit
174174
history, not plans**.
175175

176+
### Publishing to npm
177+
178+
The same release also **publishes the widget to npm** as
179+
[`claudius-chat-widget`](https://www.npmjs.com/package/claudius-chat-widget). The
180+
publish step in `.github/workflows/release-please.yml` runs only when a release is
181+
cut, builds the dual ESM/CJS package, and authenticates with an `NPM_TOKEN`
182+
repository secret (publishing with provenance):
183+
184+
- Create an **Automation** access token — or a **granular** token scoped to
185+
publish `claudius-chat-widget` — at npmjs.com → *Access Tokens*.
186+
- Store it as a repository Actions secret:
187+
188+
```bash
189+
gh secret set NPM_TOKEN --repo PMDevSolutions/Claudius
190+
```
191+
192+
The very first version must be published manually once, because release-please
193+
only triggers the publish step on a *new* release after the workflow is wired up:
194+
195+
```bash
196+
npm login
197+
cd widget && pnpm build && npm publish --access public
198+
```
199+
200+
(`--provenance` is omitted for the local manual publish; it requires the OIDC
201+
token only available in CI.) Every release after that publishes automatically.
202+
176203
Two conventions follow from that:
177204

178205
- **Milestones are themes, not version numbers.** Issues are grouped into

README.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
# Claudius - Embeddable AI Chat Widget
22

3+
[![npm](https://img.shields.io/npm/v/claudius-chat-widget.svg)](https://www.npmjs.com/package/claudius-chat-widget)
4+
[![license](https://img.shields.io/npm/l/claudius-chat-widget.svg)](LICENSE)
5+
36
An open-source, embeddable AI chat widget powered by Claude. Drop it into any
4-
website with a single script tag.
7+
website with a single script tag, or install it as a React component.
58

69
**Full documentation: [claudius-docs.pages.dev](https://claudius-docs.pages.dev)**
710

@@ -50,6 +53,28 @@ Add before `</body>`:
5053

5154
The `@1` CDN channel auto-updates within v1.x. That's it.
5255

56+
### 3. Or install as a React component
57+
58+
Building a React app? Install from npm instead of the script embed:
59+
60+
```bash
61+
npm install claudius-chat-widget react react-dom
62+
```
63+
64+
```tsx
65+
import { ChatWidget } from "claudius-chat-widget";
66+
import "claudius-chat-widget/style.css";
67+
68+
<ChatWidget
69+
apiUrl="https://claudius-chat-worker.<you>.workers.dev"
70+
title="Support"
71+
/>;
72+
```
73+
74+
The package ships dual ESM/CJS builds with TypeScript types. See the
75+
[documentation](https://claudius-docs.pages.dev) for theming, localization, and
76+
SSR notes.
77+
5378
## Documentation
5479

5580
| Section | What's there |

widget/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 PMDevSolutions
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

widget/README.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# claudius-chat-widget
2+
3+
[![npm](https://img.shields.io/npm/v/claudius-chat-widget.svg)](https://www.npmjs.com/package/claudius-chat-widget)
4+
[![license](https://img.shields.io/npm/l/claudius-chat-widget.svg)](https://github.com/PMDevSolutions/Claudius/blob/main/LICENSE)
5+
6+
Embeddable AI chat widget powered by Claude. Drop it into any React app as a
7+
component, or use the standalone script embed on any website.
8+
9+
**Full documentation: [claudius-docs.pages.dev](https://claudius-docs.pages.dev)**
10+
11+
> Claudius is two pieces: a **Cloudflare Worker** that keeps your Anthropic API
12+
> key server-side, and this **widget**. You point the widget at your deployed
13+
> worker via `apiUrl`. See the
14+
> [worker setup guide](https://claudius-docs.pages.dev/deployment/worker/) to
15+
> stand up the backend first.
16+
17+
## Install
18+
19+
```bash
20+
npm install claudius-chat-widget react react-dom
21+
```
22+
23+
`react` and `react-dom` (v18 or v19) are peer dependencies — install them
24+
alongside the widget.
25+
26+
## Usage
27+
28+
```tsx
29+
import { ChatWidget } from "claudius-chat-widget";
30+
import "claudius-chat-widget/style.css";
31+
32+
export function App() {
33+
return (
34+
<ChatWidget
35+
apiUrl="https://claudius-chat-worker.<you>.workers.dev"
36+
title="Support"
37+
subtitle="Ask me anything"
38+
theme="auto"
39+
/>
40+
);
41+
}
42+
```
43+
44+
Import the stylesheet **once** anywhere in your app (it ships separately so
45+
bundlers can tree-shake the component when unused).
46+
47+
### Common props
48+
49+
| Prop | Type | Required | Description |
50+
| ---------- | -------------------- | -------- | -------------------------------------------- |
51+
| `apiUrl` | `string` | Yes | URL of your deployed Claudius worker. |
52+
| `title` | `string` | No | Header title shown in the chat window. |
53+
| `subtitle` | `string` | No | Header subtitle / tagline. |
54+
| `theme` | `ClaudiusThemeInput` | No | `"auto"`, a built-in theme name, or a custom token object. |
55+
| `position` | `WidgetPosition` | No | Corner the launcher docks to. |
56+
57+
The full prop set is exported as the `ChatWidgetProps` type. See the
58+
[configuration docs](https://claudius-docs.pages.dev/configuration/widget/) for
59+
triggers, localization, and theming.
60+
61+
## Exports
62+
63+
- `claudius-chat-widget` — the `ChatWidget` component plus theming, i18n, and the
64+
typed `ChatApiClient`. Ships dual **ESM** (`import`) and **CommonJS**
65+
(`require`) builds with TypeScript declarations.
66+
- `claudius-chat-widget/style.css` — the widget stylesheet.
67+
- `claudius-chat-widget/embed` — the prebuilt IIFE bundle for `<script>` usage.
68+
69+
## Standalone script embed (no build step)
70+
71+
Prefer a single `<script>` tag? Use the CDN channel instead of npm:
72+
73+
```html
74+
<script>
75+
window.ClaudiusConfig = {
76+
apiUrl: "https://claudius-chat-worker.<you>.workers.dev",
77+
title: "Support",
78+
};
79+
</script>
80+
<link
81+
rel="stylesheet"
82+
href="https://cdn.jsdelivr.net/gh/PMDevSolutions/Claudius@1/cdn/claudius.css"
83+
/>
84+
<script src="https://cdn.jsdelivr.net/gh/PMDevSolutions/Claudius@1/cdn/claudius.iife.js"></script>
85+
```
86+
87+
## License
88+
89+
MIT © PMDevSolutions. See [LICENSE](./LICENSE).

widget/package.json

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,55 @@
11
{
22
"name": "claudius-chat-widget",
33
"version": "1.5.0",
4-
"private": true,
54
"type": "module",
6-
"main": "dist/claudius.js",
7-
"module": "dist/claudius.js",
8-
"types": "dist/index.d.ts",
5+
"description": "Embeddable AI chat widget powered by Claude. Drop-in React component or standalone script embed, backed by a Cloudflare Worker.",
6+
"keywords": [
7+
"react",
8+
"chat-widget",
9+
"ai-chat",
10+
"claude",
11+
"anthropic",
12+
"cloudflare-workers",
13+
"embeddable-widget",
14+
"customer-support",
15+
"typescript"
16+
],
17+
"author": "PAMulligan",
18+
"license": "MIT",
19+
"homepage": "https://claudius-docs.pages.dev",
20+
"repository": {
21+
"type": "git",
22+
"url": "git+https://github.com/PMDevSolutions/Claudius.git",
23+
"directory": "widget"
24+
},
25+
"bugs": {
26+
"url": "https://github.com/PMDevSolutions/Claudius/issues"
27+
},
28+
"sideEffects": [
29+
"**/*.css"
30+
],
31+
"main": "./dist/claudius.cjs",
32+
"module": "./dist/claudius.js",
33+
"types": "./dist/index.d.ts",
934
"exports": {
1035
".": {
1136
"types": "./dist/index.d.ts",
12-
"import": "./dist/claudius.js"
37+
"import": "./dist/claudius.js",
38+
"require": "./dist/claudius.cjs"
1339
},
1440
"./embed": "./dist/claudius.iife.js",
1541
"./style.css": "./dist/claudius.css"
1642
},
1743
"files": [
1844
"dist"
1945
],
46+
"publishConfig": {
47+
"access": "public"
48+
},
2049
"scripts": {
2150
"dev": "vite",
22-
"build": "tsc --emitDeclarationOnly && vite build && vite build --config vite.config.embed.ts",
23-
"build:lib": "tsc --emitDeclarationOnly && vite build",
51+
"build": "vite build && vite build --config vite.config.embed.ts && tsc --emitDeclarationOnly",
52+
"build:lib": "vite build && tsc --emitDeclarationOnly",
2453
"build:embed": "vite build --config vite.config.embed.ts",
2554
"test": "vitest run",
2655
"test:watch": "vitest",
@@ -40,10 +69,6 @@
4069
"react": "^18.0.0 || ^19.0.0",
4170
"react-dom": "^18.0.0 || ^19.0.0"
4271
},
43-
"dependencies": {
44-
"react": "^18.3.0",
45-
"react-dom": "^18.3.0"
46-
},
4772
"devDependencies": {
4873
"@eslint/js": "^9.24.0",
4974
"@playwright/test": "^1.59.1",
@@ -65,6 +90,8 @@
6590
"jsdom": "^26.0.0",
6691
"postcss": "^8.5.0",
6792
"prettier": "^3.5.0",
93+
"react": "^18.3.0",
94+
"react-dom": "^18.3.0",
6895
"storybook": "10.4.1",
6996
"tailwindcss": "^3.4.0",
7097
"typescript": "^5.8.0",

0 commit comments

Comments
 (0)