hacklab 0.4.2 → 0.5.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.
@@ -0,0 +1,214 @@
1
+ import * as clack from '@clack/prompts';
2
+ import { loadSession } from '../session.js';
3
+ import { bold, dim, error, info, success } from '../ui.js';
4
+ const FIELDS = [
5
+ { key: 'name', label: 'Name', type: 'text' },
6
+ { key: 'slug', label: 'Slug (URL handle)', type: 'text' },
7
+ { key: 'logoUrl', label: 'Logo URL', type: 'url' },
8
+ { key: 'website', label: 'Website', type: 'url' },
9
+ { key: 'description', label: 'Short description', type: 'text' },
10
+ { key: 'longDescription', label: 'Long description', type: 'text' },
11
+ { key: 'ycBatch', label: 'YC batch', type: 'text' },
12
+ { key: 'ycSlug', label: 'YC slug', type: 'text' },
13
+ { key: 'ycUrl', label: 'YC URL', type: 'url' },
14
+ { key: 'waasUrl', label: 'WaaS URL', type: 'url' },
15
+ { key: 'teamSize', label: 'Team size', type: 'number' },
16
+ { key: 'status', label: 'Status', type: 'text' },
17
+ { key: 'stage', label: 'Stage', type: 'text' },
18
+ { key: 'isHiring', label: 'Hiring?', type: 'boolean' },
19
+ { key: 'industries', label: 'Industries', type: 'list' },
20
+ { key: 'tags', label: 'Tags', type: 'list' },
21
+ { key: 'locations', label: 'Locations', type: 'list' },
22
+ ];
23
+ // Short, human label for the current value (shown as a select-menu hint).
24
+ function displayValue(spec, value) {
25
+ if (value == null || value === '')
26
+ return '(empty)';
27
+ if (spec.type === 'boolean')
28
+ return value ? 'yes' : 'no';
29
+ if (spec.type === 'list') {
30
+ return Array.isArray(value) ? value.join(', ') || '(empty)' : String(value);
31
+ }
32
+ const s = String(value);
33
+ return s.length > 48 ? `${s.slice(0, 47)}…` : s;
34
+ }
35
+ async function fetchOrgs(session) {
36
+ const res = await fetch(`${session.appUrl}/api/cli/org`, {
37
+ headers: { Authorization: `Bearer ${session.token}` },
38
+ });
39
+ const data = await res.json().catch(() => null);
40
+ if (!res.ok) {
41
+ throw new Error(data?.error ?? `failed to load organizations (${res.status})`);
42
+ }
43
+ return (data?.organizations ?? []);
44
+ }
45
+ async function patchOrg(session, orgId, fields) {
46
+ const res = await fetch(`${session.appUrl}/api/cli/org`, {
47
+ method: 'PATCH',
48
+ headers: {
49
+ 'Content-Type': 'application/json',
50
+ Authorization: `Bearer ${session.token}`,
51
+ },
52
+ body: JSON.stringify({ orgId, fields }),
53
+ });
54
+ const data = await res.json().catch(() => null);
55
+ if (!res.ok) {
56
+ throw new Error(data?.error ?? `update failed (${res.status})`);
57
+ }
58
+ return data;
59
+ }
60
+ // Prompt for one field, prefilled with the current value. Returns the new
61
+ // value to send, or a clack cancel symbol.
62
+ async function promptField(spec, current) {
63
+ if (spec.type === 'boolean') {
64
+ return clack.confirm({
65
+ message: spec.label,
66
+ initialValue: Boolean(current),
67
+ });
68
+ }
69
+ if (spec.type === 'list') {
70
+ const initial = Array.isArray(current) ? current.join(', ') : '';
71
+ const value = await clack.text({
72
+ message: `${spec.label} ${dim('(comma-separated, blank to clear)')}`,
73
+ initialValue: initial,
74
+ });
75
+ if (clack.isCancel(value))
76
+ return value;
77
+ const items = value
78
+ .split(',')
79
+ .map((s) => s.trim())
80
+ .filter(Boolean);
81
+ return items.length ? items : null;
82
+ }
83
+ if (spec.type === 'number') {
84
+ const value = await clack.text({
85
+ message: `${spec.label} ${dim('(blank to clear)')}`,
86
+ initialValue: current == null ? '' : String(current),
87
+ validate: (v) => {
88
+ const t = (v ?? '').trim();
89
+ return !t || /^\d+$/.test(t) ? undefined : 'must be a whole number';
90
+ },
91
+ });
92
+ if (clack.isCancel(value))
93
+ return value;
94
+ return value.trim() ? Number(value.trim()) : null;
95
+ }
96
+ const value = await clack.text({
97
+ message: spec.type === 'url'
98
+ ? `${spec.label} ${dim('(blank to clear)')}`
99
+ : spec.label,
100
+ initialValue: current == null ? '' : String(current),
101
+ validate: spec.type === 'url'
102
+ ? (v) => {
103
+ const t = (v ?? '').trim();
104
+ if (!t)
105
+ return undefined;
106
+ try {
107
+ new URL(t);
108
+ return undefined;
109
+ }
110
+ catch {
111
+ return 'must be a valid URL (include https://)';
112
+ }
113
+ }
114
+ : undefined,
115
+ });
116
+ if (clack.isCancel(value))
117
+ return value;
118
+ const trimmed = value.trim();
119
+ // name/slug are required (notNull): a blank keeps the current value.
120
+ if ((spec.key === 'name' || spec.key === 'slug') && !trimmed)
121
+ return current;
122
+ return trimmed ? trimmed : null;
123
+ }
124
+ export async function org() {
125
+ const session = await loadSession();
126
+ if (!session) {
127
+ error('not logged in');
128
+ info(`run ${dim('hacklab login')} first`);
129
+ process.exit(1);
130
+ }
131
+ clack.intro(bold('hacklab org'));
132
+ let orgs;
133
+ try {
134
+ orgs = await fetchOrgs(session);
135
+ }
136
+ catch (err) {
137
+ clack.cancel(err instanceof Error ? err.message : String(err));
138
+ process.exit(1);
139
+ }
140
+ if (orgs.length === 0) {
141
+ clack.cancel(`you don't manage an organization yet — claim one at ${session.appUrl} first.`);
142
+ process.exit(1);
143
+ }
144
+ let target = orgs[0];
145
+ if (orgs.length > 1) {
146
+ const picked = await clack.select({
147
+ message: 'which organization?',
148
+ options: orgs.map((o) => ({
149
+ value: o.id,
150
+ label: `${o.name} ${dim(`/o/${o.slug}`)}`,
151
+ })),
152
+ });
153
+ if (clack.isCancel(picked)) {
154
+ clack.outro(dim('cancelled.'));
155
+ return;
156
+ }
157
+ target = orgs.find((o) => o.id === picked) ?? target;
158
+ }
159
+ // Autosave: editing a field writes it immediately (mirrors the web settings'
160
+ // "saves instantly, no Save button"). Pick a field, set its value, it saves,
161
+ // and the menu shows the saved value. Leave any time with "done" or Esc —
162
+ // nothing is pending, so nothing is lost.
163
+ const DONE = '__done__';
164
+ let savedCount = 0;
165
+ while (true) {
166
+ const choice = await clack.select({
167
+ message: `editing ${bold(target.name)} ${dim('(saves as you go)')}`,
168
+ options: [
169
+ ...FIELDS.map((f) => ({
170
+ value: f.key,
171
+ label: f.label,
172
+ hint: displayValue(f, target[f.key]),
173
+ })),
174
+ { value: DONE, label: '← done' },
175
+ ],
176
+ });
177
+ // Esc / Ctrl+C at the menu, or "done": leave. Every edit is already saved.
178
+ if (clack.isCancel(choice) || choice === DONE)
179
+ break;
180
+ const spec = FIELDS.find((f) => f.key === choice);
181
+ if (!spec)
182
+ continue;
183
+ const next = await promptField(spec, target[spec.key]);
184
+ // Cancelling a single field drops just that edit and returns to the menu.
185
+ if (clack.isCancel(next))
186
+ continue;
187
+ const label = spec.label.toLowerCase();
188
+ const prevSlug = target.slug;
189
+ const spin = clack.spinner();
190
+ spin.start(`saving ${label}`);
191
+ try {
192
+ const updated = await patchOrg(session, target.id, {
193
+ [spec.key]: next,
194
+ });
195
+ target = { ...target, ...updated };
196
+ savedCount++;
197
+ spin.stop(`saved ${label}`);
198
+ if (spec.key === 'slug' && target.slug !== prevSlug) {
199
+ clack.log.warn(`old links to /o/${prevSlug} will no longer resolve`);
200
+ }
201
+ }
202
+ catch (err) {
203
+ spin.stop(`could not save ${label}`);
204
+ error(err instanceof Error ? err.message : String(err));
205
+ // Stay in the loop so they can retry or edit something else.
206
+ }
207
+ }
208
+ if (savedCount > 0) {
209
+ success(`saved ${savedCount} change${savedCount === 1 ? '' : 's'} to ${bold(target.name)}`);
210
+ info(`${session.appUrl}/o/${target.slug}`);
211
+ }
212
+ clack.outro(dim('done.'));
213
+ }
214
+ //# sourceMappingURL=org.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"org.js","sourceRoot":"","sources":["../../src/commands/org.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,13 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import { brag, parseBragArgs } from './commands/brag.js';
3
+ import { chat } from './commands/chat.js';
3
4
  import { configCommand } from './commands/config.js';
