janela 0.14.2 → 0.15.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 +18 -4
- package/bin/janela.mjs +55 -11
- package/bin/lib.mjs +27 -0
- package/package.json +1 -1
- package/templates/index.html +12 -21
- package/templates/react/files/src/App.tsx +1 -8
- package/templates/react/files/src/styles.css +11 -19
- package/templates/solid/files/src/App.tsx +1 -8
- package/templates/solid/files/src/styles.css +11 -19
- package/templates/svelte/files/src/App.svelte +1 -4
- package/templates/svelte/files/src/styles.css +11 -19
- package/templates/vue/files/src/App.vue +1 -4
- package/templates/vue/files/src/styles.css +11 -19
package/README.md
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
<picture>
|
|
2
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/mmamedel/janela/main/packages/janela/brand/janela-mark-dark.svg">
|
|
3
|
+
<img src="https://raw.githubusercontent.com/mmamedel/janela/main/packages/janela/brand/janela-mark-light.svg" alt="" width="88" align="right">
|
|
4
|
+
</picture>
|
|
5
|
+
|
|
1
6
|
# janela
|
|
2
7
|
|
|
3
8
|
> *janela* — Portuguese for **window**.
|
|
@@ -6,9 +11,9 @@ Desktop and mobile apps in pure TypeScript, compiled to native. No Rust, no
|
|
|
6
11
|
Node, no Electron. The backend is TypeScript compiled to a native binary by
|
|
7
12
|
[scriptc](https://scriptc.dev); the window is the OS webview via
|
|
8
13
|
[webview/webview](https://github.com/webview/webview). A desktop binary comes
|
|
9
|
-
out around
|
|
14
|
+
out around 240–420 KB — 241 KB for the smallest template — with no bundled
|
|
10
15
|
browser and no bundled runtime; iOS and Android bundles land around
|
|
11
|
-
|
|
16
|
+
244–421 KB. Those are the *starter's* figures, and about 35 KB of each is the
|
|
12
17
|
native file dialog and worker-thread reader it demonstrates: delete the "Files
|
|
13
18
|
and the window" card and its two commands and the smallest binary is 212 KB. Per-template figures are in
|
|
14
19
|
[docs/frontend.md](../../docs/frontend.md).
|
|
@@ -31,7 +36,11 @@ desktop-only for now; on mobile they report clearly when called.
|
|
|
31
36
|
## Quick start
|
|
32
37
|
|
|
33
38
|
```bash
|
|
34
|
-
|
|
39
|
+
pnpm create janela # the front door: prompts, scaffolds, installs
|
|
40
|
+
# (npm create janela@latest / yarn / bun also work)
|
|
41
|
+
|
|
42
|
+
# or drive the CLI yourself:
|
|
43
|
+
npm install -g janela
|
|
35
44
|
janela --version # which janela you actually have
|
|
36
45
|
janela init my-app # (or `jn init my-app`)
|
|
37
46
|
cd my-app
|
|
@@ -43,10 +52,15 @@ Or start from a frontend framework:
|
|
|
43
52
|
|
|
44
53
|
```bash
|
|
45
54
|
janela init my-app --template vue # or react | svelte | solid | vanilla
|
|
46
|
-
cd my-app
|
|
55
|
+
cd my-app # deps are already installed
|
|
47
56
|
janela dev # Vite dev server + HMR, in a native window
|
|
48
57
|
```
|
|
49
58
|
|
|
59
|
+
`init` installs the template's dependencies with whichever package manager
|
|
60
|
+
ran it — `pnpm janela init` uses pnpm — so `janela dev` works straight
|
|
61
|
+
afterwards. Pass `--no-install` to skip that, and if the install fails the
|
|
62
|
+
project is still written; the message names the one command to retry.
|
|
63
|
+
|
|
50
64
|
A `--template` a globally installed CLI has never heard of is now an error
|
|
51
65
|
rather than a silent fallback, and `janela --version` says which one you are
|
|
52
66
|
running — worth checking first if a scaffolded project comes out looking
|
package/bin/janela.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// janela — the CLI (the tauri-cli analogue).
|
|
3
3
|
//
|
|
4
|
-
// janela init <name> scaffold a new project
|
|
4
|
+
// janela init <name> scaffold a new project (and install its dependencies)
|
|
5
5
|
// janela build compile the project to a native binary (+ .app on macOS)
|
|
6
6
|
// janela dev build, then run the binary with logs in the terminal
|
|
7
7
|
// janela --version which janela this is
|
|
@@ -21,8 +21,8 @@ import { dirname, join, relative, resolve, sep } from "node:path";
|
|
|
21
21
|
import { fileURLToPath } from "node:url";
|
|
22
22
|
import {
|
|
23
23
|
ANDROID_ABI, ANDROID_TARGET_SDK, androidConf, ffiManifest, iosConf,
|
|
24
|
-
libraryProfile, mimeFor, NAME_RE,
|
|
25
|
-
rewriteHostSpecifier, suggestName,
|
|
24
|
+
installCommand, libraryProfile, mimeFor, NAME_RE, packageManager as pmFor,
|
|
25
|
+
patchPeSubsystem, PeError, rewriteHostSpecifier, suggestName,
|
|
26
26
|
} from "./lib.mjs";
|
|
27
27
|
|
|
28
28
|
const KIT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
@@ -107,8 +107,9 @@ function viteCommand(root) {
|
|
|
107
107
|
if (existsSync(shim)) return { argv: [shim], shell: process.platform === "win32" };
|
|
108
108
|
|
|
109
109
|
fail(
|
|
110
|
-
"this project has a vite config but no local vite —
|
|
111
|
-
|
|
110
|
+
"this project has a vite config but no local vite — its dependencies are not " +
|
|
111
|
+
`installed yet:\n ${installCommand(pmFor(process.env)).join(" ")}\n` +
|
|
112
|
+
" (janela init installs them for you unless you pass --no-install)",
|
|
112
113
|
);
|
|
113
114
|
}
|
|
114
115
|
|
|
@@ -1160,7 +1161,29 @@ function copyTemplate(from, to, name) {
|
|
|
1160
1161
|
|
|
1161
1162
|
// Best-effort repair of a rejected name, so the error can suggest something
|
|
1162
1163
|
// that would have worked instead of only stating the rule.
|
|
1163
|
-
|
|
1164
|
+
/**
|
|
1165
|
+
* Install a scaffolded project's dependencies.
|
|
1166
|
+
*
|
|
1167
|
+
* Returns true on success. A failure is NOT fatal: the project is already
|
|
1168
|
+
* written, and the useful thing to do is name the one command to retry rather
|
|
1169
|
+
* than exit non-zero on a tree that is fine. Offline, an unreachable registry
|
|
1170
|
+
* and missing auth all land here.
|
|
1171
|
+
*
|
|
1172
|
+
* Windows needs a shell: npm/pnpm/yarn are .cmd shims, and Node has refused to
|
|
1173
|
+
* spawn those directly since the CVE-2024-27980 fix.
|
|
1174
|
+
*/
|
|
1175
|
+
function installDeps(dir, pm) {
|
|
1176
|
+
const cmd = installCommand(pm);
|
|
1177
|
+
console.log(`janela: installing dependencies with ${pm}…`);
|
|
1178
|
+
const r = spawnSync(cmd[0], cmd.slice(1), {
|
|
1179
|
+
stdio: "inherit",
|
|
1180
|
+
cwd: dir,
|
|
1181
|
+
shell: process.platform === "win32",
|
|
1182
|
+
});
|
|
1183
|
+
return r.status === 0;
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
function init(name, template, { install = true } = {}) {
|
|
1164
1187
|
if (!name) {
|
|
1165
1188
|
fail(
|
|
1166
1189
|
"no project name given.\n" +
|
|
@@ -1216,8 +1239,27 @@ function init(name, template) {
|
|
|
1216
1239
|
writeFileSync(join(dir, ".gitignore"), ".janela/\nnode_modules/\ndist/\n");
|
|
1217
1240
|
writeFileSync(join(dir, "package.json"), JSON.stringify(pkg, null, 2) + "\n");
|
|
1218
1241
|
|
|
1219
|
-
|
|
1220
|
-
|
|
1242
|
+
// The no-framework template has no dependencies to install: it needs no
|
|
1243
|
+
// frontend toolchain, and `janela dev` works on it straight out of init.
|
|
1244
|
+
const hasDeps = template !== "vanilla";
|
|
1245
|
+
if (!hasDeps || !install) {
|
|
1246
|
+
// Only a skipped install on a template that HAS dependencies leaves the
|
|
1247
|
+
// caller something to run.
|
|
1248
|
+
const manual = hasDeps ? `${installCommand(pmFor(process.env)).join(" ")} && ` : "";
|
|
1249
|
+
console.log(`janela: created ${name}/ (${template}) — next: cd ${name} && ${manual}janela dev`);
|
|
1250
|
+
return;
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
const pm = pmFor(process.env);
|
|
1254
|
+
if (installDeps(dir, pm)) {
|
|
1255
|
+
console.log(`janela: created ${name}/ (${template}) — next: cd ${name} && janela dev`);
|
|
1256
|
+
} else {
|
|
1257
|
+
console.log(
|
|
1258
|
+
`janela: created ${name}/ (${template}), but installing its dependencies failed.\n` +
|
|
1259
|
+
` The project is written and fine — retry the install and you are set:\n` +
|
|
1260
|
+
` cd ${name} && ${installCommand(pm).join(" ")} && janela dev`,
|
|
1261
|
+
);
|
|
1262
|
+
}
|
|
1221
1263
|
}
|
|
1222
1264
|
|
|
1223
1265
|
// ---- dev --------------------------------------------------------------------
|
|
@@ -1349,9 +1391,11 @@ function assertPositionals(max) {
|
|
|
1349
1391
|
|
|
1350
1392
|
switch (cmd) {
|
|
1351
1393
|
case "init":
|
|
1352
|
-
assertKnownFlags(["template"]);
|
|
1394
|
+
assertKnownFlags(["template", "no-install"]);
|
|
1353
1395
|
assertPositionals(1);
|
|
1354
|
-
init(positionals()[0], flag("template", "vanilla")
|
|
1396
|
+
init(positionals()[0], flag("template", "vanilla"), {
|
|
1397
|
+
install: !argv.includes("--no-install"),
|
|
1398
|
+
});
|
|
1355
1399
|
break;
|
|
1356
1400
|
case "build":
|
|
1357
1401
|
assertKnownFlags(["target"]);
|
|
@@ -1371,7 +1415,7 @@ switch (cmd) {
|
|
|
1371
1415
|
default:
|
|
1372
1416
|
console.log(
|
|
1373
1417
|
`janela ${VERSION}\n\n` +
|
|
1374
|
-
"usage: janela init <name> [--template vanilla|vue|react|svelte|solid]\n" +
|
|
1418
|
+
"usage: janela init <name> [--template vanilla|vue|react|svelte|solid] [--no-install]\n" +
|
|
1375
1419
|
" janela build [--target desktop|ios|android]\n" +
|
|
1376
1420
|
" janela dev [--target desktop|ios|android]\n" +
|
|
1377
1421
|
" janela --version",
|
package/bin/lib.mjs
CHANGED
|
@@ -345,3 +345,30 @@ export function patchPeSubsystem(input) {
|
|
|
345
345
|
buf.writeUInt16LE(IMAGE_SUBSYSTEM_WINDOWS_GUI, subOff);
|
|
346
346
|
return { patched: true, buf };
|
|
347
347
|
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Which package manager to install a scaffolded project with.
|
|
351
|
+
*
|
|
352
|
+
* `npm_config_user_agent` is set by whichever manager ran janela, so
|
|
353
|
+
* `pnpm janela init` installs with pnpm. Run as a plain global binary it is
|
|
354
|
+
* unset, and npm is the only manager guaranteed to exist alongside node.
|
|
355
|
+
*
|
|
356
|
+
* Takes the environment rather than reading process.env, so it is testable.
|
|
357
|
+
*/
|
|
358
|
+
export function packageManager(env = {}) {
|
|
359
|
+
const ua = env.npm_config_user_agent ?? "";
|
|
360
|
+
for (const pm of ["pnpm", "yarn", "bun"]) if (ua.startsWith(`${pm}/`)) return pm;
|
|
361
|
+
return "npm";
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* The install invocation for a manager.
|
|
366
|
+
*
|
|
367
|
+
* yarn's is the bare command. npm gets --no-fund --no-audit: neither is useful
|
|
368
|
+
* on a freshly scaffolded tree, and the audit is the slowest part of it.
|
|
369
|
+
*/
|
|
370
|
+
export function installCommand(pm) {
|
|
371
|
+
if (pm === "yarn") return ["yarn"];
|
|
372
|
+
if (pm === "npm") return ["npm", "install", "--no-fund", "--no-audit"];
|
|
373
|
+
return [pm, "install"];
|
|
374
|
+
}
|
package/package.json
CHANGED
package/templates/index.html
CHANGED
|
@@ -7,9 +7,7 @@
|
|
|
7
7
|
<style>
|
|
8
8
|
/* Everything here is yours to replace. It is deliberately one file with
|
|
9
9
|
no dependencies: this template has no bundler, so what you see is what
|
|
10
|
-
runs.
|
|
11
|
-
a janela frontend is embedded in the binary, so every asset has to be
|
|
12
|
-
inlined anyway, and a window needs no artwork. */
|
|
10
|
+
runs. */
|
|
13
11
|
:root {
|
|
14
12
|
color-scheme: light dark;
|
|
15
13
|
--bg: #f6f6f7;
|
|
@@ -17,7 +15,7 @@
|
|
|
17
15
|
--text: #18181b;
|
|
18
16
|
--muted: #71717a;
|
|
19
17
|
--line: #e4e4e7;
|
|
20
|
-
--accent: #
|
|
18
|
+
--accent: #1c6fd4;
|
|
21
19
|
--accent-soft: #eff4ff;
|
|
22
20
|
--shadow: 0 1px 2px rgb(0 0 0 / 0.04), 0 8px 24px -12px rgb(0 0 0 / 0.12);
|
|
23
21
|
}
|
|
@@ -28,7 +26,7 @@
|
|
|
28
26
|
--text: #fafafa;
|
|
29
27
|
--muted: #a1a1aa;
|
|
30
28
|
--line: #2e2e34;
|
|
31
|
-
--accent: #
|
|
29
|
+
--accent: #58a6ff;
|
|
32
30
|
--accent-soft: #1d2433;
|
|
33
31
|
--shadow: 0 1px 2px rgb(0 0 0 / 0.3), 0 8px 24px -12px rgb(0 0 0 / 0.5);
|
|
34
32
|
}
|
|
@@ -49,18 +47,14 @@
|
|
|
49
47
|
|
|
50
48
|
/* --- header ------------------------------------------------------- */
|
|
51
49
|
header { text-align: center; margin-bottom: 20px; }
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
display: flex; align-items: center; gap: 3px; padding: 0 4px;
|
|
61
|
-
}
|
|
62
|
-
.mark .bar i { width: 3px; height: 3px; border-radius: 50%; background: var(--text); }
|
|
63
|
-
.mark .pane { flex: 1; background: linear-gradient(135deg, var(--accent), transparent 70%); opacity: 0.85; }
|
|
50
|
+
/* The mark: a round window, which is what janela means. Inlined rather
|
|
51
|
+
than linked, because a janela frontend is embedded in the binary and
|
|
52
|
+
every asset has to be inlined anyway — and inline rather than a CSS
|
|
53
|
+
data URI so ONE copy serves both themes: the frame follows the text
|
|
54
|
+
colour, the glass follows the accent. Percent-encoding a data URI
|
|
55
|
+
would also have cost 4x the bytes. Delete it and the header still
|
|
56
|
+
works. */
|
|
57
|
+
.mark { display: block; width: 56px; height: 56px; margin: 0 auto 14px; }
|
|
64
58
|
h1 { margin: 0; font-size: 26px; letter-spacing: -0.02em; font-weight: 650; }
|
|
65
59
|
.sub { margin: 5px 0 0; color: var(--muted); font-size: 13.5px; }
|
|
66
60
|
|
|
@@ -145,10 +139,7 @@
|
|
|
145
139
|
<body>
|
|
146
140
|
<main>
|
|
147
141
|
<header>
|
|
148
|
-
<
|
|
149
|
-
<div class="bar"><i></i><i></i><i></i></div>
|
|
150
|
-
<div class="pane"></div>
|
|
151
|
-
</div>
|
|
142
|
+
<svg class="mark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 970.64 970.64" role="img" aria-label="janela"><path fill="currentColor" d="M970.64,485.32c0,268.03-217.28,485.32-485.32,485.32S0,753.35,0,485.32,217.28,0,485.32,0s485.32,217.28,485.32,485.32ZM938.11,485.34c0-250.08-202.73-452.8-452.8-452.8S32.51,235.26,32.51,485.34s202.73,452.8,452.8,452.8,452.8-202.73,452.8-452.8Z"/><path fill="currentColor" d="M892.79,485.25c0,225.05-182.44,407.49-407.49,407.49S77.82,710.3,77.82,485.25,260.26,77.77,485.31,77.77s407.49,182.44,407.49,407.49ZM470.27,112.09v335.5c0,1.05,13.11,12.99,15.36,14.43,1.65-2.06,14.64-13.4,14.64-14.43V112.59c0-1.1-2.44-1.43-3.45-1.55-8.42-.99-18.1.83-26.55,1.05ZM858.27,438.09c-20.14-166.94-158.46-303.59-325-324v324h325ZM437.27,115.09c-21.65,1.62-44.22,7.07-65,13.5-137.62,42.61-242.41,165.92-260,309.5h325V115.09ZM109.27,500.09h338.5c1,0,12.36-12.44,13.54-14.5,0-1-12.54-14.5-13.54-14.5H109.27c-1.81,9.94-.24,19.09,0,29ZM861.27,471.09h-338.5c-1,0-13.53,13.5-13.54,14.5.52,2.76,3.61,3.57,5.57,5.47,1.64,1.59,7.37,9.03,7.97,9.03h338.5c.9-9.78.9-19.22,0-29ZM500.27,860.09v-336.5c0-1.03-12.98-12.37-14.64-14.43-2.26,1.44-15.36,13.37-15.36,14.43v336.5h30ZM437.27,533.09H112.27c19.95,166.03,159.46,303.1,325,323v-323ZM858.27,533.09h-325v324c165.97-22.51,304.48-156.63,325-324Z"/><path fill="var(--accent)" d="M858.27,438.09h-325V114.09c166.54,20.41,304.86,157.06,325,324Z"/><path fill="var(--accent)" d="M858.27,533.09c-20.52,167.37-159.03,301.49-325,324v-324h325Z"/><path fill="var(--accent)" d="M437.27,533.09v323c-165.54-19.9-305.05-156.97-325-323h325Z"/><path fill="var(--accent)" d="M437.27,115.09v323H112.27c17.6-143.57,122.38-266.89,260-309.5,20.78-6.43,43.34-11.88,65-13.5ZM324.93,239.42c-5.22-5.22-14.48-5.8-20.62-1.79-23.51,27.2-56.28,50.77-79.07,77.93-3.21,3.83-6.62,7.81-7,13.05-.97,13.35,13.8,21.88,24.98,14.93,28.09-28.84,58.16-56.14,84.78-86.22,2.71-5.58,1.25-13.58-3.07-17.9ZM375.06,280.3c-4.15.41-7.65,2.76-10.8,5.27-2.42,1.93-17.06,17.64-18.19,19.81-7.64,14.76,7.17,29.85,21.55,22.56,2.83-1.44,19.3-18.18,21.64-21.36,8.21-11.17-.52-27.62-14.2-26.28ZM310.03,344.3c-2.88.42-6.45,2.49-8.78,4.26-4.52,3.45-32.55,31.28-34.83,35.17-8.84,15.07,8.47,31.23,23.59,21.59,4.35-2.77,34.16-32.7,36.28-36.72,6.36-12.04-2.95-26.26-16.27-24.31Z"/><path fill="var(--card)" d="M500.27,860.09h-30v-336.5c0-1.05,13.11-12.99,15.36-14.43,1.65,2.06,14.64,13.4,14.64,14.43v336.5Z"/><path fill="var(--card)" d="M470.27,112.09c8.45-.22,18.13-2.04,26.55-1.05,1.01.12,3.45.46,3.45,1.55v335c0,1.03-12.98,12.37-14.64,14.43-2.26-1.44-15.36-13.37-15.36-14.43V112.09Z"/><path fill="var(--card)" d="M109.27,500.09c-.24-9.91-1.81-19.06,0-29h338.5c1,0,13.54,13.5,13.54,14.5-1.17,2.06-12.54,14.5-13.54,14.5H109.27Z"/><path fill="var(--card)" d="M861.27,471.09c.9,9.78.9,19.22,0,29h-338.5c-.6,0-6.34-7.44-7.97-9.03-1.96-1.9-5.04-2.72-5.57-5.47,0-1,12.54-14.5,13.54-14.5h338.5Z"/><path fill="currentColor" d="M324.93,239.42c4.32,4.32,5.78,12.32,3.07,17.9-26.62,30.07-56.7,57.37-84.78,86.22-11.18,6.94-25.95-1.58-24.98-14.93.38-5.24,3.79-9.22,7-13.05,22.8-27.16,55.56-50.73,79.07-77.93,6.13-4.01,15.39-3.43,20.62,1.79Z"/><path fill="currentColor" d="M310.03,344.3c13.33-1.95,22.63,12.27,16.27,24.31-2.12,4.02-31.93,33.94-36.28,36.72-15.12,9.64-32.44-6.52-23.59-21.59,2.28-3.89,30.31-31.72,34.83-35.17,2.33-1.78,5.9-3.84,8.78-4.26Z"/><path fill="currentColor" d="M375.06,280.3c13.69-1.35,22.42,15.11,14.2,26.28-2.34,3.18-18.81,19.93-21.64,21.36-14.39,7.3-29.19-7.8-21.55-22.56,1.13-2.18,15.76-17.88,18.19-19.81,3.16-2.51,6.65-4.86,10.8-5.27Z"/></svg>
|
|
152
143
|
<h1>__NAME__</h1>
|
|
153
144
|
<p class="sub">TypeScript, compiled to a native binary. No Rust, no Node, no Electron.</p>
|
|
154
145
|
</header>
|
|
@@ -64,14 +64,7 @@ export default function App() {
|
|
|
64
64
|
return (
|
|
65
65
|
<main>
|
|
66
66
|
<header>
|
|
67
|
-
<
|
|
68
|
-
<div className="bar">
|
|
69
|
-
<i />
|
|
70
|
-
<i />
|
|
71
|
-
<i />
|
|
72
|
-
</div>
|
|
73
|
-
<div className="pane" />
|
|
74
|
-
</div>
|
|
67
|
+
<svg class="mark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 970.64 970.64" role="img" aria-label="janela"><path fill="currentColor" d="M970.64,485.32c0,268.03-217.28,485.32-485.32,485.32S0,753.35,0,485.32,217.28,0,485.32,0s485.32,217.28,485.32,485.32ZM938.11,485.34c0-250.08-202.73-452.8-452.8-452.8S32.51,235.26,32.51,485.34s202.73,452.8,452.8,452.8,452.8-202.73,452.8-452.8Z" /><path fill="currentColor" d="M892.79,485.25c0,225.05-182.44,407.49-407.49,407.49S77.82,710.3,77.82,485.25,260.26,77.77,485.31,77.77s407.49,182.44,407.49,407.49ZM470.27,112.09v335.5c0,1.05,13.11,12.99,15.36,14.43,1.65-2.06,14.64-13.4,14.64-14.43V112.59c0-1.1-2.44-1.43-3.45-1.55-8.42-.99-18.1.83-26.55,1.05ZM858.27,438.09c-20.14-166.94-158.46-303.59-325-324v324h325ZM437.27,115.09c-21.65,1.62-44.22,7.07-65,13.5-137.62,42.61-242.41,165.92-260,309.5h325V115.09ZM109.27,500.09h338.5c1,0,12.36-12.44,13.54-14.5,0-1-12.54-14.5-13.54-14.5H109.27c-1.81,9.94-.24,19.09,0,29ZM861.27,471.09h-338.5c-1,0-13.53,13.5-13.54,14.5.52,2.76,3.61,3.57,5.57,5.47,1.64,1.59,7.37,9.03,7.97,9.03h338.5c.9-9.78.9-19.22,0-29ZM500.27,860.09v-336.5c0-1.03-12.98-12.37-14.64-14.43-2.26,1.44-15.36,13.37-15.36,14.43v336.5h30ZM437.27,533.09H112.27c19.95,166.03,159.46,303.1,325,323v-323ZM858.27,533.09h-325v324c165.97-22.51,304.48-156.63,325-324Z" /><path fill="var(--accent)" d="M858.27,438.09h-325V114.09c166.54,20.41,304.86,157.06,325,324Z" /><path fill="var(--accent)" d="M858.27,533.09c-20.52,167.37-159.03,301.49-325,324v-324h325Z" /><path fill="var(--accent)" d="M437.27,533.09v323c-165.54-19.9-305.05-156.97-325-323h325Z" /><path fill="var(--accent)" d="M437.27,115.09v323H112.27c17.6-143.57,122.38-266.89,260-309.5,20.78-6.43,43.34-11.88,65-13.5ZM324.93,239.42c-5.22-5.22-14.48-5.8-20.62-1.79-23.51,27.2-56.28,50.77-79.07,77.93-3.21,3.83-6.62,7.81-7,13.05-.97,13.35,13.8,21.88,24.98,14.93,28.09-28.84,58.16-56.14,84.78-86.22,2.71-5.58,1.25-13.58-3.07-17.9ZM375.06,280.3c-4.15.41-7.65,2.76-10.8,5.27-2.42,1.93-17.06,17.64-18.19,19.81-7.64,14.76,7.17,29.85,21.55,22.56,2.83-1.44,19.3-18.18,21.64-21.36,8.21-11.17-.52-27.62-14.2-26.28ZM310.03,344.3c-2.88.42-6.45,2.49-8.78,4.26-4.52,3.45-32.55,31.28-34.83,35.17-8.84,15.07,8.47,31.23,23.59,21.59,4.35-2.77,34.16-32.7,36.28-36.72,6.36-12.04-2.95-26.26-16.27-24.31Z" /><path fill="var(--card)" d="M500.27,860.09h-30v-336.5c0-1.05,13.11-12.99,15.36-14.43,1.65,2.06,14.64,13.4,14.64,14.43v336.5Z" /><path fill="var(--card)" d="M470.27,112.09c8.45-.22,18.13-2.04,26.55-1.05,1.01.12,3.45.46,3.45,1.55v335c0,1.03-12.98,12.37-14.64,14.43-2.26-1.44-15.36-13.37-15.36-14.43V112.09Z" /><path fill="var(--card)" d="M109.27,500.09c-.24-9.91-1.81-19.06,0-29h338.5c1,0,13.54,13.5,13.54,14.5-1.17,2.06-12.54,14.5-13.54,14.5H109.27Z" /><path fill="var(--card)" d="M861.27,471.09c.9,9.78.9,19.22,0,29h-338.5c-.6,0-6.34-7.44-7.97-9.03-1.96-1.9-5.04-2.72-5.57-5.47,0-1,12.54-14.5,13.54-14.5h338.5Z" /><path fill="currentColor" d="M324.93,239.42c4.32,4.32,5.78,12.32,3.07,17.9-26.62,30.07-56.7,57.37-84.78,86.22-11.18,6.94-25.95-1.58-24.98-14.93.38-5.24,3.79-9.22,7-13.05,22.8-27.16,55.56-50.73,79.07-77.93,6.13-4.01,15.39-3.43,20.62,1.79Z" /><path fill="currentColor" d="M310.03,344.3c13.33-1.95,22.63,12.27,16.27,24.31-2.12,4.02-31.93,33.94-36.28,36.72-15.12,9.64-32.44-6.52-23.59-21.59,2.28-3.89,30.31-31.72,34.83-35.17,2.33-1.78,5.9-3.84,8.78-4.26Z" /><path fill="currentColor" d="M375.06,280.3c13.69-1.35,22.42,15.11,14.2,26.28-2.34,3.18-18.81,19.93-21.64,21.36-14.39,7.3-29.19-7.8-21.55-22.56,1.13-2.18,15.76-17.88,18.19-19.81,3.16-2.51,6.65-4.86,10.8-5.27Z" /></svg>
|
|
75
68
|
<h1>__NAME__</h1>
|
|
76
69
|
<p className="sub">TypeScript, compiled to a native binary. No Rust, no Node, no Electron.</p>
|
|
77
70
|
</header>
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
/* The janela starter's look. Shared by every template so a project scaffolded
|
|
2
2
|
with --template vue looks the same as one scaffolded without a framework.
|
|
3
|
-
All of it is yours to replace.
|
|
4
|
-
|
|
5
|
-
The window mark in App is drawn in CSS rather than shipped as an image: a
|
|
6
|
-
janela frontend is embedded in the binary, so every asset has to be inlined
|
|
7
|
-
anyway, and a window needs no artwork. */
|
|
3
|
+
All of it is yours to replace. */
|
|
8
4
|
|
|
9
5
|
:root {
|
|
10
6
|
color-scheme: light dark;
|
|
@@ -13,7 +9,7 @@
|
|
|
13
9
|
--text: #18181b;
|
|
14
10
|
--muted: #71717a;
|
|
15
11
|
--line: #e4e4e7;
|
|
16
|
-
--accent: #
|
|
12
|
+
--accent: #1c6fd4;
|
|
17
13
|
--accent-soft: #eff4ff;
|
|
18
14
|
--shadow: 0 1px 2px rgb(0 0 0 / 0.04), 0 8px 24px -12px rgb(0 0 0 / 0.12);
|
|
19
15
|
}
|
|
@@ -24,7 +20,7 @@
|
|
|
24
20
|
--text: #fafafa;
|
|
25
21
|
--muted: #a1a1aa;
|
|
26
22
|
--line: #2e2e34;
|
|
27
|
-
--accent: #
|
|
23
|
+
--accent: #58a6ff;
|
|
28
24
|
--accent-soft: #1d2433;
|
|
29
25
|
--shadow: 0 1px 2px rgb(0 0 0 / 0.3), 0 8px 24px -12px rgb(0 0 0 / 0.5);
|
|
30
26
|
}
|
|
@@ -45,18 +41,14 @@ main { width: 100%; max-width: 760px; padding: 26px 22px 32px; }
|
|
|
45
41
|
|
|
46
42
|
/* --- header ------------------------------------------------------- */
|
|
47
43
|
header { text-align: center; margin-bottom: 20px; }
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
display: flex; align-items: center; gap: 3px; padding: 0 4px;
|
|
57
|
-
}
|
|
58
|
-
.mark .bar i { width: 3px; height: 3px; border-radius: 50%; background: var(--text); }
|
|
59
|
-
.mark .pane { flex: 1; background: linear-gradient(135deg, var(--accent), transparent 70%); opacity: 0.85; }
|
|
44
|
+
/* The mark: a round window, which is what janela means. Inlined rather
|
|
45
|
+
than linked, because a janela frontend is embedded in the binary and
|
|
46
|
+
every asset has to be inlined anyway — and inline rather than a CSS
|
|
47
|
+
data URI so ONE copy serves both themes: the frame follows the text
|
|
48
|
+
colour, the glass follows the accent. Percent-encoding a data URI
|
|
49
|
+
would also have cost 4x the bytes. Delete it and the header still
|
|
50
|
+
works. */
|
|
51
|
+
.mark { display: block; width: 56px; height: 56px; margin: 0 auto 14px; }
|
|
60
52
|
h1 { margin: 0; font-size: 26px; letter-spacing: -0.02em; font-weight: 650; }
|
|
61
53
|
.sub { margin: 5px 0 0; color: var(--muted); font-size: 13.5px; }
|
|
62
54
|
|
|
@@ -59,14 +59,7 @@ export default function App() {
|
|
|
59
59
|
return (
|
|
60
60
|
<main>
|
|
61
61
|
<header>
|
|
62
|
-
<
|
|
63
|
-
<div class="bar">
|
|
64
|
-
<i />
|
|
65
|
-
<i />
|
|
66
|
-
<i />
|
|
67
|
-
</div>
|
|
68
|
-
<div class="pane" />
|
|
69
|
-
</div>
|
|
62
|
+
<svg class="mark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 970.64 970.64" role="img" aria-label="janela"><path fill="currentColor" d="M970.64,485.32c0,268.03-217.28,485.32-485.32,485.32S0,753.35,0,485.32,217.28,0,485.32,0s485.32,217.28,485.32,485.32ZM938.11,485.34c0-250.08-202.73-452.8-452.8-452.8S32.51,235.26,32.51,485.34s202.73,452.8,452.8,452.8,452.8-202.73,452.8-452.8Z"/><path fill="currentColor" d="M892.79,485.25c0,225.05-182.44,407.49-407.49,407.49S77.82,710.3,77.82,485.25,260.26,77.77,485.31,77.77s407.49,182.44,407.49,407.49ZM470.27,112.09v335.5c0,1.05,13.11,12.99,15.36,14.43,1.65-2.06,14.64-13.4,14.64-14.43V112.59c0-1.1-2.44-1.43-3.45-1.55-8.42-.99-18.1.83-26.55,1.05ZM858.27,438.09c-20.14-166.94-158.46-303.59-325-324v324h325ZM437.27,115.09c-21.65,1.62-44.22,7.07-65,13.5-137.62,42.61-242.41,165.92-260,309.5h325V115.09ZM109.27,500.09h338.5c1,0,12.36-12.44,13.54-14.5,0-1-12.54-14.5-13.54-14.5H109.27c-1.81,9.94-.24,19.09,0,29ZM861.27,471.09h-338.5c-1,0-13.53,13.5-13.54,14.5.52,2.76,3.61,3.57,5.57,5.47,1.64,1.59,7.37,9.03,7.97,9.03h338.5c.9-9.78.9-19.22,0-29ZM500.27,860.09v-336.5c0-1.03-12.98-12.37-14.64-14.43-2.26,1.44-15.36,13.37-15.36,14.43v336.5h30ZM437.27,533.09H112.27c19.95,166.03,159.46,303.1,325,323v-323ZM858.27,533.09h-325v324c165.97-22.51,304.48-156.63,325-324Z"/><path fill="var(--accent)" d="M858.27,438.09h-325V114.09c166.54,20.41,304.86,157.06,325,324Z"/><path fill="var(--accent)" d="M858.27,533.09c-20.52,167.37-159.03,301.49-325,324v-324h325Z"/><path fill="var(--accent)" d="M437.27,533.09v323c-165.54-19.9-305.05-156.97-325-323h325Z"/><path fill="var(--accent)" d="M437.27,115.09v323H112.27c17.6-143.57,122.38-266.89,260-309.5,20.78-6.43,43.34-11.88,65-13.5ZM324.93,239.42c-5.22-5.22-14.48-5.8-20.62-1.79-23.51,27.2-56.28,50.77-79.07,77.93-3.21,3.83-6.62,7.81-7,13.05-.97,13.35,13.8,21.88,24.98,14.93,28.09-28.84,58.16-56.14,84.78-86.22,2.71-5.58,1.25-13.58-3.07-17.9ZM375.06,280.3c-4.15.41-7.65,2.76-10.8,5.27-2.42,1.93-17.06,17.64-18.19,19.81-7.64,14.76,7.17,29.85,21.55,22.56,2.83-1.44,19.3-18.18,21.64-21.36,8.21-11.17-.52-27.62-14.2-26.28ZM310.03,344.3c-2.88.42-6.45,2.49-8.78,4.26-4.52,3.45-32.55,31.28-34.83,35.17-8.84,15.07,8.47,31.23,23.59,21.59,4.35-2.77,34.16-32.7,36.28-36.72,6.36-12.04-2.95-26.26-16.27-24.31Z"/><path fill="var(--card)" d="M500.27,860.09h-30v-336.5c0-1.05,13.11-12.99,15.36-14.43,1.65,2.06,14.64,13.4,14.64,14.43v336.5Z"/><path fill="var(--card)" d="M470.27,112.09c8.45-.22,18.13-2.04,26.55-1.05,1.01.12,3.45.46,3.45,1.55v335c0,1.03-12.98,12.37-14.64,14.43-2.26-1.44-15.36-13.37-15.36-14.43V112.09Z"/><path fill="var(--card)" d="M109.27,500.09c-.24-9.91-1.81-19.06,0-29h338.5c1,0,13.54,13.5,13.54,14.5-1.17,2.06-12.54,14.5-13.54,14.5H109.27Z"/><path fill="var(--card)" d="M861.27,471.09c.9,9.78.9,19.22,0,29h-338.5c-.6,0-6.34-7.44-7.97-9.03-1.96-1.9-5.04-2.72-5.57-5.47,0-1,12.54-14.5,13.54-14.5h338.5Z"/><path fill="currentColor" d="M324.93,239.42c4.32,4.32,5.78,12.32,3.07,17.9-26.62,30.07-56.7,57.37-84.78,86.22-11.18,6.94-25.95-1.58-24.98-14.93.38-5.24,3.79-9.22,7-13.05,22.8-27.16,55.56-50.73,79.07-77.93,6.13-4.01,15.39-3.43,20.62,1.79Z"/><path fill="currentColor" d="M310.03,344.3c13.33-1.95,22.63,12.27,16.27,24.31-2.12,4.02-31.93,33.94-36.28,36.72-15.12,9.64-32.44-6.52-23.59-21.59,2.28-3.89,30.31-31.72,34.83-35.17,2.33-1.78,5.9-3.84,8.78-4.26Z"/><path fill="currentColor" d="M375.06,280.3c13.69-1.35,22.42,15.11,14.2,26.28-2.34,3.18-18.81,19.93-21.64,21.36-14.39,7.3-29.19-7.8-21.55-22.56,1.13-2.18,15.76-17.88,18.19-19.81,3.16-2.51,6.65-4.86,10.8-5.27Z"/></svg>
|
|
70
63
|
<h1>__NAME__</h1>
|
|
71
64
|
<p class="sub">TypeScript, compiled to a native binary. No Rust, no Node, no Electron.</p>
|
|
72
65
|
</header>
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
/* The janela starter's look. Shared by every template so a project scaffolded
|
|
2
2
|
with --template vue looks the same as one scaffolded without a framework.
|
|
3
|
-
All of it is yours to replace.
|
|
4
|
-
|
|
5
|
-
The window mark in App is drawn in CSS rather than shipped as an image: a
|
|
6
|
-
janela frontend is embedded in the binary, so every asset has to be inlined
|
|
7
|
-
anyway, and a window needs no artwork. */
|
|
3
|
+
All of it is yours to replace. */
|
|
8
4
|
|
|
9
5
|
:root {
|
|
10
6
|
color-scheme: light dark;
|
|
@@ -13,7 +9,7 @@
|
|
|
13
9
|
--text: #18181b;
|
|
14
10
|
--muted: #71717a;
|
|
15
11
|
--line: #e4e4e7;
|
|
16
|
-
--accent: #
|
|
12
|
+
--accent: #1c6fd4;
|
|
17
13
|
--accent-soft: #eff4ff;
|
|
18
14
|
--shadow: 0 1px 2px rgb(0 0 0 / 0.04), 0 8px 24px -12px rgb(0 0 0 / 0.12);
|
|
19
15
|
}
|
|
@@ -24,7 +20,7 @@
|
|
|
24
20
|
--text: #fafafa;
|
|
25
21
|
--muted: #a1a1aa;
|
|
26
22
|
--line: #2e2e34;
|
|
27
|
-
--accent: #
|
|
23
|
+
--accent: #58a6ff;
|
|
28
24
|
--accent-soft: #1d2433;
|
|
29
25
|
--shadow: 0 1px 2px rgb(0 0 0 / 0.3), 0 8px 24px -12px rgb(0 0 0 / 0.5);
|
|
30
26
|
}
|
|
@@ -45,18 +41,14 @@ main { width: 100%; max-width: 760px; padding: 26px 22px 32px; }
|
|
|
45
41
|
|
|
46
42
|
/* --- header ------------------------------------------------------- */
|
|
47
43
|
header { text-align: center; margin-bottom: 20px; }
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
display: flex; align-items: center; gap: 3px; padding: 0 4px;
|
|
57
|
-
}
|
|
58
|
-
.mark .bar i { width: 3px; height: 3px; border-radius: 50%; background: var(--text); }
|
|
59
|
-
.mark .pane { flex: 1; background: linear-gradient(135deg, var(--accent), transparent 70%); opacity: 0.85; }
|
|
44
|
+
/* The mark: a round window, which is what janela means. Inlined rather
|
|
45
|
+
than linked, because a janela frontend is embedded in the binary and
|
|
46
|
+
every asset has to be inlined anyway — and inline rather than a CSS
|
|
47
|
+
data URI so ONE copy serves both themes: the frame follows the text
|
|
48
|
+
colour, the glass follows the accent. Percent-encoding a data URI
|
|
49
|
+
would also have cost 4x the bytes. Delete it and the header still
|
|
50
|
+
works. */
|
|
51
|
+
.mark { display: block; width: 56px; height: 56px; margin: 0 auto 14px; }
|
|
60
52
|
h1 { margin: 0; font-size: 26px; letter-spacing: -0.02em; font-weight: 650; }
|
|
61
53
|
.sub { margin: 5px 0 0; color: var(--muted); font-size: 13.5px; }
|
|
62
54
|
|
|
@@ -58,10 +58,7 @@
|
|
|
58
58
|
|
|
59
59
|
<main>
|
|
60
60
|
<header>
|
|
61
|
-
<
|
|
62
|
-
<div class="bar"><i></i><i></i><i></i></div>
|
|
63
|
-
<div class="pane"></div>
|
|
64
|
-
</div>
|
|
61
|
+
<svg class="mark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 970.64 970.64" role="img" aria-label="janela"><path fill="currentColor" d="M970.64,485.32c0,268.03-217.28,485.32-485.32,485.32S0,753.35,0,485.32,217.28,0,485.32,0s485.32,217.28,485.32,485.32ZM938.11,485.34c0-250.08-202.73-452.8-452.8-452.8S32.51,235.26,32.51,485.34s202.73,452.8,452.8,452.8,452.8-202.73,452.8-452.8Z"/><path fill="currentColor" d="M892.79,485.25c0,225.05-182.44,407.49-407.49,407.49S77.82,710.3,77.82,485.25,260.26,77.77,485.31,77.77s407.49,182.44,407.49,407.49ZM470.27,112.09v335.5c0,1.05,13.11,12.99,15.36,14.43,1.65-2.06,14.64-13.4,14.64-14.43V112.59c0-1.1-2.44-1.43-3.45-1.55-8.42-.99-18.1.83-26.55,1.05ZM858.27,438.09c-20.14-166.94-158.46-303.59-325-324v324h325ZM437.27,115.09c-21.65,1.62-44.22,7.07-65,13.5-137.62,42.61-242.41,165.92-260,309.5h325V115.09ZM109.27,500.09h338.5c1,0,12.36-12.44,13.54-14.5,0-1-12.54-14.5-13.54-14.5H109.27c-1.81,9.94-.24,19.09,0,29ZM861.27,471.09h-338.5c-1,0-13.53,13.5-13.54,14.5.52,2.76,3.61,3.57,5.57,5.47,1.64,1.59,7.37,9.03,7.97,9.03h338.5c.9-9.78.9-19.22,0-29ZM500.27,860.09v-336.5c0-1.03-12.98-12.37-14.64-14.43-2.26,1.44-15.36,13.37-15.36,14.43v336.5h30ZM437.27,533.09H112.27c19.95,166.03,159.46,303.1,325,323v-323ZM858.27,533.09h-325v324c165.97-22.51,304.48-156.63,325-324Z"/><path fill="var(--accent)" d="M858.27,438.09h-325V114.09c166.54,20.41,304.86,157.06,325,324Z"/><path fill="var(--accent)" d="M858.27,533.09c-20.52,167.37-159.03,301.49-325,324v-324h325Z"/><path fill="var(--accent)" d="M437.27,533.09v323c-165.54-19.9-305.05-156.97-325-323h325Z"/><path fill="var(--accent)" d="M437.27,115.09v323H112.27c17.6-143.57,122.38-266.89,260-309.5,20.78-6.43,43.34-11.88,65-13.5ZM324.93,239.42c-5.22-5.22-14.48-5.8-20.62-1.79-23.51,27.2-56.28,50.77-79.07,77.93-3.21,3.83-6.62,7.81-7,13.05-.97,13.35,13.8,21.88,24.98,14.93,28.09-28.84,58.16-56.14,84.78-86.22,2.71-5.58,1.25-13.58-3.07-17.9ZM375.06,280.3c-4.15.41-7.65,2.76-10.8,5.27-2.42,1.93-17.06,17.64-18.19,19.81-7.64,14.76,7.17,29.85,21.55,22.56,2.83-1.44,19.3-18.18,21.64-21.36,8.21-11.17-.52-27.62-14.2-26.28ZM310.03,344.3c-2.88.42-6.45,2.49-8.78,4.26-4.52,3.45-32.55,31.28-34.83,35.17-8.84,15.07,8.47,31.23,23.59,21.59,4.35-2.77,34.16-32.7,36.28-36.72,6.36-12.04-2.95-26.26-16.27-24.31Z"/><path fill="var(--card)" d="M500.27,860.09h-30v-336.5c0-1.05,13.11-12.99,15.36-14.43,1.65,2.06,14.64,13.4,14.64,14.43v336.5Z"/><path fill="var(--card)" d="M470.27,112.09c8.45-.22,18.13-2.04,26.55-1.05,1.01.12,3.45.46,3.45,1.55v335c0,1.03-12.98,12.37-14.64,14.43-2.26-1.44-15.36-13.37-15.36-14.43V112.09Z"/><path fill="var(--card)" d="M109.27,500.09c-.24-9.91-1.81-19.06,0-29h338.5c1,0,13.54,13.5,13.54,14.5-1.17,2.06-12.54,14.5-13.54,14.5H109.27Z"/><path fill="var(--card)" d="M861.27,471.09c.9,9.78.9,19.22,0,29h-338.5c-.6,0-6.34-7.44-7.97-9.03-1.96-1.9-5.04-2.72-5.57-5.47,0-1,12.54-14.5,13.54-14.5h338.5Z"/><path fill="currentColor" d="M324.93,239.42c4.32,4.32,5.78,12.32,3.07,17.9-26.62,30.07-56.7,57.37-84.78,86.22-11.18,6.94-25.95-1.58-24.98-14.93.38-5.24,3.79-9.22,7-13.05,22.8-27.16,55.56-50.73,79.07-77.93,6.13-4.01,15.39-3.43,20.62,1.79Z"/><path fill="currentColor" d="M310.03,344.3c13.33-1.95,22.63,12.27,16.27,24.31-2.12,4.02-31.93,33.94-36.28,36.72-15.12,9.64-32.44-6.52-23.59-21.59,2.28-3.89,30.31-31.72,34.83-35.17,2.33-1.78,5.9-3.84,8.78-4.26Z"/><path fill="currentColor" d="M375.06,280.3c13.69-1.35,22.42,15.11,14.2,26.28-2.34,3.18-18.81,19.93-21.64,21.36-14.39,7.3-29.19-7.8-21.55-22.56,1.13-2.18,15.76-17.88,18.19-19.81,3.16-2.51,6.65-4.86,10.8-5.27Z"/></svg>
|
|
65
62
|
<h1>__NAME__</h1>
|
|
66
63
|
<p class="sub">TypeScript, compiled to a native binary. No Rust, no Node, no Electron.</p>
|
|
67
64
|
</header>
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
/* The janela starter's look. Shared by every template so a project scaffolded
|
|
2
2
|
with --template vue looks the same as one scaffolded without a framework.
|
|
3
|
-
All of it is yours to replace.
|
|
4
|
-
|
|
5
|
-
The window mark in App is drawn in CSS rather than shipped as an image: a
|
|
6
|
-
janela frontend is embedded in the binary, so every asset has to be inlined
|
|
7
|
-
anyway, and a window needs no artwork. */
|
|
3
|
+
All of it is yours to replace. */
|
|
8
4
|
|
|
9
5
|
:root {
|
|
10
6
|
color-scheme: light dark;
|
|
@@ -13,7 +9,7 @@
|
|
|
13
9
|
--text: #18181b;
|
|
14
10
|
--muted: #71717a;
|
|
15
11
|
--line: #e4e4e7;
|
|
16
|
-
--accent: #
|
|
12
|
+
--accent: #1c6fd4;
|
|
17
13
|
--accent-soft: #eff4ff;
|
|
18
14
|
--shadow: 0 1px 2px rgb(0 0 0 / 0.04), 0 8px 24px -12px rgb(0 0 0 / 0.12);
|
|
19
15
|
}
|
|
@@ -24,7 +20,7 @@
|
|
|
24
20
|
--text: #fafafa;
|
|
25
21
|
--muted: #a1a1aa;
|
|
26
22
|
--line: #2e2e34;
|
|
27
|
-
--accent: #
|
|
23
|
+
--accent: #58a6ff;
|
|
28
24
|
--accent-soft: #1d2433;
|
|
29
25
|
--shadow: 0 1px 2px rgb(0 0 0 / 0.3), 0 8px 24px -12px rgb(0 0 0 / 0.5);
|
|
30
26
|
}
|
|
@@ -45,18 +41,14 @@ main { width: 100%; max-width: 760px; padding: 26px 22px 32px; }
|
|
|
45
41
|
|
|
46
42
|
/* --- header ------------------------------------------------------- */
|
|
47
43
|
header { text-align: center; margin-bottom: 20px; }
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
display: flex; align-items: center; gap: 3px; padding: 0 4px;
|
|
57
|
-
}
|
|
58
|
-
.mark .bar i { width: 3px; height: 3px; border-radius: 50%; background: var(--text); }
|
|
59
|
-
.mark .pane { flex: 1; background: linear-gradient(135deg, var(--accent), transparent 70%); opacity: 0.85; }
|
|
44
|
+
/* The mark: a round window, which is what janela means. Inlined rather
|
|
45
|
+
than linked, because a janela frontend is embedded in the binary and
|
|
46
|
+
every asset has to be inlined anyway — and inline rather than a CSS
|
|
47
|
+
data URI so ONE copy serves both themes: the frame follows the text
|
|
48
|
+
colour, the glass follows the accent. Percent-encoding a data URI
|
|
49
|
+
would also have cost 4x the bytes. Delete it and the header still
|
|
50
|
+
works. */
|
|
51
|
+
.mark { display: block; width: 56px; height: 56px; margin: 0 auto 14px; }
|
|
60
52
|
h1 { margin: 0; font-size: 26px; letter-spacing: -0.02em; font-weight: 650; }
|
|
61
53
|
.sub { margin: 5px 0 0; color: var(--muted); font-size: 13.5px; }
|
|
62
54
|
|
|
@@ -58,10 +58,7 @@ async function pick() {
|
|
|
58
58
|
<template>
|
|
59
59
|
<main>
|
|
60
60
|
<header>
|
|
61
|
-
<
|
|
62
|
-
<div class="bar"><i /><i /><i /></div>
|
|
63
|
-
<div class="pane" />
|
|
64
|
-
</div>
|
|
61
|
+
<svg class="mark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 970.64 970.64" role="img" aria-label="janela"><path fill="currentColor" d="M970.64,485.32c0,268.03-217.28,485.32-485.32,485.32S0,753.35,0,485.32,217.28,0,485.32,0s485.32,217.28,485.32,485.32ZM938.11,485.34c0-250.08-202.73-452.8-452.8-452.8S32.51,235.26,32.51,485.34s202.73,452.8,452.8,452.8,452.8-202.73,452.8-452.8Z"/><path fill="currentColor" d="M892.79,485.25c0,225.05-182.44,407.49-407.49,407.49S77.82,710.3,77.82,485.25,260.26,77.77,485.31,77.77s407.49,182.44,407.49,407.49ZM470.27,112.09v335.5c0,1.05,13.11,12.99,15.36,14.43,1.65-2.06,14.64-13.4,14.64-14.43V112.59c0-1.1-2.44-1.43-3.45-1.55-8.42-.99-18.1.83-26.55,1.05ZM858.27,438.09c-20.14-166.94-158.46-303.59-325-324v324h325ZM437.27,115.09c-21.65,1.62-44.22,7.07-65,13.5-137.62,42.61-242.41,165.92-260,309.5h325V115.09ZM109.27,500.09h338.5c1,0,12.36-12.44,13.54-14.5,0-1-12.54-14.5-13.54-14.5H109.27c-1.81,9.94-.24,19.09,0,29ZM861.27,471.09h-338.5c-1,0-13.53,13.5-13.54,14.5.52,2.76,3.61,3.57,5.57,5.47,1.64,1.59,7.37,9.03,7.97,9.03h338.5c.9-9.78.9-19.22,0-29ZM500.27,860.09v-336.5c0-1.03-12.98-12.37-14.64-14.43-2.26,1.44-15.36,13.37-15.36,14.43v336.5h30ZM437.27,533.09H112.27c19.95,166.03,159.46,303.1,325,323v-323ZM858.27,533.09h-325v324c165.97-22.51,304.48-156.63,325-324Z"/><path fill="var(--accent)" d="M858.27,438.09h-325V114.09c166.54,20.41,304.86,157.06,325,324Z"/><path fill="var(--accent)" d="M858.27,533.09c-20.52,167.37-159.03,301.49-325,324v-324h325Z"/><path fill="var(--accent)" d="M437.27,533.09v323c-165.54-19.9-305.05-156.97-325-323h325Z"/><path fill="var(--accent)" d="M437.27,115.09v323H112.27c17.6-143.57,122.38-266.89,260-309.5,20.78-6.43,43.34-11.88,65-13.5ZM324.93,239.42c-5.22-5.22-14.48-5.8-20.62-1.79-23.51,27.2-56.28,50.77-79.07,77.93-3.21,3.83-6.62,7.81-7,13.05-.97,13.35,13.8,21.88,24.98,14.93,28.09-28.84,58.16-56.14,84.78-86.22,2.71-5.58,1.25-13.58-3.07-17.9ZM375.06,280.3c-4.15.41-7.65,2.76-10.8,5.27-2.42,1.93-17.06,17.64-18.19,19.81-7.64,14.76,7.17,29.85,21.55,22.56,2.83-1.44,19.3-18.18,21.64-21.36,8.21-11.17-.52-27.62-14.2-26.28ZM310.03,344.3c-2.88.42-6.45,2.49-8.78,4.26-4.52,3.45-32.55,31.28-34.83,35.17-8.84,15.07,8.47,31.23,23.59,21.59,4.35-2.77,34.16-32.7,36.28-36.72,6.36-12.04-2.95-26.26-16.27-24.31Z"/><path fill="var(--card)" d="M500.27,860.09h-30v-336.5c0-1.05,13.11-12.99,15.36-14.43,1.65,2.06,14.64,13.4,14.64,14.43v336.5Z"/><path fill="var(--card)" d="M470.27,112.09c8.45-.22,18.13-2.04,26.55-1.05,1.01.12,3.45.46,3.45,1.55v335c0,1.03-12.98,12.37-14.64,14.43-2.26-1.44-15.36-13.37-15.36-14.43V112.09Z"/><path fill="var(--card)" d="M109.27,500.09c-.24-9.91-1.81-19.06,0-29h338.5c1,0,13.54,13.5,13.54,14.5-1.17,2.06-12.54,14.5-13.54,14.5H109.27Z"/><path fill="var(--card)" d="M861.27,471.09c.9,9.78.9,19.22,0,29h-338.5c-.6,0-6.34-7.44-7.97-9.03-1.96-1.9-5.04-2.72-5.57-5.47,0-1,12.54-14.5,13.54-14.5h338.5Z"/><path fill="currentColor" d="M324.93,239.42c4.32,4.32,5.78,12.32,3.07,17.9-26.62,30.07-56.7,57.37-84.78,86.22-11.18,6.94-25.95-1.58-24.98-14.93.38-5.24,3.79-9.22,7-13.05,22.8-27.16,55.56-50.73,79.07-77.93,6.13-4.01,15.39-3.43,20.62,1.79Z"/><path fill="currentColor" d="M310.03,344.3c13.33-1.95,22.63,12.27,16.27,24.31-2.12,4.02-31.93,33.94-36.28,36.72-15.12,9.64-32.44-6.52-23.59-21.59,2.28-3.89,30.31-31.72,34.83-35.17,2.33-1.78,5.9-3.84,8.78-4.26Z"/><path fill="currentColor" d="M375.06,280.3c13.69-1.35,22.42,15.11,14.2,26.28-2.34,3.18-18.81,19.93-21.64,21.36-14.39,7.3-29.19-7.8-21.55-22.56,1.13-2.18,15.76-17.88,18.19-19.81,3.16-2.51,6.65-4.86,10.8-5.27Z"/></svg>
|
|
65
62
|
<h1>__NAME__</h1>
|
|
66
63
|
<p class="sub">TypeScript, compiled to a native binary. No Rust, no Node, no Electron.</p>
|
|
67
64
|
</header>
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
/* The janela starter's look. Shared by every template so a project scaffolded
|
|
2
2
|
with --template vue looks the same as one scaffolded without a framework.
|
|
3
|
-
All of it is yours to replace.
|
|
4
|
-
|
|
5
|
-
The window mark in App is drawn in CSS rather than shipped as an image: a
|
|
6
|
-
janela frontend is embedded in the binary, so every asset has to be inlined
|
|
7
|
-
anyway, and a window needs no artwork. */
|
|
3
|
+
All of it is yours to replace. */
|
|
8
4
|
|
|
9
5
|
:root {
|
|
10
6
|
color-scheme: light dark;
|
|
@@ -13,7 +9,7 @@
|
|
|
13
9
|
--text: #18181b;
|
|
14
10
|
--muted: #71717a;
|
|
15
11
|
--line: #e4e4e7;
|
|
16
|
-
--accent: #
|
|
12
|
+
--accent: #1c6fd4;
|
|
17
13
|
--accent-soft: #eff4ff;
|
|
18
14
|
--shadow: 0 1px 2px rgb(0 0 0 / 0.04), 0 8px 24px -12px rgb(0 0 0 / 0.12);
|
|
19
15
|
}
|
|
@@ -24,7 +20,7 @@
|
|
|
24
20
|
--text: #fafafa;
|
|
25
21
|
--muted: #a1a1aa;
|
|
26
22
|
--line: #2e2e34;
|
|
27
|
-
--accent: #
|
|
23
|
+
--accent: #58a6ff;
|
|
28
24
|
--accent-soft: #1d2433;
|
|
29
25
|
--shadow: 0 1px 2px rgb(0 0 0 / 0.3), 0 8px 24px -12px rgb(0 0 0 / 0.5);
|
|
30
26
|
}
|
|
@@ -45,18 +41,14 @@ main { width: 100%; max-width: 760px; padding: 26px 22px 32px; }
|
|
|
45
41
|
|
|
46
42
|
/* --- header ------------------------------------------------------- */
|
|
47
43
|
header { text-align: center; margin-bottom: 20px; }
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
display: flex; align-items: center; gap: 3px; padding: 0 4px;
|
|
57
|
-
}
|
|
58
|
-
.mark .bar i { width: 3px; height: 3px; border-radius: 50%; background: var(--text); }
|
|
59
|
-
.mark .pane { flex: 1; background: linear-gradient(135deg, var(--accent), transparent 70%); opacity: 0.85; }
|
|
44
|
+
/* The mark: a round window, which is what janela means. Inlined rather
|
|
45
|
+
than linked, because a janela frontend is embedded in the binary and
|
|
46
|
+
every asset has to be inlined anyway — and inline rather than a CSS
|
|
47
|
+
data URI so ONE copy serves both themes: the frame follows the text
|
|
48
|
+
colour, the glass follows the accent. Percent-encoding a data URI
|
|
49
|
+
would also have cost 4x the bytes. Delete it and the header still
|
|
50
|
+
works. */
|
|
51
|
+
.mark { display: block; width: 56px; height: 56px; margin: 0 auto 14px; }
|
|
60
52
|
h1 { margin: 0; font-size: 26px; letter-spacing: -0.02em; font-weight: 650; }
|
|
61
53
|
.sub { margin: 5px 0 0; color: var(--muted); font-size: 13.5px; }
|
|
62
54
|
|