+```
+
+Inside the `handleClick` function, all we need to do is change the value of `count`:
+
+```js
+function handleClick() {
+ count += 1;
+}
+```
+
+Svelte 'instruments' this assignment with some code that tells it the DOM will need to be updated.
\ No newline at end of file
diff --git a/site/content/tutorial/02-reactivity/02-reactive-declarations/App.svelte b/site/content/tutorial/02-reactivity/02-reactive-declarations/App.svelte
new file mode 100644
index 0000000000..bc50d74cfc
--- /dev/null
+++ b/site/content/tutorial/02-reactivity/02-reactive-declarations/App.svelte
@@ -0,0 +1,11 @@
+
+
+
+ Clicked {count} {count === 1 ? 'time' : 'times'}
+
\ No newline at end of file
diff --git a/site/content/tutorial/02-reactivity/02-reactive-declarations/text.md b/site/content/tutorial/02-reactivity/02-reactive-declarations/text.md
new file mode 100644
index 0000000000..365908cf22
--- /dev/null
+++ b/site/content/tutorial/02-reactivity/02-reactive-declarations/text.md
@@ -0,0 +1,22 @@
+---
+title: Declarations
+---
+
+Svelte automatically updates the DOM when your component's state changes. Often, some parts of a component's state need to be computed from *other* parts (such as a `fullname` derived from a `firstname` and a `lastname`), and recomputed whenever they change.
+
+For these, we have *reactive declarations*. They look like this:
+
+```js
+let count = 0;
+$: doubled = count * 2;
+```
+
+> Don't worry if this looks a little alien. It's valid (if unconventional) JavaScript, which Svelte interprets to mean 're-run this code whenever any of the referenced values change'. Once you get used to it, there's no going back.
+
+Let's use `doubled` in our markup:
+
+```html
+{count} doubled is {doubled}
+```
+
+Of course, you could just write `{count * 2}` in the markup instead — you don't have to use reactive values. Reactive values become particularly valuable when you need to reference them multiple times, or you have values that depend on *other* reactive values.
\ No newline at end of file
diff --git a/site/content/tutorial/02-reactivity/03-reactive-statements/App.svelte b/site/content/tutorial/02-reactivity/03-reactive-statements/App.svelte
new file mode 100644
index 0000000000..bc50d74cfc
--- /dev/null
+++ b/site/content/tutorial/02-reactivity/03-reactive-statements/App.svelte
@@ -0,0 +1,11 @@
+
+
+
+ Clicked {count} {count === 1 ? 'time' : 'times'}
+
\ No newline at end of file
diff --git a/site/content/tutorial/02-reactivity/03-reactive-statements/text.md b/site/content/tutorial/02-reactivity/03-reactive-statements/text.md
new file mode 100644
index 0000000000..1b0e90b7d5
--- /dev/null
+++ b/site/content/tutorial/02-reactivity/03-reactive-statements/text.md
@@ -0,0 +1,27 @@
+---
+title: Statements
+---
+
+We're not limited to declaring reactive *values* — we can also run arbitrary *statements* reactively. For example, we can log the value of `count` whenever it changes:
+
+```js
+$: console.log(`the count is ${count}`);
+```
+
+You can easily group statements together with a block:
+
+```js
+$: {
+ console.log(`the count is ${count}`);
+ alert(`I SAID THE COUNT IS ${count}`);
+}
+```
+
+You can even put the `$:` in front of things like `if` blocks:
+
+```js
+$: if (count >= 10) {
+ alert(`count is dangerously high!`);
+ count = 9;
+}
+```
\ No newline at end of file
diff --git a/site/content/tutorial/02-reactivity/meta.json b/site/content/tutorial/02-reactivity/meta.json
new file mode 100644
index 0000000000..c908815e04
--- /dev/null
+++ b/site/content/tutorial/02-reactivity/meta.json
@@ -0,0 +1,3 @@
+{
+ "title": "Reactivity"
+}
\ No newline at end of file
diff --git a/site/content/tutorial/01-introduction/99-todo/App.svelte b/site/content/tutorial/99-todo/99-todo/App.svelte
similarity index 100%
rename from site/content/tutorial/01-introduction/99-todo/App.svelte
rename to site/content/tutorial/99-todo/99-todo/App.svelte
diff --git a/site/content/tutorial/99-todo/99-todo/text.md b/site/content/tutorial/99-todo/99-todo/text.md
new file mode 100644
index 0000000000..960d009378
--- /dev/null
+++ b/site/content/tutorial/99-todo/99-todo/text.md
@@ -0,0 +1,126 @@
+---
+title: TODO
+---
+
+* write the rest of the tutorial
+* add an 'open this in REPL' button that takes you to the full REPL
+* figure out wtf to do on mobile
+
+Outline (subject to change):
+
+
+## Introduction
+
+* [x] Tags
+* [x] Dynamic attributes
+* [x] Styling (mention DCE? global styles?)
+* [x] Nested components
+* [ ] HTML tags
+* [ ] Creating an app — how to import components into JS, etc
+
+
+## Reactivity
+
+* [x] Assignments
+* [x] Declarations
+* [x] Statements
+
+
+## Logic
+
+* [ ] If blocks
+* [ ] Else/elseif blocks
+* [ ] Each blocks
+* [ ] Keyed each blocks (maybe? kind of need to cover transitions before we can make this obvious)
+* [ ] Await blocks
+
+
+## Props
+
+* [ ] `export let foo`
+* [ ] `export let foo = 1`
+* [ ] `export function foo(){...}`
+
+
+## Events
+
+* [ ] `createEventDispatcher` and `dispatch`
+* [ ] `on:blah`
+* [ ] DOM event modifiers
+
+
+## Bindings
+
+* [ ] Form bindings (input, textarea, select)
+* [ ] Dimensions
+* [ ] `this`
+
+
+## Stores
+
+* [ ] `writable` (and second argument?)
+* [ ] `$foo`
+* [ ] `readable`
+* [ ] `derive`
+* [ ] `$foo += 1` (if we implement it)
+
+
+## Lifecycle
+
+* [ ] `onMount`
+* [ ] `onDestroy`
+* [ ] `beforeUpdate`
+* [ ] `afterUpdate`
+* [ ] `tick`
+* [ ] how lifecycle functions behave in SSR mode?
+
+
+## Context
+
+* [ ] `setContext` and `getContext`
+
+
+## Transitions
+
+* [ ] `transition` with built-in transitions
+* [ ] Custom CSS transitions
+* [ ] Custom JS transitions
+* [ ] `in`
+* [ ] `out`
+
+## Animations
+
+* [ ] `animate:flip`
+
+
+## use: directive
+
+* `use:foo`
+* `use:foo={bar}`
+
+## class: directive
+
+* `class:foo={bar}`
+* `class:foo`
+
+
+## Composition
+
+* [ ] ``
+* [ ] ``
+* [ ] `` and `let:bar`
+
+
+## Special elements
+
+* ``
+* ``
+* ``
+* ``
+* ``
+
+
+## Miscellaneous
+
+* Keyed each blocks
+* Debug tags
\ No newline at end of file
diff --git a/site/content/tutorial/99-todo/meta.json b/site/content/tutorial/99-todo/meta.json
new file mode 100644
index 0000000000..ae14de1ea1
--- /dev/null
+++ b/site/content/tutorial/99-todo/meta.json
@@ -0,0 +1,3 @@
+{
+ "title": "TODO"
+}
\ No newline at end of file
diff --git a/site/src/routes/tutorial/[slug]/index.json.js b/site/src/routes/tutorial/[slug]/index.json.js
index 31c72777b4..2e8682020e 100644
--- a/site/src/routes/tutorial/[slug]/index.json.js
+++ b/site/src/routes/tutorial/[slug]/index.json.js
@@ -63,7 +63,12 @@ function get_tutorial(slug) {
return ``;
};
- const html = marked(content, { renderer });
+ let html = marked(content, { renderer });
+ if (found.chapter.startsWith('01')) {
+ const meta = JSON.parse(fs.readFileSync(`content/tutorial/${found.section}/meta.json`));
+ html = `${meta.title} \n${html}`;
+ }
+
return {
html,
diff --git a/site/src/routes/tutorial/[slug]/index.svelte b/site/src/routes/tutorial/[slug]/index.svelte
index 5a96ca78f1..b5fe971c67 100644
--- a/site/src/routes/tutorial/[slug]/index.svelte
+++ b/site/src/routes/tutorial/[slug]/index.svelte
@@ -1,10 +1,14 @@
@@ -92,6 +96,11 @@
color: white;
}
+ .chapter-markup :global(ul) {
+ padding: 0;
+ list-style: none;
+ }
+
.chapter-markup :global(blockquote) {
background-color: rgba(255,255,255,0.1);
color: white;
@@ -113,7 +122,8 @@
outline: 1px solid green;
}
- .chapter-markup :global(p) > :global(code) {
+ .chapter-markup :global(p) > :global(code),
+ .chapter-markup :global(ul) :global(code) {
color: white;
background: rgba(255,255,255,0.1);
padding: 0.2em 0.4em;