| 📦 Turbo JS 91999d1 k33g 12h ago | 1 | # Tutorial: your first Node program in Turbo JS |
| 2 | |
| 3 | By the end of this tutorial you will have written, run and broken a small Node program without leaving the editor — and seen the editor tell you where the mistake was. |
| 4 | |
| 5 | No prior knowledge of Turbo JS is needed. You need Go 1.26 or later to build the editor, and Node to run the program. |
| 6 | |
| 7 | ## Prerequisites |
| 8 | |
| 9 | Check Go: |
| 10 | |
| 11 | ```bash |
| 12 | go version |
| 13 | ``` |
| 14 | |
| 15 | You should see something like: |
| 16 | |
| 17 | ``` |
| 18 | go version go1.26.5 linux/arm64 |
| 19 | ``` |
| 20 | |
| 21 | Check Node and npm: |
| 22 | |
| 23 | ```bash |
| 24 | node --version && npm --version |
| 25 | ``` |
| 26 | |
| 27 | ``` |
| 28 | v24.19.0 |
| 29 | 11.17.0 |
| 30 | ``` |
| 31 | |
| 32 | If `node` is not found, install it first — [a version manager or one installer does it](../how-to/install-node.md). |
| 33 | |
| 34 | ## Step 1 — Install the editor and the language server |
| 35 | |
| 36 | ```bash |
| 37 | git clone https://rickub.com/turbo-editors/turbo-js.git |
| 38 | cd turbo-js |
| 39 | make install |
| 40 | npm install -g typescript-language-server typescript@6 |
| 41 | ``` |
| 42 | |
| 43 | The installer builds, installs, and then checks what it installed. After the `npm install`, the last lines of a second `make install` read: |
| 44 | |
| 45 | ``` |
| 46 | ==> Checking the language server |
| 47 | ✓ typescript-language-server at /usr/local/bin/typescript-language-server |
| 48 | |
| 49 | ==> Ready |
| 50 | ``` |
| 51 | |
| 52 | We now have a `turbo-js` command. The `@6` on the last line matters: TypeScript 7 ships no `tsserver.js`, and the server refuses to start beside it. |
| 53 | |
| 54 | ## Step 2 — Make a project |
| 55 | |
| 56 | ```bash |
| 57 | mkdir /tmp/greeter |
| 58 | cd /tmp/greeter |
| 59 | npm init -y |
| 60 | ``` |
| 61 | |
| 62 | You should see the `package.json` npm wrote, ending in: |
| 63 | |
| 64 | ``` |
| 65 | "type": "commonjs" |
| 66 | } |
| 67 | ``` |
| 68 | |
| 69 | That file is what makes this directory a Node project. **The directory you start the editor in** is where the JavaScript menu's commands will run, and the nearest `package.json` above the file you open is where the language server is started — so start it here. |
| 70 | |
| 71 | ## Step 3 — Open a file that does not exist yet |
| 72 | |
| 73 | ```bash |
| 74 | turbo-js main.js |
| 75 | ``` |
| 76 | |
| 77 | The screen fills. Along the top: |
| 78 | |
| 79 | ``` |
| 80 | File Edit Search Run Code Options Window Snippets Agent JavaScript Help |
| 81 | ``` |
| 82 | |
| 83 | Eleven menus, and the tenth is named after the language. In the middle, an empty window titled `main.js`. Along the bottom, at the right-hand end, you should see: |
| 84 | |
| 85 | ``` |
| 86 | 1:1 LSP: ready |
| 87 | ``` |
| 88 | |
| 89 | `LSP: ready` means `typescript-language-server` started in this directory. We will use it in Step 8. |
| 90 | |
| 91 | ## Step 4 — Write the program |
| 92 | |
| 93 | Type this in. Type it exactly; we will look at the colours next. |
| 94 | |
| 95 | ```javascript |
| 96 | // A greeting, several times over. |
| 97 | const { argv } = require("node:process"); |
| 98 | |
| 99 | /** Greets one person. */ |
| 100 | class Greeter { |
| 101 | #name; |
| 102 | |
| 103 | constructor(name) { |
| 104 | this.#name = name; |
| 105 | } |
| 106 | |
| 107 | greet(times = 1) { |
| 108 | const pattern = /^[A-Z]/; |
| 109 | for (let i = 1; i <= times; i++) { |
| 110 | console.log(`Hello, ${this.#name}! (${i})`); |
| 111 | } |
| 112 | return pattern.test(this.#name); |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | const who = argv[2] ?? "JavaScript"; |
| 117 | new Greeter(who).greet(3); |
| 118 | ``` |
| 119 | |
| 120 | Two things about typing it. **The editor repeats the previous line's indentation when you press `Enter`**, so type only the change: two more spaces after a line that ends in `{`, and `Backspace` twice before a closing `}`. And if a completion list drops down while you type — a `.` asks for one by itself, and `this.` is one — keep typing or press `Escape`; `Enter` would accept the first entry. |
| 121 | |
| 122 | Press `F2` to save. The status bar says `Saved main.js`. |
| 123 | |
| 124 | ## Step 5 — Read the colours |
| 125 | |
| 126 | Look at what you have typed. In the default `turbo-classic` theme: |
| 127 | |
| 128 | | What | Colour | |
| 129 | | --- | --- | |
| 130 | | `const`, `class`, `for`, `let`, `return`, `new` | bright white, bold — keywords | |
| 131 | | `Greeter`, where it is declared and where it is called | bright cyan — a class | |
| 132 | | `constructor`, `greet`, `log`, `test` | bright yellow, bold — functions and methods | |
| 133 | | `console`, `require` | bright cyan, bold — the globals Node provides | |
| 134 | | `argv`, `name`, `times`, `who`, `#name` | bright yellow — ordinary names | |
| 135 | | `"node:process"`, `` `Hello, ${this.#name}! (${i})` `` | green — strings | |
| 136 | | `/^[A-Z]/` | green — a regular expression, drawn with the string colour in this theme | |
| 137 | | `1`, `3`, `this` | magenta — numbers and constants | |
| 138 | | `// A greeting…`, `/** Greets one person. */` | grey — comments | |
| 139 | | `=`, `<=`, `++`, `??`, `{`, `}`, `.` | white — operators and punctuation | |
| 140 | |
| 141 | Three of those rows are worth a second look. |
| 142 | |
| 143 | **`Greeter` is cyan and `greet` is yellow**, and nothing in the editor was told which of them is a class. JavaScript's convention decides it: classes are the names people capitalise, so a capital letter is coloured as a class — even in `new Greeter(who)`, where a parenthesis follows. |
| 144 | |
| 145 | **`/^[A-Z]/` is a regular expression, not two divisions.** The scanner reads the `=` before it and knows a slash there opens a literal. Change the line to `const half = times / 2;` and the slash goes white again. |
| 146 | |
| 147 | **`#name` is one name**, the `#` included, and it is yellow where a comment would be grey — [a deliberate rule](../explanation/colouring-and-completion.md), because `#` opens a comment in half the other languages this editor colours. |
| 148 | |
| 149 | ## Step 6 — Give the project its tools |
| 150 | |
| 151 | Press `F10` to open the menu bar, then `→` **nine times** to reach **JavaScript** — past Edit, Search, Run, Code, Options, Window, Snippets and Agent. Faster: press `Alt-J`. |
| 152 | |
| 153 | The menu holds two items, and only one of them is available: |
| 154 | |
| 155 | ``` |
| 156 | ┌───────────────────┐ |
| 157 | │ Create tools file │ |
| 158 | │ Open tools file │ ← greyed out; there is no file to open yet |
| 159 | └───────────────────┘ |
| 160 | ``` |
| 161 | |
| 162 | Choose **Create tools file**. |
| 163 | |
| 164 | A second window opens on the file that was just written, `.turbo-js/tools.toml`. Read it if you like — it explains every key it uses — then press `Ctrl-W` to close it. |
| 165 | |
| 166 | Look at the menu bar: a **Tools** menu has appeared between JavaScript and Help. The starter file's last entry names a menu of its own, and that one line is the whole mechanism. |
| 167 | |
| 168 | Open the JavaScript menu again. It now holds six commands, and the two items have swapped: `Create tools file` is greyed out, and `Open tools file` is the one you can choose. |
| 169 | |
| 170 | ## Step 7 — Run it |
| 171 | |
| 172 | Press `Alt-J` and choose **Run**. A box asks for a value before the command runs, because a Node project has no single entry point the editor could know: |
| 173 | |
| 174 | ``` |
| 175 | ┌──────────────── Run ────────────────┐ |
| 176 | │ script, e.g. main.js │ |
| 177 | │ [ ] │ |
| 178 | └─────────────────────────────────────┘ |
| 179 | ``` |
| 180 | |
| 181 | Type `main.js` and press `Enter`. A terminal window opens and the program runs in it: |
| 182 | |
| 183 | ``` |
| 184 | Hello, JavaScript! (1) |
| 185 | Hello, JavaScript! (2) |
| 186 | Hello, JavaScript! (3) |
| 187 | ``` |
| 188 | |
| 189 | A terminal rather than a dialog, because a program that reads the keyboard has to be answerable. The program has finished, so the window has stopped behaving like a terminal and every key reaches the editor again: press `Ctrl-W` to close it. |
| 190 | |
| 191 | ## Step 8 — Break it, and see where |
| 192 | |
| 193 | Go to the last line, `new Greeter(who).greet(3);`, and delete its closing parenthesis, so it reads: |
| 194 | |
| 195 | ```javascript |
| 196 | new Greeter(who).greet(3; |
| 197 | ``` |
| 198 | |
| 199 | Press `F2` to save. |
| 200 | |
| 201 | Within a second, two things happen. A `×` appears in the gutter, just left of that line's number. And the status bar reads: |
| 202 | |
| 203 | ``` |
| 204 | ⚠ ')' expected. |
| 205 | ``` |
| 206 | |
| 207 | Nothing asked for that. `typescript-language-server` publishes it by itself whenever the file changes — this is what the server does for a plain `.js` file: it finds the syntax errors. Put the parenthesis back and save again; both the mark and the message go away. |
| 208 | |
| 209 | Now put the cursor on `greet` in that last line and press `F1`. A box titled **Symbol** opens with the method's signature, beginning `(method) Greeter.greet(times?: number)` — the server worked out the parameter's type from its default value and the return type from the `return pattern.test(…)` line, in a language that never declared either. Press `Escape` to close it, then `F12` on the same word: the cursor jumps to the line where `greet` is declared. |
| 210 | |
| 211 | ## Step 9 — Change the theme |
| 212 | |
| 213 | `F10`, then `→` **five times** to reach **Options** — past Edit, Search, Run and Code. Choose **Theme…**. |
| 214 | |
| 215 | A list opens on the theme you are in, `turbo-classic`. Press `↑` until `cobalt` is selected — five times — and `Enter`. The whole screen changes, keeping the same shape. |
| 216 | |
| 217 | Press `Alt-X` to leave. The editor asks about unsaved files first, if there are any. |
| 218 | |
| 219 | ## What now? |
| 220 | |
| 221 | You have written a Node program in the editor, run it, broken it, and seen the editor say where. To go further: |
| 222 | |
| 223 | - To do specific things → the [how-to guides](../how-to/) |
| 224 | - To see exactly what is coloured and how → [languages coloured](../reference/languages.md) |
| 225 | - To understand why the editor is built this way → the [explanation](../explanation/) |