cfsa-antigravity 2.9.0 → 2.10.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/package.json +1 -1
- package/template/.agent/kit-sync.md +3 -3
- package/template/.agent/skill-library/MANIFEST.md +2 -0
- package/template/.agent/skill-library/stack/frameworks/svelte5/SKILL.md +81 -0
- package/template/.agent/skill-library/stack/frameworks/svelte5/references/events.md +353 -0
- package/template/.agent/skill-library/stack/frameworks/svelte5/references/migration.md +339 -0
- package/template/.agent/skill-library/stack/frameworks/svelte5/references/performance.md +443 -0
- package/template/.agent/skill-library/stack/frameworks/svelte5/references/runes.md +394 -0
- package/template/.agent/skill-library/stack/frameworks/svelte5/references/snippets.md +291 -0
- package/template/.agent/skill-library/stack/frameworks/svelte5/references/sveltekit.md +401 -0
- package/template/.agent/skill-library/stack/frameworks/svelte5/references/typescript.md +305 -0
- package/template/.agent/skill-library/stack/ui/svelte-flow/SKILL.md +390 -0
- package/template/.agent/skills/idea-extraction/SKILL.md +17 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Kit Sync State
|
|
2
2
|
|
|
3
3
|
upstream: https://github.com/RepairYourTech/cfsa-antigravity
|
|
4
|
-
last_synced_commit:
|
|
5
|
-
last_synced_at: 2026-03-
|
|
6
|
-
kit_version: 2.
|
|
4
|
+
last_synced_commit: e60781547ac48627470760d78942ad063e22c9dc
|
|
5
|
+
last_synced_at: 2026-03-17T15:19:28Z
|
|
6
|
+
kit_version: 2.10.0
|
|
@@ -55,6 +55,7 @@ When a stack key matches a value pattern (case-insensitive), install the listed
|
|
|
55
55
|
| `FRONTEND_FRAMEWORK` | `*astro*` | `stack/frameworks/astro-framework` | `astro-framework` |
|
|
56
56
|
| `FRONTEND_FRAMEWORK` | `*next*` | `stack/frameworks/nextjs` | `nextjs` |
|
|
57
57
|
| `FRONTEND_FRAMEWORK` | `*svelte*` OR `*sveltekit*` | `stack/frameworks/sveltekit` | `sveltekit` |
|
|
58
|
+
| `FRONTEND_FRAMEWORK` | `*svelte*` OR `*sveltekit*` | `stack/frameworks/svelte5` | `svelte5` |
|
|
58
59
|
| `FRONTEND_FRAMEWORK` | `*nuxt*` | `stack/frameworks/nuxt` | `nuxt` |
|
|
59
60
|
| `BACKEND_FRAMEWORK` | `*hono*` | `stack/frameworks/hono` | `hono` |
|
|
60
61
|
| `BACKEND_FRAMEWORK` | `*fastapi*` | `stack/frameworks/fastapi` | `fastapi` |
|
|
@@ -94,6 +95,7 @@ When a stack key matches a value pattern (case-insensitive), install the listed
|
|
|
94
95
|
| `CSS_FRAMEWORK` | `*sass*` OR `*scss*` | `stack/css/sass-scss` | `sass-scss` |
|
|
95
96
|
| `UI_LIBRARY` | `*shadcn*` | `stack/ui/shadcn-ui` | `shadcn-ui` |
|
|
96
97
|
| `UI_LIBRARY` | `*react-flow*` OR `*xyflow*` | `stack/ui/react-flow` | `react-flow` |
|
|
98
|
+
| `UI_LIBRARY` | `*svelte-flow*` OR `*svelteflow*` OR `*xyflow*` | `stack/ui/svelte-flow` | `svelte-flow` |
|
|
97
99
|
| `FRONTEND_FRAMEWORK` | `*react*` | `stack/ui/react-best-practices` | `react-best-practices` |
|
|
98
100
|
| `FRONTEND_FRAMEWORK` | `*react*` | `stack/ui/react-composition-patterns` | `react-composition-patterns` |
|
|
99
101
|
| `DESIGN_DIRECTION` | `*` (any confirmed value) | Fills `{{PLACEHOLDER}}`s in `.agent/skills/brand-guidelines/SKILL.md` in-place | `brand-guidelines` (in-place fill, not copy) |
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: svelte5-best-practices
|
|
3
|
+
description: "Svelte 5 runes, snippets, SvelteKit patterns, and modern best practices for TypeScript and component development. Use when writing, reviewing, or refactoring Svelte 5 components and SvelteKit applications. Triggers on: Svelte components, runes ($state, $derived, $effect, $props, $bindable, $inspect), snippets ({#snippet}, {@render}), event handling, SvelteKit data loading, form actions, Svelte 4 to Svelte 5 migration, store to rune migration, slots to snippets migration, TypeScript props typing, generic components, SSR state isolation, performance optimization, or component testing."
|
|
4
|
+
license: MIT
|
|
5
|
+
metadata:
|
|
6
|
+
author: ejirocodes
|
|
7
|
+
version: '1.0.0'
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Svelte 5 Best Practices
|
|
11
|
+
|
|
12
|
+
## Quick Reference
|
|
13
|
+
|
|
14
|
+
| Topic | When to Use | Reference |
|
|
15
|
+
|-------|-------------|-----------|
|
|
16
|
+
| **Runes** | $state, $derived, $effect, $props, $bindable, $inspect | [runes.md](references/runes.md) |
|
|
17
|
+
| **Snippets** | Replacing slots, {#snippet}, {@render} | [snippets.md](references/snippets.md) |
|
|
18
|
+
| **Events** | onclick handlers, callback props, context API | [events.md](references/events.md) |
|
|
19
|
+
| **TypeScript** | Props typing, generic components | [typescript.md](references/typescript.md) |
|
|
20
|
+
| **Migration** | Svelte 4 to 5, stores to runes | [migration.md](references/migration.md) |
|
|
21
|
+
| **SvelteKit** | Load functions, form actions, SSR, page typing | [sveltekit.md](references/sveltekit.md) |
|
|
22
|
+
| **Performance** | Universal reactivity, avoiding over-reactivity, streaming | [performance.md](references/performance.md) |
|
|
23
|
+
|
|
24
|
+
## Essential Patterns
|
|
25
|
+
|
|
26
|
+
### Reactive State
|
|
27
|
+
|
|
28
|
+
```svelte
|
|
29
|
+
<script>
|
|
30
|
+
let count = $state(0); // Reactive state
|
|
31
|
+
let doubled = $derived(count * 2); // Computed value
|
|
32
|
+
</script>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Component Props
|
|
36
|
+
|
|
37
|
+
```svelte
|
|
38
|
+
<script>
|
|
39
|
+
let { name, count = 0 } = $props();
|
|
40
|
+
let { value = $bindable() } = $props(); // Two-way binding
|
|
41
|
+
</script>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Snippets (replacing slots)
|
|
45
|
+
|
|
46
|
+
```svelte
|
|
47
|
+
<script>
|
|
48
|
+
let { children, header } = $props();
|
|
49
|
+
</script>
|
|
50
|
+
|
|
51
|
+
{@render header?.()}
|
|
52
|
+
{@render children()}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Event Handlers
|
|
56
|
+
|
|
57
|
+
```svelte
|
|
58
|
+
<!-- Svelte 5: use onclick, not on:click -->
|
|
59
|
+
<button onclick={() => count++}>Click</button>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Callback Props (replacing createEventDispatcher)
|
|
63
|
+
|
|
64
|
+
```svelte
|
|
65
|
+
<script>
|
|
66
|
+
let { onclick } = $props();
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<button onclick={() => onclick?.({ data })}>Click</button>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Common Mistakes
|
|
73
|
+
|
|
74
|
+
1. **Using `let` without `$state`** - Variables are not reactive without `$state()`
|
|
75
|
+
2. **Using `$effect` for derived values** - Use `$derived` instead
|
|
76
|
+
3. **Using `on:click` syntax** - Use `onclick` in Svelte 5
|
|
77
|
+
4. **Using `createEventDispatcher`** - Use callback props instead
|
|
78
|
+
5. **Using `<slot>`** - Use snippets with `{@render}`
|
|
79
|
+
6. **Forgetting `$bindable()`** - Required for `bind:` to work
|
|
80
|
+
7. **Setting module-level state in SSR** - Causes cross-request leaks
|
|
81
|
+
8. **Sequential awaits in load functions** - Use `Promise.all` for parallel requests
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
# Svelte 5 Events Reference
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
- [Event Handler Syntax](#event-handler-syntax)
|
|
5
|
+
- [Callback Props Pattern](#callback-props-pattern)
|
|
6
|
+
- [Context API](#context-api)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Event Handler Syntax
|
|
11
|
+
|
|
12
|
+
Svelte 5 replaces `on:click` directive syntax with standard HTML attribute syntax `onclick`.
|
|
13
|
+
|
|
14
|
+
### Basic Event Handlers
|
|
15
|
+
|
|
16
|
+
**Svelte 4:**
|
|
17
|
+
```svelte
|
|
18
|
+
<button on:click={handleClick}>Click</button>
|
|
19
|
+
<input on:input={handleInput} />
|
|
20
|
+
<form on:submit={handleSubmit}>...</form>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Svelte 5:**
|
|
24
|
+
```svelte
|
|
25
|
+
<button onclick={handleClick}>Click</button>
|
|
26
|
+
<input oninput={handleInput} />
|
|
27
|
+
<form onsubmit={handleSubmit}>...</form>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Event Modifiers Migration
|
|
31
|
+
|
|
32
|
+
Event modifiers no longer exist. Use wrapper functions:
|
|
33
|
+
|
|
34
|
+
**Svelte 4:**
|
|
35
|
+
```svelte
|
|
36
|
+
<form on:submit|preventDefault={handleSubmit}>...</form>
|
|
37
|
+
<button on:click|stopPropagation={handleClick}>...</button>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**Svelte 5:**
|
|
41
|
+
```svelte
|
|
42
|
+
<script>
|
|
43
|
+
function handleSubmit(event) {
|
|
44
|
+
event.preventDefault();
|
|
45
|
+
// ... handle form
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function handleClick(event) {
|
|
49
|
+
event.stopPropagation();
|
|
50
|
+
// ... handle click
|
|
51
|
+
}
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<form onsubmit={handleSubmit}>...</form>
|
|
55
|
+
<button onclick={handleClick}>...</button>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Capture, Passive, and NonPassive
|
|
59
|
+
|
|
60
|
+
```svelte
|
|
61
|
+
<!-- Capture phase -->
|
|
62
|
+
<div onclickcapture={handleCapture}>
|
|
63
|
+
<button onclick={handleClick}>Click</button>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<!-- Passive listener -->
|
|
67
|
+
<div ontouchstartpassive={handleTouch}>...</div>
|
|
68
|
+
|
|
69
|
+
<!-- Non-passive -->
|
|
70
|
+
<div ontouchmovenonpassive={(e) => e.preventDefault()}>...</div>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Inline Handlers
|
|
74
|
+
|
|
75
|
+
```svelte
|
|
76
|
+
<button onclick={() => count++}>Count: {count}</button>
|
|
77
|
+
<input oninput={(e) => name = e.target.value} />
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Event Handler Shorthand
|
|
81
|
+
|
|
82
|
+
```svelte
|
|
83
|
+
<script>
|
|
84
|
+
function onclick(event) {
|
|
85
|
+
console.log('Clicked!', event);
|
|
86
|
+
}
|
|
87
|
+
</script>
|
|
88
|
+
|
|
89
|
+
<button {onclick}>Click</button>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Spreading Event Handlers
|
|
93
|
+
|
|
94
|
+
```svelte
|
|
95
|
+
<script>
|
|
96
|
+
let handlers = {
|
|
97
|
+
onclick: () => console.log('clicked'),
|
|
98
|
+
onmouseenter: () => console.log('entered'),
|
|
99
|
+
onmouseleave: () => console.log('left')
|
|
100
|
+
};
|
|
101
|
+
</script>
|
|
102
|
+
|
|
103
|
+
<button {...handlers}>Hover or Click</button>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Multiple Handlers for Same Event
|
|
107
|
+
|
|
108
|
+
In Svelte 5, combine logic into one handler:
|
|
109
|
+
|
|
110
|
+
```svelte
|
|
111
|
+
<script>
|
|
112
|
+
function handleClick(event) {
|
|
113
|
+
handler1(event);
|
|
114
|
+
handler2(event);
|
|
115
|
+
}
|
|
116
|
+
</script>
|
|
117
|
+
|
|
118
|
+
<button onclick={handleClick}>...</button>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### TypeScript Event Typing
|
|
122
|
+
|
|
123
|
+
```svelte
|
|
124
|
+
<script lang="ts">
|
|
125
|
+
function handleClick(event: MouseEvent) {
|
|
126
|
+
console.log(event.clientX, event.clientY);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function handleInput(event: Event) {
|
|
130
|
+
const target = event.target as HTMLInputElement;
|
|
131
|
+
console.log(target.value);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function handleSubmit(event: SubmitEvent) {
|
|
135
|
+
event.preventDefault();
|
|
136
|
+
const formData = new FormData(event.currentTarget as HTMLFormElement);
|
|
137
|
+
}
|
|
138
|
+
</script>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Callback Props Pattern
|
|
144
|
+
|
|
145
|
+
Svelte 5 deprecates `createEventDispatcher` in favor of callback props for component-to-parent communication.
|
|
146
|
+
|
|
147
|
+
### Basic Event Pattern
|
|
148
|
+
|
|
149
|
+
**Svelte 4:**
|
|
150
|
+
```svelte
|
|
151
|
+
<!-- Button.svelte -->
|
|
152
|
+
<script>
|
|
153
|
+
import { createEventDispatcher } from 'svelte';
|
|
154
|
+
const dispatch = createEventDispatcher();
|
|
155
|
+
</script>
|
|
156
|
+
|
|
157
|
+
<button on:click={() => dispatch('click', { timestamp: Date.now() })}>Click</button>
|
|
158
|
+
|
|
159
|
+
<!-- Parent.svelte -->
|
|
160
|
+
<Button on:click={(e) => console.log(e.detail)} />
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Svelte 5:**
|
|
164
|
+
```svelte
|
|
165
|
+
<!-- Button.svelte -->
|
|
166
|
+
<script>
|
|
167
|
+
let { onclick } = $props();
|
|
168
|
+
</script>
|
|
169
|
+
|
|
170
|
+
<button onclick={() => onclick?.({ timestamp: Date.now() })}>Click</button>
|
|
171
|
+
|
|
172
|
+
<!-- Parent.svelte -->
|
|
173
|
+
<Button onclick={(data) => console.log(data)} />
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Multiple Callbacks
|
|
177
|
+
|
|
178
|
+
```svelte
|
|
179
|
+
<!-- Dialog.svelte -->
|
|
180
|
+
<script>
|
|
181
|
+
let { onconfirm, oncancel, onclose } = $props();
|
|
182
|
+
</script>
|
|
183
|
+
|
|
184
|
+
<dialog>
|
|
185
|
+
<button onclick={() => onconfirm?.()}>Confirm</button>
|
|
186
|
+
<button onclick={() => oncancel?.()}>Cancel</button>
|
|
187
|
+
<button onclick={() => onclose?.()}>X</button>
|
|
188
|
+
</dialog>
|
|
189
|
+
|
|
190
|
+
<!-- Parent.svelte -->
|
|
191
|
+
<Dialog
|
|
192
|
+
onconfirm={() => save()}
|
|
193
|
+
oncancel={() => reset()}
|
|
194
|
+
onclose={() => visible = false}
|
|
195
|
+
/>
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Typed Callbacks with TypeScript
|
|
199
|
+
|
|
200
|
+
```svelte
|
|
201
|
+
<script lang="ts">
|
|
202
|
+
interface Props {
|
|
203
|
+
value?: string;
|
|
204
|
+
onsearch?: (query: string) => void;
|
|
205
|
+
onchange?: (value: string) => void;
|
|
206
|
+
onclear?: () => void;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
let { value = '', onsearch, onchange, onclear }: Props = $props();
|
|
210
|
+
|
|
211
|
+
function handleInput(e: Event) {
|
|
212
|
+
const newValue = (e.target as HTMLInputElement).value;
|
|
213
|
+
value = newValue;
|
|
214
|
+
onchange?.(newValue);
|
|
215
|
+
}
|
|
216
|
+
</script>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Forwarding Native Events
|
|
220
|
+
|
|
221
|
+
```svelte
|
|
222
|
+
<script lang="ts">
|
|
223
|
+
import type { MouseEventHandler } from 'svelte/elements';
|
|
224
|
+
|
|
225
|
+
interface Props {
|
|
226
|
+
onclick?: MouseEventHandler<HTMLButtonElement>;
|
|
227
|
+
children: import('svelte').Snippet;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
let { onclick, children, ...rest }: Props = $props();
|
|
231
|
+
</script>
|
|
232
|
+
|
|
233
|
+
<button {onclick} {...rest}>{@render children()}</button>
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Context API
|
|
239
|
+
|
|
240
|
+
Context functions must be called synchronously during component initialization.
|
|
241
|
+
|
|
242
|
+
### Correct Context Usage
|
|
243
|
+
|
|
244
|
+
```svelte
|
|
245
|
+
<script>
|
|
246
|
+
import { setContext, getContext } from 'svelte';
|
|
247
|
+
|
|
248
|
+
// These run during initialization - CORRECT
|
|
249
|
+
setContext('theme', 'dark');
|
|
250
|
+
const theme = getContext('theme');
|
|
251
|
+
|
|
252
|
+
// INCORRECT - in $effect or callback
|
|
253
|
+
// $effect(() => { setContext('theme', 'dark'); }); // ERROR
|
|
254
|
+
</script>
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Reactive Context Values
|
|
258
|
+
|
|
259
|
+
Pass `$state` objects for reactive context:
|
|
260
|
+
|
|
261
|
+
```svelte
|
|
262
|
+
<!-- Provider.svelte -->
|
|
263
|
+
<script>
|
|
264
|
+
import { setContext } from 'svelte';
|
|
265
|
+
|
|
266
|
+
let theme = $state('light');
|
|
267
|
+
|
|
268
|
+
setContext('theme', {
|
|
269
|
+
get current() { return theme; },
|
|
270
|
+
toggle() { theme = theme === 'light' ? 'dark' : 'light'; }
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
let { children } = $props();
|
|
274
|
+
</script>
|
|
275
|
+
|
|
276
|
+
{@render children()}
|
|
277
|
+
|
|
278
|
+
<!-- Consumer.svelte -->
|
|
279
|
+
<script>
|
|
280
|
+
import { getContext } from 'svelte';
|
|
281
|
+
const themeContext = getContext('theme');
|
|
282
|
+
</script>
|
|
283
|
+
|
|
284
|
+
<p>Theme: {themeContext.current}</p>
|
|
285
|
+
<button onclick={themeContext.toggle}>Toggle</button>
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Type-Safe Context Pattern
|
|
289
|
+
|
|
290
|
+
```ts
|
|
291
|
+
// context.ts
|
|
292
|
+
import { setContext, getContext } from 'svelte';
|
|
293
|
+
|
|
294
|
+
const THEME_KEY = Symbol('theme');
|
|
295
|
+
|
|
296
|
+
interface ThemeContext {
|
|
297
|
+
current: 'light' | 'dark';
|
|
298
|
+
toggle: () => void;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export function setThemeContext(context: ThemeContext) {
|
|
302
|
+
setContext(THEME_KEY, context);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export function getThemeContext(): ThemeContext {
|
|
306
|
+
const context = getContext<ThemeContext>(THEME_KEY);
|
|
307
|
+
if (!context) throw new Error('Theme context not found');
|
|
308
|
+
return context;
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Avoid Generic Keys
|
|
313
|
+
|
|
314
|
+
```svelte
|
|
315
|
+
<script>
|
|
316
|
+
// Option 1: Symbol
|
|
317
|
+
const USER_KEY = Symbol('user');
|
|
318
|
+
setContext(USER_KEY, userData);
|
|
319
|
+
|
|
320
|
+
// Option 2: Unique string
|
|
321
|
+
setContext('myapp:user', userData);
|
|
322
|
+
|
|
323
|
+
// Option 3: Object key
|
|
324
|
+
const userKey = {};
|
|
325
|
+
setContext(userKey, userData);
|
|
326
|
+
</script>
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### hasContext Check
|
|
330
|
+
|
|
331
|
+
```svelte
|
|
332
|
+
<script>
|
|
333
|
+
import { hasContext, getContext } from 'svelte';
|
|
334
|
+
|
|
335
|
+
const hasTheme = hasContext('theme');
|
|
336
|
+
const theme = hasTheme ? getContext('theme') : { current: 'light' };
|
|
337
|
+
</script>
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Context Boundaries
|
|
341
|
+
|
|
342
|
+
Context flows down the component tree:
|
|
343
|
+
|
|
344
|
+
```svelte
|
|
345
|
+
<!-- Parent.svelte -->
|
|
346
|
+
<script>
|
|
347
|
+
import { getContext, setContext } from 'svelte';
|
|
348
|
+
const level = getContext('level'); // 0
|
|
349
|
+
setContext('level', level + 1); // Override for children
|
|
350
|
+
</script>
|
|
351
|
+
|
|
352
|
+
<Child /> <!-- Will see level = 1 -->
|
|
353
|
+
```
|