kreftjs 0.0.7-beta → 0.0.9-beta

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.
Files changed (92) hide show
  1. package/README.md +5 -31
  2. package/bin/artisan-more.js +2 -0
  3. package/bin/artisan.js +51 -49
  4. package/bin/backend/config.js +2 -2
  5. package/bin/backend/http.js +5 -5
  6. package/bin/backend/index.js +2 -2
  7. package/bin/backend/mcp.js +3 -5
  8. package/bin/backend/migrator.js +1 -3
  9. package/bin/backend/query.js +1 -1
  10. package/bin/backend/queue.js +8 -9
  11. package/bin/backend/redis.js +1 -1
  12. package/bin/backend/typescript.js +1 -1
  13. package/bin/build.js +22 -18
  14. package/bin/db-api.js +2 -2
  15. package/bin/db.js +4 -4
  16. package/bin/deps.js +1 -1
  17. package/bin/electron.js +3 -5
  18. package/bin/kreftjs-config.js +1 -6
  19. package/bin/kreftjs.js +34 -35
  20. package/bin/layout.js +1 -1
  21. package/bin/no-auth.js +18 -18
  22. package/bin/prerender.js +1 -1
  23. package/bin/ssr.js +3 -3
  24. package/bin/update.js +10 -10
  25. package/docs/{Docs.kreftjs → Docs.kreft} +1 -1
  26. package/docs/README.md +89 -102
  27. package/editors/vscode/README.md +3 -3
  28. package/editors/vscode/package.json +3 -4
  29. package/editors/vscode/snippets/kreftjs.json +2 -2
  30. package/kreftjs.d.ts +15 -27
  31. package/kreftjs.js +69 -79
  32. package/package.json +4 -4
  33. package/templates/app/README.md +10 -10
  34. package/templates/app/_env.example +2 -2
  35. package/templates/app/_vscode/settings.json +3 -2
  36. package/templates/app/backend/app/Http/Controllers/Admin/DashboardController.js +2 -2
  37. package/templates/app/backend/app/Http/Controllers/Admin/UserController.js +1 -1
  38. package/templates/app/backend/app/Http/Controllers/Auth/ApiTokenController.js +1 -1
  39. package/templates/app/backend/app/Http/Controllers/Auth/AuthenticatedSessionController.js +1 -1
  40. package/templates/app/backend/app/Http/Controllers/Auth/ConfirmablePasswordController.js +1 -1
  41. package/templates/app/backend/app/Http/Controllers/Auth/EmailVerificationController.js +1 -1
  42. package/templates/app/backend/app/Http/Controllers/Auth/NewPasswordController.js +1 -1
  43. package/templates/app/backend/app/Http/Controllers/Auth/PasswordResetLinkController.js +1 -1
  44. package/templates/app/backend/app/Http/Controllers/Auth/RegisteredUserController.js +1 -1
  45. package/templates/app/backend/app/Http/Controllers/Auth/SessionController.js +1 -1
  46. package/templates/app/backend/app/Http/Controllers/Auth/TwoFactorController.js +1 -1
  47. package/templates/app/backend/app/Http/Controllers/ProfileController.js +1 -1
  48. package/templates/app/backend/app/Http/Middleware/RequirePassword.js +1 -1
  49. package/templates/app/frontend/{App.kreftjs → App.kreft} +1 -1
  50. package/templates/app/frontend/components/profile/{ApiTokens.kreftjs → ApiTokens.kreft} +1 -1
  51. package/templates/app/frontend/components/profile/{Sessions.kreftjs → Sessions.kreft} +1 -1
  52. package/templates/app/frontend/components/profile/{TwoFactor.kreftjs → TwoFactor.kreft} +1 -1
  53. package/templates/app/frontend/errors/{ErrorMonitor.kreftjs → ErrorMonitor.kreft} +3 -3
  54. package/templates/app/frontend/index.html +8 -8
  55. package/templates/app/frontend/kreftjs.d.ts +15 -27
  56. package/templates/app/frontend/kreftjs.js +69 -79
  57. package/templates/app/frontend/layouts/{docs.kreftjs → docs.kreft} +1 -1
  58. package/templates/app/frontend/pages/{Dashboard.kreftjs → Dashboard.kreft} +1 -1
  59. package/templates/app/frontend/pages/{ErrorMonitor.kreftjs → ErrorMonitor.kreft} +2 -2
  60. package/templates/app/frontend/pages/{Home.kreftjs → Home.kreft} +2 -2
  61. package/templates/app/frontend/pages/{Profile.kreftjs → Profile.kreft} +3 -3
  62. package/templates/app/frontend/routes/web.kreft +34 -0
  63. package/templates/app/frontend/tests/components/{Counter.kreftjs → Counter.kreft} +1 -1
  64. package/templates/app/frontend/tests/pages/About.kreft +12 -0
  65. package/templates/app/frontend/tests/pages/{Test.kreftjs → Test.kreft} +1 -1
  66. package/templates/errors/{401.kreftjs → 401.kreft} +2 -2
  67. package/templates/errors/{402.kreftjs → 402.kreft} +2 -2
  68. package/templates/errors/{403.kreftjs → 403.kreft} +2 -2
  69. package/templates/errors/{404.kreftjs → 404.kreft} +2 -2
  70. package/templates/errors/{419.kreftjs → 419.kreft} +2 -2
  71. package/templates/errors/{429.kreftjs → 429.kreft} +2 -2
  72. package/templates/errors/{500.kreftjs → 500.kreft} +2 -2
  73. package/templates/errors/{503.kreftjs → 503.kreft} +2 -2
  74. package/templates/errors/{ErrorMonitor.kreftjs → ErrorMonitor.kreft} +13 -12
  75. package/templates/errors/{error.kreftjs → error.kreft} +2 -2
  76. package/templates/errors/{minimal.kreftjs → minimal.kreft} +1 -1
  77. package/tools/dev-client.js +2 -2
  78. package/tools/vite-plugin-kreftjs.d.ts +3 -5
  79. package/tools/vite-plugin-kreftjs.js +12 -14
  80. package/templates/app/frontend/routes/web.kreftjs +0 -34
  81. package/templates/app/frontend/tests/pages/About.kreftjs +0 -12
  82. /package/templates/app/frontend/components/{Field.kreftjs → Field.kreft} +0 -0
  83. /package/templates/app/frontend/components/{StatCard.kreftjs → StatCard.kreft} +0 -0
  84. /package/templates/app/frontend/layouts/{app.kreftjs → app.kreft} +0 -0
  85. /package/templates/app/frontend/layouts/{guest.kreftjs → guest.kreft} +0 -0
  86. /package/templates/app/frontend/pages/{Users.kreftjs → Users.kreft} +0 -0
  87. /package/templates/app/frontend/pages/auth/{ConfirmPassword.kreftjs → ConfirmPassword.kreft} +0 -0
  88. /package/templates/app/frontend/pages/auth/{ForgotPassword.kreftjs → ForgotPassword.kreft} +0 -0
  89. /package/templates/app/frontend/pages/auth/{Login.kreftjs → Login.kreft} +0 -0
  90. /package/templates/app/frontend/pages/auth/{Register.kreftjs → Register.kreft} +0 -0
  91. /package/templates/app/frontend/pages/auth/{ResetPassword.kreftjs → ResetPassword.kreft} +0 -0
  92. /package/templates/app/frontend/pages/auth/{VerifyEmail.kreftjs → VerifyEmail.kreft} +0 -0