4
5
  import { drop } from './commands/drop.js';
5
6
  import { exam } from './commands/exam.js';
6
7
  import { join } from './commands/join.js';
7
8
  import { login } from './commands/login.js';
9
+ import { org } from './commands/org.js';
8
10
  import { scanProfile } from './commands/scan-profile.js';
9
11
  import { sync } from './commands/sync.js';
10
12
  import { whoami } from './commands/whoami.js';
13
+ import { resolveCommand } from './resolve-command.js';
11
14
  import { HACKLAB_ENVIRONMENTS, isHacklabEnv, loadSession } from './session.js';
12
15
  import { banner, bold, dim } from './ui.js';
13
16
  /**
@@ -54,6 +57,8 @@ function printHelp() {
54
57
  console.log(` hacklab ${dim('scan')} build your full profile (skills, repos, blog)`);
55
58
  console.log(` hacklab ${dim('config')} ${dim('<key> <val>')} set config (cursor-api-key, cursor-email)`);
56
59
  console.log(` hacklab ${dim('brag')} ${dim('[path]')} sync .hacklab/project.yaml`);
60
+ console.log(` hacklab ${dim('org')} edit your organization`);
61
+ console.log(` hacklab ${dim('chat')} ${dim('<sub>')} channel + DMs (tail/post/dm/...); --json for agents`);
57
62
  console.log('');
58
63
  console.log(` ${dim('--env')} ${dim('<production|staging|development>')} pick the backend (default: production)`);
59
64
  console.log('');
@@ -78,7 +83,7 @@ async function main() {
78
83
  process.exit(0);
79
84
  }
80
85
  if (cmd === '--version' || cmd === '-v') {
81
- console.log('0.4.2');
86
+ console.log('0.5.0');
82
87
  process.exit(0);
83
88
  }
84
89
  // Bare invocation (e.g. `npx hacklab@latest`): join for newcomers, sync for
@@ -93,37 +98,52 @@ async function main() {
93
98
  }
94
99
  return;
95
100
  }
96
- if (cmd === 'join') {
101
+ // Resolve a possibly-abbreviated command to its full name (e.g. `sy` -> sync,
102
+ // `or` -> org). Exact matches always win; an ambiguous prefix is
103
+ // rejected with the candidates so the user can disambiguate.
104
+ const resolution = resolveCommand(cmd);
105
+ if (resolution.kind === 'ambiguous') {
106
+ console.error(`ambiguous command "${cmd}": ${resolution.matches.join(' or ')}?`);
107
+ process.exit(1);
108
+ }
109
+ const command = resolution.kind === 'match' ? resolution.name : cmd;
110
+ if (command === 'join') {
97
111
  await join();
98
112
  }
99
- else if (cmd === 'login') {
113
+ else if (command === 'login') {
100
114
  await login();
101
115
  }
102
- else if (cmd === 'whoami') {
116
+ else if (command === 'whoami') {
103
117
  await whoami();
104
118
  }
105
- else if (cmd === 'sync') {
119
+ else if (command === 'sync') {
106
120
  await sync();
107
121
  }
108
- else if (cmd === 'drop') {
122
+ else if (command === 'drop') {
109
123
  const content = parseDropArgs(args);
110
124
  await drop(content.text, content.url);
111
125
  }
112
- else if (cmd === 'exam') {
126
+ else if (command === 'exam') {
113
127
  const pyro = args.includes('--pyro');
114
128
  const hacker = args.includes('--hacker');
115
129
  await exam({ pyro, hacker });
116
130
  }
117
- else if (cmd === 'scan') {
131
+ else if (command === 'scan') {
118
132
  await scanProfile();
119
133
  }
120
- else if (cmd === 'config') {
134
+ else if (command === 'config') {
121
135
  await configCommand(args);
122
136
  }
123
- else if (cmd === 'brag') {
137
+ else if (command === 'brag') {
124
138
  const options = parseBragArgs(args);
125
139
  await brag(options.manifestPath);
126
140
  }
141
+ else if (command === 'org') {
142
+ await org();
143
+ }
144
+ else if (command === 'chat') {
145
+ await chat(args);
146
+ }
127
147
  else {
128
148
  console.error(`unknown command: ${cmd}`);
129
149
  console.error('run hacklab --help for usage');
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export declare const COMMANDS: readonly ["join", "login", "whoami", "sync", "drop", "exam", "scan", "config", "brag", "org", "chat"];
2
+ export type ResolvedCommand = {
3
+ kind: 'match';
4
+ name: string;
5
+ } | {
6
+ kind: 'ambiguous';
7
+ matches: string[];
8
+ } | {
9
+ kind: 'unknown';
10
+ };
11
+ /**
12
+ * Resolve a (possibly abbreviated) command token to a full command name by
13
+ * shortest unambiguous prefix:
14
+ * - an exact match always wins, so a full command is never shadowed by a longer
15
+ * one (e.g. if `scan` and `scanner` both existed, `scan` resolves to `scan`);
16
+ * - a prefix that matches exactly one command resolves to it (`sy` -> sync);
17
+ * - a prefix matching several is ambiguous (`s` -> sync | scan);
18
+ * - a token matching none is unknown (a typo like `ogr` does not resolve).
19
+ */
20
+ export declare function resolveCommand(token: string, commands?: readonly string[]): ResolvedCommand;
21
+ //# sourceMappingURL=resolve-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-command.d.ts","sourceRoot":"","sources":["../src/resolve-command.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,QAAQ,uGAYX,CAAA;AAEV,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAA;AAEvB;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,SAAS,MAAM,EAAa,GACrC,eAAe,CAOjB"}
@@ -0,0 +1,36 @@
1
+ // All top-level hacklab subcommands. Used both to dispatch and to resolve a
2
+ // typed prefix to its full name (e.g. `sy` -> sync). Keep in sync with the
3
+ // dispatch chain in index.ts.
4
+ export const COMMANDS = [
5
+ 'join',
6
+ 'login',
7
+ 'whoami',
8
+ 'sync',
9
+ 'drop',
10
+ 'exam',
11
+ 'scan',
12
+ 'config',
13
+ 'brag',
14
+ 'org',
15
+ 'chat',
16
+ ];
17
+ /**
18
+ * Resolve a (possibly abbreviated) command token to a full command name by
19
+ * shortest unambiguous prefix:
20
+ * - an exact match always wins, so a full command is never shadowed by a longer
21
+ * one (e.g. if `scan` and `scanner` both existed, `scan` resolves to `scan`);
22
+ * - a prefix that matches exactly one command resolves to it (`sy` -> sync);
23
+ * - a prefix matching several is ambiguous (`s` -> sync | scan);
24
+ * - a token matching none is unknown (a typo like `ogr` does not resolve).
25
+ */
26
+ export function resolveCommand(token, commands = COMMANDS) {
27
+ if (commands.includes(token))
28
+ return { kind: 'match', name: token };
29
+ const matches = commands.filter((c) => c.startsWith(token));
30
+ if (matches.length === 1)
31
+ return { kind: 'match', name: matches[0] };
32
+ if (matches.length > 1)
33
+ return { kind: 'ambiguous', matches };
34
+ return { kind: 'unknown' };
35
+ }
36
+ //# sourceMappingURL=resolve-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-command.js","sourceRoot":"","sources":["../src/resolve-command.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,2EAA2E;AAC3E,8BAA8B;AAC9B,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,MAAM;IACN,OAAO;IACP,QAAQ;IACR,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,QAAQ;IACR,MAAM;IACN,KAAK;IACL,MAAM;CACE,CAAA;AAOV;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAC5B,KAAa,EACb,WAA8B,QAAQ;IAEtC,IAAI,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAA;IAEnE,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAA;IAC3D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAE,EAAE,CAAA;IACrE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAA;IAC7D,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAA;AAC5B,CAAC"}
@@ -0,0 +1,19 @@
1
+ export declare const BELT_COLOR_HEX: Record<string, string>;
2
+ /** Unknown / missing belt falls back to the white-belt hex (matches the web). */
3
+ export declare const DEFAULT_ACCENT_HEX = "#E8E8E8";
4
+ export type Accent = {
5
+ solid: string;
6
+ alpha: (a: number) => string;
7
+ };
8
+ export declare function hexToRgb(hex: string): {
9
+ r: number;
10
+ g: number;
11
+ b: number;
12
+ };
13
+ /**
14
+ * The accent for a belt/rank colour: the solid hue plus an alpha() helper that
15
+ * reuses the original mint opacities (0.1 track, 0.18/0.38/0.62/1 heat tiers) in
16
+ * this hue, so only the colour changes, not the relative brightness.
17
+ */
18
+ export declare function accentShades(beltColor: string): Accent;
19
+ //# sourceMappingURL=share-card-colors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"share-card-colors.d.ts","sourceRoot":"","sources":["../src/share-card-colors.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAYjD,CAAA;AAED,iFAAiF;AACjF,eAAO,MAAM,kBAAkB,YAAY,CAAA;AAE3C,MAAM,MAAM,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;CAAE,CAAA;AAEpE,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAKzE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAItD"}
@@ -0,0 +1,36 @@
1
+ // Accent palette for the share card. The accent is the user's belt/rank colour
2
+ // (same hex values as the web profile's BELT_COLOR_HEX), so the card reads
3
+ // identically to hacklab.so/<handle>. Kept separate from share-card.tsx so it's
4
+ // testable without loading the satori/resvg renderer.
5
+ export const BELT_COLOR_HEX = {
6
+ white: '#E8E8E8',
7
+ orange: '#FF8C00',
8
+ red: '#DC2626',
9
+ blue: '#2563EB',
10
+ cyan: '#06B6D4',
11
+ yellow: '#EAB308',
12
+ lime: '#84CC16',
13
+ green: '#22C55E',
14
+ pink: '#EC4899',
15
+ purple: '#A855F7',
16
+ black: '#FFFFFF',
17
+ };
18
+ /** Unknown / missing belt falls back to the white-belt hex (matches the web). */
19
+ export const DEFAULT_ACCENT_HEX = '#E8E8E8';
20
+ export function hexToRgb(hex) {
21
+ const h = hex.replace('#', '');
22
+ const full = h.length === 3 ? h.replace(/(.)/g, '$1$1') : h;
23
+ const n = Number.parseInt(full, 16);
24
+ return { r: (n >> 16) & 255, g: (n >> 8) & 255, b: n & 255 };
25
+ }
26
+ /**
27
+ * The accent for a belt/rank colour: the solid hue plus an alpha() helper that
28
+ * reuses the original mint opacities (0.1 track, 0.18/0.38/0.62/1 heat tiers) in
29
+ * this hue, so only the colour changes, not the relative brightness.
30
+ */
31
+ export function accentShades(beltColor) {
32
+ const hex = BELT_COLOR_HEX[beltColor] ?? DEFAULT_ACCENT_HEX;
33
+ const { r, g, b } = hexToRgb(hex);
34
+ return { solid: hex, alpha: (a) => `rgba(${r}, ${g}, ${b}, ${a})` };
35
+ }
36
+ //# sourceMappingURL=share-card-colors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"share-card-colors.js","sourceRoot":"","sources":["../src/share-card-colors.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,2EAA2E;AAC3E,gFAAgF;AAChF,sDAAsD;AAEtD,MAAM,CAAC,MAAM,cAAc,GAA2B;IACpD,KAAK,EAAE,SAAS;IAChB,MAAM,EAAE,SAAS;IACjB,GAAG,EAAE,SAAS;IACd,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,SAAS;IACjB,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,SAAS;IAChB,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,SAAS;CACjB,CAAA;AAED,iFAAiF;AACjF,MAAM,CAAC,MAAM,kBAAkB,GAAG,SAAS,CAAA;AAI3C,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IAC9B,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAC3D,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;IACnC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAA;AAC9D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,SAAiB;IAC5C,MAAM,GAAG,GAAG,cAAc,CAAC,SAAS,CAAC,IAAI,kBAAkB,CAAA;IAC3D,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;IACjC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,CAAA;AACrE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"share-card.d.ts","sourceRoot":"","sources":["../src/share-card.tsx"],"names":[],"mappings":"AAwCA,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAqBlD;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE;QACb,UAAU,EAAE,MAAM,CAAA;QAClB,KAAK,EAAE,MAAM,CAAA;QACb,MAAM,EAAE,MAAM,CAAA;KACf,CAAA;IACD,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC/C,aAAa,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACvD,CAAA;AA2dD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CA4C5E;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CA4C5D;AAED,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CASzE"}
1
+ {"version":3,"file":"share-card.d.ts","sourceRoot":"","sources":["../src/share-card.tsx"],"names":[],"mappings":"AAwCA,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAqBlD;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE;QACb,UAAU,EAAE,MAAM,CAAA;QAClB,KAAK,EAAE,MAAM,CAAA;QACb,MAAM,EAAE,MAAM,CAAA;KACf,CAAA;IACD,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC/C,aAAa,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACvD,CAAA;AAkeD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CA4C5E;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CA4C5D;AAED,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CASzE"}
@@ -5,13 +5,13 @@ import { homedir } from 'node:os';
5
5
  import { join } from 'node:path';
