diff --git a/cheatsheets/gleam-for-javascript-users.md b/cheatsheets/gleam-for-javascript-users.md
new file mode 100644
index 00000000..03d706e7
--- /dev/null
+++ b/cheatsheets/gleam-for-javascript-users.md
@@ -0,0 +1,700 @@
+---
+layout: page
+title: Gleam for JavaScript users
+subtitle: Hello JavaScripticians!
+---
+
+- [Comments](#comments)
+- [Variables](#variables)
+ - [Variables type annotations](#variables-type-annotations)
+- [Functions](#functions)
+ - [Function capturing with `_`](#function-capturing-with-_)
+ - [Exporting functions](#exporting-functions)
+ - [Function type annotations](#function-type-annotations)
+ - [Referencing functions](#referencing-function)
+ - [Labelled arguments](#labelled-arguments)
+- [Modules](#modules)
+- [Operators](#operators)
+- [Constants](#constants)
+- [Blocks](#blocks)
+- [Data types](#data-types)
+ - [Strings](#strings)
+ - [Tuples](#tuples)
+ - [Lists](#lists)
+ - [Dicts](#dicts)
+- [Flow control](#flow-control)
+ - [Case](#case)
+ - [Piping](#piping)
+
+
+## Comments
+
+### JavaScript
+
+In JavaScript, comments are written with a `//` prefix.
+
+```javascript
+// Hello, Joe!
+```
+
+Multi-line comments may be written like so:
+
+```javascript
+/*
+ * Hello, Joe!
+ */
+```
+
+In JavaScript, above `class` and `function` declarations there can be
+`docblocks` like so:
+
+```javascript
+/**
+ * A Bar class
+ */
+class Bar {}
+
+/**
+ * A quux function.
+ *
+ * @param {string} str String passed to quux
+ * @returns {string} An unprocessed string
+ */
+function quux(string) { return str; }
+```
+
+Documentation blocks (docblocks) are extracted into generated API
+documentation.
+
+### Gleam
+
+In Gleam comments are written with a `//` prefix.
+
+```gleam
+// Hello, Joe!
+```
+
+Comments starting with `///` are used to document the following statement.
+Comments starting with `////` are used to document the current module.
+
+```gleam
+//// This module is very important.
+
+/// The answer to life, the universe, and everything.
+const answer: Int = 42
+```
+
+## Variables
+
+In JavaScript, you can declare variables using `let`, `const`, or `var`. `let`
+and `var` variables can be reassigned, and `const`s cannot.
+
+#### JavaScript
+
+```javascript
+let size = 50;
+size = size + 100;
+
+const height = 60;
+height = height + 100; // Error!
+```
+
+#### Gleam
+
+Gleam has the `let` keyword before each variable assignment. Variables can't be
+mutated or reassigned. If a new variable has the same name as an existing
+variable, the new definition _shadows_ the old one, but the old variable is not
+overwritten:
+
+```gleam
+import gleam/io
+
+let size = 50
+let print_it = fn() { io.debug(size) }
+let size = size + 100
+let size = 1
+io.debug(size) // prints 1
+print_it() // prints 50
+```
+
+### Variables type annotations
+
+#### JavaScript/TypeScript
+
+In plain JavaScript there are no static types, but in TypeScript variables can
+optionally be annotated with types.
+
+```typescript
+const some_list: number[] = [1, 2, 3];
+```
+
+#### Gleam
+
+In Gleam type annotations can optionally be given when binding variables.
+
+```gleam
+let some_list: List(Int) = [1, 2, 3]
+```
+
+Gleam will check the type annotation to ensure that it matches the type of the
+assigned value. It does not need annotations to type-check your code, but you
+may find it useful to annotate variables to hint to the compiler that you want a
+specific type to be inferred.
+
+## Functions
+
+#### JavaScript
+
+In JavaScript, you can define functions with the `function` keyword, or assign
+anonymous functions to variables.
+
+```javascript
+function sum(x, y) {
+ return x + y;
+}
+
+const mul = (x, y) => x * y;
+```
+
+#### Gleam
+
+Gleam's functions are declared using a syntax similar to Rust. Gleam's anonymous
+functions have a similar syntax, just without the function name.
+
+```gleam
+pub fn sum(x, y) {
+ x + y
+}
+
+let mul = fn(x, y) { x * y }
+mul(1, 2)
+```
+
+### Function capturing with `_`
+
+To turn a multi-parameter function into a function with just one parameter,
+Gleam has a special function-capturing syntax:
+
+```gleam
+fn add(a: Int, b: Int) -> Int {
+ a + b
+}
+
+let add2 = fn(x) { add(x, 2) }
+// is equivalent to:
+let add2 = add(_, 2)
+```
+
+This is particularly useful in combination with the [pipe operator](#piping).
+
+### Exporting functions
+
+#### JavaScript
+
+In both JavaScript and Gleam, functions are private by default. In JavaScript,
+functions can be made public with the `export` keyword.
+
+```javascript
+// this is public
+export function sum(x, y) {
+ return x + y;
+}
+
+// this is private
+function mul(x, y) {
+ return x * y;
+}
+```
+
+#### Gleam
+
+In Gleam functions need the `pub` keyword to be public.
+
+```gleam
+// this is public
+pub fn sum(x, y) {
+ x + y
+}
+
+// this is private
+fn mul(x, y) {
+ x * y
+}
+```
+
+### Function type annotations
+
+#### JavaScript/TypeScript
+
+In TypeScript, you can annotate the types of function parameters and return
+values.
+
+```typescript
+function sum(x: number, y: number): number {
+ return x + y;
+}
+```
+
+The choice of whether, and exactly how to annotate a function can influence how
+type-safe your code is.
+
+#### Gleam
+
+In Gleam, functions can **optionally** have their argument and return types
+annotated. These type annotations will always be checked by the compiler and
+throw a compilation error if not valid. The compiler will still type check your
+program using type inference if annotations are omitted.
+
+```gleam
+pub fn add(x: Int, y: Int) -> Int {
+ x + y
+}
+
+pub fn mul(x: Int, y: Int) -> Bool { // compile error, type mismatch
+ x * y
+}
+```
+
+### Referencing functions
+
+Referencing functions in Gleam works like in JavaScript, without any special
+syntax.
+
+#### JavaScript
+```javascript
+function identity(x) {
+ return x
+}
+
+function main() {
+ const func = identity;
+ func(100);
+}
+```
+
+#### Gleam
+```gleam
+fn identity(x) {
+ x
+}
+
+fn main() {
+ let func = identity
+ func(100)
+}
+```
+
+
+### Labelled arguments
+
+#### JavaScript
+
+JavaScript doesn't really have a syntax for passing arguments by name and in any
+order, but this behaviour can be approximated using an object literal.
+
+```javascript
+function replace({ inside: string, each: pattern, with: replacement }) {
+ return string.replace(new RegExp(pattern, "g"), replacement);
+}
+```
+
+```javascript
+replace({ each: ",", with: " ", inside: "A,B,C" });
+```
+
+Because the arguments are stored in an object there is a small runtime
+performance penalty for this pattern.
+
+#### Gleam
+
+In Gleam arguments can be given a label as well as an internal name. The name
+used at the call-site does not have to match the name used for the variable
+inside the function.
+
+```gleam
+import gleam/string
+
+pub fn replace(inside string, each pattern, with replacement) {
+ string.replace(string, pattern, replacement)
+}
+```
+
+```gleam
+replace(each: ",", with: " ", inside: "A,B,C")
+```
+
+There is no performance cost to Gleam's labelled arguments as they are
+optimised to regular function calls at compile time, and all the arguments
+are fully type checked.
+
+## Modules
+
+Just like in JavaScript, each Gleam file is a module, and values can only be
+accessed if they are explicitly made public. Gleam doesn't have an equivalent of
+JavaScript's `export default` -- all exports are named.
+
+### JavaScript
+
+In JavaScript, `export` marks values as public. Import paths are usually
+relative to the current file.
+
+```javascript
+//// my_library/tools/math.js
+export function add(a, b) {
+ return a + b;
+}
+
+//// my_library/other_file.js
+import { add } from "./tools/math";
+import * as math from "./tools/math";
+
+add(2, 2);
+math.add(2, 2);
+```
+
+### Gleam
+
+In Gleam, `pub` marks values as public. Import paths are always absolute,
+starting at the project root.
+
+```gleam
+//// my_library/tools/math.gleam
+pub type Color {
+ Red
+ Green
+ Blue
+}
+
+pub fn add(a, b) {
+ a + b
+}
+
+//// my_library/other_file.gleam
+// You can import a whole module
+import my_library/tools/math
+
+let pixel = math.Green
+let sum = math.add(2, 2)
+
+// Or specify exactly what you want
+import my_library/tools/math.{type Color, Red, add}
+
+let colors: Color = [Red, math.Green]
+let sum = add(2, 2)
+```
+
+## Operators
+
+| Operator | JavaScript | Gleam | Notes |
+| ----------------- | ---------- | ----- | ---------------------------------------------- |
+| Equal | `==` | `==` | In Gleam both values must be of the same type |
+| Strictly equal to | `===` | `==` | Comparison in Gleam is always strict |
+| Not equal | `!==` | `!=` | In Gleam both values must be of the same type |
+| Greater than | `>` | `>` | In Gleam both values must be **ints** |
+| Greater than | `>` | `>.` | In Gleam both values must be **floats** |
+| Greater or equal | `>=` | `>=` | In Gleam both values must be **ints** |
+| Greater or equal | `>=` | `>=.` | In Gleam both values must be **floats** |
+| Less than | `<` | `<` | In Gleam both values must be **ints** |
+| Less than | `<` | `<.` | In Gleam both values must be **floats** |
+| Less or equal | `<=` | `<=` | In Gleam both values must be **ints** |
+| Less or equal | `<=` | `<=.` | In Gleam both values must be **floats** |
+| Boolean and | `&&` | `&&` | In Gleam both values must be **bools** |
+| Boolean or | `||` | `||` | In Gleam both values must be **bools** |
+| Add | `+` | `+` | In Gleam both values must be **ints** |
+| Add | `+` | `+.` | In Gleam both values must be **floats** |
+| Subtract | `-` | `-` | In Gleam both values must be **ints** |
+| Subtract | `-` | `-.` | In Gleam both values must be **floats** |
+| Multiply | `*` | `*` | In Gleam both values must be **ints** |
+| Multiply | `*` | `*.` | In Gleam both values must be **floats** |
+| Divide | `/` | `/` | In Gleam both values **ints** |
+| Divide | `/` | `/.` | In Gleam both values must be **floats** |
+| Remainder | `%` | `%` | In Gleam both values must be **ints** |
+| Concatenate | `+` | `<>` | In Gleam both values must be **strings** |
+| Pipe | | `|>` | Gleam's pipe can pipe into anonymous functions |
+
+### Notes on operators
+
+- JavaScript operators are short-circuiting as in Gleam.
+- Gleam's `/` operator always returns an integer.
+- Chains and pipes:
+ - In JavaScript chaining is usually done by constructing class methods that
+ return an object: `foo.bar(1).quux(2)` means `bar(1)` is called as a method
+ of `foo` and then `quux()` is called as a method of the return value
+ (object) of the `bar(1)` call.
+ - In contrast in Gleam piping, no objects are being returned but mere data is
+ pushed from left to right, much like in unix tooling.
+
+## Constants
+
+#### JavaScript
+
+In JavaScript constants are just regular variables using the `const` keyword.
+
+```javascript
+const THE_ANSWER = 42;
+
+function main() {
+ const justANormalVariable = "can also use the const keyword";
+ return THE_ANSWER;
+}
+```
+
+#### Gleam
+
+In Gleam constants are also created using the `const` keyword. The difference to
+JavaScript is that Gleam constants can only live at the top-level of a module
+(not inside a function), and variables defined using `let` can only live inside
+functions (not at the top-level of a module).
+
+```gleam
+const the_answer = 42
+
+pub fn main() {
+ the_answer
+}
+```
+
+Additionally, Gleam constants can be referenced from other modules.
+
+```gleam
+// in file other_module.gleam
+pub const the_answer: Int = 42
+```
+
+```gleam
+import other_module
+
+fn main() {
+ other_module.the_answer
+}
+```
+
+## Blocks
+
+#### JavaScript
+
+In JavaScript statements can be grouped together using braces `{` `}`. These
+blocks are usually associated with specific language constructs like functions,
+conditionals, loops, etc. The only way to create multi-line expression blocks
+like in Gleam is using an immediately-invoked function expression (IIFE).
+
+Parentheses `(` `)` are used to group arithmetic expressions.
+
+```javascript
+function main() {
+ // x gets assigned the result of the IIFE
+ const x = (() => {
+ console.log(1);
+ return 2;
+ })();
+ const y = x * (x + 10); // parentheses are used to change arithmetic operations order
+ return y;
+}
+```
+
+#### Gleam
+
+In Gleam curly braces, `{` and `}`, are used to group expressions.
+
+```gleam
+pub fn main() {
+ let x = {
+ print(1)
+ 2
+ }
+ // Braces are used to change arithmetic operations order
+ let y = x * { x + 10 }
+ y
+}
+```
+
+Unlike in JavaScript, in Gleam function blocks are always expressions, so are
+`case` blocks or arithmetic sub groups. Because they are expressions they always
+return a value.
+
+For Gleam the last value in a block's expression is always the value being
+returned from an expression.
+
+## Data types
+
+### Strings
+
+#### JavaScript
+
+In JavaScript strings are sequences of UTF-16 code units, and can be delimited
+by single quotes `'`, double quotes `"`, or backticks `
.
+Strings using backticks support interpolation.
+
+```javascript
+const world = 'world';
+"Hellø, world!"
+`Hello, ${world}!`
+```
+
+#### Gleam
+
+In Gleam strings are encoded as UTF-8 binaries, and must be delimited by double
+quotes. Gleam strings do not allow interpolation, yet. Gleam however offers a
+`string_builder` via its standard library for performant string building.
+
+```gleam
+"Hellø, world!"
+```
+
+### Tuples
+
+Tuples are very useful in Gleam as they're the only collection data type that
+allows mixed types in the collection.
+
+#### JavaScript
+
+JavaScript doesn't have a concept of tuples, but some tuple behavior can be
+imitated using arrays.
+
+```javascript
+const myArray = ["username", "password", 10];
+const [_, password] = myArray;
+console.log(password); // "password"
+// Direct index access
+console.log(myArray[0]); // "username"
+```
+
+#### Gleam
+
+```gleam
+let my_tuple = #("username", "password", 10)
+let #(_, pwd, _) = my_tuple
+io.print(pwd) // "password"
+// Direct index access
+io.print(my_tuple.0) // "username"
+```
+
+### Lists
+
+Arrays in JavaScript are allowed to be of mixed types, but not in Gleam.
+
+#### JavaScript
+
+JavaScript arrays are delimited by square brackets `[` `]`. The `...` operator
+can insert one array into another.
+
+```javascript
+let list = [2, 3, 4];
+list = [1, ...list, 3];
+const [firstElement, secondElement, ...rest] = list;
+console.log(["hello", ...list]); // works
+```
+
+#### Gleam
+
+Gleam has a "cons" operator that works for lists destructuring and pattern
+matching. In Gleam lists are immutable so adding and removing elements from the
+start of a list is highly efficient.
+
+```gleam
+let list = [2, 3, 4]
+let list = [1, ..list]
+let [1, second_element, ..] = list
+[1.0, ..list] // compile error, type mismatch
+```
+
+An important difference between Gleam's "cons" operator and JavaScript's `...`
+is that the `..tail` can only appear as the last item between the brackets.
+
+```gleam
+let list = [2, 3, 4]
+let list = [1, ..list] // works
+let list = [1, 2, ..list] // still works
+let list = [1, ..list, 5] // compile error
+```
+
+To store items of different types in a list, you need to create a custom type:
+
+```gleam
+type Value {
+ Number(Int)
+ Text(String)
+ BinaryData(BitArray)
+}
+
+let my_list = [BinaryData(<<"hello":utf8>>), Text("👋"), Number(5)]
+```
+
+### Dicts
+
+#### JavaScript
+
+In JavaScript, key–value pairs are usually stored in objects, whose keys can
+only be strings, numbers, or symbols. There is also the `Map` class, which
+allows any type to be used for keys. In both cases, types of keys and values can
+be mixed in a given map.
+
+```javascript
+const map1 = {
+ key1: "value1",
+ key2: 5,
+};
+
+const actualMap = new Map([
+ ["key1", "value1"],
+ [9, 5],
+]);
+```
+
+#### Gleam
+
+In a Gleam `dict`, the type for keys and the type for values are fixed. So, for
+example, you can't have a dict with some `String` values and some `Int` values,
+and you can't have a dict with some `String` keys and some `Int` keys. But you
+can have a dict with `String` keys and `Int` values.
+
+There is no dict literal syntax in Gleam, and you cannot pattern match on a
+dict. Maps are generally not used much in Gleam, custom types are more common.
+
+(You would usually translate a TypeScript `type` or `class` to a Gleam custom
+type, and only use a Gleam `Map` for arbitrary key–value pairs, equivalent to a
+TypeScript `Map` or `Record`.)
+
+```gleam
+import gleam/dict
+
+dict.from_list([#("key1", "value1"), #("key2", "value2")])
+dict.from_list([#("key1", "value1"), #("key2", 2)]) // Type error!
+```
+
+## Flow control
+
+### Case
+
+`case` is one of the most used control flow methods in Gleam. It can be seen as
+a `switch` statement on steroids. It provides a terse way to match a value type
+to an expression. It is also used to replace `if`/`else` statements, which Gleam
+doesn't have.
+
+### Piping
+
+In JavaScript, method calls are easy to chain together:
+
+```javascript
+"hello, world".toUpperCase().repeat(2).split(',')
+```
+
+Since Gleam doesn't have objects with methods, the equivalent code might look
+like this:
+
+```gleam
+import gleam/string
+
+string.split(string.repeat(string.uppercase("hello, world"), times: 2), ",")
+```
+
+To make this more readable, Gleam has the pipe operator `|>`
+
+```gleam
+import gleam/string
+
+"hello, world"
+|> string.uppercase
+|> string.repeat(2) // defaults to piping into the first argument
+|> string.split(_, ",") // you can use _ to specify the argument to pipe into
+```
diff --git a/cheatsheets/gleam-for-php-users.md b/cheatsheets/gleam-for-php-users.md
index 6dcdbc03..23a8a4d4 100644
--- a/cheatsheets/gleam-for-php-users.md
+++ b/cheatsheets/gleam-for-php-users.md
@@ -55,7 +55,7 @@ Multi line comments may be written like so:
*/
```
-IN PHP, above `trait`, `interface`, `class`, `member`, `function` declarations
+In PHP, above `trait`, `interface`, `class`, `member`, `function` declarations
there can be `docblocks` like so:
```php
@@ -512,7 +512,7 @@ are fully type checked.
| Divide | `/` | `/` | In Gleam both values must be **Int** |
| Divide | `/` | `/.` | In Gleam both values must be **Float** |
| Remainder | `%` | `%` | In Gleam both values must be **Int** |
-| Concatenate | `.` | `<>` | In Gleam both values must be **String**
+| Concatenate | `.` | `<>` | In Gleam both values must be **String** |
| Pipe | `->` | |>
| Gleam's pipe can chain function calls. See note for PHP |
### Notes on operators
@@ -520,8 +520,8 @@ are fully type checked.
- For bitwise operators, which exist in PHP but not in Gleam,
see: .
- `==` is by default comparing by value in PHP:
- - Types may be autocast to be compareable.
- - Two objects with the same members values will equal:
+ - Types may be autocast to be comparable.
+ - Two objects with the same members values will equal.
- `===` is for comparing by strict equality in PHP:
- Types will not be autocast for comparison
- Two objects with the same members will not equal. Only if a variable binds
@@ -765,9 +765,9 @@ between floats and integers in various ways including `rounding`, `floor`,
### Case
-Case is one of the most used control flow in Gleam. It can be seen as a switch
-statement on steroids. It provides a terse way to match a value type to an
-expression. It is also used to replace `if`/`else` statements.
+Case is one of the most used control flow methods in Gleam. It can be seen as a
+switch statement on steroids. It provides a terse way to match a value type to
+an expression. It is also used to replace `if`/`else` statements.
#### PHP
@@ -1293,7 +1293,7 @@ pub fn main() {
#### PHP
PHP features ways to load arbitrary PHP code: `require`, `include` and
-autoload such as `spl_autoload_register`. Once class pathes are known and
+autoload such as `spl_autoload_register`. Once class paths are known and
registered for autoloading, they can brought into the scope of a file by using
the `use`statement which is part of PHP's namespacing.
Also see .
@@ -1443,12 +1443,12 @@ To iterate a few foundational differences:
or the memory limit is exceeded.
- Gleam on Erlang/BEAM allows to processes requests in a similar isolation
level that PHP offers in contrast to applications running *Go* or *Ruby*.
- The level of isoluation means that, very similar to PHP, if a process
+ The level of isolation means that, very similar to PHP, if a process
crashes (in PHP read: if a request crashes) then the supervision system
can restart that process or after a while or amount of tries abort
repeating restarts on the process with that given input data. This means
Erlang/BEAM will yield similar robustness that PHP developers are used
- to and similar isolation guarantuees.
+ to and similar isolation guarantees.
- When executing Gleam code in fact its compiled Erlang or JavaScript is
executed. So in case there are runtime crashes, the crash log will show
Erlang (or browser-console/NodeJS/Deno) debug information. In Gleam
diff --git a/documentation.md b/documentation.md
index 7617ee38..2327191e 100644
--- a/documentation.md
+++ b/documentation.md
@@ -47,6 +47,7 @@ layout: page
- [Gleam for Elixir users](/cheatsheets/gleam-for-elixir-users)
- [Gleam for Elm users](/cheatsheets/gleam-for-elm-users)
- [Gleam for Erlang users](/cheatsheets/gleam-for-erlang-users)
+- [Gleam for JavaScript users](/cheatsheets/gleam-for-javascript-users)
- [Gleam for PHP users](/cheatsheets/gleam-for-php-users)
- [Gleam for Python users](/cheatsheets/gleam-for-python-users)
- [Gleam for Rust users](/cheatsheets/gleam-for-rust-users)