create-izi-noir 0.2.1 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +358 -130
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import { Command } from "commander";
6
6
  // src/commands/init.ts
7
7
  import path2 from "path";
8
8
  import { execSync } from "child_process";
9
- import pc4 from "picocolors";
9
+ import pc3 from "picocolors";
10
10
 
11
11
  // src/prompts/project.ts
12
12
  import prompts from "prompts";
@@ -17,8 +17,7 @@ var TEMPLATES = [
17
17
  { title: "Balance Proof only", value: "balance-proof" }
18
18
  ];
19
19
  var NETWORKS = [
20
- { title: "Solana (recommended)", value: "solana", description: "Uses Groth16 for on-chain verification" },
21
- { title: "EVM (Ethereum, Base, etc.)", value: "evm", description: "Uses UltraHonk proofs" }
20
+ { title: "Solana", value: "solana", description: "Uses Groth16 for on-chain verification" }
22
21
  ];
23
22
  function networkToProvider(network) {
24
23
  return network === "solana" ? "arkworks" : "barretenberg";
@@ -117,44 +116,8 @@ async function isDirectoryEmpty(dir) {
117
116
  }
118
117
  }
119
118
 
120
- // src/utils/spinner.ts
121
- import pc2 from "picocolors";
122
- var frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
123
- var Spinner = class {
124
- message;
125
- interval = null;
126
- frameIndex = 0;
127
- constructor(message) {
128
- this.message = message;
129
- }
130
- start() {
131
- process.stdout.write("\x1B[?25l");
132
- this.interval = setInterval(() => {
133
- const frame = pc2.cyan(frames[this.frameIndex]);
134
- process.stdout.write(`\r${frame} ${this.message}`);
135
- this.frameIndex = (this.frameIndex + 1) % frames.length;
136
- }, 80);
137
- }
138
- stop(success = true) {
139
- if (this.interval) {
140
- clearInterval(this.interval);
141
- this.interval = null;
142
- }
143
- process.stdout.write("\x1B[?25h");
144
- const icon = success ? pc2.green("\u2713") : pc2.red("\u2717");
145
- process.stdout.write(`\r${icon} ${this.message}
146
- `);
147
- }
148
- update(message) {
149
- this.message = message;
150
- }
151
- };
152
- function createSpinner(message) {
153
- return new Spinner(message);
154
- }
155
-
156
119
  // src/utils/progress.ts