package/bin/update.js CHANGED
@@ -31,7 +31,7 @@ module.exports = function update(args = []) {
31
31
  const a = args[i];
32
32
  if (a === '--latest' || a === '-L') flags.add('latest');
33
33
  else if (a === '--check' || a === '--dry-run') flags.add('check');
34
- else if (a === '--core' || a === '--kreft' || a === '--som') flags.add('core'); // --som: the Som.js name
34
+ else if (a === '--core' || a === '--kreft') flags.add('core');
35
35
  else if (a === '--npm') flags.add('npm');
36
36
  else if (a === '--help' || a === '-h') {
37
37
  printHelp();
@@ -74,16 +74,16 @@ function updateRuntimeFiles(lay, project) {
74
74
  const targets = [];
75
75
 
76
76
  // Check frontend / local kreftjs.js
77
- // an older project has kreft.js / som.js (and the .d.ts): those files keep their names (index.html loads them) but get the new code
77
+ // an older project has kreft.js (and the .d.ts): those files keep their names (index.html loads them) but get the new code
78
78
  const named = (dir, name, ...legacy) => (!fs.existsSync(path.join(dir, name)) ? legacy.find((l) => fs.existsSync(path.join(dir, l))) || name : name);
79
- const frontKreftJs = path.join(lay.frontend, named(lay.frontend, 'kreftjs.js', 'kreft.js', 'som.js'));
80
- const rootKreftJs = path.join(project, named(project, 'kreftjs.js', 'kreft.js', 'som.js'));
79
+ const frontKreftJs = path.join(lay.frontend, named(lay.frontend, 'kreftjs.js', 'kreft.js'));
80
+ const rootKreftJs = path.join(project, named(project, 'kreftjs.js', 'kreft.js'));
81
81
  if (fs.existsSync(frontKreftJs) && frontKreftJs !== sourceKreftJs) targets.push({ src: sourceKreftJs, dest: frontKreftJs, label: 'frontend/' + path.basename(frontKreftJs) });
82
82
  else if (fs.existsSync(rootKreftJs) && rootKreftJs !== sourceKreftJs) targets.push({ src: sourceKreftJs, dest: rootKreftJs, label: path.basename(rootKreftJs) });
83
83
 
84
84
  // Check frontend / local kreftjs.d.ts
85
- const frontKreftDts = path.join(lay.frontend, named(lay.frontend, 'kreftjs.d.ts', 'kreft.d.ts', 'som.d.ts'));
86
- const rootKreftDts = path.join(project, named(project, 'kreftjs.d.ts', 'kreft.d.ts', 'som.d.ts'));
85
+ const frontKreftDts = path.join(lay.frontend, named(lay.frontend, 'kreftjs.d.ts', 'kreft.d.ts'));
86
+ const rootKreftDts = path.join(project, named(project, 'kreftjs.d.ts', 'kreft.d.ts'));
87
87
  if (fs.existsSync(frontKreftDts) && frontKreftDts !== sourceKreftDts) targets.push({ src: sourceKreftDts, dest: frontKreftDts, label: 'frontend/' + path.basename(frontKreftDts) });
88
88
  else if (fs.existsSync(rootKreftDts) && rootKreftDts !== sourceKreftDts) targets.push({ src: sourceKreftDts, dest: rootKreftDts, label: path.basename(rootKreftDts) });
89
89
 
@@ -134,8 +134,8 @@ function updateRuntimeFiles(lay, project) {
134
134
  }
135
135
 
136
136
  function upgradeAppLayout(lay) {
137
- let layoutFile = path.join(lay.frontend, 'layouts', 'app.kreftjs');
138
- if (!fs.existsSync(layoutFile)) layoutFile = ['app.kreft', 'app.som'].map((n) => path.join(lay.frontend, 'layouts', n)).find((p) => fs.existsSync(p)) || layoutFile; // older projects
137
+ let layoutFile = path.join(lay.frontend, 'layouts', 'app.kreft');
138
+ if (!fs.existsSync(layoutFile)) layoutFile = ['app.kreftjs'].map((n) => path.join(lay.frontend, 'layouts', n)).find((p) => fs.existsSync(p)) || layoutFile; // older projects
139
139
  if (!fs.existsSync(layoutFile)) return;
140
140
  let text = fs.readFileSync(layoutFile, 'utf8');
141
141
  let changed = false;
@@ -162,9 +162,9 @@ function upgradeAppLayout(lay) {
162
162
  if (changed) {
163
163
  try {
164
164
  fs.writeFileSync(layoutFile, text);
165
- console.log(` ${green('DONE')} frontend/layouts/app.kreftjs ${dim('(upgraded sidebar navigation to route names)')}`);
165
+ console.log(` ${green('DONE')} frontend/layouts/app.kreft ${dim('(upgraded sidebar navigation to route names)')}`);
166
166
  } catch (err) {
167
- console.error(` ${red('FAIL')} frontend/layouts/app.kreftjs: ${err.message}`);
167
+ console.error(` ${red('FAIL')} frontend/layouts/app.kreft: ${err.message}`);
168
168
  }
169
169
  }
170
170
  }
@@ -1,4 +1,4 @@
1
- <!-- Kreft documentation viewer (docs/Docs.kreftjs)
1
+ <!-- Kreft documentation viewer (docs/Docs.kreft)
2
2
  Reads docs/README.md, shows it as a manual: parts and chapters on the left, the page in the middle,
3
3
  "On this page" on the right. It sits under the site header, so it uses the site's colours (ui.css),
4
4
  including the light/dark switch. Keys: ⌘K or / search · [ and ] previous / next chapter · Esc closes. -->
package/docs/README.md CHANGED
@@ -2,10 +2,10 @@
2
2
 
3
3
  ## Introduction
4
4
 
5
- Kreft is a small reactive framework with its own component language. You write a component in a `.kreftjs` file: declare your state, derived values and actions in plain words, then describe the page in a `<view>`. The framework also ships a full Node.js backend (routes, controllers, models, migrations, queues, mail) so one project can cover the whole stack.
5
+ Kreft is a small reactive framework with its own component language. You write a component in a `.kreft` file: declare your state, derived values and actions in plain words, then describe the page in a `<view>`. The framework also ships a full Node.js backend (routes, controllers, models, migrations, queues, mail) so one project can cover the whole stack.
6
6
 
7
7
  ```html
8
- <!-- Counter.kreftjs -->
8
+ <!-- Counter.kreft -->
9
9
  state count = 0
10
10
  derive double = count * 2
11
11
  action add() { count++ }
@@ -19,7 +19,7 @@ action add() { count++ }
19
19
 
20
20
  | Part | What it gives you |
21
21
  |---|---|
22
- | **The `.kreftjs` language** | `state`, `derive`, `action`, `watch`, props, events, slots, stores, a router with layouts and nested routes, forms with validation, animations. |
22
+ | **The `.kreft` language** | `state`, `derive`, `action`, `watch`, props, events, slots, stores, a router with layouts and nested routes, forms with validation, animations. |
23
23
  | **The backend** | `Route`, controllers, an Active Record `Model`, migrations, seeders, factories, jobs, mail, cache, file storage, policies, scheduling. |
24
24
  | **Authentication** | Sign-in pages, password reset, email verification, two-factor codes, device sessions and API tokens, ready in every new project (leave them out with `--no-auth`). |
25
25
  | **Tooling** | `kreft dev` with hot reload that keeps state, DevTools, an error monitor, `kreft build`, TypeScript, Vite and Electron support. |
@@ -82,7 +82,7 @@ npx kreftjs dev
82
82
  ### Check that it works
83
83
 
84
84
  ```bash
85
- kreft --version # for example 0.0.7-beta
85
+ kreft --version # for example 0.0.9-beta
86
86
  kreft about # Kreft and Node.js versions, this project's settings and drivers
87
87
  kreft list # every command your version has
88
88
  ```
@@ -95,7 +95,7 @@ kreft list # every command your version has
95
95
  kreft vscode
96
96
  ```
97
97
 
98
- installs colors and snippets for `.kreftjs` files in VS Code (also Cursor and VSCodium). Restart the editor afterwards.
98
+ installs colors and snippets for `.kreft` files in VS Code (also Cursor and VSCodium). Restart the editor afterwards.
99
99
 
100
100
  ### Update
101
101
 
@@ -131,21 +131,6 @@ Run `npm link` inside the Kreft folder. The `kreft` command then runs that folde
131
131
 
132
132
  Next: [Your first app](#your-first-app).
133
133
 
134
- ### Migrating from Som.js
135
-
136
- Kreft is Som.js under a new name (the package and command are `kreftjs`), and an existing project keeps working without edits. `kreft`, an earlier spelling of the new name, is accepted in the same places:
137
-
138
- - **Files:** `.som` (and `.kreft`) files still compile, next to `.kreftjs` ones. A name that is missing with one extension is tried with the others. Everything the tools write is `.kreftjs`.
139
- - **Templates:** `s-if`, `s-each` and every other `s-` directive are read as `k-if`, `k-each` …, and `<som-view>`, `<som-link>` … as `<kreft-view>`, `<kreft-link>` …
140
- - **JavaScript:** `Som` and `Kreft` are other names for `Kreftjs` (same object; `Som` is deprecated), and `Som.compileSom` is `Kreftjs.compile`.
141
- - **Command:** use `kreft` (or `kreftjs`). Kreft does not install a `som` command, so it can be installed next to an old Som.js without an `EEXIST` error; remove the old one with `npm rm -g somjs`.
142
- - **Server code:** `require('somjs/server')` (also `som/server`, `@somjs/server`, `kreft/server`) still works; new code uses `require('kreftjs/server')`.
143
- - **Settings:** `kreft.config.json`, `som.config.json` and `SOM_` environment variables (`SOM_SSR`, `SOM_ALLOWED_HOSTS` …) are read when the `kreftjs.config.json` file or the `KREFT_` variable is missing.
144
- - **Cookies:** new projects use `kreft_session`, `kreft_2fa` and `kreft_bypass`. An existing project keeps its `som_` names until you change `app/Auth/Session.js`, and the framework's CSRF check accepts both.
145
- - **Kept on purpose:** the `som_migrations` table, the `som:` prefix of saved data in `localStorage`, and the `som:` Redis keys of the queue. Renaming them needs a migration, planned for 3.1.
146
-
147
- To move a project over, rename `*.som` (or `*.kreft`) to `*.kreftjs` (and the paths that mention them), run `kreft update` and replace `s-` with `k-`.
148
-
149
134
  ## Your first app
150
135
 
151
136
  Create a project, move into it and start the development server:
@@ -186,19 +171,19 @@ The new project already has a working login page. `npm run dev` creates the tabl
186
171
 
187
172
  ### The smallest possible app
188
173
 
189
- You can use Kreft without any project at all. An app is an HTML page plus `.kreftjs` files:
174
+ You can use Kreft without any project at all. An app is an HTML page plus `.kreft` files:
190
175
 
191
176
  ```html
192
177
  <!-- index.html -->
193
178
  <div id="app"></div>
194
179
  <script src="kreftjs.js"></script>
195
180
  <script>
196
- Kreftjs.app('App.kreftjs').mount('#app')
181
+ Kreftjs.app('App.kreft').mount('#app')
197
182
  </script>
198
183
  ```
199
184
 
200
185
  ```html
201
- <!-- App.kreftjs -->
186
+ <!-- App.kreft -->
202
187
  state name = 'World'
203
188
 
204
189
  <view>
@@ -208,7 +193,7 @@ state name = 'World'
208
193
  ```
209
194
 
210
195
  > [!WARNING]
211
- > `.kreftjs` files need a web server. Browsers refuse to load files from `file://`, so always open your app through `npm run dev` or any other server.
196
+ > `.kreft` files need a web server. Browsers refuse to load files from `file://`, so always open your app through `npm run dev` or any other server.
212
197
 
213
198
  ## Project structure
214
199
 
@@ -218,10 +203,10 @@ state name = 'World'
218
203
  my-app/
219
204
  ├── frontend/
220
205
  │ ├── index.html entry point
221
- │ ├── App.kreftjs root component and router container
222
- │ ├── routes/web.kreftjs page routes
223
- │ ├── layouts/ app.kreftjs (signed in), guest.kreftjs (sign-in pages)
224
- │ ├── pages/ one .kreftjs file per screen, auth/ for sign-in pages
206
+ │ ├── App.kreft root component and router container
207
+ │ ├── routes/web.kreft page routes
208
+ │ ├── layouts/ app.kreft (signed in), guest.kreft (sign-in pages)
209
+ │ ├── pages/ one .kreft file per screen, auth/ for sign-in pages
225
210
  │ ├── components/ reusable pieces
226
211
  │ ├── ui.css the design system
227
212
  │ └── tests/ component tests
@@ -246,16 +231,16 @@ my-app/
246
231
 
247
232
  ### Adding a CSS library
248
233
 
249
- Any CSS library works. Add its `<link>` to `index.html`, or install it and import the file from a `.kreftjs` file; it becomes a `<link>` added once, and `kreft build` copies it (with its fonts and images) into `dist/vendor/`.
234
+ Any CSS library works. Add its `<link>` to `index.html`, or install it and import the file from a `.kreft` file; it becomes a `<link>` added once, and `kreft build` copies it (with its fonts and images) into `dist/vendor/`.
250
235
 
251
236
  ```html
252
237
  import 'bootstrap/dist/css/bootstrap.min.css' // npm i bootstrap
253
- import './theme.css' // your own file, next to this .kreftjs file
238
+ import './theme.css' // your own file, next to this .kreft file
254
239
  ```
255
240
 
256
241
  ### npm packages in the browser
257
242
 
258
- Install a package with `kreft add`, then import it in any `.kreftjs` file:
243
+ Install a package with `kreft add`, then import it in any `.kreft` file:
259
244
 
260
245
  ```bash
261
246
  kreft add dayjs nanoid lodash
@@ -277,9 +262,9 @@ state id = nanoid()
277
262
 
278
263
  # The Kreft language
279
264
 
280
- ## Components and the .kreftjs file
265
+ ## Components and the .kreft file
281
266
 
282
- A `.kreftjs` file has three parts:
267
+ A `.kreft` file has three parts:
283
268
 
284
269
  1. **The script**: everything outside `<view>` and `<style>`. Each line starts with a keyword.
285
270
  2. **`<view>`**: the HTML of the component.
@@ -299,7 +284,7 @@ A `.kreftjs` file has three parts:
299
284
  | `event` | `event save, remove` | Events this component sends to its parent with `send('save', data)`. |
300
285
  | `use` | `use cart` | Use a shared store. `use mouse = trackMouse()` uses shared logic from a `.js` file. |
301
286
  | `share` / `receive` | `share theme = 'dark'` | Give a value to everything inside this component / take a value a parent shared. |
302
- | `import` | `import Card from './Card.kreftjs'` | Use another component or a JavaScript module. |
287
+ | `import` | `import Card from './Card.kreft'` | Use another component or a JavaScript module. |
303
288
  | `saved` | `saved todos = []` | Like `state`, but kept in the browser (localStorage). |
304
289
  | `load` | `load users = api.get('/api/users')` | Loads data and gives `users.data`, `users.loading`, `users.error`, `users.reload()`. |
305
290
 
@@ -308,7 +293,7 @@ Inside the script you use names **directly**: write `count++`, not `this.count++
308
293
  ### A complete example
309
294
 
310
295
  ```html
311
- <!-- TodoPage.kreftjs -->
296
+ <!-- TodoPage.kreft -->
312
297
  state todos = []
313
298
  state text = ''
314
299
 
@@ -344,7 +329,7 @@ when todos.length && remaining === 0 {
344
329
  - An `action` that uses `await` becomes async automatically.
345
330
  - A line that does not start with a keyword is normal JavaScript (`let timer`, `const max = 10`). Your actions can use it, but the view cannot. Use `state`, `derive` or `action` for anything the view needs.
346
331
  - Every Kreft function is available in the script: `bus`, `store`, `signal`, `watch`, `tick`, `send`, `props`, `$route`, `$router`.
347
- - Errors name the file and line, for example `"state" needs a name, like: state count = 0 (Bad.kreftjs, line 3)`.
332
+ - Errors name the file and line, for example `"state" needs a name, like: state count = 0 (Bad.kreft, line 3)`.
348
333
 
349
334
  ### Lifecycle
350
335
 
@@ -497,13 +482,13 @@ app.directive('focus', {
497
482
  Register it once by its path, or import it where you need it:
498
483
 
499
484
  ```js
500
- Kreftjs.app('App.kreftjs')
501
- .component('UserCard', 'components/UserCard.kreftjs')
485
+ Kreftjs.app('App.kreft')
486
+ .component('UserCard', 'components/UserCard.kreft')
502
487
  .mount('#app')
503
488
  ```
504
489
 
505
490
  ```html
506
- import UserCard from './UserCard.kreftjs'
491
+ import UserCard from './UserCard.kreft'
507
492
 
508
493
  <view>
509
494
  <user-card name="Alice Smith" age={30}></user-card>
@@ -515,7 +500,7 @@ In the view, write component names in **kebab-case** (`<user-card>`).
515
500
  ### Props: parent to child
516
501
 
517
502
  ```html
518
- <!-- UserCard.kreftjs -->
503
+ <!-- UserCard.kreft -->
519
504
  prop name
520
505
  prop age = 0
521
506
  prop admin = false
@@ -534,7 +519,7 @@ The default's type decides how plain text attributes are read: `age="30"` become
534
519
  ### Events: child to parent
535
520
 
536
521
  ```html
537
- <!-- TodoItem.kreftjs -->
522
+ <!-- TodoItem.kreft -->
538
523
  prop todo
539
524
  event remove
540
525
 
@@ -555,7 +540,7 @@ action removeTodo(id) { todos = todos.filter((t) => t.id !== id) }
555
540
  ### `k-model` on a component
556
541
 
557
542
  ```html
558
- <!-- Toggle.kreftjs -->
543
+ <!-- Toggle.kreft -->
559
544
  prop modelValue = false
560
545
  event update:modelValue
561
546
 
@@ -573,7 +558,7 @@ Named models: `k-model:title="pageTitle"` uses `prop title` and the event `updat
573
558
  ### Slots
574
559
 
575
560
  ```html
576
- <!-- Card.kreftjs -->
561
+ <!-- Card.kreft -->
577
562
  prop items = []
578
563
 
579
564
  <view>
@@ -648,7 +633,7 @@ Kreftjs.store('cart', {
648
633
  })
649
634
  ```
650
635
 
651
- Use it in any `.kreftjs` file. Every component sees the same data:
636
+ Use it in any `.kreft` file. Every component sees the same data:
652
637
 
653
638
  ```html
654
639
  use cart
@@ -686,7 +671,7 @@ use mouse = trackMouse()
686
671
  ### Share and receive
687
672
 
688
673
  ```html
689
- <!-- Layout.kreftjs -->
674
+ <!-- Layout.kreft -->
690
675
  state settings = { theme: 'dark', lang: 'so' }
691
676
  share settings = settings
692
677
 
@@ -722,7 +707,7 @@ saved token = '' as 'auth.token' <!-- choose the storage key yourself -->
722
707
  ```
723
708
 
724
709
  - Every change is saved by itself, including deep ones: `todos.push(…)`, `todo.done = true`.
725
- - The default key is `<Component>.<name>` (stored as `som:Home.todos`). Use `as '…'` to share one value between components.
710
+ - The default key is `<Component>.<name>`, for example `Home.todos`. Use `as '…'` to share one value between components.
726
711
  - A change made in another tab of the same site shows up in this tab too.
727
712
 
728
713
  A store keeps its plain values when you add `saved`:
@@ -751,20 +736,20 @@ Kreftjs.storage.clear() // removes only what Kreft save
751
736
  ```js
752
737
  const router = Kreftjs.router({
753
738
  routes: [
754
- { path: '/', component: 'pages/Home.kreftjs', meta: { title: 'Home' } },
755
- { path: '/users/:id', name: 'user', component: 'pages/User.kreftjs', props: true },
756
- { path: '/posts/:slug?', component: 'pages/Posts.kreftjs' },
739
+ { path: '/', component: 'pages/Home.kreft', meta: { title: 'Home' } },
740
+ { path: '/users/:id', name: 'user', component: 'pages/User.kreft', props: true },
741
+ { path: '/posts/:slug?', component: 'pages/Posts.kreft' },
757
742
  { path: '/old', redirect: '/' },
758
- { path: '/admin', component: 'pages/Admin.kreftjs', guard: () => isAdmin() || '/login' },
759
- { path: '*', component: 'pages/NotFound.kreftjs' },
743
+ { path: '/admin', component: 'pages/Admin.kreft', guard: () => isAdmin() || '/login' },
744
+ { path: '*', component: 'pages/NotFound.kreft' },
760
745
  ],
761
746
  })
762
747
 
763
- Kreftjs.app('App.kreftjs').use(router).mount('#app')
748
+ Kreftjs.app('App.kreft').use(router).mount('#app')
764
749
  ```
765
750
 
766
751
  ```html
767
- <!-- App.kreftjs -->
752
+ <!-- App.kreft -->
768
753
  <view>
769
754
  <nav>
770
755
  <kreft-link to="/">Home</kreft-link>
@@ -777,7 +762,7 @@ Kreftjs.app('App.kreftjs').use(router).mount('#app')
777
762
  With `props: true`, the `:id` parameter arrives as a prop:
778
763
 
779
764
  ```html
780
- <!-- pages/User.kreftjs -->
765
+ <!-- pages/User.kreft -->
781
766
  prop id
782
767
  derive user = users.find(id)
783
768
  action back() { $router.back() }
@@ -797,11 +782,11 @@ Each page file is loaded the first time someone opens it.
797
782
 
798
783
  ### Route files
799
784
 
800
- New projects keep their pages in `frontend/routes/web.kreftjs`, and `index.html` only points to it:
785
+ New projects keep their pages in `frontend/routes/web.kreft`, and `index.html` only points to it:
801
786
 
802
787
  ```js
803
788
  Kreftjs.router({
804
- routes: ['routes/web.kreftjs', 'routes/shop.kreftjs'],
789
+ routes: ['routes/web.kreft', 'routes/shop.kreft'],
805
790
  layout: 'app',
806
791
  errors: 'errors',
807
792
  middleware: {
@@ -812,27 +797,27 @@ Kreftjs.router({
812
797
  ```
813
798
 
814
799
  ```js
815
- // routes/web.kreftjs
816
- Route.view('/', 'pages/Home.kreftjs').name('home').title('Home')
817
- Route.view('/posts/:id', 'pages/Post.kreftjs')
800
+ // routes/web.kreft
801
+ Route.view('/', 'pages/Home.kreft').name('home').title('Home')
802
+ Route.view('/posts/:id', 'pages/Post.kreft')
818
803
 
819
804
  Route.middleware('auth').group(() => {
820
- Route.view('/dashboard', 'pages/Dashboard.kreftjs').middleware('verified')
805
+ Route.view('/dashboard', 'pages/Dashboard.kreft').middleware('verified')
821
806
  })
822
807
 
823
808
  Route.layout('guest').middleware('guest').group(() => {
824
- Route.view('/login', 'pages/auth/Login.kreftjs').title('Log in')
809
+ Route.view('/login', 'pages/auth/Login.kreft').title('Log in')
825
810
  })
826
811
 
827
812
  Route.prefix('/account').name('account.').middleware('auth').group(() => {
828
- Route.view('/settings', 'pages/account/Settings.kreftjs').children(() => {
829
- Route.view('', 'pages/account/General.kreftjs') // /account/settings
830
- Route.view('mail', 'pages/account/Mail.kreftjs') // /account/settings/mail
813
+ Route.view('/settings', 'pages/account/Settings.kreft').children(() => {
814
+ Route.view('', 'pages/account/General.kreft') // /account/settings
815
+ Route.view('mail', 'pages/account/Mail.kreft') // /account/settings/mail
831
816
  })
832
817
  })
833
818
 
834
819
  Route.redirect('/home', '/')
835
- Route.fallback('pages/NotFound.kreftjs')
820
+ Route.fallback('pages/NotFound.kreft')
836
821
  ```
837
822
 
838
823
  | On a route | What it does |
@@ -852,7 +837,7 @@ Route.fallback('pages/NotFound.kreftjs')
852
837
  A layout is the frame around your pages: bar, menu, footer. Put it in `layouts/` and use `<slot>` where the page goes.
853
838
 
854
839
  ```html
855
- <!-- layouts/app.kreftjs -->
840
+ <!-- layouts/app.kreft -->
856
841
  state menuOpen = false
857
842
 
858
843
  <view>
@@ -887,12 +872,12 @@ A page can also fill other places in its layout:
887
872
  Each HTTP error can have its own page in `errors/`. Turn them on with `errors: 'errors'` in the router. New projects already have the folder (`kreft make:errors` adds it to an older one):
888
873
 
889
874
  ```text
890
- errors/401.kreftjs 402.kreftjs 403.kreftjs 404.kreftjs 419.kreftjs 429.kreftjs 500.kreftjs 503.kreftjs
891
- errors/error.kreftjs any other status
892
- errors/minimal.kreftjs the shared frame
875
+ errors/401.kreft 402.kreft 403.kreft 404.kreft 419.kreft 429.kreft 500.kreft 503.kreft
876
+ errors/error.kreft any other status
877
+ errors/minimal.kreft the shared frame
893
878
  ```
894
879
 
895
- An unknown address shows `errors/404.kreftjs`; a page that cannot load shows `errors/500.kreftjs`. From any `.kreftjs` file, `abort(404)` (also `$router.abort()` and `Kreftjs.abort()`) shows the matching page:
880
+ An unknown address shows `errors/404.kreft`; a page that cannot load shows `errors/500.kreft`. From any `.kreft` file, `abort(404)` (also `$router.abort()` and `Kreftjs.abort()`) shows the matching page:
896
881
 
897
882
  ```html
898
883
  prop id
@@ -911,7 +896,7 @@ If you cannot change the server, use `mode: 'hash'`; URLs then look like `/#/use
911
896
 
912
897
  ## Fetching data
913
898
 
914
- The global `api` client is available in every `.kreftjs` file, and `Kreftjs.api` in plain JavaScript:
899
+ The global `api` client is available in every `.kreft` file, and `Kreftjs.api` in plain JavaScript:
915
900
 
916
901
  ```js
917
902
  const users = await api.get('/api/users', { query: { page: 2 } })
@@ -926,7 +911,7 @@ await api.delete('/api/users/1')
926
911
  `load` declares a reactive resource. It handles the loading state, the error, and fetches again when the values it reads change:
927
912
 
928
913
  ```html
929
- <!-- pages/Posts.kreftjs -->
914
+ <!-- pages/Posts.kreft -->
930
915
  state query = ''
931
916
  state page = 1
932
917
 
@@ -1112,7 +1097,7 @@ On the server, request language comes from `?lang=`, the `lang` cookie or `Accep
1112
1097
 
1113
1098
  ## Using Kreft from JavaScript
1114
1099
 
1115
- You can write components as plain objects. The rules match the `.kreftjs` language: values are state, getters are derived values, functions are actions.
1100
+ You can write components as plain objects. The rules match the `.kreft` language: values are state, getters are derived values, functions are actions.
1116
1101
 
1117
1102
  ```js
1118
1103
  Kreftjs.app({
@@ -1123,7 +1108,7 @@ Kreftjs.app({
1123
1108
  }).mount('#app')
1124
1109
  ```
1125
1110
 
1126
- | JavaScript | Same as in `.kreftjs` |
1111
+ | JavaScript | Same as in `.kreft` |
1127
1112
  |---|---|
1128
1113
  | `Kreftjs.state({ … })` | `state` + `derive` + `action` together, for code outside components. |
1129
1114
  | `Kreftjs.signal(0)` | One value, read and written with `.value`. |
@@ -1141,7 +1126,7 @@ Kreftjs.render(`<ul><li k-each="u in users">{u}</li></ul>`, { users: ['Alex', 'A
1141
1126
 
1142
1127
  ### Server templates
1143
1128
 
1144
- Blade and similar engines use `{{ }}`; Kreft uses `{ }`, so they do not clash. Put `kreftjs.js` and your `.kreftjs` files in your public folder and mount as usual.
1129
+ Blade and similar engines use `{{ }}`; Kreft uses `{ }`, so they do not clash. Put `kreftjs.js` and your `.kreft` files in your public folder and mount as usual.
1145
1130
 
1146
1131
  # Backend
1147
1132
 
@@ -1397,13 +1382,13 @@ New projects come with every sign-in screen and the backend behind it:
1397
1382
 
1398
1383
  | Page | Address | What it does |
1399
1384
  |---|---|---|
1400
- | `pages/auth/Login.kreftjs` | `/login` | Log in with email and password. |
1401
- | `pages/auth/Register.kreftjs` | `/register` | Make an account and get an email to verify the address. |
1402
- | `pages/auth/ForgotPassword.kreftjs` | `/forgot-password` | Email a link to choose a new password. |
1403
- | `pages/auth/ResetPassword.kreftjs` | `/reset-password/:token` | The link from that email. |
1404
- | `pages/auth/VerifyEmail.kreftjs` | `/verify-email` | "Check your email", and the link from it opens `/verify-email/:id/:hash`. |
1405
- | `pages/auth/ConfirmPassword.kreftjs` | `/confirm-password` | Type the password again before something serious. |
1406
- | `pages/Dashboard.kreftjs`, `pages/Profile.kreftjs` | `/dashboard`, `/profile` | The first page after logging in; account settings. |
1385
+ | `pages/auth/Login.kreft` | `/login` | Log in with email and password. |
1386
+ | `pages/auth/Register.kreft` | `/register` | Make an account and get an email to verify the address. |
1387
+ | `pages/auth/ForgotPassword.kreft` | `/forgot-password` | Email a link to choose a new password. |
1388
+ | `pages/auth/ResetPassword.kreft` | `/reset-password/:token` | The link from that email. |
1389
+ | `pages/auth/VerifyEmail.kreft` | `/verify-email` | "Check your email", and the link from it opens `/verify-email/:id/:hash`. |
1390
+ | `pages/auth/ConfirmPassword.kreft` | `/confirm-password` | Type the password again before something serious. |
1391
+ | `pages/Dashboard.kreft`, `pages/Profile.kreft` | `/dashboard`, `/profile` | The first page after logging in; account settings. |
1407
1392
 
1408
1393
  ### How a login works
1409
1394
 
@@ -1649,7 +1634,7 @@ Run `kreft list` to see every command your installed version has, and `kreft hel
1649
1634
  | `kreft add <package>` | A safer `npm install`. See [Packages](#packages). |
1650
1635
  | `kreft about`, `kreft env`, `kreft log`, `kreft tinker` | Versions and folders, environment, logs, a console with your models (`await User.count()`). |
1651
1636
  | `kreft down --secret=x` / `kreft up` | Maintenance mode: visitors get `503`, and `/x` lets you in. |
1652
- | `kreft vscode` | Installs colors, snippets and folding for `.kreftjs` files in VS Code, Cursor and VSCodium. |
1637
+ | `kreft vscode` | Installs colors, snippets and folding for `.kreft` files in VS Code, Cursor and VSCodium. |
1653
1638
 
1654
1639
  ### Generators and database
1655
1640
 
@@ -1675,7 +1660,7 @@ Run `kreft list` to see every command your installed version has, and `kreft hel
1675
1660
 
1676
1661
  Everything here comes with Kreft. Nothing else to install.
1677
1662
 
1678
- **Hot reload.** While `kreft dev` runs, save a `.kreftjs` file and only that component is swapped; its state stays. A `.css` file is reloaded without a page refresh, and an error shows an overlay with the file and line.
1663
+ **Hot reload.** While `kreft dev` runs, save a `.kreft` file and only that component is swapped; its state stays. A `.css` file is reloaded without a page refresh, and an error shows an overlay with the file and line.
1679
1664
 
1680
1665
  **Kreft DevTools.** The **S** button in the corner (or <kbd>Alt</kbd>+<kbd>Shift</kbd>+<kbd>D</kbd>) opens a panel:
1681
1666
 
@@ -1702,10 +1687,10 @@ In development, an uncaught error on the server shows an interactive page instea
1702
1687
 
1703
1688
  The page is only shown when `APP_ENV` is not `production` and `APP_DEBUG` is true. **In production the same error answers a plain `Server error.`** with no stack or file names.
1704
1689
 
1705
- Frontend errors use the same design through `errors/ErrorMonitor.kreftjs`; pass it a caught exception:
1690
+ Frontend errors use the same design through `errors/ErrorMonitor.kreft`; pass it a caught exception:
1706
1691
 
1707
1692
  ```html
1708
- import ErrorMonitor from 'errors/ErrorMonitor.kreftjs'
1693
+ import ErrorMonitor from 'errors/ErrorMonitor.kreft'
1709
1694
  state caught = null
1710
1695
 
1711
1696
  <view>
@@ -1726,16 +1711,16 @@ npm run preview # check the result: kreft dev dist
1726
1711
  |---|---|
1727
1712
  | `index.html` | Your page, now loading the files below. |
1728
1713
  | `kreftjs.js` | The framework. |
1729
- | `app.js` | Every `.kreftjs` file, already compiled. |
1714
+ | `app.js` | Every `.kreft` file, already compiled. |
1730
1715
  | `app.css` | All `<style>` blocks; scoped ones already scoped. |
1731
1716
  | `main.js` | The inline `<script>` code from `index.html`. |
1732
- | `deps/`, `vendor/` | The npm packages and CSS your `.kreftjs` files import, minified. |
1717
+ | `deps/`, `vendor/` | The npm packages and CSS your `.kreft` files import, minified. |
1733
1718
 
1734
1719
  What you get:
1735
1720
 
1736
1721
  - **A faster first load.** The browser downloads one `app.js` and compiles nothing.
1737
1722
  - **A strict Content-Security-Policy works.** Every expression becomes a real function, so the built app never uses `eval` or `new Function`.
1738
- - **Errors before you deploy.** A mistake in any `.kreftjs` file stops the build and names the file and line.
1723
+ - **Errors before you deploy.** A mistake in any `.kreft` file stops the build and names the file and line.
1739
1724
 
1740
1725
  Options: `kreft build ./site --out public` builds another folder, and `--base /` changes `<base href>`. `--no-htaccess` skips the `.htaccess` file described below.
1741
1726
 
@@ -1751,10 +1736,12 @@ RewriteBase /
1751
1736
  RewriteRule ^index\.html$ - [L]
1752
1737
  RewriteCond %{REQUEST_FILENAME} !-f
1753
1738
  RewriteCond %{REQUEST_FILENAME} !-d
1739
+ RewriteCond %{REQUEST_URI} !^/api/
1740
+ RewriteCond %{REQUEST_URI} !\.[A-Za-z0-9]+$
1754
1741
  RewriteRule . /index.html [L]
1755
1742
  ```
1756
1743
 
1757
- Apache only knows the files on disk, so without these rules `/docs` or any other clean address gives a 404 when someone opens or reloads it. With them, every address that is not a real file or folder opens `index.html` and the router takes over. Upload the file too (it starts with a dot, so some file managers hide it; turn on "show hidden files"). If the site lives in a folder, build with `--base /folder/` and the rules follow it. An `.htaccess` you keep in `public/` is used as it is. A relative base (`--base ./`, used by the desktop build) gets no file.
1744
+ Apache only knows the files on disk, so without these rules `/docs` or any other clean address gives a 404 when someone opens or reloads it. With them, every page address (no file extension, not under `/api/`) that is not a real file or folder opens `index.html` and the router takes over. A missing file such as `app.js`, or an `/api/` address, stays a plain 404, so code that asks for data never receives the page's HTML. Upload the file too (it starts with a dot, so some file managers hide it; turn on "show hidden files"). If the site lives in a folder, build with `--base /folder/` and the rules follow it. An `.htaccess` you keep in `public/` is used as it is. A relative base (`--base ./`, used by the desktop build) gets no file.
1758
1745
 
1759
1746
  > [!NOTE]
1760
1747
  > This hosts the front end only. Login, the database and everything under `/api` need the Node.js server, which Apache does not run.
@@ -1828,7 +1815,7 @@ module.exports = {
1828
1815
 
1829
1816
  ### Whole pages for crawlers
1830
1817
 
1831
- A crawler or link preview (Googlebot, Bingbot, WhatsApp, Facebook, X, Slack, Telegram …) that doesn't run JavaScript would see an empty `<div id="app">`. For these visitors `kreft dev` and `kreft serve` open the page in the same simulated browser as `--prerender`, wait until its data has loaded, and answer with the page already drawn. If the app shows its `errors/404.kreftjs` page, the answer has status 404. A page that `kreft build --prerender` already drew is sent as it is. Everyone else gets the normal page.
1818
+ A crawler or link preview (Googlebot, Bingbot, WhatsApp, Facebook, X, Slack, Telegram …) that doesn't run JavaScript would see an empty `<div id="app">`. For these visitors `kreft dev` and `kreft serve` open the page in the same simulated browser as `--prerender`, wait until its data has loaded, and answer with the page already drawn. If the app shows its `errors/404.kreft` page, the answer has status 404. A page that `kreft build --prerender` already drew is sent as it is. Everyone else gets the normal page.
1832
1819
 
1833
1820
  ```bash
1834
1821
  npm i -D jsdom # once per project
@@ -1847,7 +1834,7 @@ kreft sitemap --url https://example.com # public/sitemap.xml an
1847
1834
  kreft sitemap --url https://example.com --urls urls.js # and the addresses in that file
1848
1835
  ```
1849
1836
 
1850
- It lists the routes of `Kreftjs.router({ routes })` in `index.html` and `routes/web.kreftjs`, skipping redirects and patterns like `/posts/:id`, plus the `urls` of `backend/routes/seo.js` and `--urls`. A `lastmod` is written only when you give one (a database date such as `2026-01-02 10:00:00` becomes `2026-01-02`). A route can list `alternates: { en: '/about', ar: '/ar/about' }` for `xhtml:link` entries.
1837
+ It lists the routes of `Kreftjs.router({ routes })` in `index.html` and `routes/web.kreft`, skipping redirects and patterns like `/posts/:id`, plus the `urls` of `backend/routes/seo.js` and `--urls`. A `lastmod` is written only when you give one (a database date such as `2026-01-02 10:00:00` becomes `2026-01-02`). A route can list `alternates: { en: '/about', ar: '/ar/about' }` for `xhtml:link` entries.
1851
1838
 
1852
1839
  ### Deploying the backend
1853
1840
 
@@ -1859,13 +1846,13 @@ Before you do, work through the [Production checklist](#production-checklist).
1859
1846
 
1860
1847
  ## TypeScript
1861
1848
 
1862
- TypeScript works in the browser (`.kreftjs` files and `.ts` modules) and on the server (`routes/api.ts`, `app/**/*.ts`, migrations, seeders).
1849
+ TypeScript works in the browser (`.kreft` files and `.ts` modules) and on the server (`routes/api.ts`, `app/**/*.ts`, migrations, seeders).
1863
1850
 
1864
1851
  ```bash
1865
1852
  kreft new my-app --ts
1866
1853
  ```
1867
1854
 
1868
- Inside a `.kreftjs` file you can write `interface`, `type`, `enum`, `import type`, and typed `prop`, `state`, `derive` and `saved`. `kreftjs make:*` writes `.ts` files when the project has a `tsconfig.json` (or with `--ts`; `--js` forces JavaScript).
1855
+ Inside a `.kreft` file you can write `interface`, `type`, `enum`, `import type`, and typed `prop`, `state`, `derive` and `saved`. `kreftjs make:*` writes `.ts` files when the project has a `tsconfig.json` (or with `--ts`; `--js` forces JavaScript).
1869
1856
 
1870
1857
  Execution needs no setup: Kreft uses `esbuild` if installed, otherwise Node's built-in type stripping (Node 22.6+), otherwise its own zero-dependency stripper.
1871
1858
 
@@ -1874,7 +1861,7 @@ Execution needs no setup: Kreft uses `esbuild` if installed, otherwise Node's bu
1874
1861
 
1875
1862
  ## Vite and Electron
1876
1863
 
1877
- **Vite.** If your team prefers the Vite ecosystem, Kreft has a plugin that compiles `.kreftjs` files on the fly:
1864
+ **Vite.** If your team prefers the Vite ecosystem, Kreft has a plugin that compiles `.kreft` files on the fly:
1878
1865
 
1879
1866
  ```bash
1880
1867
  kreft vite:init # writes vite.config.js with the Kreft plugin
@@ -1887,7 +1874,7 @@ kreft vite:preview
1887
1874
 
1888
1875
  ## Desktop apps with Electron
1889
1876
 
1890
- Kreft can package your app as a desktop application for Windows, macOS and Linux. The pages are the same `.kreftjs` files you already have; Electron only supplies the window.
1877
+ Kreft can package your app as a desktop application for Windows, macOS and Linux. The pages are the same `.kreft` files you already have; Electron only supplies the window.
1891
1878
 
1892
1879
  ### Quick start
1893
1880
 
@@ -2221,7 +2208,7 @@ Go through this before your first real user:
2221
2208
  - The memory of which two-factor codes were already used, and login tickets, is kept per process. Behind several servers, a code can be replayed once on each. The per-account lockout (kept in the cache) still limits guessing.
2222
2209
  - The sanitizer removes unsafe markup; it is not a substitute for choosing carefully what HTML you show.
2223
2210
  - `--prerender` makes static HTML at build time. On a running server whole pages are drawn only for crawlers and link previews; every other visitor gets the page drawn by the browser, and an address the app does not have answers 200 (the app shows its own 404 page) unless `seo.js` says otherwise.
2224
- - `.kreftjs` files must be served over `http://` or `https://`, not opened from `file://`.
2211
+ - `.kreft` files must be served over `http://` or `https://`, not opened from `file://`.
2225
2212
 
2226
2213
  # Reference
2227
2214
 
@@ -2284,7 +2271,7 @@ Set these in `.env` (never commit it). Variables that start with `PUBLIC_` are c
2284
2271
 
2285
2272
  | Group | Names |
2286
2273
  |---|---|
2287
- | `.kreftjs` keywords | `state` `derive` `action` `when` `watch` `on` `prop` `event` `use` `share` `receive` `import` `saved` `load` `layout` |
2274
+ | `.kreft` keywords | `state` `derive` `action` `when` `watch` `on` `prop` `event` `use` `share` `receive` `import` `saved` `load` `layout` |
2288
2275
  | In the script | `send` `props` `bus` `store` `$route` `$router` `tick` and every `Kreft` function |
2289
2276
  | In the view | `{expr}` `attr={expr}` `@event` `k-if` `k-elif` `k-else` `k-each` `k-key` `k-model` `k-show` `k-text` `k-html` `k-ref` `k-skip` `k-once` `k-memo` `k-animate` `{for}` |
2290
2277
  | App | `Kreftjs.app(rootOrPath)` then `.component()` `.directive()` `.share()` `.use()` `.mount()` `.unmount()` |
@@ -2305,7 +2292,7 @@ Kreft is one framework for the browser and the server. The others below each cov
2305
2292
  | | **Kreft** | **Next.js** | **Nuxt** | **Astro** | **AdonisJS** | **NestJS** |
2306
2293
  |---|---|---|---|---|---|---|
2307
2294
  | **What it is** | Frontend and backend in one | React framework | Vue framework | Content sites with islands of interactivity | Backend (MVC) | Backend (modules, dependency injection) |
2308
- | **Components** | `.kreftjs` files, no Virtual DOM | React | Vue | Astro files; React, Vue, Svelte … inside | none (Edge templates, or Inertia) | none |
2295
+ | **Components** | `.kreft` files, no Virtual DOM | React | Vue | Astro files; React, Vue, Svelte … inside | none (Edge templates, or Inertia) | none |
2309
2296
  | **Pages drawn on the server** | At build time (`--prerender`), and for crawlers and link previews on request | Yes, for every visitor | Yes, for every visitor | Yes, mostly at build time | Only with Inertia | no |
2310
2297
  | **Database layer** | Active Record `Model`, migrations, seeders, factories | none (use Prisma, Drizzle …) | none | none | Lucid (Active Record) | none (TypeORM, Prisma, MikroORM …) |
2311
2298
  | **Sign-in, 2FA, API tokens** | Built in, in every new project | none (Auth.js …) | none (a module) | none | Built in | none (Passport, your own) |
@@ -2324,13 +2311,13 @@ Kreft is one framework for the browser and the server. The others below each cov
2324
2311
  - **AdonisJS:** you want the same Laravel-like backend with a larger community and years of production use, and you will bring your own frontend.
2325
2312
  - **NestJS:** you build a large API or microservices with many teams, and you want strict structure and dependency injection.
2326
2313
 
2327
- **Things to weigh before choosing Kreft:** it is young and has one small community, few third-party packages are made for `.kreftjs` files, and nobody has run it at large scale yet. See [Known limits](#known-limits).
2314
+ **Things to weigh before choosing Kreft:** it is young and has one small community, few third-party packages are made for `.kreft` files, and nobody has run it at large scale yet. See [Known limits](#known-limits).
2328
2315
 
2329
2316
  ## Coming from Vue
2330
2317
 
2331
2318
  | Vue | Kreft |
2332
2319
  |---|---|
2333
- | `.vue` single-file component | `.kreftjs` file: script, `<view>`, `<style scoped>` |
2320
+ | `.vue` single-file component | `.kreft` file: script, `<view>`, `<style scoped>` |
2334
2321
  | `ref()`, `reactive()`, `computed()` | `state`, `derive` (JS: `Kreftjs.signal`, `Kreftjs.state`, `Kreftjs.derived`) |
2335
2322
  | `watch`, `watchEffect` | `watch x { }`, `when cond { }` (JS: `Kreftjs.watch`, `Kreftjs.effect`) |
2336
2323
  | `{{ x }}`, `:attr`, `@click` | `{x}`, `attr={x}`, `@click={fn}` |
@@ -2353,7 +2340,7 @@ Kreft is one framework for the browser and the server. The others below each cov
2353
2340
 
2354
2341
  | Term | Meaning |
2355
2342
  |---|---|
2356
- | **Component** | A `.kreftjs` file: script, view and style together. |
2343
+ | **Component** | A `.kreft` file: script, view and style together. |
2357
2344
  | **State** | A value that can change; the view follows it. |
2358
2345
  | **Derived value** | A value calculated from other values; stays up to date by itself. |
2359
2346
  | **Store** | State shared by many components. |