Repository: o1-labs/zkapp-cli (js)

Issue:
Update the project scaffold for Svelte 5 (or explicitly stay with Svelte 4 while work on the v5 support)
Svelte 5 was recently released and it brings some changes in project structure and the way it is being generated. See failed Nightly CI job (https://github.com/o1-labs/zkapp-cli/actions/runs/11470447626/job/31919637353).
We either need to support new version or explicitly fallback to Svelte 4 and previous project generation steps.

Pull request description:
Support for the Svelte 5 env.
- [x] Svelte 5 support;
- [x] Tests;
- [x] Changelog.

---

Closes #700 

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7c139f5..8e9fc33 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,12 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
 
 ## Unreleased
 
+## [0.21.8](https://github.com/o1-labs/zkapp-cli/compare/0.21.7...0.21.8) - 2024-10-23
+
+### Changed
+
+- Svelte project scaffold now uses latest `sv create` and sources migrated to `Svelte 5`. [#701](https://github.com/o1-labs/zkapp-cli/pull/701)
+
 ## [0.21.7](https://github.com/o1-labs/zkapp-cli/compare/0.21.6...0.21.7) - 2024-10-01
 
 ### Changed
diff --git a/package-lock.json b/package-lock.json
index 42e40fb..fbbd5b1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "zkapp-cli",
-  "version": "0.21.7",
+  "version": "0.21.8",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "zkapp-cli",
-      "version": "0.21.7",
+      "version": "0.21.8",
       "license": "Apache-2.0",
       "dependencies": {
         "acorn": "^8.12.1",
diff --git a/package.json b/package.json
index cecd704..c98b5eb 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "zkapp-cli",
-  "version": "0.21.7",
+  "version": "0.21.8",
   "description": "CLI to create zkApps (zero-knowledge apps) for Mina Protocol",
   "homepage": "https://github.com/o1-labs/zkapp-cli/",
   "repository": {
diff --git a/src/lib/project.js b/src/lib/project.js
index c7683b0..b8cf964 100644
--- a/src/lib/project.js
+++ b/src/lib/project.js
@@ -7,8 +7,8 @@ import url from 'node:url';
 import util from 'node:util';
 import ora from 'ora';
 import shell from 'shelljs';
-import customNextPage from '../lib/ui/next/customNextPage.js';
 import customNextLayout from '../lib/ui/next/customNextLayout.js';
+import customNextPage from '../lib/ui/next/customNextPage.js';
 import customNuxtIndex from '../lib/ui/nuxt/customNuxtIndex.js';
 import nuxtGradientBackground from '../lib/ui/nuxt/nuxtGradientBackground.js';
 import customLayoutSvelte from '../lib/ui/svelte/customLayoutSvelte.js';
@@ -175,8 +175,7 @@ async function project({ name, ui }) {
 }
 
 function scaffoldSvelte() {
-  // `-y` installs the latest version of create-svelte without prompting.
-  spawnSync('npm', ['create', 'svelte@latest', '-y', 'ui'], {
+  spawnSync('npx', ['sv', 'create', 'ui'], {
     stdio: 'inherit',
     shell: true,
   });
diff --git a/src/lib/ui/svelte/customLayoutSvelte.js b/src/lib/ui/svelte/customLayoutSvelte.js
index 6780946..15eae41 100644
--- a/src/lib/ui/svelte/customLayoutSvelte.js
+++ b/src/lib/ui/svelte/customLayoutSvelte.js
@@ -1,6 +1,13 @@
 export default `
 <script>
   import '../styles/globals.css'
+  /**
+   * @typedef {Object} Props
+   * @property {import('svelte').Snippet} [children]
+   */
+
+  /** @type {Props} */
+  let { children } = $props();
 </script>
-<slot/>
+{@render children?.()}
 `;
diff --git a/src/lib/ui/svelte/gradientBackground.js b/src/lib/ui/svelte/gradientBackground.js
index 396fba9..9bca7da 100644
--- a/src/lib/ui/svelte/gradientBackground.js
+++ b/src/lib/ui/svelte/gradientBackground.js
@@ -1,6 +1,13 @@
 export default `
 <script>
   import { onMount } from 'svelte'
+  /**
+   * @typedef {Object} Props
+   * @property {import('svelte').Snippet} [children]
+   */
+
+  /** @type {Props} */
+  let { children } = $props();
   let ctx
   let pixels = []
   let canvas
@@ -131,9 +138,9 @@ export default `
 </style>
 
 <div class="background">
-  <canvas class="background-gradients" width="6" height="6" />
+  <canvas class="background-gradients" width="6" height="6"></canvas>
 </div>
 <div class="container">
-  <slot />
+  {@render children?.()}
 </div>
 `;


Test patch:
diff --git a/src/lib/project.test.js b/src/lib/project.test.js
index c7272b5..15098e6 100644
--- a/src/lib/project.test.js
+++ b/src/lib/project.test.js
@@ -381,11 +381,10 @@ describe('project.js', () => {
 
       expect(shell.mkdir).toHaveBeenCalledWith('-p', 'test-project');
       expect(shell.cd).toHaveBeenCalledWith('test-project');
-      expect(spawnSync).toHaveBeenCalledWith(
-        'npm',
-        ['create', 'svelte@latest', '-y', 'ui'],
-        { stdio: 'inherit', shell: true }
-      );
+      expect(spawnSync).toHaveBeenCalledWith('npx', ['sv', 'create', 'ui'], {
+        stdio: 'inherit',
+        shell: true,
+      });
       expect(shell.cd).toHaveBeenCalledWith('contracts');
       checkUiProjectSetup(shell.exec.mock.calls);
       checkIfProjectSetupSuccessful();
@@ -678,11 +677,10 @@ describe('project.js', () => {
 
       scaffoldSvelte();
 
-      expect(spawnSync).toHaveBeenCalledWith(
-        'npm',
-        ['create', 'svelte@latest', '-y', 'ui'],
-        { stdio: 'inherit', shell: true }
-      );
+      expect(spawnSync).toHaveBeenCalledWith('npx', ['sv', 'create', 'ui'], {
+        stdio: 'inherit',
+        shell: true,
+      });
       expect(fs.writeFileSync).toHaveBeenCalled();
     });
   });
diff --git a/tests/utils/project-utils.ts b/tests/utils/project-utils.ts
index e89a5ad..4df1265 100644
--- a/tests/utils/project-utils.ts
+++ b/tests/utils/project-utils.ts
@@ -47,9 +47,9 @@ export async function zkProject(
     case 'svelte': {
       interactiveDialog = {
         ...interactiveDialog,
-        'Which Svelte app template?': ['arrowDown', 'enter'],
-        'Add type checking with TypeScript?': ['arrowDown', 'enter'],
-        'Select additional options (use arrow keys/space bar)': [
+        'Which template would you like?': ['enter'],
+        'Add type checking with Typescript?': ['enter'],
+        'What would you like to add to your project?': [
           'space',
           'arrowDown',
           'space',
@@ -59,6 +59,9 @@ export async function zkProject(
           'space',
           'enter',
         ],
+        'Which package manager do you want to install dependencies with?': [
+          'enter',
+        ],
       };
       break;
     }