PG-QR-000 · IT HELP · JULIA & PLUTO · REFERENCE GUIDE
Julia and Pluto Reference
Write, format, and explain a Pluto.jl notebook: Julia syntax, notebook Markdown, and the math and interactivity that connect them.
This guide replaces two separate quick references with one page organized around what writing a Pluto.jl notebook actually involves: the notebook model itself, where Pluto's behavior surprises readers coming from ordinary Julia, the language, the notebook's Markdown, its math, and its interactivity. Sections 1-7 are the complete Beginner-to- intermediate core path. Sections 8-11 are Advanced material: multiple dispatch and type stability in more depth, reactive patterns beyond a single slider, accessible mathematics, and keeping a growing notebook maintainable.
Tooling disclosure. This guide was developed using a repository governance harness and AI-assisted research/curation workflow engineered by Joe Waller and enabled through OpenAI and Anthropic tooling. These tools support research and documentation, including source review, summarization, validation, and guide drafting, and do not replace the author's judgment.
1Notebook Fundamentals Core
A Pluto notebook is a sequence of cells. Each cell holds one piece of Julia code, and
Pluto shows that code next to the value it produces -- a cell displays the value of its
last expression automatically, with no print needed for a simple result.
radius = 3
area = pi * radius^2
That cell displays 28.274333882308138 automatically, because it is the
value of the last (and only) expression in the cell. Section 2 covers what happens when
you reach for println instead.
Prose lives in its own cells, written as a Markdown string using triple-quoted
md"""...""" blocks. A notebook mixes code cells and Markdown cells freely --
neither has to come before the other.
md"""
## Circle area
We computed the area of a circle with radius $radius above.
"""
The other defining trait is reactivity: when you edit a cell, Pluto does not just re-run that cell -- it re-runs every other cell whose code depends on what changed, in whichever order the dependencies require. Cells can be arranged on the page in any order; Pluto determines execution order from the code itself, not from top-to-bottom position. Section 2 covers the sharpest edges of what that guarantee actually requires from your code.
2Where Pluto Differs from Ordinary Julia Core
Pluto runs real Julia, but its notebook model enforces a few rules an ordinary Julia session or a Jupyter notebook does not. Knowing these four before you write real code avoids the errors that catch nearly every new Pluto user in the first hour.
Each global variable can be defined in only one cell
Pluto's reactivity depends on knowing, unambiguously, which cell defines which variable. Assigning the same global name in two different cells is not a style issue -- Pluto disables one of the cells and reports a multiple-definitions error.
# Cell A
x = 1
# Cell B
x = 2 # Pluto disables one of these cells
If two related values genuinely belong together, combine their assignments into one
cell using a begin ... end block instead of splitting them across cells.
begin
x = 1
y = x + 1
end
- This rule applies to global assignments only -- a variable local to a function or a loop can be reused freely across cells.
- If you see "multiple definitions for
x," look for a second top-level assignment to that name and merge it with the first.
Pluto manages your packages automatically
You do not run Pkg.add before using a package in Pluto. Import it directly,
and Pluto reads the notebook's code to work out which packages it needs, then installs
and tracks them for you.
using Plots # Pluto installs Plots.jl automatically the first time this runs
Pluto stores the resulting Project.toml and Manifest.toml
directly inside the notebook file itself, as two extra cells at the bottom you do not
normally edit by hand. Every notebook gets its own isolated package environment, so
packages you install in one notebook cannot silently affect another -- unlike a shared
Jupyter kernel or a normal Julia REPL session, where packages live in one common
environment unless you deliberately activate a different one.
Reactivity tracks code, not values -- mutations do not trigger it
Pluto decides what to re-run by analyzing which cells reference which variable names, not by watching values change at runtime. Re-assigning a variable triggers dependent cells to re-run; mutating it in place does not, because no cell's code actually changed.
items = ["a", "b"]
# later, in another cell:
push!(items, "c") # items is now length 3, but any cell that already
# displayed items will not automatically refresh
The common workaround is a small "dummy" trigger variable that you deliberately re-assign to force a re-run of anything that should reflect the mutation.
begin
push!(items, "c")
items_trigger = items_trigger + 1 # any cell using items_trigger now re-runs
end
print, println, and display do not write to the notebook
These functions write to the terminal that launched Pluto, not to the cell itself -- a notebook cell only ever shows the value of its own last expression. If you want a value visible in the notebook, make it the last thing the cell evaluates rather than printing it.
# Shows nothing useful in the notebook -- goes to the launching terminal instead
println("The area is $area")
# Shows the value in the notebook, because it is the cell's last expression
"The area is $area"
3Julia Language Essentials Core
The constructs every notebook eventually needs: conditionals, loops, collections, functions, dispatch, and handling errors without crashing the whole notebook.
Control flow
if radius > 10
"large circle"
elseif radius > 0
"small circle"
else
"not a circle"
end
for i in 1:5
println(i) # goes to the launching terminal -- see section 2
end
n = 5
while n > 0
n -= 1
end
Collections
values = [1, 2, 3]
push!(values, 4)
lookup = Dict("a" => 1, "b" => 2)
struct Point
x::Float64
y::Float64
end
squares = [v^2 for v in values]
doubled = map(v -> v * 2, values)
evens = filter(v -> iseven(v), values)
Tuple unpacking assigns several names from one expression at once, and is common enough
in Pluto cells that it is worth knowing on sight: a, b = 1, 2.
Functions and multiple dispatch
Julia lets you define the same function name more than once, with a different method for each combination of argument types -- this is multiple dispatch, and it is one of the language's defining features. Section 8 covers why it also matters for performance.
area(radius::Float64) = pi * radius^2
area(length::Float64, width::Float64) = length * width
area(3.0) # calls the one-argument method: circle area
area(2.0, 5.0) # calls the two-argument method: rectangle area
Handling errors with try/catch/finally
Wrap code that might fail in a try block, and handle the failure in a
catch block instead of letting it stop the whole cell.
function safe_divide(a, b)
try
a / b
catch e
if isa(e, DivideError)
"cannot divide by zero"
else
rethrow(e)
end
finally
# runs whether or not an error occurred
end
end
- Check the caught exception's type with
isa(e, SomeErrorType)rather than treating every error the same way. rethrow(e)re-raises an error you did not intend to handle, instead of silently swallowing it.
4Writing Markdown in Pluto Core
Markdown cells (md"""...""", introduced in section 1) support the same core
syntax you would use anywhere else, with two Pluto-specific extensions covered in
section 5.
md"""
## A second-level heading
Use **bold** sparingly, and `inline code` for literal tokens like variable names.
- Bulleted list item
- Another item
1. Numbered step
2. Next step
> A blockquote for a quoted or emphasized aside.
[A descriptive link](https://plutojl.org/)

| Column A | Column B |
|---|---|
| value | value |
"""
Fenced code blocks inside Markdown cells are for showing code as text, not for running it -- give them a language tag so they render with the right highlighting.
md"""
```julia
area(radius::Float64) = pi * radius^2
```
"""
- Use headings in descending order, matching the notebook's actual structure.
- Give every image real alt text and keep local images alongside the notebook.
- Keep tables simple -- a table that needs heavy formatting to stay readable is usually better as a short list.
5Math and Interpolation Core
Pluto renders Markdown math with KaTeX rather than MathJax, specifically because KaTeX supports interpolating live Julia values into an equation and numbering equations by their position in the notebook -- both of which a static math renderer cannot do.
md"""
Inline: the area is $\pi r^2$.
Display, for a longer expression:
$$\pi r^2 = \pi \cdot r \cdot r$$
"""
A single $(value) interpolates a live Julia value directly into Markdown
text -- the same interpolation syntax Julia strings use elsewhere in the language.
md"""
With radius $(radius), the computed area is $(round(area, digits=2)).
"""
- Prefer display math for anything longer than a short inline expression -- it reads far more clearly.
- Define any Greek letters or unfamiliar symbols in the nearby prose the first time they appear.
The full LaTeX math syntax -- AMS environments, equation numbering, and accessible math publishing -- is its own dedicated guide: LaTeX Math Quick Reference.
6Interactivity and Plots Core
The @bind macro links an HTML input element to a Julia variable: whenever
the input changes, every cell that uses the bound variable re-runs automatically.
PlutoUI supplies the common input widgets so you rarely write the HTML by hand.
using PlutoUI
@bind r Slider(1:10; default=3, show_value=true)
@bind label TextField(20, "default text")
@bind show_grid CheckBox(true)
@bind shape Select(["circle", "rectangle"])
@bind shapes MultiSelect(["circle", "rectangle", "triangle"])
@bind go Button("Recompute")
@bind confirmed_value confirm(Slider(1:100)) # only updates when confirmed, not live
confirm wraps any widget so it only sends its value on explicit
confirmation rather than on every intermediate change -- useful when the bound cell
triggers an expensive computation.
Plots.jl composes a chart from a base call plus mutating follow-up calls: plot
starts a new plot, and functions ending in ! add to the existing one.
using Plots
@bind r Slider(1:20; default=5, show_value=true)
theta = range(0, 2pi, length=200)
plot(r .* cos.(theta), r .* sin.(theta), label="circle, r=$r", aspect_ratio=:equal)
scatter!([0], [0], label="center")
hline!([0], label=false, linestyle=:dash)
- Moving
r's slider re-runs the plot cell automatically, because the cell readsr. plotstarts a new figure;scatter!,hline!, andvline!add to the one already open.
7Writing Readable Notebooks Core
These apply to both the Julia and the Markdown you write -- a notebook is read far more often than it is written.
- Use a consistent heading hierarchy that matches how the notebook is actually organized, not just visual size.
- Keep paragraphs and cells short -- one idea per cell makes reactivity easier to reason about, not just easier to read.
- Limit list nesting to what a reader can track at a glance.
- Avoid raw HTML inside Markdown cells when plain Markdown says the same thing.
- Use fenced code blocks with a language tag for any code shown as text (section 4), never a bare Markdown paragraph.
- Give every image real alt text, and keep local images alongside the notebook or in an approved child directory (repeated from section 4 because it is the most commonly skipped item).
8Multiple Dispatch and Type Stability Optional advanced
Section 3 introduced multiple dispatch as a way to write one function name with several type-specific methods. The reason it matters beyond readability is compilation: Julia compiles a specialized version of a method for the actual argument types it sees, and that specialization is what makes Julia fast without giving up the expressiveness of a dynamic language.
Type stability is the property that a function returns the same output type for a given combination of input types, every time. A type-stable function lets the compiler know the result type ahead of time and generate tight, C-like code; a type-unstable one forces Julia to check types at runtime and box and unbox values, which is where most avoidable performance loss in Julia code comes from.
# Unstable: the return type depends on a runtime value, not just the input type
function maybe_int(x)
if x > 0
return x # returns whatever type x is
else
return 0 # always returns Int, even if x was a Float64
end
end
# Stable: the return type is fixed by the input type alone
function always_float(x::Float64)
return x > 0 ? x : 0.0
end
You do not need to chase type stability everywhere -- it matters most in code that runs many times, such as the body of a loop or a function called from a reactive cell that re-runs on every slider movement.
9Reactive Pluto Patterns Beyond @bind Optional advanced
Section 2's "dummy trigger" pattern generalizes: any time a cell's real effect is a mutation Pluto cannot see, a small re-assigned counter variable is what makes dependent cells re-run.
@bind r Slider(1:20; default=5)
@bind color Select(["blue", "red", "green"])
# This cell re-runs whenever *either* r or color changes, because it reads both.
plot(r .* cos.(theta), r .* sin.(theta); color=Symbol(color))
Wrap an expensive bound widget in confirm (section 6) when its cell triggers
real work -- a large computation or a network call -- so it only runs once per deliberate
confirmation instead of on every intermediate slider position.
10Accessible Mathematics in Notebooks Optional advanced
The same accessibility practices covered on Accessibility and Dyslexia-Friendly Publishing apply directly inside a notebook.
- Define every symbol in nearby prose the first time it appears (section 5) -- a screen reader announces a bare Greek letter as its own name, not its mathematical meaning.
- Do not rely on color alone to distinguish plot series (section 6); pair color with a label, marker shape, or line style.
- Prefer display math over dense inline math for any expression a reader needs time to parse.
- Give every figure a caption that states what it shows, not just what it is titled.
11Maintainable Rich Notebook Layouts Optional advanced
A notebook that starts small tends to grow. These keep a larger notebook navigable instead of becoming a long scroll of near-duplicate cells.
- Group related code into one
begin ... endcell (section 2) when the pieces only make sense together, rather than splitting them for no reason. - Write a helper function once and call it from multiple cells instead of copy-pasting a computation.
- Keep computation and display separate: compute a value in one cell, and format or plot it in a later one, so Pluto's dependency graph stays easy to follow.
- Use section headings (section 7) to break a long notebook into named parts a reader can jump to from the table of contents Pluto generates automatically.
References
- [1] JuliaPluto. Reactivity -- how Pluto notebooks update automatically. The one-definition-per-variable rule and syntax-based reactivity. Verified 2026-08-17.
- [2] JuliaPluto. Packages -- built-in package management. Automatic per-notebook Project.toml/Manifest.toml handling. Verified 2026-08-17.
- [3] JuliaPluto. LaTeX. Inline and display math syntax inside Pluto Markdown cells. Verified 2026-08-17.
- [4] JuliaPluto. PlutoUI and @bind. How the @bind macro links UI elements to reactive variables. Verified 2026-08-17.
- [5] JuliaHub. PlutoUI.jl documentation. The full widget catalog: Slider, TextField, CheckBox, Select, MultiSelect, Button, confirm. Verified 2026-08-17.
- [6] JuliaPluto. Assign a variable more than once (issue #276). The begin...end workaround for combining related assignments. Verified 2026-08-17.
- [7] The Julia Language. Control Flow. Conditionals, loops, and exception handling syntax. Verified 2026-08-17.
- [8] Julia community documentation. Writing type-stable Julia code. Practical explanation of type stability's performance effect. Verified 2026-08-17.
- [9] JuliaPlots. Plots.jl documentation. The plot/scatter!/hline! composition pattern. Verified 2026-08-17.
- [10] Polymath Global. Julia_Programming_Guide.md. Original topic coverage this page consolidates. Snapshot verified 2026-07-24.
- [11] Polymath Global. Pluto_JL_Markdown_Guide.md. Original topic coverage this page consolidates. Snapshot verified 2026-07-24.