6
6
  import { Resvg } from '@resvg/resvg-js';
7
7
  import satori from 'satori';
8
+ import { accentShades } from './share-card-colors.js';
8
9
  // ── Design tokens (DESIGN.md) ──────────────────────────────────────────────
9
- // Phosphor Mint is the one signal colour: corner brackets, the belt progress
10
- // bar, the ASCII proficiency bars, and the lit heatmap cells. Everything else
11
- // is neutral graphite + grey. Numbers + the nametag are Orbitron; every other
12
- // glyph is JetBrains Mono.
13
- const ACCENT = '#82F5C6';
14
- const ACCENT_TRACK = 'rgba(130,245,198,0.1)'; // unfilled bar / belt track
10
+ // The accent is the user's belt/rank colour (same palette as the web profile),
11
+ // so the card reads identically to hacklab.so/<handle>. It's the one signal
12
+ // colour: corner brackets, the belt + proficiency bars, and the lit heatmap
13
+ // cells. Everything else is neutral graphite + grey. Numbers + the nametag are
14
+ // Orbitron; every other glyph is JetBrains Mono.
15
15
  const PAGE_BG = '#0B0D0C';
16
16
  const CARD_BG = '#101513';
17
17
  const BORDER = '#1D221F';
@@ -99,7 +99,7 @@ function buildMatrix(daily) {
99
99
  return r > 0.75 ? 4 : r > 0.5 ? 3 : r > 0.25 ? 2 : 1;
100
100
  }));
