diff --git a/docs.json b/docs.json
index 2b2a15983..0aa2e8fac 100644
--- a/docs.json
+++ b/docs.json
@@ -428,6 +428,7 @@
"group": "Fift",
"pages": [
"languages/fift/overview",
+ "languages/fift/variables",
"languages/fift/fift-and-tvm-assembly",
"languages/fift/deep-dive",
"languages/fift/multisig",
diff --git a/languages/fift/variables.mdx b/languages/fift/variables.mdx
new file mode 100644
index 000000000..f043d7c91
--- /dev/null
+++ b/languages/fift/variables.mdx
@@ -0,0 +1,278 @@
+---
+title: "Words, Constants, and Variables"
+sidebarTitle: "Words, Constants, and Variables"
+noindex: "true"
+---
+
+import { Aside } from '/snippets/aside.jsx';
+
+## Words
+
+A _word_ is an identifier for an execution token, also known as a `WordDef`. To define a new word, first define a `WordDef` by enclosing code inside `{ }`; then invoke word `:` followed by the identifier for the word. For instance,
+
+```fift
+// square takes the square of the integer at the top of the stack
+{ dup * } : square
+```
+
+defines a new word `square`, which executes `dup` and `*` when invoked. Typing `5 square` becomes equivalent to typing `5 dup *`, and produces the same result:
+
+```fift
+5 square // Produces 25 at the top of the stack
+5 dup * // Produces 25 at the top of the stack
+```
+
+It is possible to use the new word inside new word definitions:
+
+```fift
+// **5 raises the integer at the top of the stack to the 5th power
+{ dup square square * } : **5
+3 **5 // Produces 243 at the top of the stack.
+```
+
+If the word indicated after `:` is already defined, it is redefined. However, all existing definitions of other words will continue to use the old definition of the redefined word. For instance, if `square` is redefined after the definition of `**5` above, `**5` will continue to use the original definition of `square`.
+
+## Constants
+
+A _constant_ is a word that pushes a predefined value when invoked. Constants can defined using the word `constant`. For instance,
+
+```fift
+1000000000 constant Gram
+```
+
+defines a constant `Gram` equal to `10^9`. In other words, `1000000000` will be pushed into the stack whenever `Gram` is invoked:
+
+```fift
+// Pushes Gram and 2 into the stack.
+// Then, multiplies them, producing
+// 2000000000 at the top of the stack.
+Gram 2 *
+```
+
+Of course, it is possible to use the result of a computation to initialize the value of a constant:
+
+```fift
+// Define constant mGram with the result
+// of the computation Gram 1000 /
+Gram 1000 / constant mGram
+mGram // Pushes 1000000 into the stack
+```
+
+The value of a constant does not necessarily have to be an `Integer`. For instance, a string constant can be defined in the same way:
+
+```fift
+"Hello, world!" constant hello
+hello // Pushes "Hello, world!" into the stack
+```
+
+
+
+It is possible to store two values into one "double" constant by using the word `2constant`. For instance:
+
+```fift
+355 113 2constant pifrac
+```
+
+defines a new word `pifrac`, which will push `355` and `113` (in that order) when invoked. The two components of a double constant can be of different types.
+
+If a constant with a fixed name within a block or a colon definition is needed, use `=:` and `2=:`, instead of `constant` and `2constant`.
+The word `=: ` takes the value at the top of stack, creates constant `` and assigns the value to ``.
+Similarly, word `2=: ` takes the two top-most values in the stack, creates constant `` and assigns the values to ``.
+
+For instance, the following defines a word `setxy`, which sets constants `x` and `y`:
+
+```fift
+{ dup =: x dup * =: y } : setxy
+3 setxy x y + // Produces 12 at the top of the stack
+7 setxy x y + // Produces 56 at the top of the stack
+```
+
+The code `3 setxy x y +`, which is equivalent to `3 dup =: x dup * =: y x y +`, changes the stack as follows:
+
+```fift
+3 // Stack: 3
+dup // Stack: 3 3
+=: x // Stack: 3 (x is 3)
+dup // Stack: 3 3
+* // Stack: 9
+=: y // Stack: (y is 9)
+x // Stack: 3
+y // Stack: 3 9
++ // Stack: 12
+```
+
+The code `7 setxy x y +` has a similar explanation.
+
+To recover the execution-time value of a constant inside a block definition, prefix the constant name with the word `@'`. For instance, using the definition of `setxy` as above, the following code defines a new word `addxy` which accesses the constants `x` and `y` and adds them:
+
+```fift
+{ @' x @' y + } : addxy
+3 setxy addxy // Produces 12 at the top of the stack
+```
+
+The code `3 setxy addxy` has the same effect as the code `3 setxy x y +`. The main difference between `3 setxy addxy` and `3 setxy x y +` is that in `3 setxy addxy`, constants `x` and `y` are accessed inside a code block definition, which require the use of word `@'` to access them; while in `3 setxy x y +`, the constants are accessed outside a code block definition, which does not require the use of word `@'` to access them.
+
+The drawback of this approach is that `@'` has to look up the current definition of constants `x` and `y` in the dictionary each time `addxy` is executed. [Variables](#variables) provide a more efficient way to achieve similar results.
+
+## Variables
+
+_Variables_ are a much more efficient way to represent changeable values. To declare a variable, use the word `variable` followed by the identifier. Internally, the word `variable` creates an empty box, which can then be updated with word `!`, and read with word `@`.
+
+For instance:
+
+```fift
+// Create two variables x and y, initialized to null
+variable x variable y
+// Set the value of x to 2
+2 x !
+// Set the value of y to 10
+10 y !
+// Read x and place the value at the top of the stack
+x @
+// Read y and place the value at the top of the stack
+y @
+// Add the two values
++ // Produces 12 at the top of the stack
+```
+
+The word `variable` produces variables initialized to `null`. Instead, to create initialized variables to a specific value, use the phrase `box constant`:
+
+```fift
+// Creates variable x and initializes it with value 17
+17 box constant x
+// Read x and place the value at the top of the stack
+x @ // 17 at the top of the stack
+// Increase 17 by 1
+1 +
+// Update x, now storing 18
+x !
+```
+
+It is possible to define a special word for creating variables, if they are needed often:
+
+```fift
+{ box constant } : init-variable
+// Create a variable x, initialized to 17
+17 init-variable x
+// Create a variable y, initialized to "test"
+"test" init-variable y
+```
+
+Variables have one disadvantage compared to [constants](#constants): accessing the value stored in a variable requires the use of word @. This can be mitigated by defining a "getter" and a "setter" word for a variable, and use these words to write better-looking code:
+
+```fift
+// First, create the box storing the variable contents
+variable x-box
+
+// Define word x so that it is the procedure that
+// reads the box contents.
+// So, that now, x can be treated as if
+// it was the "variable".
+// Instead of writing "x-box @"
+// to read the variable contents, simply write "x".
+{ x-box @ } : x
+
+// Define a similar procedure for updating variables x.
+{ x-box ! } : x!
+
+// Update variable with 5
+5 x!
+
+// Read the variable twice and add the results
+x x + // Produces 10 at the top of the stack
+```
+
+It is possible to define "getters" and "setters" for variables in a more generic way. The following code defines the word `variable-get-set`, which creates a fresh variable and takes the two strings following `variable-get-set` to name the variable's getter and setter, respectively. For example, `variable-get-set x x!` will create a variable with getter `x` and setter `x!`.
+
+```fift
+{ hole dup 1 ' @ does create 1 ' ! does create } : variable-get-set
+```
+
+Word `variable-get-set` works as follows:
+
+```fift
+// Create a fresh box containing null
+hole // Stack: Box
+// Duplicate the box
+dup // Stack: Box Box
+// Push 1
+1 // Stack: Box Box 1
+// Push the word definition for @
+' @ // Stack: Box Box 1 WordDef-for-@
+// Create an execution token { Box WordDef-for-@ }
+// that first pushes Box and then calls @.
+// The 1 argument in the stack tells "does" that it should
+// consume only one argument below 1
+// in the stack.
+does // Stack: Box { Box WordDef-for-@ }
+// Assign the execution token { Box WordDef-for-@ }
+// to the first string comming after the invocation of variable-get-set
+create // Stack: Box
+// Push 1
+1 // Stack: Box 1
+// Push the word definition for !
+' ! // Stack: Box 1 WordDef-for-!
+// Create an execution token { Box WordDef-for-! }
+// that first pushes Box and then calls !.
+// The 1 argument in the stack tells "does" that it should
+// consume only one argument below 1
+// in the stack.
+does // Stack: { Box WordDef-for-! }
+// Assign the execution token { Box WordDef-for-! }
+// to the second string comming after the invocation of variable-get-set
+create // Stack:
+```
+
+For instance, `variable-get-set` can be used as follows:
+
+```fift
+// Create a fresh variable with getter x and setter x!
+variable-get-set x x!
+// Create a fresh variable with getter y and setter y!
+variable-get-set y y!
+// Set x and y to 5 and 10, respectively.
+5 x! 10 y!
+// Swap variables x and y
+x y x! y!
+// Push x
+x // Top of stack has 10
+// Push y
+y // Top of stack has 5
+```
+
+For more details on words `create`, `' `, `does`, refer to Sections [4.5](/languages/fift/whitepaper#4-5-defining-words-and-dictionary-manipulation), [4.6](/languages/fift/whitepaper#4-6-dictionary-lookup), and [4.7](/languages/fift/whitepaper#4-7-creating-and-manipulating-word-lists) in the Fift whitepaper.
+
+As another example of `variable-get-set`, the following implements a simple counter. The example uses auxiliary words `reset-counter` and `incr-counter` to reset the counter variable to `0` and increment the counter by one, respectively.
+
+```fift
+// Create the getter "counter" and setter "counter!"
+variable-get-set counter counter!
+
+// Resets the counter to 0
+{ 0 counter! } : reset-counter
+
+// Increments the counter by one.
+{ counter 1 + counter! } : incr-counter
+
+reset-counter // counter variable has 0
+incr-counter // counter variable has 1
+incr-counter // counter variable has 2
+reset-counter // counter variable has 0
+incr-counter // counter variable has 1
+counter // Pushes 1 to the top of the stack
+```
+
+Word `incr-counter` works as follows:
+
+```fift
+// Push the current value of counter
+counter // Stack: c
+// Push 1
+1 // Stack: c 1
+// Add c and 1
++ // Stack: c+1
+// Store the new value back into the counter variable
+counter! // Stack:
+```