You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: rename core package webjs → @webjs/core for npm publish
The unscoped `webjs` name is already taken on npm (webjs@0.6.1, unrelated
project). Moving to the `@webjs` scope lets us publish `@webjs/core`,
`@webjs/server`, and `@webjs/cli` together.
* Package name: `webjs` → `@webjs/core`. CLI binary stays `webjs`.
* All imports migrated: `from 'webjs'` → `from '@webjs/core'`,
subpaths `'webjs/client-router'` → `'@webjs/core/client-router'`, etc.
* Import map + builtin set + dev server core resolver updated.
* publishConfig.access = public, files whitelist, repository,
homepage, bugs, license, keywords added to each published package.
* README.md added for @webjs/core, @webjs/server, @webjs/cli.
* Scaffolded template deps updated (webjs → @webjs/core).
* Test symlinks updated (node_modules/webjs → node_modules/@webjs/core).
* Docs, AGENTS.md, examples all rewritten to use the new specifier.
* Lockfile regenerated.
All 571 unit tests pass.
|`richFetch<T>(url, init?)`| Client-side fetch that adds `Accept: application/vnd.webjs+json`, encodes plain-object bodies via superjson, and decodes responses with rich types. |
321
321
322
-
### Directives — `import { … } from 'webjs/directives'`
322
+
### Directives — `import { … } from '@webjs/core/directives'`
323
323
324
324
webjs follows a **"less is more"** philosophy: only directives that solve
325
325
problems with NO native alternative are included. AI agents don't need
@@ -349,7 +349,7 @@ syntax sugar — they write code that works, not code that looks pretty.
349
349
| Async data in page |`async` page function (just `await`) |
350
350
| Lists without reorder |`${items.map(item => html\`…\`)}` |
351
351
352
-
### Context Protocol — `import { … } from 'webjs/context'`
352
+
### Context Protocol — `import { … } from '@webjs/core/context'`
353
353
354
354
Share data across deeply nested components without prop drilling.
355
355
@@ -362,7 +362,7 @@ Share data across deeply nested components without prop drilling.
362
362
363
363
**When to use Context (AI hint):** Use when data (theme, auth state, locale, config) must reach components many levels deep without threading it through every intermediate component's attributes. Do NOT use for data that changes on every render (use state for that) or for data that only one component needs (use a server action or prop).
- On the server these modules are imported normally; you can freely use Prisma, `fs`, environment variables, etc.
862
862
- **Expose as REST**: wrap any action with `expose('METHOD /path', fn)` to ALSO make it reachable at a stable REST URL. The same function body powers both callers:
When called over HTTP, the adapter merges `{ ...query, ...urlParams, ...jsonBody }` into a single object argument. This is the recommended way to surface a server action to external consumers — no `route.js` wrapper needed.
@@ -988,7 +988,7 @@ no client-side runtime, no diff from writing the classes by hand.
@@ -1060,7 +1060,7 @@ the class-prefix rule documented in the Shadow-vs-Light DOM section.
1060
1060
1061
1061
```js
1062
1062
// app/about/page.js
1063
-
import { html } from'webjs';
1063
+
import { html } from'@webjs/core';
1064
1064
exportdefaultfunctionAbout() {
1065
1065
returnhtml`<h1>About</h1><p>…</p>`;
1066
1066
}
@@ -1070,7 +1070,7 @@ export default function About() {
1070
1070
1071
1071
```js
1072
1072
// app/users/[id]/page.js
1073
-
import { html } from'webjs';
1073
+
import { html } from'@webjs/core';
1074
1074
exportdefaultasyncfunctionUser({ params }) {
1075
1075
// use a server action to fetch; never import a DB client directly in a page
1076
1076
constuser=awaitfetchUser(params.id);
@@ -1132,7 +1132,7 @@ if (!r.success) this.setState({ error: r.error });
1132
1132
1133
1133
```js
1134
1134
// components/hello-world.js
1135
-
import { WebComponent, html } from'webjs';
1135
+
import { WebComponent, html } from'@webjs/core';
1136
1136
exportclassHelloWorldextendsWebComponent {
1137
1137
render() { returnhtml`<p>Hello!</p>`; }
1138
1138
}
@@ -1305,7 +1305,7 @@ export async function GET() {
1305
1305
1306
1306
```ts
1307
1307
// caller — client side
1308
-
import { richFetch } from'webjs';
1308
+
import { richFetch } from'@webjs/core';
1309
1309
constposts=await richFetch<Post[]>('/api/posts');
1310
1310
// posts[0].createdAt is a Date here (richFetch sends
1311
1311
// Accept: application/vnd.webjs+json and superjson-parses the response).
@@ -1474,7 +1474,7 @@ and what stays in-memory.
1474
1474
### Streaming SSR / Suspense
1475
1475
1476
1476
```js
1477
-
import { html, Suspense } from'webjs';
1477
+
import { html, Suspense } from'@webjs/core';
1478
1478
1479
1479
exportdefaultfunctionPage() {
1480
1480
returnhtml`
@@ -1580,7 +1580,7 @@ then segment-scoped files.
1580
1580
1581
1581
### Client router — Turbo Drive-style navigation
1582
1582
1583
-
`import'webjs/client-router'` enables SPA-style navigation without full page reloads. Intercepts same-origin `<a>` clicks (including inside shadow DOM via `composedPath()`), fetches the target HTML, and swaps DOM content.
1583
+
`import'@webjs/core/client-router'` enables SPA-style navigation without full page reloads. Intercepts same-origin `<a>` clicks (including inside shadow DOM via `composedPath()`), fetches the target HTML, and swaps DOM content.
@@ -133,7 +133,7 @@ export async function POST(req: Request) {
133
133
134
134
<h2>richFetch() -- Typed Client Calls</h2>
135
135
<p>On the client side, <code>richFetch()</code> from <code>webjs</code> is a drop-in replacement for <code>fetch()</code> that enables the superjson round trip:</p>
<p><code>expose()</code> turns a server action into a typed REST endpoint. This is especially useful in backend-only mode because it lets you define your API logic as plain functions with validation, then expose them over HTTP:</p>
0 commit comments