101
101
  }
102
- function Heatmap({ matrix }) {
102
+ function Heatmap({ matrix, accent }) {
103
103
  return (_jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: HEAT_GAP }, children: matrix.map((row) => (
104
104
  // biome-ignore lint/correctness/useJsxKeyInIterable: satori has no keys
105
105
  _jsx("div", { style: { display: 'flex', gap: HEAT_GAP }, children: row.map((tier) => tier === 0 ? (
@@ -115,29 +115,29 @@ function Heatmap({ matrix }) {
115
115
  display: 'flex',
116
116
  width: 3,
117
117
  height: 3,
118
- backgroundColor: 'rgba(130,245,198,0.35)',
118
+ backgroundColor: accent.alpha(0.35),
119
119
  } }) })) : (
120
120
  // biome-ignore lint/correctness/useJsxKeyInIterable: satori has no keys
121
121
  _jsx("div", { style: {
122
122
  display: 'flex',
123
123
  width: HEAT_CELL,
124
124
  height: HEAT_CELL,
125
- backgroundColor: `rgba(130,245,198,${TIER_OPACITY[tier]})`,
125
+ backgroundColor: accent.alpha(TIER_OPACITY[tier] ?? 0),
126
126
  } }))) }))) }));
127
127
  }
128
128
  // ── Proficiency bar: solid mint fill over a 10%-mint track. ──────────────────
