> is there a reason to use jsconsole/console.log over echo other than looks?
Yes, for cstrings in particular. Compare the outputs of the following examples (all compiled with `-d:danger` to remove noise, and cleaned up slightly to make it clearer): Example 1: using echo with a regular Nim string let str = "Hello world" echo str Run The generated JS: function toJSStr(s_33556901) { // a big function to convert a nim string (array of numbers) to a javascript string // ... } function rawEcho() { // a function that converts all of its arguments to js strings using toJSStr, and then console.logs them // ... } // the string "Hello world", represented as an array of numbers var str_536870913 = [72,101,108,108,111,32,119,111,114,108,100]; rawEcho(str_536870913); Run Example 2: using echo with a cstring ("compatible string") let str = cstring "Hello world" echo str Run The generated JS: function toJSStr(s_33556901) { // a big function to convert a nim string (array of numbers) to a javascript string // ... } function rawEcho() { // a function that converts all of its arguments to js strings using toJSStr, and then console.logs them // ... } function cstrToNimstr(c_33556898) { // a large function that converts a JS string to an array of numbers (the representation of a Nim string) } // the "Hello world" string as a JS string var str_536870913 = "Hello world"; // echo by first converting the JS string to a Nim string rawEcho(cstrToNimstr(str_536870913)); Run Example3: using console.log with a cstring import std/jsconsole let str = cstring "Hello world" console.log str Run The generated JS: var str_536870914 = "Hello world"; console.log(str_536870914); Run As you can see the final output is the simplest with the lowest overhead. When using the JS backend, a good rule of thumb is to use `string` when you want compatibility with Nim libraries, and to use `cstring` when you want compatibility with JS libraries, or smaller codegen output and faster execution.