tkeron 5.3.0 → 6.0.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 +17 -16
- package/bun.lock +13 -196
- package/changelog.md +37 -0
- package/examples/init_sample/websrc/api-service.ts +24 -24
- package/examples/init_sample/websrc/counter-card.com.html +5 -2
- package/examples/init_sample/websrc/hero-section.com.html +35 -5
- package/examples/init_sample/websrc/html-components-card.com.html +6 -2
- package/examples/init_sample/websrc/index.html +58 -25
- package/examples/init_sample/websrc/index.pre.ts +20 -15
- package/examples/init_sample/websrc/ts-components-card.com.html +7 -2
- package/index.ts +15 -0
- package/package.json +9 -13
- package/skills/tkeron/SKILL.md +286 -0
- package/skills/tkeron-components/SKILL.md +785 -0
- package/skills/tkeron-organization/SKILL.md +230 -0
- package/skills/tkeron-patterns/SKILL.md +495 -0
- package/skills/tkeron-testing/SKILL.md +194 -0
- package/skills/tkeron-troubleshooting/SKILL.md +259 -0
- package/src/build.ts +4 -6
- package/src/develop.ts +1 -2
- package/src/init.ts +1 -2
- package/src/skills.ts +139 -0
- package/src/skillsWrapper.ts +79 -0
- package/docs/mcp-server.md +0 -240
- package/mcp-server.ts +0 -272
- package/src/cleanupOrphanedTempDirs.ts +0 -31
- package/src/promptUser.ts +0 -15
- package/src/setupSigintHandler.ts +0 -6
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
box-sizing: border-box;
|
|
13
13
|
}
|
|
14
14
|
body {
|
|
15
|
-
font-family:
|
|
15
|
+
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
|
|
16
16
|
line-height: 1.6;
|
|
17
17
|
color: #1a1a1a;
|
|
18
18
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
backdrop-filter: blur(10px);
|
|
50
50
|
padding: 1.5rem;
|
|
51
51
|
border-radius: 12px;
|
|
52
|
-
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
|
52
|
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
53
53
|
grid-row: span 2;
|
|
54
54
|
}
|
|
55
55
|
.hero .features {
|
|
@@ -67,17 +67,22 @@
|
|
|
67
67
|
width: 200px;
|
|
68
68
|
height: 200px;
|
|
69
69
|
margin-bottom: 1rem;
|
|
70
|
-
filter: drop-shadow(0 4px 6px rgba(0,0,0,0.2));
|
|
70
|
+
filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.2));
|
|
71
71
|
animation: float 3s ease-in-out infinite;
|
|
72
72
|
}
|
|
73
73
|
@keyframes float {
|
|
74
|
-
0%,
|
|
75
|
-
|
|
74
|
+
0%,
|
|
75
|
+
100% {
|
|
76
|
+
transform: translateY(0);
|
|
77
|
+
}
|
|
78
|
+
50% {
|
|
79
|
+
transform: translateY(-10px);
|
|
80
|
+
}
|
|
76
81
|
}
|
|
77
82
|
h1 {
|
|
78
83
|
font-size: 2rem;
|
|
79
84
|
margin-bottom: 0.25rem;
|
|
80
|
-
text-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
|
85
|
+
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
|
81
86
|
}
|
|
82
87
|
.subtitle {
|
|
83
88
|
font-size: 0.9rem;
|
|
@@ -87,12 +92,14 @@
|
|
|
87
92
|
background: white;
|
|
88
93
|
padding: 1.25rem;
|
|
89
94
|
border-radius: 12px;
|
|
90
|
-
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
|
91
|
-
transition:
|
|
95
|
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
96
|
+
transition:
|
|
97
|
+
transform 0.2s,
|
|
98
|
+
box-shadow 0.2s;
|
|
92
99
|
}
|
|
93
100
|
section:hover {
|
|
94
101
|
transform: translateY(-4px);
|
|
95
|
-
box-shadow: 0 8px 12px rgba(0,0,0,0.15);
|
|
102
|
+
box-shadow: 0 8px 12px rgba(0, 0, 0, 0.15);
|
|
96
103
|
}
|
|
97
104
|
h2 {
|
|
98
105
|
color: #667eea;
|
|
@@ -118,12 +125,14 @@
|
|
|
118
125
|
cursor: pointer;
|
|
119
126
|
font-size: 1rem;
|
|
120
127
|
font-weight: 600;
|
|
121
|
-
transition:
|
|
122
|
-
|
|
128
|
+
transition:
|
|
129
|
+
transform 0.1s,
|
|
130
|
+
box-shadow 0.2s;
|
|
131
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
|
123
132
|
}
|
|
124
133
|
button:hover {
|
|
125
134
|
transform: scale(1.05);
|
|
126
|
-
box-shadow: 0 4px 8px rgba(0,0,0,0.3);
|
|
135
|
+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
|
|
127
136
|
}
|
|
128
137
|
button:active {
|
|
129
138
|
transform: scale(0.98);
|
|
@@ -141,18 +150,20 @@
|
|
|
141
150
|
background: #f0f0f0;
|
|
142
151
|
padding: 0.2rem 0.4rem;
|
|
143
152
|
border-radius: 4px;
|
|
144
|
-
font-family:
|
|
153
|
+
font-family: "Courier New", monospace;
|
|
145
154
|
font-size: 0.9em;
|
|
146
155
|
}
|
|
147
156
|
p {
|
|
148
157
|
margin-bottom: 0.5rem;
|
|
149
158
|
}
|
|
150
159
|
a {
|
|
151
|
-
transition:
|
|
160
|
+
transition:
|
|
161
|
+
transform 0.2s,
|
|
162
|
+
box-shadow 0.2s;
|
|
152
163
|
}
|
|
153
164
|
a:hover {
|
|
154
165
|
transform: translateY(-2px);
|
|
155
|
-
box-shadow: 0 4px 8px rgba(0,0,0,0.3);
|
|
166
|
+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
|
|
156
167
|
}
|
|
157
168
|
.crypto-prices-container {
|
|
158
169
|
display: grid;
|
|
@@ -165,7 +176,7 @@
|
|
|
165
176
|
padding: 1.25rem;
|
|
166
177
|
border-radius: 12px;
|
|
167
178
|
color: white;
|
|
168
|
-
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
|
179
|
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
169
180
|
transition: transform 0.2s;
|
|
170
181
|
}
|
|
171
182
|
.crypto-card:hover {
|
|
@@ -182,7 +193,7 @@
|
|
|
182
193
|
font-size: 1rem;
|
|
183
194
|
}
|
|
184
195
|
.crypto-symbol {
|
|
185
|
-
background: rgba(255,255,255,0.2);
|
|
196
|
+
background: rgba(255, 255, 255, 0.2);
|
|
186
197
|
padding: 0.25rem 0.5rem;
|
|
187
198
|
border-radius: 4px;
|
|
188
199
|
font-size: 0.75rem;
|
|
@@ -207,20 +218,42 @@
|
|
|
207
218
|
<html-components-card></html-components-card>
|
|
208
219
|
<ts-components-card></ts-components-card>
|
|
209
220
|
<counter-card></counter-card>
|
|
210
|
-
|
|
221
|
+
|
|
211
222
|
<!-- Crypto Prices - fetched at build time -->
|
|
212
|
-
<section style="grid-column: span 3
|
|
223
|
+
<section style="grid-column: span 3">
|
|
213
224
|
<h2>💰 Asset Prices (Build Time)</h2>
|
|
214
|
-
<p style="font-size: 0.85rem; margin-bottom: 0.75rem
|
|
225
|
+
<p style="font-size: 0.85rem; margin-bottom: 0.75rem">
|
|
226
|
+
Real cryptocurrency prices fetched from CoinGecko API at build time:
|
|
227
|
+
</p>
|
|
215
228
|
<div id="crypto-prices" class="crypto-prices-container"></div>
|
|
216
229
|
</section>
|
|
217
|
-
|
|
230
|
+
|
|
218
231
|
<!-- Pre-rendered content with external API data -->
|
|
219
|
-
<section style="grid-column: span 3
|
|
232
|
+
<section style="grid-column: span 3">
|
|
220
233
|
<h2>💬 Quote of the Build</h2>
|
|
221
|
-
<p style="font-size: 0.85rem; margin-bottom: 0.75rem
|
|
222
|
-
|
|
223
|
-
|
|
234
|
+
<p style="font-size: 0.85rem; margin-bottom: 0.75rem">
|
|
235
|
+
This content was fetched from an external API at build time:
|
|
236
|
+
</p>
|
|
237
|
+
<div
|
|
238
|
+
id="pre-rendered-quote"
|
|
239
|
+
style="
|
|
240
|
+
margin: 1rem 0;
|
|
241
|
+
padding: 0.75rem;
|
|
242
|
+
background: #f8f9fa;
|
|
243
|
+
border-radius: 8px;
|
|
244
|
+
border-left: 4px solid #667eea;
|
|
245
|
+
"
|
|
246
|
+
></div>
|
|
247
|
+
<div
|
|
248
|
+
id="build-metadata"
|
|
249
|
+
style="
|
|
250
|
+
margin-top: 1rem;
|
|
251
|
+
padding-top: 0.75rem;
|
|
252
|
+
border-top: 1px solid #eee;
|
|
253
|
+
font-size: 0.75rem;
|
|
254
|
+
color: #999;
|
|
255
|
+
"
|
|
256
|
+
></div>
|
|
224
257
|
</section>
|
|
225
258
|
</div>
|
|
226
259
|
</div>
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
// Pre-rendering - runs at build time
|
|
2
2
|
// Demonstrates importing any TypeScript module for pre-rendering
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
getRandomQuote,
|
|
5
|
+
getBuildMetadata,
|
|
6
|
+
getCryptoPrices,
|
|
7
|
+
} from "./api-service";
|
|
4
8
|
|
|
5
|
-
const buildTimeElement = document.getElementById(
|
|
9
|
+
const buildTimeElement = document.getElementById("build-time");
|
|
6
10
|
|
|
7
11
|
if (buildTimeElement) {
|
|
8
12
|
const now = new Date();
|
|
@@ -10,7 +14,7 @@ if (buildTimeElement) {
|
|
|
10
14
|
}
|
|
11
15
|
|
|
12
16
|
// Fetch data from external API at build time
|
|
13
|
-
const quoteElement = document.getElementById(
|
|
17
|
+
const quoteElement = document.getElementById("pre-rendered-quote");
|
|
14
18
|
if (quoteElement) {
|
|
15
19
|
const quote = await getRandomQuote();
|
|
16
20
|
quoteElement.innerHTML = `
|
|
@@ -22,7 +26,7 @@ if (quoteElement) {
|
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
// Add build metadata
|
|
25
|
-
const metadataElement = document.getElementById(
|
|
29
|
+
const metadataElement = document.getElementById("build-metadata");
|
|
26
30
|
if (metadataElement) {
|
|
27
31
|
const metadata = await getBuildMetadata();
|
|
28
32
|
metadataElement.innerHTML = `
|
|
@@ -38,15 +42,17 @@ if (metadataElement) {
|
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
// Fetch crypto prices at build time
|
|
41
|
-
const cryptoPricesElement = document.getElementById(
|
|
45
|
+
const cryptoPricesElement = document.getElementById("crypto-prices");
|
|
42
46
|
if (cryptoPricesElement) {
|
|
43
47
|
const prices = await getCryptoPrices();
|
|
44
|
-
|
|
45
|
-
const pricesHtml = prices
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
|
|
49
|
+
const pricesHtml = prices
|
|
50
|
+
.map((crypto) => {
|
|
51
|
+
const changeColor =
|
|
52
|
+
crypto.price_change_percentage_24h >= 0 ? "#10b981" : "#ef4444";
|
|
53
|
+
const changeSymbol = crypto.price_change_percentage_24h >= 0 ? "▲" : "▼";
|
|
54
|
+
|
|
55
|
+
return `
|
|
50
56
|
<div class="crypto-card">
|
|
51
57
|
<div class="crypto-header">
|
|
52
58
|
<span class="crypto-name">${crypto.name}</span>
|
|
@@ -58,9 +64,8 @@ if (cryptoPricesElement) {
|
|
|
58
64
|
</div>
|
|
59
65
|
</div>
|
|
60
66
|
`;
|
|
61
|
-
|
|
62
|
-
|
|
67
|
+
})
|
|
68
|
+
.join("");
|
|
69
|
+
|
|
63
70
|
cryptoPricesElement.innerHTML = pricesHtml;
|
|
64
71
|
}
|
|
65
|
-
|
|
66
|
-
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
<section>
|
|
2
2
|
<h2>⚡ TypeScript Components</h2>
|
|
3
|
-
<p style="margin-bottom: 0.75rem
|
|
3
|
+
<p style="margin-bottom: 0.75rem">
|
|
4
|
+
Dynamic generation with <code>.com.ts</code>:
|
|
5
|
+
</p>
|
|
4
6
|
<user-badge count="3"></user-badge>
|
|
5
|
-
<p style="font-size: 0.85rem; color: #666; margin-top: 0.75rem
|
|
7
|
+
<p style="font-size: 0.85rem; color: #666; margin-top: 0.75rem">
|
|
8
|
+
✓ Loops & conditionals<br />✓ Read attributes dynamically<br />✓ Build-time
|
|
9
|
+
code execution
|
|
10
|
+
</p>
|
|
6
11
|
</section>
|
package/index.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { getCommands } from "@tkeron/commands";
|
|
|
3
3
|
import { buildWrapper } from "./src/buildWrapper";
|
|
4
4
|
import { develop } from "./src/develop";
|
|
5
5
|
import { initWrapper } from "./src/initWrapper";
|
|
6
|
+
import { skillsWrapper } from "./src/skillsWrapper";
|
|
6
7
|
import { showBanner } from "./src/banner";
|
|
7
8
|
import packageJson from "./package.json";
|
|
8
9
|
|
|
@@ -36,5 +37,19 @@ getCommands("tkeron", packageJson.version)
|
|
|
36
37
|
.addOption("force")
|
|
37
38
|
.setCallback(initWrapper)
|
|
38
39
|
|
|
40
|
+
.commands()
|
|
41
|
+
|
|
42
|
+
.addCommand("skills")
|
|
43
|
+
.addDescription("Install AI agent skills into the current project")
|
|
44
|
+
.addPositionedArgument("target")
|
|
45
|
+
.addOption("force")
|
|
46
|
+
.addOption({
|
|
47
|
+
name: "dryRun",
|
|
48
|
+
aliases: ["dry-run"],
|
|
49
|
+
type: "boolean",
|
|
50
|
+
description: "Preview what would be installed without making changes",
|
|
51
|
+
})
|
|
52
|
+
.setCallback(skillsWrapper)
|
|
53
|
+
|
|
39
54
|
.commands()
|
|
40
55
|
.start();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tkeron",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "CLI build tool for vanilla web development with TypeScript.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -12,8 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"bin": {
|
|
14
14
|
"tkeron": "./index.ts",
|
|
15
|
-
"tk": "./index.ts"
|
|
16
|
-
"tkeron-mcp": "./mcp-server.ts"
|
|
15
|
+
"tk": "./index.ts"
|
|
17
16
|
},
|
|
18
17
|
"scripts": {
|
|
19
18
|
"tk": "bun index.ts ",
|
|
@@ -23,15 +22,14 @@
|
|
|
23
22
|
"author": "tkeron",
|
|
24
23
|
"license": "MIT",
|
|
25
24
|
"dependencies": {
|
|
26
|
-
"@
|
|
27
|
-
"@tkeron/
|
|
28
|
-
"@tkeron/
|
|
29
|
-
"@tkeron/tools": "^0.4.1"
|
|
25
|
+
"@tkeron/commands": "0.4.8",
|
|
26
|
+
"@tkeron/html-parser": "1.5.7",
|
|
27
|
+
"@tkeron/tools": "^0.5.0"
|
|
30
28
|
},
|
|
31
29
|
"devDependencies": {
|
|
32
|
-
"@types/bun": "^1.3.
|
|
33
|
-
"prettier": "^3.8.
|
|
34
|
-
"typescript": "^6.0.
|
|
30
|
+
"@types/bun": "^1.3.14",
|
|
31
|
+
"prettier": "^3.8.3",
|
|
32
|
+
"typescript": "^6.0.3"
|
|
35
33
|
},
|
|
36
34
|
"keywords": [
|
|
37
35
|
"cli",
|
|
@@ -41,9 +39,7 @@
|
|
|
41
39
|
"pre-rendering",
|
|
42
40
|
"static-site-generator",
|
|
43
41
|
"backend-driven",
|
|
44
|
-
"
|
|
45
|
-
"model-context-protocol",
|
|
46
|
-
"ai-integration"
|
|
42
|
+
"ai-agents"
|
|
47
43
|
],
|
|
48
44
|
"publishConfig": {
|
|
49
45
|
"access": "public"
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tkeron
|
|
3
|
+
description: "Tkeron core overview: what it is, full CLI reference (build, dev, init, skills), file-type summary, build lifecycle, IDE support files, environment variables, build-time vs runtime. Load this skill first when starting any tkeron task — it is the entry point that points to the other tkeron-* skills."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Tkeron — Core
|
|
7
|
+
|
|
8
|
+
## What It Is
|
|
9
|
+
|
|
10
|
+
CLI build tool for vanilla web development. Compiles TypeScript, processes HTML/TS/Markdown components, runs pre-/post-rendering scripts, generates static files ready to deploy. Powered by **Bun**. Zero frameworks. Zero runtime. Zero external bundlers.
|
|
11
|
+
|
|
12
|
+
## The tkeron skill set
|
|
13
|
+
|
|
14
|
+
| Skill | When to load it |
|
|
15
|
+
| ------------------------ | -------------------------------------------------------------------------- |
|
|
16
|
+
| `tkeron` (this one) | Always first. CLI, lifecycle, file-type overview. |
|
|
17
|
+
| `tkeron-components` | Creating/editing `.com.html`, `.com.ts`, `.com.md`, `.pre.ts`, `.post.ts`. |
|
|
18
|
+
| `tkeron-organization` | Designing project structure, deciding when to componentize, naming. |
|
|
19
|
+
| `tkeron-patterns` | Implementing features — best patterns, anti-patterns, max-pre-render rule. |
|
|
20
|
+
| `tkeron-testing` | Writing tests with `getBuildResult` from `tkeron`. |
|
|
21
|
+
| `tkeron-troubleshooting` | Build fails, dev server crashes, component is not replaced, common errors. |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Input and Output
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
project/
|
|
29
|
+
├── tkeron.d.ts # IDE types (com, document globals)
|
|
30
|
+
├── tsconfig.json # TS config for IDE
|
|
31
|
+
├── websrc/ # ← INPUT (all source files live here)
|
|
32
|
+
│ ├── index.html # Pages (root = sitemap)
|
|
33
|
+
│ ├── index.ts # Browser TypeScript (compiled to .js)
|
|
34
|
+
│ ├── index.pre.ts # Pre-rendering (build time, before components)
|
|
35
|
+
│ ├── index.post.ts # Post-processing (build time, after components)
|
|
36
|
+
│ ├── about.html # More pages at root = more routes
|
|
37
|
+
│ ├── docs/ # Subdirectories = sub-routes
|
|
38
|
+
│ │ └── *.html
|
|
39
|
+
│ ├── components/ # Components (NOT routes) — see tkeron-organization
|
|
40
|
+
│ ├── styles/ # CSS, assets
|
|
41
|
+
│ └── utils/ # Helpers imported by .com.ts or .pre.ts
|
|
42
|
+
└── web/ # ← OUTPUT (generated by tk build)
|
|
43
|
+
├── index.html # Processed HTML (components inlined)
|
|
44
|
+
├── index.js # TS compiled
|
|
45
|
+
└── styles/ # CSS copied
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Fixed directories**: `websrc/` is input, `web/` is output. No configuration. Convention over configuration.
|
|
49
|
+
|
|
50
|
+
> **IMPORTANT**: `web/` is generated by `tk build` and `tk dev`. It MUST be in `.gitignore`. **Never edit or commit its contents** — any manual change is overwritten on the next build.
|
|
51
|
+
|
|
52
|
+
**Files NOT copied to output**: `*.com.html`, `*.com.ts`, `*.com.md`, `*.pre.ts`, `*.post.ts`.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## CLI Reference
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
tk # Banner + version
|
|
60
|
+
tk init <name> # New project in <name>/
|
|
61
|
+
tk init . # Initialize in current directory
|
|
62
|
+
tk init <name> --force # Overwrite existing
|
|
63
|
+
tk build # Compile websrc/ → web/
|
|
64
|
+
tk b # Alias for build
|
|
65
|
+
tk dev # Dev server on localhost:3000 + hot reload
|
|
66
|
+
tk dev 8080 # Custom port
|
|
67
|
+
tk dev 8080 0.0.0.0 # Custom port + host
|
|
68
|
+
tk skills # Install AI agent skills (auto-detect env)
|
|
69
|
+
tk skills <dir> # Install into a custom directory
|
|
70
|
+
tk skills --force # Overwrite existing skill files
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
| Command | Aliases | What it does |
|
|
74
|
+
| ------------ | ---------------- | ------------------------------------------- |
|
|
75
|
+
| `tk build` | `tk b` | Full build of `websrc/` → `web/` |
|
|
76
|
+
| `tk develop` | `tk dev`, `tk d` | Dev server + watch + hot reload (singleton) |
|
|
77
|
+
| `tk init` | `tk i` | Create project from template |
|
|
78
|
+
| `tk skills` | — | Install AI agent skills |
|
|
79
|
+
|
|
80
|
+
### `tk dev` — important
|
|
81
|
+
|
|
82
|
+
- Defaults: port `3000`, host `localhost`. Positional args: `tk dev <port> <host>`.
|
|
83
|
+
- **Singleton per port**: only one instance at a time. Check `fuser 3000/tcp 2>/dev/null` before launching.
|
|
84
|
+
- Watches `websrc/`, rebuilds on save, broadcasts via SSE on `/dev-reload`, injects the reload script before `</body>`.
|
|
85
|
+
- Clean URLs: `/about` serves `about.html`, `/blog/` serves `blog/index.html`.
|
|
86
|
+
- **In agent sessions**: ALWAYS run `tk dev` in background (it blocks indefinitely). NEVER run it synchronously.
|
|
87
|
+
- If it crashes after a `websrc/` edit → see `tkeron-troubleshooting`.
|
|
88
|
+
|
|
89
|
+
### `tk build` — required after editing `websrc/`
|
|
90
|
+
|
|
91
|
+
> **RULE**: After any change in `websrc/`, run `tk build` and then read the relevant files in `web/` (`web/*.html`, `web/*.js`) to verify components were inlined and TS compiled as expected.
|
|
92
|
+
|
|
93
|
+
If output is wrong → fix in `websrc/` and rebuild. **NEVER edit `web/` directly.**
|
|
94
|
+
|
|
95
|
+
### `tk init` — what it creates
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
project/
|
|
99
|
+
├── websrc/
|
|
100
|
+
│ ├── index.html # Sample home page
|
|
101
|
+
│ ├── index.ts # Sample browser TS
|
|
102
|
+
│ ├── index.pre.ts # Sample pre-render
|
|
103
|
+
│ ├── api-service.ts # Sample service
|
|
104
|
+
│ ├── *.com.html # Sample HTML components
|
|
105
|
+
│ └── user-badge.com.ts # Sample TS component
|
|
106
|
+
├── tkeron.d.ts # IDE types
|
|
107
|
+
└── tsconfig.json # TS config for IDE
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Behavior:
|
|
111
|
+
|
|
112
|
+
- In an empty/new directory: creates the full template.
|
|
113
|
+
- In a directory with an existing `websrc/` or `tkeron.d.ts`: prompts before overwriting (use `--force` to skip the prompt).
|
|
114
|
+
- Always preserves any pre-existing fields in your `tsconfig.json` and merges the tkeron defaults.
|
|
115
|
+
|
|
116
|
+
### `tk skills` — environment auto-detection
|
|
117
|
+
|
|
118
|
+
`tk skills` (no argument) detects the AI environment from the current directory and installs into the matching folder:
|
|
119
|
+
|
|
120
|
+
| Detected marker | Environment | Install target | Special transform |
|
|
121
|
+
| ------------------------- | ----------- | ----------------- | ---------------------------------------- |
|
|
122
|
+
| `.cursor/` | cursor | `.cursor/rules/` | adds `alwaysApply: false` to frontmatter |
|
|
123
|
+
| `.github/` | copilot | `.github/skills/` | none |
|
|
124
|
+
| `.claude/` or `CLAUDE.md` | claude | `.claude/rules/` | none |
|
|
125
|
+
|
|
126
|
+
- Multiple environments detected → installs into all of them.
|
|
127
|
+
- None detected → prompts to create `./skills/`.
|
|
128
|
+
- Explicit target (`tk skills my-skills-dir`) → installs there, no env detection, no transform.
|
|
129
|
+
- Conflicts (skill file already exists) → fails with a clear message; use `--force` to overwrite.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Build Lifecycle — Exact Order
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
websrc/ ─────────────────────────────────────────────────→ web/
|
|
137
|
+
|
|
138
|
+
[1] .pre.ts Run pre-render scripts (Bun runtime)
|
|
139
|
+
Each .pre.ts modifies its paired .html
|
|
140
|
+
— runs BEFORE components, can inject custom elements
|
|
141
|
+
|
|
142
|
+
[2] Iterative loop (max 10 iterations, until no more changes):
|
|
143
|
+
├─ .com.ts Execute TypeScript components
|
|
144
|
+
├─ .com.html Inline HTML components
|
|
145
|
+
└─ .com.md Render Markdown components
|
|
146
|
+
|
|
147
|
+
[3] .post.ts Run post-render scripts (Bun runtime)
|
|
148
|
+
Each .post.ts mutates its paired .html with the
|
|
149
|
+
components ALREADY resolved — final DOM walk
|
|
150
|
+
|
|
151
|
+
[4] .ts → .js Compile TypeScript (Bun.build)
|
|
152
|
+
|
|
153
|
+
[5] Asset copy Copy everything else to the output
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Key order**: `.pre.ts` runs FIRST (can inject custom elements that the component loop then processes). `.post.ts` runs LAST (sees the fully-resolved DOM — perfect for `loading="lazy"`, `rel="noopener"`, TOCs, heading `id`s).
|
|
157
|
+
|
|
158
|
+
Limits: max **10 iterations**, max **50 nesting levels**, no circular dependencies.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## File Types — Summary
|
|
163
|
+
|
|
164
|
+
| Extension | When it runs | Runtime | Special variable | Copied to web/ |
|
|
165
|
+
| ----------- | ------------------------ | ---------- | -------------------- | -------------- |
|
|
166
|
+
| `.html` | — | — | — | ✅ (processed) |
|
|
167
|
+
| `.ts` | Browser | V8/Browser | `window`, `document` | ✅ (→ .js) |
|
|
168
|
+
| `.com.html` | Build time | — | — | ❌ |
|
|
169
|
+
| `.com.ts` | Build time | Bun | `com` | ❌ |
|
|
170
|
+
| `.com.md` | Build time | — | — | ❌ |
|
|
171
|
+
| `.pre.ts` | Build time (BEFORE coms) | Bun | `document` | ❌ |
|
|
172
|
+
| `.post.ts` | Build time (AFTER coms) | Bun | `document` | ❌ |
|
|
173
|
+
|
|
174
|
+
> Full reference (the `com` API, attribute reading, nesting, examples) lives in `tkeron-components`.
|
|
175
|
+
|
|
176
|
+
### `.html` — Page essentials
|
|
177
|
+
|
|
178
|
+
```html
|
|
179
|
+
<!DOCTYPE html>
|
|
180
|
+
<html lang="en">
|
|
181
|
+
<head>
|
|
182
|
+
<meta charset="UTF-8" />
|
|
183
|
+
<title>My Site</title>
|
|
184
|
+
<link rel="stylesheet" href="./styles.css" />
|
|
185
|
+
</head>
|
|
186
|
+
<body>
|
|
187
|
+
<site-header></site-header>
|
|
188
|
+
<main>Content</main>
|
|
189
|
+
<script type="module" src="./index.ts"></script>
|
|
190
|
+
</body>
|
|
191
|
+
</html>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Two non-negotiable rules**:
|
|
195
|
+
|
|
196
|
+
1. **`src="index.ts"` with `type="module"`**, NEVER `.js`. Tkeron compiles and rewrites the reference.
|
|
197
|
+
2. **Relative paths only** (`./`, `../`). NEVER absolute (`/styles.css`) — Bun cannot resolve them at build time. Applies to `.html`, `.com.html`, and `url()` in CSS.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## IDE — Support Files
|
|
202
|
+
|
|
203
|
+
Generated by `tk init`. For the IDE only, do not affect the build.
|
|
204
|
+
|
|
205
|
+
### `tkeron.d.ts`
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
declare module "*.com.ts" {
|
|
209
|
+
global {
|
|
210
|
+
const com: HTMLElement;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
declare module "*.pre.ts" {
|
|
215
|
+
global {
|
|
216
|
+
const document: Document;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
declare module "*.post.ts" {
|
|
221
|
+
global {
|
|
222
|
+
const document: Document;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### `tsconfig.json`
|
|
228
|
+
|
|
229
|
+
```json
|
|
230
|
+
{
|
|
231
|
+
"compilerOptions": {
|
|
232
|
+
"target": "ESNext",
|
|
233
|
+
"module": "ESNext",
|
|
234
|
+
"lib": ["ESNext", "DOM"],
|
|
235
|
+
"moduleResolution": "bundler",
|
|
236
|
+
"strict": true,
|
|
237
|
+
"skipLibCheck": true
|
|
238
|
+
},
|
|
239
|
+
"include": ["websrc/**/*", "tkeron.d.ts"]
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Environment Variables
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
// In .pre.ts, .post.ts or .com.ts (build time)
|
|
249
|
+
process.env.TKERON_VERSION; // tkeron version (injected automatically)
|
|
250
|
+
process.env.NODE_ENV; // development / production
|
|
251
|
+
process.env.MY_VAR; // any custom variable
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
NODE_ENV=production MY_VAR=value tk build
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Browser `.ts` files do **not** see `process.env` — `process` does not exist in the browser. To pass build-time values to the runtime, write them into the DOM from a `.pre.ts` (e.g. `<meta name="config" content="...">`) and read them from `.ts`.
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Type Checking
|
|
263
|
+
|
|
264
|
+
Tkeron does NOT type-check, it only compiles. To check types:
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
bun x tsc --noEmit && tk build
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## Build Time vs Runtime — Quick Reference
|
|
273
|
+
|
|
274
|
+
| Aspect | Build (`.pre.ts`, `.com.ts`, `.post.ts`) | Runtime (`.ts` → `.js`) |
|
|
275
|
+
| -------------- | ---------------------------------------- | ----------------------- |
|
|
276
|
+
| When it runs | `tk build` | User's browser |
|
|
277
|
+
| Runtime | Bun | V8/Browser |
|
|
278
|
+
| `fetch()` | ✅ | ✅ |
|
|
279
|
+
| `window` | ❌ | ✅ |
|
|
280
|
+
| `localStorage` | ❌ | ✅ |
|
|
281
|
+
| DOM events | ❌ (lost in output) | ✅ |
|
|
282
|
+
| npm packages | ✅ | ❌ (not bundled) |
|
|
283
|
+
| Bun APIs | ✅ | ❌ |
|
|
284
|
+
| `process.env` | ✅ | ❌ |
|
|
285
|
+
|
|
286
|
+
For full do/don't rules and the **maximum pre-render** rule, load `tkeron-patterns`.
|