129
- function Bar({ pct }) {
129
+ function Bar({ pct, accent }) {
130
130
  const fill = Math.max(0, Math.min(100, pct));
131
131
  return (_jsx("div", { style: {
132
132
  display: 'flex',
133
133
  width: 64,
134
134
  height: 6,
135
- backgroundColor: ACCENT_TRACK,
135
+ backgroundColor: accent.alpha(0.1),
136
136
  }, children: _jsx("div", { style: {
137
137
  display: 'flex',
138
138
  height: 6,
139
139
  width: `${fill}%`,
140
- backgroundColor: ACCENT,
140
+ backgroundColor: accent.solid,
141
141
  } }) }));
142
142
  }
143
143
  function StatCard({ value, label }) {
@@ -189,7 +189,7 @@ function PillStat({ value, label }) {
189
189
  color: LABEL,
190
190
  }, children: label })] }));
191
191
  }
192
- function CornerBracket({ pos }) {
192
+ function CornerBracket({ pos, accent, }) {
193
193
  const arm = 11;
194
194
  const thick = 2;
195
195
  const inset = 0;
@@ -202,8 +202,8 @@ function CornerBracket({ pos }) {
202
202
  height: arm,
203
203
  [vert]: inset,
204
204
  [horiz]: inset,
205
- [`border${vert === 'top' ? 'Top' : 'Bottom'}`]: `${thick}px solid ${ACCENT}`,
206
- [`border${horiz === 'left' ? 'Left' : 'Right'}`]: `${thick}px solid ${ACCENT}`,
205
+ [`border${vert === 'top' ? 'Top' : 'Bottom'}`]: `${thick}px solid ${accent.solid}`,
206
+ [`border${horiz === 'left' ? 'Left' : 'Right'}`]: `${thick}px solid ${accent.solid}`,
207
207
  } }));