157
- import pc3 from "picocolors";
120
+ import pc2 from "picocolors";
158
121
  var THINKING_PHRASES = [
159
122
  "Initializing ZK environment",
160
123
  "Configuring proof system",
@@ -191,15 +154,15 @@ var ProgressReporter = class {
191
154
  this.showThinking();
192
155
  }
193
156
  showThinking() {
194
- const frames2 = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
157
+ const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
195
158
  let frameIndex = 0;
196
159
  let dotCount = 0;
197
160
  this.thinkingInterval = setInterval(() => {
198
- const frame = pc3.cyan(frames2[frameIndex]);
161
+ const frame = pc2.cyan(frames[frameIndex]);
199
162
  const phrase = THINKING_PHRASES[this.thinkingIndex % THINKING_PHRASES.length];
200
163
  const dots = ".".repeat(dotCount % 4);
201
- process.stdout.write(`\r${frame} ${pc3.dim(phrase)}${dots} `);
202
- frameIndex = (frameIndex + 1) % frames2.length;
164
+ process.stdout.write(`\r${frame} ${pc2.dim(phrase)}${dots} `);
165
+ frameIndex = (frameIndex + 1) % frames.length;
203
166
  dotCount++;
204
167
  if (dotCount % 12 === 0) {
205
168
  this.thinkingIndex++;
@@ -215,29 +178,29 @@ var ProgressReporter = class {
215
178
  }
216
179
  async reportFile(filename, isLast = false) {
217
180
  const icon = getFileIcon(filename);
218
- const line = ` ${icon} ${pc3.dim("created")} ${pc3.white(filename)}`;
219
- process.stdout.write(" " + icon + " " + pc3.dim("created") + " ");
181
+ const line = ` ${icon} ${pc2.dim("created")} ${pc2.white(filename)}`;
182
+ process.stdout.write(" " + icon + " " + pc2.dim("created") + " ");
220
183
  for (const char of filename) {
221
- process.stdout.write(pc3.white(char));
184
+ process.stdout.write(pc2.white(char));
222
185
  await sleep(8 + Math.random() * 12);
223
186
  }
224
187
  process.stdout.write("\n");
225
188
  this.currentLine = line;
226
189
  }
227
190
  async reportDirectory(dirname) {
228
- process.stdout.write(` \u{1F4C1} ${pc3.dim("mkdir")} ${pc3.blue(dirname)}/
191
+ process.stdout.write(` \u{1F4C1} ${pc2.dim("mkdir")} ${pc2.blue(dirname)}/
229
192
  `);
230
193
  await sleep(30);
231
194
  }
232
195
  showSuccess(message) {
233
196
  process.stdout.write("\x1B[?25h");
234
197
  console.log();
235
- console.log(pc3.green("\u2713") + " " + message);
198
+ console.log(pc2.green("\u2713") + " " + message);
236
199
  }
237
200
  showError(message) {
238
201
  process.stdout.write("\x1B[?25h");
239
202
  console.log();
240
- console.log(pc3.red("\u2717") + " " + message);
203
+ console.log(pc2.red("\u2717") + " " + message);
241
204
  }
242
205
  };
243
206
  function createProgressReporter() {
@@ -260,18 +223,18 @@ var InstallProgress = class {
260
223
  start() {
261
224
  process.stdout.write("\x1B[?25l");
262
225
  const barWidth = 30;
263
- const frames2 = ["\u25D0", "\u25D3", "\u25D1", "\u25D2"];
226
+ const frames = ["\u25D0", "\u25D3", "\u25D1", "\u25D2"];
264
227
  let frameIndex = 0;
265
228
  this.interval = setInterval(() => {
266
- const frame = pc3.cyan(frames2[frameIndex]);
229
+ const frame = pc2.cyan(frames[frameIndex]);
267
230
  const filled = Math.floor(this.progress / 100 * barWidth);
268
231
  const empty = barWidth - filled;
269
- const bar = pc3.green("\u2588".repeat(filled)) + pc3.dim("\u2591".repeat(empty));
232
+ const bar = pc2.green("\u2588".repeat(filled)) + pc2.dim("\u2591".repeat(empty));
270
233
  const pkg = this.packages[this.currentPackage % this.packages.length];
271
234
  process.stdout.write(
272
- `\r${frame} Installing dependencies ${bar} ${pc3.dim(pkg)} `
235
+ `\r${frame} Installing dependencies ${bar} ${pc2.dim(pkg)} `
273
236
  );
274
- frameIndex = (frameIndex + 1) % frames2.length;
237
+ frameIndex = (frameIndex + 1) % frames.length;
275
238
  if (this.progress < 95) {
276
239
  this.progress += Math.random() * 3;
277
240
  if (this.progress > (this.currentPackage + 1) * 12) {
@@ -287,7 +250,7 @@ var InstallProgress = class {
287
250
  }
288
251
  process.stdout.write("\x1B[?25h");
289
252
  process.stdout.write("\r\x1B[K");
290
- const icon = success ? pc3.green("\u2713") : pc3.red("\u2717");
253
+ const icon = success ? pc2.green("\u2713") : pc2.red("\u2717");
291
254
  const message = success ? "Dependencies installed" : "Failed to install dependencies";
292
255
  console.log(`${icon} ${message}`);
293
256
  }
@@ -295,17 +258,61 @@ var InstallProgress = class {
295
258
  function createInstallProgress() {
296
259
  return new InstallProgress();
297
260
  }
261
+ var GitProgress = class {
262
+ interval = null;
263
+ phases = [
264
+ "Initializing repository",
265
+ "Setting up version control",
266
+ "Creating .git directory",
267
+ "Configuring git objects",
268
+ "Preparing initial branch"
269
+ ];
270
+ phaseIndex = 0;
271
+ dotCount = 0;
272
+ start() {
273
+ process.stdout.write("\x1B[?25l");
274
+ const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
275
+ let frameIndex = 0;
276
+ this.interval = setInterval(() => {
277
+ const frame = pc2.cyan(frames[frameIndex]);
278
+ const phase = this.phases[this.phaseIndex % this.phases.length];
279
+ const dots = ".".repeat(this.dotCount % 4);
280
+ process.stdout.write(`\r${frame} ${pc2.dim(phase)}${dots} `);
281
+ frameIndex = (frameIndex + 1) % frames.length;
282
+ this.dotCount++;
283
+ if (this.dotCount % 8 === 0) {
284
+ this.phaseIndex++;
285
+ }
286
+ }, 80);
287
+ }
288
+ stop(success = true) {
289
+ if (this.interval) {
290
+ clearInterval(this.interval);
291
+ this.interval = null;
292
+ }
293
+ process.stdout.write("\x1B[?25h");
294
+ process.stdout.write("\r\x1B[K");
295
+ const icon = success ? pc2.green("\u2713") : pc2.red("\u2717");
296
+ const message = success ? "Git repository initialized" : "Failed to initialize git";
297
+ console.log(`${icon} ${message}`);
298
+ }
299
+ };
300
+ function createGitProgress() {
301
+ return new GitProgress();
302
+ }
298
303
 
299
304
  // src/generators/package-json.ts
300
305
  function generatePackageJson(options) {
301
306
  const isSolana = options.provider === "arkworks";
302
307
  const dependencies = {
303
- "@izi-noir/sdk": "^0.1.4",
308
+ "@izi-noir/sdk": "^0.1.5",
304
309
  "@noir-lang/acvm_js": "1.0.0-beta.13-1d260df.nightly",
305
310
  "@noir-lang/noirc_abi": "1.0.0-beta.13-1d260df.nightly",
306
311
  "react": "^18.3.1",
307
312
  "react-dom": "^18.3.1",
308
- "prism-react-renderer": "^2.4.1"
313
+ "prism-react-renderer": "^2.4.1",
314
+ "buffer": "^6.0.3",
315
+ "util": "^0.12.5"
309
316
  };
310
317
  if (isSolana) {
311
318
  dependencies["@solana/wallet-adapter-react"] = "^0.15.0";
@@ -592,14 +599,23 @@ export default defineConfig({
592
599
  alias: {
593
600
  "@": path.resolve(__dirname, "./src"),
594
601
  buffer: "buffer/",
602
+ util: "util/",
595
603
  },
596
604
  },
597
605
  define: {
598
606
  "global": "globalThis",
607
+ "process.env": {},
599
608
  },
600
609
  optimizeDeps: {
601
- exclude: ["@noir-lang/noir_wasm", "@aztec/bb.js", "@izi-noir/sdk"],
602
- include: ["buffer"],
610
+ exclude: [
611
+ "@noir-lang/noir_wasm",
612
+ "@noir-lang/noir_js",
613
+ "@noir-lang/acvm_js",
614
+ "@noir-lang/noirc_abi",
615
+ "@aztec/bb.js",
616
+ "@izi-noir/sdk",
617
+ ],
618
+ include: ["buffer", "util"],
603
619
  },
604
620
  build: {
605
621
  rollupOptions: {
@@ -633,6 +649,9 @@ function generateIndexHtml(options) {
633
649
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
634
650
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
635
651
  <title>${options.projectName} - ZK Proof Demo</title>
652
+ <link rel="preconnect" href="https://fonts.googleapis.com">
653
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
654
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
636
655
  </head>
637
656
  <body>
638
657
  <div id="root"></div>
@@ -765,10 +784,17 @@ import { Chain, Network } from '@izi-noir/sdk';` : "";
765
784
  </div>
766
785
 
767
786
  <div className="verify-box">
787
+ {publicInputs && (
788
+ <div className="public-inputs-display">
789
+ <span>Public inputs:</span>
790
+ <code>{JSON.stringify(publicInputs)}</code>
791
+ </div>
792
+ )}
768
793
  <button
769
794
  onClick={handleVerify}
770
795
  disabled={!vkAccount || isVerifying}
771
796
  className="btn btn-primary"
797
+ style={{ marginTop: publicInputs ? '0.5rem' : 0 }}
772
798
  >
773
799
  {isVerifying ? 'Verifying...' : verified ? 'Verified!' : 'Verify On-Chain'}
774
800
  </button>
@@ -836,6 +862,7 @@ function App() {
836
862
  const [proofTime, setProofTime] = useState<number | null>(null);
837
863
  const [proofError, setProofError] = useState<string | null>(null);
838
864
  const [localVerified, setLocalVerified] = useState<boolean | null>(null);
865
+ const [publicInputs, setPublicInputs] = useState<string[] | null>(null);
839
866
 
840
867
  // IziNoir instance
841
868
  const [iziInstance, setIziInstance] = useState<IziNoir | null>(null);
@@ -852,6 +879,7 @@ ${solanaState}
852
879
  setProof(null);
853
880
  setProofTime(null);
854
881
  setLocalVerified(null);
882
+ setPublicInputs(null);
855
883
  setNoirCode(null);
856
884
  }
857
885
  }, [selectedCircuit]);
@@ -924,6 +952,7 @@ ${solanaState}
924
952
  const endTime = performance.now();
925
953
  setProof(proofBytes);
926
954
  setProofTime(Math.round(endTime - startTime));
955
+ setPublicInputs(publicInputsHex);
927
956
  } catch (error) {
928
957
  console.error('Proof generation error:', error);
929
958
  setProofError((error as Error).message);
@@ -937,7 +966,7 @@ ${solanaHandlers}
937
966
  <div className="app">
938
967
  <header>
939
968
  <h1>${options.projectName}</h1>
940
- <p>Zero-Knowledge Proof Demo</p>
969
+ <p>Built with IZI-NOIR</p>
941
970
  </header>
942
971
 
943
972
  <main>
@@ -1100,29 +1129,65 @@ function capitalizeFirst(str) {
1100
1129
  return str.charAt(0).toUpperCase() + str.slice(1);
1101
1130
  }
1102
1131
  function generateAppCss() {
1103
- return `* {
1132
+ return `/* ================================
1133
+ CSS Variables - IZI-NOIR Theme
1134
+ ================================ */
1135
+ :root {
1136
+ --solana-purple: #9945FF;
1137
+ --solana-green: #14F195;
1138
+ --noir-primary: #050505;
1139
+ --noir-elevated: #0A0A0A;
1140
+ --noir-orange: #FF6B35;
1141
+ --izi-cyan: #00D4FF;
1142
+ --text: #ffffff;
1143
+ --text-muted: #888888;
1144
+ --border: rgba(255, 255, 255, 0.1);
1145
+ }
1146
+
1147
+ /* ================================
1148
+ Reset & Base Styles
1149
+ ================================ */
1150
+ * {
1104
1151
  box-sizing: border-box;
1105
1152
  margin: 0;
1106
1153
  padding: 0;
1107
1154
  }
1108
1155
 
1109
- :root {
1110
- --purple: #9945FF;
1111
- --green: #14F195;
1112
- --bg: #0a0a0a;
1113
- --bg-elevated: #111111;
1114
- --border: #222222;
1115
- --text: #ffffff;
1116
- --text-muted: #888888;
1156
+ html {
1157
+ scroll-behavior: smooth;
1117
1158
  }
1118
1159
 
1119
1160
  body {
1120
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1121
- background: var(--bg);
1161
+ font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
1162
+ background-color: var(--noir-primary);
1163
+ /* Noise texture + radial gradients like the main frontend */
1164
+ background-image:
1165
+ url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.015'/%3E%3C/svg%3E"),
1166
+ radial-gradient(
1167
+ ellipse 60% 40% at 50% 30%,
1168
+ rgba(153, 69, 255, 0.06) 0%,
1169
+ transparent 50%
1170
+ ),
1171
+ radial-gradient(
1172
+ ellipse 80% 50% at 50% 110%,
1173
+ rgba(20, 241, 149, 0.04) 0%,
1174
+ transparent 40%
1175
+ );
1176
+ background-attachment: fixed;
1122
1177
  color: var(--text);
1123
1178
  line-height: 1.6;
1179
+ -webkit-font-smoothing: antialiased;
1180
+ -moz-osx-font-smoothing: grayscale;
1181
+ }
1182
+
1183
+ ::selection {
1184
+ background: rgba(153, 69, 255, 0.3);
1185
+ color: white;
1124
1186
  }
1125
1187
 
1188
+ /* ================================
1189
+ Layout
1190
+ ================================ */
1126
1191
  .app {
1127
1192
  min-height: 100vh;
1128
1193
  display: flex;
@@ -1133,11 +1198,14 @@ header {
1133
1198
  padding: 2rem;
1134
1199
  text-align: center;
1135
1200
  border-bottom: 1px solid var(--border);
1201
+ backdrop-filter: blur(8px);
1202
+ background: rgba(0, 0, 0, 0.3);
1136
1203
  }
1137
1204
 
1138
1205
  header h1 {
1139
1206
  font-size: 2rem;
1140
- background: linear-gradient(90deg, var(--purple), var(--green));
1207
+ font-weight: 700;
1208
+ background: linear-gradient(135deg, var(--solana-purple) 0%, var(--noir-orange) 100%);
1141
1209
  -webkit-background-clip: text;
1142
1210
  -webkit-text-fill-color: transparent;
1143
1211
  background-clip: text;
@@ -1156,34 +1224,51 @@ main {
1156
1224
  width: 100%;
1157
1225
  }
1158
1226
 
1227
+ /* ================================
1228
+ Section Cards - Glassmorphism
1229
+ ================================ */
1159
1230
  .section {
1160
1231
  margin-bottom: 2rem;
1161
1232
  padding: 1.5rem;
1162
- background: var(--bg-elevated);
1233
+ background: rgba(0, 0, 0, 0.3);
1234
+ backdrop-filter: blur(8px);
1163
1235
  border: 1px solid var(--border);
1164
- border-radius: 12px;
1236
+ border-radius: 16px;
1237
+ transition: border-color 0.3s ease, box-shadow 0.3s ease;
1238
+ }
1239
+
1240
+ .section:hover {
1241
+ border-color: rgba(255, 255, 255, 0.15);
1242
+ box-shadow: 0 0 30px rgba(153, 69, 255, 0.1);
1165
1243
  }
1166
1244
 
1167
1245
  .section h2 {
1168
1246
  font-size: 1.25rem;
1247
+ font-weight: 600;
1169
1248
  margin-bottom: 1rem;
1170
1249
  color: var(--text);
1171
1250
  }
1172
1251
 
1252
+ /* ================================
1253
+ Form Controls
1254
+ ================================ */
1173
1255
  .select {
1174
1256
  width: 100%;
1175
- padding: 0.75rem;
1176
- background: var(--bg);
1257
+ padding: 0.75rem 1rem;
1258
+ background: rgba(0, 0, 0, 0.4);
1177
1259
  border: 1px solid var(--border);
1178
- border-radius: 8px;
1260
+ border-radius: 12px;
1179
1261
  color: var(--text);
1262
+ font-family: inherit;
1180
1263
  font-size: 1rem;
1181
1264
  cursor: pointer;
1265
+ transition: border-color 0.3s ease, box-shadow 0.3s ease;
1182
1266
  }
1183
1267
 
1184
1268
  .select:focus {
1185
1269
  outline: none;
1186
- border-color: var(--purple);
1270
+ border-color: var(--solana-purple);
1271
+ box-shadow: 0 0 20px rgba(153, 69, 255, 0.2);
1187
1272
  }
1188
1273
 
1189
1274
  .inputs-grid {
@@ -1208,71 +1293,93 @@ main {
1208
1293
 
1209
1294
  .input-badge {
1210
1295
  font-size: 0.625rem;
1211
- padding: 0.125rem 0.375rem;
1212
- border-radius: 4px;
1296
+ padding: 0.125rem 0.5rem;
1297
+ border-radius: 6px;
1213
1298
  text-transform: uppercase;
1214
1299
  font-weight: 600;
1300
+ letter-spacing: 0.05em;
1215
1301
  }
1216
1302
 
1217
1303
  .input-badge.public {
1218
- background: var(--green);
1219
- color: #000;
1304
+ background: rgba(20, 241, 149, 0.2);
1305
+ color: var(--solana-green);
1306
+ border: 1px solid rgba(20, 241, 149, 0.3);
1220
1307
  }
1221
1308
 
1222
1309
  .input-badge.private {
1223
- background: var(--purple);
1224
- color: #fff;
1310
+ background: rgba(153, 69, 255, 0.2);
1311
+ color: var(--solana-purple);
1312
+ border: 1px solid rgba(153, 69, 255, 0.3);
1225
1313
  }
1226
1314
 
1227
1315
  .input-group input {
1228
- padding: 0.75rem;
1229
- background: var(--bg);
1316
+ padding: 0.75rem 1rem;
1317
+ background: rgba(0, 0, 0, 0.4);
1230
1318
  border: 1px solid var(--border);
1231
- border-radius: 8px;
1319
+ border-radius: 12px;
1232
1320
  color: var(--text);
1321
+ font-family: 'JetBrains Mono', 'Fira Code', monospace;
1233
1322
  font-size: 1rem;
1323
+ transition: border-color 0.3s ease, box-shadow 0.3s ease;
1234
1324
  }
1235
1325
 
1236
1326
  .input-group input:focus {
1237
1327
  outline: none;
1238
- border-color: var(--purple);
1328
+ border-color: var(--solana-purple);
1329
+ box-shadow: 0 0 20px rgba(153, 69, 255, 0.2);
1239
1330
  }
1240
1331
 
1332
+ /* ================================
1333
+ Buttons - Animated Gradient
1334
+ ================================ */
1241
1335
  .btn {
1242
1336
  padding: 0.75rem 1.5rem;
1243
1337
  font-size: 1rem;
1244
1338
  font-weight: 600;
1245
1339
  border: none;
1246
- border-radius: 8px;
1340
+ border-radius: 12px;
1247
1341
  cursor: pointer;
1248
- transition: all 0.2s;
1342
+ transition: all 0.3s ease;
1249
1343
  }
1250
1344
 
1251
1345
  .btn:disabled {
1252
- opacity: 0.5;
1346
+ opacity: 0.4;
1253
1347
  cursor: not-allowed;
1254
1348
  }
1255
1349
 
1256
1350
  .btn-primary {
1257
- background: linear-gradient(90deg, var(--purple), var(--green));
1351
+ background: linear-gradient(
1352
+ 90deg,
1353
+ var(--solana-purple) 0%,
1354
+ var(--solana-purple) 50%,
1355
+ var(--solana-green) 100%
1356
+ );
1357
+ background-size: 200% 100%;
1358
+ background-position: 0% 0%;
1258
1359
  color: white;
1360
+ box-shadow: 0 0 20px rgba(153, 69, 255, 0.3);
1259
1361
  }
1260
1362
 
1261
1363
  .btn-primary:hover:not(:disabled) {
1364
+ background-position: 100% 0%;
1262
1365
  transform: translateY(-2px);
1263
- box-shadow: 0 4px 20px rgba(153, 69, 255, 0.3);
1366
+ box-shadow: 0 0 30px rgba(20, 241, 149, 0.3);
1264
1367
  }
1265
1368
 
1266
1369
  .btn-secondary {
1267
- background: var(--bg);
1370
+ background: rgba(0, 0, 0, 0.4);
1268
1371
  border: 1px solid var(--border);
1269
1372
  color: var(--text);
1270
1373
  }
1271
1374
 
1272
1375
  .btn-secondary:hover:not(:disabled) {
1273
- border-color: var(--purple);
1376
+ border-color: var(--solana-purple);
1377
+ box-shadow: 0 0 20px rgba(153, 69, 255, 0.15);
1274
1378
  }
1275
1379
 
1380
+ /* ================================
1381
+ Results Grid
1382
+ ================================ */
1276
1383
  .results {
1277
1384
  display: grid;
1278
1385
  grid-template-columns: repeat(3, 1fr);
@@ -1280,22 +1387,36 @@ main {
1280
1387
  margin-top: 1rem;
1281
1388
  }
1282
1389
 
1390
+ @media (max-width: 640px) {
1391
+ .results {
1392
+ grid-template-columns: 1fr;
1393
+ }
1394
+ }
1395
+
1283
1396
  .result-card {
1284
- padding: 1rem;
1285
- background: var(--bg);
1397
+ padding: 1.25rem;
1398
+ background: rgba(0, 0, 0, 0.3);
1286
1399
  border: 1px solid var(--border);
1287
- border-radius: 8px;
1400
+ border-radius: 12px;
1288
1401
  text-align: center;
1402
+ transition: border-color 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease;
1403
+ }
1404
+
1405
+ .result-card:hover {
1406
+ border-color: rgba(255, 255, 255, 0.15);
1407
+ transform: translateY(-4px);
1408
+ box-shadow: 0 0 25px rgba(153, 69, 255, 0.15);
1289
1409
  }
1290
1410
 
1291
1411
  .result-value {
1292
- font-size: 1.25rem;
1293
- font-weight: 600;
1412
+ font-size: 1.5rem;
1413
+ font-weight: 700;
1414
+ font-family: 'JetBrains Mono', monospace;
1294
1415
  display: block;
1295
1416
  }
1296
1417
 
1297
1418
  .result-value.success {
1298
- color: var(--green);
1419
+ color: var(--solana-green);
1299
1420
  }
1300
1421
 
1301
1422
  .result-value.error {
@@ -1306,22 +1427,40 @@ main {
1306
1427
  font-size: 0.75rem;
1307
1428
  color: var(--text-muted);
1308
1429
  text-transform: uppercase;
1309
- margin-top: 0.25rem;
1430
+ letter-spacing: 0.1em;
1431
+ margin-top: 0.5rem;
1310
1432
  display: block;
1311
1433
  }
1312
1434
 
1435
+ /* ================================
1436
+ Messages
1437
+ ================================ */
1313
1438
  .error {
1314
- color: #ff4444;
1439
+ color: #ff6b6b;
1315
1440
  font-size: 0.875rem;
1316
1441
  margin-top: 0.5rem;
1442
+ padding: 0.75rem 1rem;
1443
+ background: rgba(255, 107, 107, 0.1);
1444
+ border: 1px solid rgba(255, 107, 107, 0.2);
1445
+ border-radius: 8px;
1446
+ word-break: break-word;
1447
+ overflow-wrap: break-word;
1448
+ max-width: 100%;
1317
1449
  }
1318
1450
 
1319
1451
  .success {
1320
- color: var(--green);
1452
+ color: var(--solana-green);
1321
1453
  font-size: 0.875rem;
1322
1454
  margin-top: 0.5rem;
1455
+ padding: 0.75rem 1rem;
1456
+ background: rgba(20, 241, 149, 0.1);
1457
+ border: 1px solid rgba(20, 241, 149, 0.2);
1458
+ border-radius: 8px;
1323
1459
  }
1324
1460
 
1461
+ /* ================================
1462
+ Noir Code Details
1463
+ ================================ */
1325
1464
  .noir-details {
1326
1465
  margin-top: 1rem;
1327
1466
  }
@@ -1330,12 +1469,21 @@ main {
1330
1469
  cursor: pointer;
1331
1470
  color: var(--text-muted);
1332
1471
  font-size: 0.875rem;
1472
+ padding: 0.5rem 0;
1473
+ transition: color 0.3s ease;
1333
1474
  }
1334
1475
 
1335
1476
  .noir-details summary:hover {
1336
- color: var(--text);
1477
+ color: var(--solana-purple);
1337
1478
  }
1338
1479
 
1480
+ .noir-details[open] summary {
1481
+ color: var(--solana-purple);
1482
+ }
1483
+
1484
+ /* ================================
1485
+ Deploy & Verify Section
1486
+ ================================ */
1339
1487
  .deploy-verify-row {
1340
1488
  display: grid;
1341
1489
  grid-template-columns: 1fr 1fr;
@@ -1343,38 +1491,118 @@ main {
1343
1491
  margin-top: 1rem;
1344
1492
  }
1345
1493
 
1494
+ @media (max-width: 640px) {
1495
+ .deploy-verify-row {
1496
+ grid-template-columns: 1fr;
1497
+ }
1498
+ }
1499
+
1346
1500
  .deploy-box,
1347
1501
  .verify-box {
1348
- padding: 1rem;
1349
- background: var(--bg);
1502
+ padding: 1.25rem;
1503
+ background: rgba(0, 0, 0, 0.3);
1504
+ border: 1px solid var(--border);
1505
+ border-radius: 12px;
1506
+ overflow: hidden;
1507
+ word-break: break-word;
1508
+ transition: border-color 0.3s ease, box-shadow 0.3s ease;
1509
+ }
1510
+
1511
+ .deploy-box:hover,
1512
+ .verify-box:hover {
1513
+ border-color: rgba(255, 255, 255, 0.15);
1514
+ box-shadow: 0 0 20px rgba(153, 69, 255, 0.1);
1515
+ }
1516
+
1517
+ .public-inputs-display {
1518
+ margin-top: 0.75rem;
1519
+ font-size: 0.75rem;
1520
+ color: var(--text-muted);
1521
+ }
1522
+
1523
+ .public-inputs-display code {
1524
+ display: block;
1525
+ margin-top: 0.5rem;
1526
+ padding: 0.75rem;
1527
+ background: rgba(0, 0, 0, 0.4);
1350
1528
  border: 1px solid var(--border);
1351
1529
  border-radius: 8px;
1530
+ font-family: 'JetBrains Mono', monospace;
1531
+ font-size: 0.7rem;
1532
+ overflow-x: auto;
1533
+ max-width: 100%;
1352
1534
  }
1353
1535
 
1536
+ /* ================================
1537
+ Footer
1538
+ ================================ */
1354
1539
  footer {
1355
1540
  padding: 1.5rem;
1356
1541
  text-align: center;
1357
1542
  border-top: 1px solid var(--border);
1543
+ backdrop-filter: blur(8px);
1544
+ background: rgba(0, 0, 0, 0.3);
1358
1545
  color: var(--text-muted);
1359
1546
  font-size: 0.875rem;
1360
1547
  }
1361
1548
 
1362
1549
  footer a {
1363
- color: var(--purple);
1550
+ color: var(--solana-purple);
1364
1551
  text-decoration: none;
1552
+ transition: color 0.3s ease;
1365
1553
  }
1366
1554
 
1367
1555
  footer a:hover {
1368
- text-decoration: underline;
1556
+ color: var(--solana-green);
1557
+ }
1558
+
1559
+ /* ================================
1560
+ Custom Scrollbar
1561
+ ================================ */
1562
+ ::-webkit-scrollbar {
1563
+ width: 6px;
1564
+ height: 6px;
1565
+ }
1566
+
1567
+ ::-webkit-scrollbar-track {
1568
+ background: var(--noir-primary);
1569
+ }
1570
+
1571
+ ::-webkit-scrollbar-thumb {
1572
+ background: rgba(255, 255, 255, 0.1);
1573
+ border-radius: 9999px;
1574
+ }
1575
+
1576
+ ::-webkit-scrollbar-thumb:hover {
1577
+ background: rgba(255, 255, 255, 0.2);
1578
+ }
1579
+
1580
+ /* ================================
1581
+ Accessibility - Reduced Motion
1582
+ ================================ */
1583
+ @media (prefers-reduced-motion: reduce) {
1584
+ *,
1585
+ *::before,
1586
+ *::after {
1587
+ animation-duration: 0.01ms !important;
1588
+ animation-iteration-count: 1 !important;
1589
+ transition-duration: 0.01ms !important;
1590
+ }
1369
1591
  }
1370
1592
  `;
1371
1593
  }
1372
1594
  function generateIndexCss() {
1373
- return `body {
1595
+ return `/* Base styles - fonts are loaded in index.html */
1596
+ body {
1374
1597
  margin: 0;
1375
1598
  -webkit-font-smoothing: antialiased;
1376
1599
  -moz-osx-font-smoothing: grayscale;
1377
1600
  }
1601
+
1602
+ /* Ensure mono font is applied to code elements */
1603
+ code, pre, .mono {
1604
+ font-family: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace;
1605
+ }
1378
1606
  `;
1379
1607
  }
1380
1608
  function generateViteEnvDts() {
@@ -1553,14 +1781,14 @@ async function initCommand(projectName, options) {
1553
1781
  });
1554
1782
  }
1555
1783
  if (!projectOptions) {
1556
- console.log(pc4.yellow("\nOperation cancelled."));
1784
+ console.log(pc3.yellow("\nOperation cancelled."));
1557
1785
  process.exit(0);
1558
1786
  }
1559
1787
  const projectDir = path2.resolve(process.cwd(), projectOptions.projectName);
1560
1788
  if (await directoryExists(projectDir)) {
1561
1789
  if (!await isDirectoryEmpty(projectDir)) {
1562
1790
  console.log(
1563
- pc4.red(`
1791
+ pc3.red(`
1564
1792
  Error: Directory "${projectOptions.projectName}" already exists and is not empty.`)
1565
1793
  );
1566
1794
  process.exit(1);
@@ -1572,23 +1800,23 @@ Error: Directory "${projectOptions.projectName}" already exists and is not empty
1572
1800
  await progress.startThinking();
1573
1801
  await new Promise((r) => setTimeout(r, 800));
1574
1802
  progress.stopThinking();
1575
- console.log(pc4.bold("\n Scaffolding your ZK project...\n"));
1803
+ console.log(pc3.bold("\n Scaffolding your ZK project...\n"));
1576
1804
  await createProjectStructure(projectDir, projectOptions, progress);
1577
1805
  progress.showSuccess("Project structure created");
1578
1806
  } catch (error) {
1579
1807
  progress.showError("Failed to create project structure");
1580
- console.error(pc4.red("\n"), error);
1808
+ console.error(pc3.red("\n"), error);
1581
1809
  process.exit(1);
1582
1810
  }
1583
1811
  if (!projectOptions.skipGit) {
1584
- const gitSpinner = createSpinner("Initializing git repository...");
1585
- gitSpinner.start();
1812
+ const gitProgress = createGitProgress();
1813
+ gitProgress.start();
1586
1814
  try {
1587
1815
  execSync("git init", { cwd: projectDir, stdio: "ignore" });
1588
- gitSpinner.stop(true);
1816
+ gitProgress.stop(true);
1589
1817
  } catch {
1590
- gitSpinner.stop(false);
1591
- console.log(pc4.yellow(" Warning: Failed to initialize git repository"));
1818
+ gitProgress.stop(false);
1819
+ console.log(pc3.yellow(" Warning: Failed to initialize git repository"));
1592
1820
  }
1593
1821
  }
1594
1822
  if (!projectOptions.skipInstall) {
@@ -1599,7 +1827,7 @@ Error: Directory "${projectOptions.projectName}" already exists and is not empty
1599
1827
  installProgress.stop(true);
1600
1828
  } catch {
1601
1829
  installProgress.stop(false);
1602
- console.log(pc4.yellow(' Run "npm install" manually.'));
1830
+ console.log(pc3.yellow(' Run "npm install" manually.'));
1603
1831
  }
1604
1832
  }
1605
1833
  printSuccessMessage(projectOptions);
@@ -1653,26 +1881,26 @@ async function createProjectStructure(projectDir, options, progress) {
1653
1881
  }
1654
1882
  function printSuccessMessage(options) {
1655
1883
  console.log();
1656
- console.log(pc4.green("\u2713") + " Project created successfully!");
1884
+ console.log(pc3.green("\u2713") + " Project created successfully!");
1657
1885
  console.log();
1658
1886
  console.log("Next steps:");
1659
1887
  console.log();
1660
- console.log(pc4.cyan(` cd ${options.projectName}`));
1888
+ console.log(pc3.cyan(` cd ${options.projectName}`));
1661
1889
  if (options.skipInstall) {
1662
- console.log(pc4.cyan(" npm install"));
1890
+ console.log(pc3.cyan(" npm install"));
1663
1891
  }
1664
- console.log(pc4.cyan(" npm run dev"));
1892
+ console.log(pc3.cyan(" npm run dev"));
1665
1893
  console.log();
1666
- console.log("Then open " + pc4.blue("http://localhost:5173") + " in your browser.");
1894
+ console.log("Then open " + pc3.blue("http://localhost:5173") + " in your browser.");
1667
1895
  console.log();
1668
1896
  console.log("To add circuits:");
1669
1897
  console.log();
1670
- console.log(pc4.dim(" 1. Create a new circuit in circuits/*.ts"));
1671
- console.log(pc4.dim(" 2. Export it from circuits/index.ts"));
1672
- console.log(pc4.dim(" 3. Add it to CIRCUITS array in src/App.tsx"));
1898
+ console.log(pc3.dim(" 1. Create a new circuit in circuits/*.ts"));
1899
+ console.log(pc3.dim(" 2. Export it from circuits/index.ts"));
1900
+ console.log(pc3.dim(" 3. Add it to CIRCUITS array in src/App.tsx"));
1673
1901
  console.log();
1674
1902
  console.log(
1675
- pc4.dim("Learn more: ") + pc4.blue("https://github.com/izi-noir/izi-noir")
1903
+ pc3.dim("Learn more: ") + pc3.blue("https://github.com/izi-noir/izi-noir")
1676
1904
  );
1677
1905
  console.log();
1678
1906
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-izi-noir",
3
- "version": "0.2.1",
3
+ "version": "0.2.5",
4
4
  "description": "CLI to scaffold IZI-NOIR ZK projects",
5
5
  "type": "module",
6
6
  "bin": {