create-rezi 0.1.0-alpha.1

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.
@@ -0,0 +1,262 @@
1
+ import { createApp, rgb, ui } from "@rezi-ui/core";
2
+ import { createNodeBackend } from "@rezi-ui/node";
3
+
4
+ type ServiceStatus = "healthy" | "warning" | "down";
5
+
6
+ type Service = {
7
+ name: string;
8
+ region: string;
9
+ status: ServiceStatus;
10
+ latencyMs: number;
11
+ errorRate: number;
12
+ };
13
+
14
+ const services: readonly Service[] = [
15
+ { name: "Auth Gateway", region: "us-east", status: "healthy", latencyMs: 18, errorRate: 0.2 },
16
+ { name: "Billing", region: "us-west", status: "warning", latencyMs: 74, errorRate: 1.7 },
17
+ { name: "Search", region: "eu-central", status: "healthy", latencyMs: 32, errorRate: 0.4 },
18
+ { name: "Realtime", region: "ap-south", status: "warning", latencyMs: 96, errorRate: 2.1 },
19
+ { name: "Exports", region: "us-east", status: "down", latencyMs: 0, errorRate: 9.4 },
20
+ ];
21
+
22
+ const incidents = [
23
+ "Exports queue is backing up (ETA 15m)",
24
+ "Realtime jitter above 90ms in ap-south",
25
+ "Billing retries spiked 2x from baseline",
26
+ ];
27
+
28
+ const activity = [
29
+ "Deploy #491 rolled to 50%",
30
+ "Cache warm-up completed",
31
+ "Latency budget tightened to 80ms",
32
+ "Tracing sampling bumped to 20%",
33
+ ];
34
+
35
+ type Filter = "all" | "healthy" | "warning" | "down";
36
+
37
+ type State = {
38
+ selected: number;
39
+ filter: Filter;
40
+ pinned: string | null;
41
+ showHelp: boolean;
42
+ };
43
+
44
+ const app = createApp<State>({
45
+ backend: createNodeBackend(),
46
+ initialState: {
47
+ selected: 0,
48
+ filter: "all",
49
+ pinned: null,
50
+ showHelp: false,
51
+ },
52
+ });
53
+
54
+ const colors = {
55
+ accent: rgb(120, 200, 255),
56
+ muted: rgb(140, 150, 170),
57
+ panel: rgb(18, 22, 34),
58
+ panelAlt: rgb(22, 28, 44),
59
+ ok: rgb(120, 220, 160),
60
+ warn: rgb(255, 190, 120),
61
+ down: rgb(255, 120, 140),
62
+ ink: rgb(10, 14, 24),
63
+ inkSoft: rgb(30, 36, 54),
64
+ };
65
+
66
+ function statusColor(status: ServiceStatus) {
67
+ if (status === "healthy") return colors.ok;
68
+ if (status === "warning") return colors.warn;
69
+ return colors.down;
70
+ }
71
+
72
+ function filterServices(filter: Filter): Service[] {
73
+ if (filter === "all") return [...services];
74
+ return services.filter((svc) => svc.status === filter);
75
+ }
76
+
77
+ function clamp(value: number, min: number, max: number) {
78
+ return Math.max(min, Math.min(max, value));
79
+ }
80
+
81
+ function panel(title: string, children: ReturnType<typeof ui.column>[], flex = 1) {
82
+ return ui.box(
83
+ {
84
+ title,
85
+ flex,
86
+ border: "rounded",
87
+ px: 1,
88
+ py: 0,
89
+ style: { bg: colors.panel, fg: colors.muted },
90
+ },
91
+ children,
92
+ );
93
+ }
94
+
95
+ app.view((state) => {
96
+ const visible = filterServices(state.filter);
97
+ const selected = visible[state.selected] ?? visible[0] ?? services[0];
98
+ const pinned = state.pinned ?? selected?.name ?? "-";
99
+
100
+ return ui.column({ flex: 1, p: 1, gap: 1, items: "stretch" }, [
101
+ ui.row({ justify: "between", items: "center" }, [
102
+ ui.text("__APP_NAME__", { fg: colors.accent, bold: true }),
103
+ ui.row({ gap: 2, items: "center" }, [
104
+ ui.text("Filter", { fg: colors.muted }),
105
+ ui.text(state.filter.toUpperCase(), { fg: colors.accent, bold: true }),
106
+ ui.text("Pinned", { fg: colors.muted }),
107
+ ui.text(pinned, { fg: colors.ok, bold: true }),
108
+ ]),
109
+ ]),
110
+
111
+ ui.row({ flex: 1, gap: 1, items: "stretch" }, [
112
+ panel(
113
+ "Services",
114
+ [
115
+ ui.column(
116
+ { gap: 0 },
117
+ visible.map((svc, index) => {
118
+ const active = index === state.selected;
119
+ return ui.row(
120
+ {
121
+ key: svc.name,
122
+ gap: 1,
123
+ style: {
124
+ bg: active ? colors.inkSoft : undefined,
125
+ fg: active ? colors.accent : colors.muted,
126
+ },
127
+ },
128
+ [
129
+ ui.text(active ? ">" : " "),
130
+ ui.text(svc.name, { bold: active }),
131
+ ui.text(`(${svc.region})`, { fg: colors.muted }),
132
+ ui.text(svc.status.toUpperCase(), {
133
+ fg: statusColor(svc.status),
134
+ bold: true,
135
+ }),
136
+ ],
137
+ );
138
+ }),
139
+ ),
140
+ ],
141
+ 1,
142
+ ),
143
+
144
+ panel(
145
+ "Service Health",
146
+ [
147
+ ui.column({ gap: 1 }, [
148
+ ui.text(selected ? selected.name : "-", { fg: colors.accent, bold: true }),
149
+ ui.row({ gap: 2 }, [
150
+ ui.text(`Latency: ${selected ? selected.latencyMs : "-"} ms`),
151
+ ui.text(`Errors: ${selected ? selected.errorRate : "-"}%`, {
152
+ fg: selected && selected.errorRate > 2 ? colors.warn : colors.muted,
153
+ }),
154
+ ]),
155
+ ui.divider({ char: "-" }),
156
+ ui.text("Active incidents", { fg: colors.muted }),
157
+ ...incidents.map((line) => ui.text(`- ${line}`)),
158
+ ]),
159
+ ],
160
+ 2,
161
+ ),
162
+
163
+ panel(
164
+ "Activity",
165
+ [
166
+ ui.column({ gap: 1 }, [
167
+ ui.text("Recent deploys", { fg: colors.muted }),
168
+ ...activity.map((line) => ui.text(`- ${line}`)),
169
+ ui.divider({ char: "-" }),
170
+ ui.text("Escalations", { fg: colors.muted }),
171
+ ui.text("- On-call rotation starts in 2h"),
172
+ ui.text("- 3 alerts awaiting acknowledgement"),
173
+ ]),
174
+ ],
175
+ 1,
176
+ ),
177
+ ]),
178
+
179
+ state.showHelp
180
+ ? ui.box(
181
+ {
182
+ border: "rounded",
183
+ px: 1,
184
+ py: 0,
185
+ style: { bg: colors.panelAlt, fg: colors.muted },
186
+ },
187
+ [
188
+ ui.row({ gap: 1 }, [
189
+ ui.kbd(["up", "down"]),
190
+ ui.text("Move"),
191
+ ui.kbd("f"),
192
+ ui.text("Filter"),
193
+ ui.kbd("enter"),
194
+ ui.text("Pin"),
195
+ ui.kbd("?"),
196
+ ui.text("Help"),
197
+ ui.kbd("q"),
198
+ ui.text("Quit"),
199
+ ]),
200
+ ],
201
+ )
202
+ : ui.box({ px: 1, py: 0, style: { bg: colors.ink, fg: colors.muted } }, [
203
+ ui.row({ justify: "between", items: "center" }, [
204
+ ui.text("Status: nominal"),
205
+ ui.row({ gap: 1 }, [
206
+ ui.kbd("up/down"),
207
+ ui.text("Move"),
208
+ ui.kbd("f"),
209
+ ui.text("Filter"),
210
+ ui.kbd("?"),
211
+ ui.text("Help"),
212
+ ]),
213
+ ]),
214
+ ]),
215
+ ]);
216
+ });
217
+
218
+ app.keys({
219
+ q: () => app.stop(),
220
+ "ctrl+c": () => app.stop(),
221
+ up: () =>
222
+ app.update((s) => {
223
+ const list = filterServices(s.filter);
224
+ return { ...s, selected: clamp(s.selected - 1, 0, Math.max(0, list.length - 1)) };
225
+ }),
226
+ down: () =>
227
+ app.update((s) => {
228
+ const list = filterServices(s.filter);
229
+ return { ...s, selected: clamp(s.selected + 1, 0, Math.max(0, list.length - 1)) };
230
+ }),
231
+ k: () =>
232
+ app.update((s) => {
233
+ const list = filterServices(s.filter);
234
+ return { ...s, selected: clamp(s.selected - 1, 0, Math.max(0, list.length - 1)) };
235
+ }),
236
+ j: () =>
237
+ app.update((s) => {
238
+ const list = filterServices(s.filter);
239
+ return { ...s, selected: clamp(s.selected + 1, 0, Math.max(0, list.length - 1)) };
240
+ }),
241
+ f: () =>
242
+ app.update((s) => {
243
+ const next: Filter =
244
+ s.filter === "all"
245
+ ? "warning"
246
+ : s.filter === "warning"
247
+ ? "healthy"
248
+ : s.filter === "healthy"
249
+ ? "down"
250
+ : "all";
251
+ return { ...s, filter: next, selected: 0 };
252
+ }),
253
+ enter: () =>
254
+ app.update((s) => {
255
+ const list = filterServices(s.filter);
256
+ const svc = list[s.selected];
257
+ return { ...s, pinned: svc ? svc.name : s.pinned };
258
+ }),
259
+ "?": () => app.update((s) => ({ ...s, showHelp: !s.showHelp })),
260
+ });
261
+
262
+ await app.start();
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Bundler",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "types": ["node"],
10
+ "noUncheckedIndexedAccess": true,
11
+ "exactOptionalPropertyTypes": true
12
+ },
13
+ "include": ["src/**/*.ts"]
14
+ }
@@ -0,0 +1,18 @@
1
+ # __APP_NAME__
2
+
3
+ Scaffolded with `npm create rezi` using the **__TEMPLATE_LABEL__** template.
4
+
5
+ ## Quickstart
6
+
7
+ ```bash
8
+ npm install
9
+ npm start
10
+ ```
11
+
12
+ ## Keybindings
13
+
14
+ - `up` / `down` or `j` / `k`: Move selection
15
+ - `enter`: Open directory / preview file
16
+ - `backspace`: Go up
17
+ - `h`: Toggle hidden files
18
+ - `q`: Quit
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "__PACKAGE_NAME__",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "start": "tsx src/main.ts",
8
+ "dev": "tsx watch src/main.ts",
9
+ "typecheck": "tsc --noEmit"
10
+ },
11
+ "dependencies": {
12
+ "@rezi-ui/core": "^0.1.0-alpha.0",
13
+ "@rezi-ui/node": "^0.1.0-alpha.0"
14
+ },
15
+ "devDependencies": {
16
+ "@types/node": "^22.13.1",
17
+ "tsx": "^4.20.0",
18
+ "typescript": "^5.6.3"
19
+ },
20
+ "engines": {
21
+ "node": ">=18"
22
+ }
23
+ }
@@ -0,0 +1,256 @@
1
+ import { createApp, rgb, ui } from "@rezi-ui/core";
2
+ import { createNodeBackend } from "@rezi-ui/node";
3
+
4
+ type EntryType = "dir" | "file";
5
+
6
+ type Entry = {
7
+ name: string;
8
+ type: EntryType;
9
+ size: string;
10
+ modified: string;
11
+ preview: string;
12
+ };
13
+
14
+ type Tree = Record<string, Entry[]>;
15
+
16
+ const tree: Tree = {
17
+ "/": [
18
+ { name: "src", type: "dir", size: "-", modified: "2026-02-10", preview: "" },
19
+ { name: "docs", type: "dir", size: "-", modified: "2026-02-08", preview: "" },
20
+ {
21
+ name: "package.json",
22
+ type: "file",
23
+ size: "2 KB",
24
+ modified: "2026-02-07",
25
+ preview: '{\n "name": "__APP_NAME__"\n}',
26
+ },
27
+ { name: ".env", type: "file", size: "1 KB", modified: "2026-02-05", preview: "API_KEY=***" },
28
+ ],
29
+ "/src": [
30
+ {
31
+ name: "main.ts",
32
+ type: "file",
33
+ size: "4 KB",
34
+ modified: "2026-02-10",
35
+ preview: "import { createApp } from '@rezi-ui/core'",
36
+ },
37
+ { name: "components", type: "dir", size: "-", modified: "2026-02-09", preview: "" },
38
+ { name: "styles", type: "dir", size: "-", modified: "2026-02-09", preview: "" },
39
+ ],
40
+ "/src/components": [
41
+ {
42
+ name: "Panel.ts",
43
+ type: "file",
44
+ size: "1 KB",
45
+ modified: "2026-02-09",
46
+ preview: "export function Panel() {}",
47
+ },
48
+ {
49
+ name: "StatusBar.ts",
50
+ type: "file",
51
+ size: "1 KB",
52
+ modified: "2026-02-09",
53
+ preview: "export function StatusBar() {}",
54
+ },
55
+ ],
56
+ "/docs": [
57
+ {
58
+ name: "overview.md",
59
+ type: "file",
60
+ size: "3 KB",
61
+ modified: "2026-02-08",
62
+ preview: "# Overview",
63
+ },
64
+ { name: "usage.md", type: "file", size: "2 KB", modified: "2026-02-08", preview: "# Usage" },
65
+ ],
66
+ "/src/styles": [
67
+ {
68
+ name: "tokens.ts",
69
+ type: "file",
70
+ size: "2 KB",
71
+ modified: "2026-02-08",
72
+ preview: "export const colors = {}",
73
+ },
74
+ ],
75
+ };
76
+
77
+ const colors = {
78
+ accent: rgb(120, 200, 255),
79
+ muted: rgb(140, 150, 170),
80
+ panel: rgb(18, 22, 34),
81
+ panelAlt: rgb(22, 28, 44),
82
+ ink: rgb(10, 14, 24),
83
+ };
84
+
85
+ type State = {
86
+ path: string;
87
+ selected: number;
88
+ showHidden: boolean;
89
+ opened: string | null;
90
+ };
91
+
92
+ const app = createApp<State>({
93
+ backend: createNodeBackend(),
94
+ initialState: {
95
+ path: "/",
96
+ selected: 0,
97
+ showHidden: false,
98
+ opened: null,
99
+ },
100
+ });
101
+
102
+ function clamp(value: number, min: number, max: number) {
103
+ return Math.max(min, Math.min(max, value));
104
+ }
105
+
106
+ function joinPath(base: string, name: string): string {
107
+ if (base === "/") return `/${name}`;
108
+ return `${base}/${name}`;
109
+ }
110
+
111
+ function parentPath(path: string): string {
112
+ if (path === "/") return "/";
113
+ const parts = path.split("/").filter(Boolean);
114
+ parts.pop();
115
+ return `/${parts.join("/")}` || "/";
116
+ }
117
+
118
+ function listEntries(state: State): Entry[] {
119
+ const entries = tree[state.path] ?? [];
120
+ if (state.showHidden) return entries;
121
+ return entries.filter((entry) => !entry.name.startsWith("."));
122
+ }
123
+
124
+ function panel(title: string, children: ReturnType<typeof ui.column>[], flex = 1) {
125
+ return ui.box(
126
+ { title, flex, border: "rounded", px: 1, py: 0, style: { bg: colors.panel, fg: colors.muted } },
127
+ children,
128
+ );
129
+ }
130
+
131
+ app.view((state) => {
132
+ const entries = listEntries(state);
133
+ const selected = entries[state.selected];
134
+ const preview = selected?.preview || "Select a file to preview.";
135
+
136
+ return ui.column({ flex: 1, p: 1, gap: 1, items: "stretch" }, [
137
+ ui.row({ justify: "between", items: "center" }, [
138
+ ui.text("__APP_NAME__", { fg: colors.accent, bold: true }),
139
+ ui.text(`Path: ${state.path}`, { fg: colors.muted }),
140
+ ]),
141
+
142
+ ui.row({ flex: 1, gap: 1, items: "stretch" }, [
143
+ panel(
144
+ "Files",
145
+ [
146
+ ui.column(
147
+ { gap: 0 },
148
+ entries.map((entry, index) => {
149
+ const active = index === state.selected;
150
+ const prefix = active ? ">" : " ";
151
+ const marker = entry.type === "dir" ? "[D]" : "[F]";
152
+ return ui.text(`${prefix} ${marker} ${entry.name}`, {
153
+ key: entry.name,
154
+ fg: active ? colors.accent : colors.muted,
155
+ bold: active,
156
+ });
157
+ }),
158
+ ),
159
+ ],
160
+ 1,
161
+ ),
162
+
163
+ panel(
164
+ "Details",
165
+ [
166
+ ui.column({ gap: 1 }, [
167
+ ui.text(selected ? selected.name : "-", { fg: colors.accent, bold: true }),
168
+ ui.text(`Type: ${selected?.type ?? "-"}`),
169
+ ui.text(`Size: ${selected?.size ?? "-"}`),
170
+ ui.text(`Modified: ${selected?.modified ?? "-"}`),
171
+ ui.divider({ char: "-" }),
172
+ ui.text("Preview", { fg: colors.muted }),
173
+ ui.text(preview),
174
+ ]),
175
+ ],
176
+ 2,
177
+ ),
178
+
179
+ panel(
180
+ "Pinned",
181
+ [
182
+ ui.column({ gap: 1 }, [
183
+ ui.text("Last opened", { fg: colors.muted }),
184
+ ui.text(state.opened ?? "-"),
185
+ ui.text(""),
186
+ ui.text("Hidden files"),
187
+ ui.text(state.showHidden ? "Visible" : "Hidden"),
188
+ ]),
189
+ ],
190
+ 1,
191
+ ),
192
+ ]),
193
+
194
+ ui.box({ px: 1, py: 0, style: { bg: colors.ink, fg: colors.muted } }, [
195
+ ui.row({ justify: "between", items: "center" }, [
196
+ ui.text("File browser ready"),
197
+ ui.row({ gap: 1 }, [
198
+ ui.kbd("up"),
199
+ ui.text("Move"),
200
+ ui.kbd("enter"),
201
+ ui.text("Open"),
202
+ ui.kbd("backspace"),
203
+ ui.text("Up"),
204
+ ui.kbd("h"),
205
+ ui.text("Hidden"),
206
+ ui.kbd("q"),
207
+ ui.text("Quit"),
208
+ ]),
209
+ ]),
210
+ ]),
211
+ ]);
212
+ });
213
+
214
+ app.keys({
215
+ q: () => app.stop(),
216
+ "ctrl+c": () => app.stop(),
217
+ up: () =>
218
+ app.update((s) => {
219
+ const entries = listEntries(s);
220
+ return { ...s, selected: clamp(s.selected - 1, 0, Math.max(0, entries.length - 1)) };
221
+ }),
222
+ down: () =>
223
+ app.update((s) => {
224
+ const entries = listEntries(s);
225
+ return { ...s, selected: clamp(s.selected + 1, 0, Math.max(0, entries.length - 1)) };
226
+ }),
227
+ k: () =>
228
+ app.update((s) => {
229
+ const entries = listEntries(s);
230
+ return { ...s, selected: clamp(s.selected - 1, 0, Math.max(0, entries.length - 1)) };
231
+ }),
232
+ j: () =>
233
+ app.update((s) => {
234
+ const entries = listEntries(s);
235
+ return { ...s, selected: clamp(s.selected + 1, 0, Math.max(0, entries.length - 1)) };
236
+ }),
237
+ h: () => app.update((s) => ({ ...s, showHidden: !s.showHidden, selected: 0 })),
238
+ backspace: () =>
239
+ app.update((s) => ({
240
+ ...s,
241
+ path: parentPath(s.path),
242
+ selected: 0,
243
+ })),
244
+ enter: () =>
245
+ app.update((s) => {
246
+ const entries = listEntries(s);
247
+ const entry = entries[s.selected];
248
+ if (!entry) return s;
249
+ if (entry.type === "dir") {
250
+ return { ...s, path: joinPath(s.path, entry.name), selected: 0 };
251
+ }
252
+ return { ...s, opened: joinPath(s.path, entry.name) };
253
+ }),
254
+ });
255
+
256
+ await app.start();
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Bundler",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "types": ["node"],
10
+ "noUncheckedIndexedAccess": true,
11
+ "exactOptionalPropertyTypes": true
12
+ },
13
+ "include": ["src/**/*.ts"]
14
+ }
@@ -0,0 +1,18 @@
1
+ # __APP_NAME__
2
+
3
+ Scaffolded with `npm create rezi` using the **__TEMPLATE_LABEL__** template.
4
+
5
+ ## Quickstart
6
+
7
+ ```bash
8
+ npm install
9
+ npm start
10
+ ```
11
+
12
+ ## Keybindings
13
+
14
+ - `tab`: Move focus between fields
15
+ - `ctrl+s`: Save
16
+ - `ctrl+r`: Reset form
17
+ - `ctrl+up` / `ctrl+down`: Switch section
18
+ - `q`: Quit
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "__PACKAGE_NAME__",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "start": "tsx src/main.ts",
8
+ "dev": "tsx watch src/main.ts",
9
+ "typecheck": "tsc --noEmit"
10
+ },
11
+ "dependencies": {
12
+ "@rezi-ui/core": "^0.1.0-alpha.0",
13
+ "@rezi-ui/node": "^0.1.0-alpha.0"
14
+ },
15
+ "devDependencies": {
16
+ "@types/node": "^22.13.1",
17
+ "tsx": "^4.20.0",
18
+ "typescript": "^5.6.3"
19
+ },
20
+ "engines": {
21
+ "node": ">=18"
22
+ }
23
+ }