208
208
  }
209
209
  function ShareCard({ data, matrix, avatar, }) {
@@ -212,6 +212,7 @@ function ShareCard({ data, matrix, avatar, }) {
212
212
  const cost = Math.round(data.estimatedCost).toLocaleString('en-US');
213
213
  const progress = Math.max(0, Math.min(100, data.progressPercent));
214
214
  const initial = (data.handle[0] ?? '?').toUpperCase();
215
+ const accent = accentShades(data.beltColor);
215
216
  return (_jsxs("div", { style: {
216
217
  position: 'relative',
217
218
  width: 800,
@@ -222,7 +223,7 @@ function ShareCard({ data, matrix, avatar, }) {
222
223
  padding: 16,
223
224
  fontFamily: 'JetBrains Mono',
224
225
  color: WHITE,
225
- }, children: [_jsx(CornerBracket, { pos: 'tl' }), _jsx(CornerBracket, { pos: 'tr' }), _jsx(CornerBracket, { pos: 'bl' }), _jsx(CornerBracket, { pos: 'br' }), _jsxs("div", { style: {
226
+ }, children: [_jsx(CornerBracket, { pos: 'tl', accent: accent }), _jsx(CornerBracket, { pos: 'tr', accent: accent }), _jsx(CornerBracket, { pos: 'bl', accent: accent }), _jsx(CornerBracket, { pos: 'br', accent: accent }), _jsxs("div", { style: {
226
227
  display: 'flex',
227
228
  height: 70,
228
229
  alignItems: 'center',
@@ -247,7 +248,7 @@ function ShareCard({ data, matrix, avatar, }) {
247
248
  fontFamily: 'Orbitron',
248
249
  fontWeight: 700,
249
250
  fontSize: 22,
250
- color: ACCENT,
251
+ color: accent.solid,
251
252
  }, children: initial })) }), _jsxs("div", { style: {
252
253
  display: 'flex',
253
254
  fontFamily: 'Orbitron',
@@ -266,12 +267,12 @@ function ShareCard({ data, matrix, avatar, }) {
266
267
  display: 'flex',
267
268
  width: 104,
268
269
  height: 8,
269
- backgroundColor: ACCENT_TRACK,
270
+ backgroundColor: accent.alpha(0.1),
270
271
  }, children: _jsx("div", { style: {
271
272
  display: 'flex',
272
273
  width: `${progress}%`,
273
274
  height: 8,
274
- backgroundColor: ACCENT,
275
+ backgroundColor: accent.solid,
275
276
  } }) })] })] }), _jsxs("div", { style: { display: 'flex', height: 114, gap: 26, marginTop: 18 }, children: [_jsx(StatCard, { value: formatTokens(data.tokensTotal), label: 'TOKENS BURNED' }), _jsx(StatCard, { value: `${data.streak}D`, label: 'STREAK' }), _jsx(StatCard, { value: `$${cost}`, label: 'EST. COST' })] }), _jsxs("div", { style: { display: 'flex', height: 142, gap: 18, marginTop: 18 }, children: [_jsx("div", { style: {
276
277
  display: 'flex',
277
278
  width: 284,
@@ -293,14 +294,14 @@ function ShareCard({ data, matrix, avatar, }) {
293
294
  fontSize: 15,
294
295
  letterSpacing: 0.4,
295
296
  color: LABEL_DIM,
296
- }, children: shortModelName(m.name) }), _jsx(Bar, { pct: (m.tokens / modelMax) * 100 })] }))) }), _jsx("div", { style: {
297
+ }, children: shortModelName(m.name) }), _jsx(Bar, { pct: (m.tokens / modelMax) * 100, accent: accent })] }))) }), _jsx("div", { style: {
297
298
  display: 'flex',
298
299
  flex: 1,
299
300
  alignItems: 'center',
300
301
  justifyContent: 'center',
301
302
  backgroundColor: CARD_BG,
302
303
  border: `1px solid ${BORDER}`,
303
- }, children: _jsx(Heatmap, { matrix: matrix }) })] }), _jsxs("div", { style: { display: 'flex', height: 42, gap: 17, marginTop: 18 }, children: [_jsx(PillStat, { value: `${data.longestStreak}D`, label: 'BEST STREAK' }), _jsx(PillStat, { value: `#${data.rank}`, label: 'RANK' }), _jsx(PillStat, { value: String(data.followers ?? 0), label: 'FOLLOWERS' })] }), _jsxs("div", { style: {
304
+ }, children: _jsx(Heatmap, { matrix: matrix, accent: accent }) })] }), _jsxs("div", { style: { display: 'flex', height: 42, gap: 17, marginTop: 18 }, children: [_jsx(PillStat, { value: `${data.longestStreak}D`, label: 'BEST STREAK' }), _jsx(PillStat, { value: `#${data.rank}`, label: 'RANK' }), _jsx(PillStat, { value: String(data.followers ?? 0), label: 'FOLLOWERS' })] }), _jsxs("div", { style: {
304
305
  display: 'flex',
305
306
  justifyContent: 'space-between',
306
307
  marginTop: 'auto',