@ozsarman/clarityjs 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,178 @@
1
+ # Clarity.js
2
+
3
+ [![pipeline status](https://gitlab.com/ozsarman/clarity.js/badges/master/pipeline.svg)](https://gitlab.com/ozsarman/clarity.js/-/pipelines)
4
+
5
+ **An AI-native, permission-aware frontend framework and DSL.**
6
+ Components declare what AI agents may read, act on, and must never touch — directly in the markup.
7
+
8
+ > **Disclaimer:** Clarity.js is an AI-native frontend framework and DSL. It is **not** affiliated with, and is unrelated to, Microsoft Clarity (the web analytics product).
9
+
10
+ - Site & docs: **https://clarity-js.com**
11
+ - Source: **https://gitlab.com/ozsarman/clarity.js**
12
+
13
+ ---
14
+
15
+ ## The idea
16
+
17
+ Everyone is building AI agents. Almost nobody defines what those agents are allowed
18
+ to **see** or **change** inside a user interface. We have authentication,
19
+ authorization and RBAC for *people* — but almost no AI-specific access control for
20
+ *interfaces*.
21
+
22
+ Clarity.js makes that a first-class language feature. A component states its AI
23
+ permissions right where the UI is declared:
24
+
25
+ ```clarity
26
+ component Checkout() {
27
+ state email = ""
28
+ state total = 0
29
+ state paymentToken = ""
30
+
31
+ ai:readable [email, total] // agents may read these
32
+ ai:actionable [applyCoupon] // agents may call this
33
+ ai:forbidden [paymentToken] // agents must never touch this
34
+
35
+ action applyCoupon(code) { /* ... */ }
36
+
37
+ render {
38
+ <form>
39
+ <input bind:value={ email } />
40
+ <button on:click={ applyCoupon('SAVE10') }>Apply</button>
41
+ </form>
42
+ }
43
+ }
44
+ ```
45
+
46
+ The UI itself becomes the source of truth for what an agent may do — instead of
47
+ teaching every agent, per integration, what it can and cannot touch. Every agent
48
+ interaction flows through an **audited contract** (`readable` · `snapshot` · `act` ·
49
+ `forbidden`) with a timestamped log.
50
+
51
+ This is the part of Clarity.js worth caring about. The signals, router and SSR are
52
+ solid table stakes; the **AI permission model is the differentiator**. There are
53
+ hundreds of frontend frameworks — but almost none that govern AI agents&#39; access at
54
+ the component level.
55
+
56
+ ---
57
+
58
+ ## Status — building in public
59
+
60
+ Clarity.js is an **early, experimental framework**: a strong, well-tested foundation,
61
+ **not yet production-hardened**. What exists today:
62
+
63
+ - A real compiler pipeline — `.clarity` DSL → lexer → parser → codegen → lean JS
64
+ - Signal-based, fine-grained reactivity — **no virtual DOM**, ~11.5 KB runtime
65
+ - AI directives with **enforced `ai:forbidden`** — reads/writes blocked in agent
66
+ context, typed errors and an audit trail (not just a declaration)
67
+ - A full-stack toolkit (routing, SSR/SSG, forms, i18n, testing, devtools…)
68
+ - 234 passing tests, and a docs site built with the framework itself
69
+
70
+ What is still ahead (tracked in [PRODUCTION_ROADMAP.md](PRODUCTION_ROADMAP.md)):
71
+ broader security hardening (XSS/CSP/CSRF), benchmarks, npm publishing, release
72
+ automation and wider coverage. Honest framing: this is research-grade and evolving fast.
73
+
74
+ ---
75
+
76
+ ## Quick start
77
+
78
+ ```bash
79
+ npm create clarity@latest my-app
80
+ cd my-app
81
+ npm install
82
+ npm run dev
83
+ ```
84
+
85
+ Your first component:
86
+
87
+ ```clarity
88
+ component Counter() {
89
+ state count = 0
90
+
91
+ render {
92
+ <button on:click={ count++ }>Clicked { count } times</button>
93
+ }
94
+ }
95
+ ```
96
+
97
+ `count++` writes to a signal; only the text node that reads `count` updates — there
98
+ is no component re-render and no virtual DOM.
99
+
100
+ ---
101
+
102
+ ## The AI contract
103
+
104
+ The `ai:` directives compile into an audited contract attached to each component, so
105
+ an agent interacts through one guarded surface:
106
+
107
+ ```js
108
+ const contract = el.__clarity_ai__
109
+
110
+ contract.snapshot() // audited read of all `ai:readable` state
111
+ contract.read('email') // audited single read — throws for non-readable fields
112
+ contract.act('applyCoupon', '…') // guarded, logged action call
113
+ contract.forbidden // ['paymentToken'] — off-limits
114
+
115
+ import { getAIAuditLog } from '@ozsarman/clarityjs'
116
+ getAIAuditLog() // full timestamped trail of every interaction
117
+ ```
118
+
119
+ `ai:forbidden` is **enforced, not just declared**. Forbidden fields are excluded from
120
+ `readable` / `snapshot` / `read`, and the underlying signal blocks **both reads and
121
+ writes** from inside any agent `act()` call — throwing a typed `ClarityAIForbiddenError`
122
+ and recording an audit entry. An agent cannot read, alias, or return a forbidden field
123
+ through the contract:
124
+
125
+ ```js
126
+ import { ClarityAIForbiddenError } from '@ozsarman/clarityjs'
127
+ try { contract.read('paymentToken') } // ✗ throws ClarityAIForbiddenError (audited)
128
+ catch (e) { e instanceof ClarityAIForbiddenError } // true
129
+ ```
130
+
131
+ Normal user/app code is completely unaffected — the guard fires only inside AI-action
132
+ context. This is the boundary that turns the idea into a working AI security layer.
133
+
134
+ ---
135
+
136
+ ## What is in the box
137
+
138
+ Beyond the reactive core and the AI layer, Clarity ships a full-stack toolkit — use
139
+ only what you need:
140
+
141
+ - **File-based routing** — `pages/` with dynamic `[slug]` routes, code-split (`scanPages`)
142
+ - **Server rendering** — SSR, SSG, ISR, islands; `useServerData()` for component-level data
143
+ - **Server actions** — `<form action={serverAction}>`, Express + edge adapters
144
+ - **Async state** — `createQuery` / `useFetch` / `createMutation` (SWR/TanStack-style)
145
+ - **Styling** — scoped CSS and CSS Modules (compile-time, no runtime CSS-in-JS)
146
+ - **Tooling** — `create-clarity`, `eslint-plugin-clarity` (9 rules), test utilities,
147
+ in-browser devtools, a VS Code extension and language server
148
+
149
+ A small `createGameLoop()` helper also powers the DOM games on the
150
+ [showcase](https://clarity-js.com) — Clarity is a UI framework, not a game engine,
151
+ but its reactivity drives more than forms.
152
+
153
+ ---
154
+
155
+ ## Documentation
156
+
157
+ Full guides and an API reference live at **https://clarity-js.com** (itself built
158
+ with Clarity.js). See also [CHANGES.md](CHANGES.md), [ROADMAP.md](ROADMAP.md) and
159
+ [GAP_ANALYSIS.md](GAP_ANALYSIS.md).
160
+
161
+ ---
162
+
163
+ ## Contributing
164
+
165
+ This is an open-source project, built in public. Issues, ideas and pull requests are
166
+ welcome at https://gitlab.com/ozsarman/clarity.js. Run `npm test` before submitting —
167
+ all 228 tests should stay green.
168
+
169
+ ---
170
+
171
+ ## License
172
+
173
+ MIT
174
+
175
+ ---
176
+
177
+ *Created by Özdemir Şarman. Built in public, with heavy use of AI tooling — fittingly,
178
+ for a framework about humans and AI agents sharing the same UI.*
package/package.json ADDED
@@ -0,0 +1,168 @@
1
+ {
2
+ "name": "@ozsarman/clarityjs",
3
+ "version": "0.6.0",
4
+ "description": "An AI-native, permission-aware frontend framework and DSL — components declare what AI agents may read, act on, and never touch.",
5
+ "type": "module",
6
+ "main": "./src/index.js",
7
+ "module": "./src/index.js",
8
+ "types": "./types/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./src/index.js",
12
+ "default": "./src/index.js"
13
+ },
14
+ "./runtime": {
15
+ "import": "./src/runtime.js",
16
+ "default": "./src/runtime.js"
17
+ },
18
+ "./hydrate": {
19
+ "import": "./src/hydrate.js",
20
+ "default": "./src/hydrate.js"
21
+ },
22
+ "./ssr": {
23
+ "import": "./src/ssr.js",
24
+ "default": "./src/ssr.js"
25
+ },
26
+ "./vite": {
27
+ "import": "./src/vite-plugin.js",
28
+ "default": "./src/vite-plugin.js"
29
+ },
30
+ "./router": {
31
+ "import": "./src/router.js",
32
+ "default": "./src/router.js"
33
+ },
34
+ "./test": {
35
+ "import": "./src/clarity-test.js",
36
+ "default": "./src/clarity-test.js"
37
+ },
38
+ "./bundle": {
39
+ "import": "./src/clarity-bundle.js",
40
+ "default": "./src/clarity-bundle.js"
41
+ },
42
+ "./async-state": {
43
+ "import": "./src/async-state.js",
44
+ "default": "./src/async-state.js"
45
+ },
46
+ "./devtools": {
47
+ "import": "./src/devtools.js",
48
+ "default": "./src/devtools.js"
49
+ },
50
+ "./head": {
51
+ "import": "./src/head.js",
52
+ "default": "./src/head.js"
53
+ },
54
+ "./image": {
55
+ "import": "./src/image.js",
56
+ "default": "./src/image.js"
57
+ },
58
+ "./font": {
59
+ "import": "./src/font.js",
60
+ "default": "./src/font.js"
61
+ },
62
+ "./layout": {
63
+ "import": "./src/layout.js",
64
+ "default": "./src/layout.js"
65
+ },
66
+ "./linter": {
67
+ "import": "./src/linter.js",
68
+ "default": "./src/linter.js"
69
+ },
70
+ "./ssg": {
71
+ "import": "./src/ssg.js",
72
+ "default": "./src/ssg.js"
73
+ },
74
+ "./isr": {
75
+ "import": "./src/isr.js",
76
+ "default": "./src/isr.js"
77
+ },
78
+ "./islands": {
79
+ "import": "./src/islands.js",
80
+ "default": "./src/islands.js"
81
+ },
82
+ "./server-actions": {
83
+ "import": "./src/server-actions.js",
84
+ "default": "./src/server-actions.js"
85
+ },
86
+ "./edge": {
87
+ "import": "./src/edge.js",
88
+ "default": "./src/edge.js"
89
+ },
90
+ "./ts-plugin": {
91
+ "import": "./src/ts-plugin.js",
92
+ "default": "./src/ts-plugin.js"
93
+ },
94
+ "./file-conventions": {
95
+ "import": "./src/file-conventions.js",
96
+ "default": "./src/file-conventions.js"
97
+ },
98
+ "./pages-router": {
99
+ "import": "./src/pages-router.js",
100
+ "default": "./src/pages-router.js"
101
+ },
102
+ "./server-data": {
103
+ "import": "./src/server-data.js",
104
+ "default": "./src/server-data.js"
105
+ },
106
+ "./game-loop": {
107
+ "import": "./src/game-loop.js",
108
+ "default": "./src/game-loop.js"
109
+ },
110
+ "./error-overlay": {
111
+ "import": "./src/error-overlay.js",
112
+ "default": "./src/error-overlay.js"
113
+ },
114
+ "./analyze": {
115
+ "import": "./src/analyze.js",
116
+ "default": "./src/analyze.js"
117
+ },
118
+ "./i18n": {
119
+ "import": "./src/i18n.js",
120
+ "default": "./src/i18n.js"
121
+ }
122
+ },
123
+ "bin": {
124
+ "clarity": "src/cli.js"
125
+ },
126
+ "files": [
127
+ "src/",
128
+ "types/",
129
+ "README.md",
130
+ "LICENSE"
131
+ ],
132
+ "scripts": {
133
+ "test": "node --experimental-vm-modules tests/run.js",
134
+ "build:examples": "node src/cli.js build examples/",
135
+ "demo": "node src/cli.js demo",
136
+ "size": "npx esbuild src/runtime.js --bundle --format=esm --minify | wc -c | xargs -I{} sh -c 'echo \"Runtime minified: {} bytes ({KB} KB)\" | sed s/{KB}/$(echo \"scale=1; {} / 1024\" | bc)/'",
137
+ "size:full": "npx esbuild src/index.js --bundle --format=esm --minify --outfile=/tmp/clarity-full.min.js && echo \"Full bundle:\" && wc -c /tmp/clarity-full.min.js",
138
+ "prepublishOnly": "npm test",
139
+ "release:patch": "node scripts/release.js patch",
140
+ "release:minor": "node scripts/release.js minor",
141
+ "release:major": "node scripts/release.js major"
142
+ },
143
+ "keywords": [
144
+ "ai-native",
145
+ "ai-permissions",
146
+ "ai-agents",
147
+ "permission-aware",
148
+ "framework",
149
+ "frontend",
150
+ "signals",
151
+ "reactivity",
152
+ "compiler",
153
+ "dsl"
154
+ ],
155
+ "author": "Özdemir Şarman",
156
+ "license": "MIT",
157
+ "engines": {
158
+ "node": ">=18.0.0"
159
+ },
160
+ "repository": {
161
+ "type": "git",
162
+ "url": "https://gitlab.com/ozsarman/clarity.js.git"
163
+ },
164
+ "bugs": {
165
+ "url": "https://gitlab.com/ozsarman/clarity.js/-/issues"
166
+ },
167
+ "homepage": "https://clarity-js.com"
168
+ }