Literate Notebooks
BioLang notebooks (.bln files) interleave Markdown prose with executable
BioLang code. They're perfect for documenting analyses, creating reproducible reports,
and sharing results with collaborators.
Quick Start
No installation needed
Use the browser notebook for core BioLang, statistics, tables, and browser-safe plots. Your local files are read in the browser and are not uploaded. Statistics workbooks fetch their small teaching-data package only when they import it.
Open browser notebook →# Run a notebook in the terminal
bl notebook analysis.bln
# The general runner auto-detects .bln and .bl.md too
bl run analysis.bln
# Export to standalone HTML
bl notebook analysis.bln --export html
# Convert from Jupyter
bl notebook experiment.ipynb --from-ipynb > experiment.bln
# Convert to Jupyter
bl notebook experiment.bln --to-ipynb > experiment.ipynb
Browser Notebook
The standalone notebook page opens local .bln
files or public URLs, lets you edit and reorder cells, and saves back to plain text.
Interpreter state is shared across code cells. If you run a later cell first, the browser
runs the required earlier code cells before it.
Code cells are checked by the same parser service used by BioLang WASM and the native language server. Syntax errors appear below the cell before you run it; execution errors still appear in that cell's output.
Add ?url= with an encoded public notebook URL to make a direct-open link.
The remote host must permit browser requests with CORS. Relative data and image links are
resolved from the notebook URL; local data can be added with Attach data files.
Regular GitHub /blob/ file links are converted to their raw form automatically.
| Runs in the browser | Use the native CLI |
|---|---|
Core language, browser-safe builtins, and statistics; optional statdata downloads on demand | Other installed packages and plugins |
| Small local text datasets | Large files, directories, and unrestricted filesystem access |
| Inline tables and SVG plots | GPU, containers, subprocesses, and native libraries |
The .bln Format
A .bln file is plain text. Markdown prose is rendered, and code blocks
are evaluated. Interpreter state carries over between blocks — variables defined
in one block are available in all later blocks.
Fenced Code Blocks
Use standard Markdown fenced code blocks with biolang, bl,
or no language tag:
## Sample Quality Control
Load the FASTQ file and check basic statistics.
```biolang
let reads = read_fastq("sample_R1.fastq.gz")
let stats = read_stats(reads)
println(stats)
```
## Filter Low-Quality Reads
Keep only reads with mean Phred score above 25.
```bl
let filtered = reads |> filter(|r| mean_phred(r.quality) > 25)
println(f"Kept {len(filtered)} of {len(reads)} reads")
```
Dash-Delimited Code Blocks
Alternatively, use --- on its own line to delimit code blocks. This
is the original BioLang notebook format:
## Load Data
Read the FASTA file and compute per-sequence GC content.
---
let seqs = read_fasta("contigs.fa")
let gc_table = seqs |> map(|s| {id: s.id, gc: gc_content(s.seq)}) |> table()
print(gc_table)
---
## Results
The table above shows GC content per contig.
You can mix both styles in the same notebook. Code blocks with other language tags
(e.g. ```python) are treated as prose and displayed but not executed.
Cell Directives
Add special comment annotations at the top of a code block to control how it behaves:
| Directive | Effect |
|---|---|
| # @hide | Execute the code but don't display it in output. Useful for setup code. |
| # @skip | Don't execute this block. Useful for draft or commented-out cells. |
| # @echo | Print the code before executing it. Shows both code and output. |
| # @hide-output | Execute the code (and show it) but suppress any printed output. |
Directives are stripped from the code before execution. You can combine them:
```biolang
# @echo
# @hide-output
let config = {min_quality: 30, threads: 8}
let reference = "GRCh38"
```
HTML Export
Export a notebook to a self-contained HTML file with syntax highlighting and a dark-themed design:
bl notebook analysis.bln --export html > report.html
The HTML output includes inline CSS styling, BioLang syntax highlighting with color-coded keywords, strings, comments, and pipe operators. It's a single file with no external dependencies — perfect for sharing via email or publishing.
Jupyter Interop
Convert between BioLang's .bln format and Jupyter's .ipynb
format for compatibility with the Jupyter ecosystem.
Import from Jupyter
# Convert .ipynb to .bln (prints to stdout)
bl notebook experiment.ipynb --from-ipynb > experiment.bln
Markdown cells become prose sections. Code cells are wrapped in fenced
```biolang blocks. Outputs are discarded (they'll be regenerated when
you run the notebook).
Export to Jupyter
# Convert .bln to .ipynb (prints to stdout)
bl notebook analysis.bln --to-ipynb > analysis.ipynb
Prose sections become Markdown cells. Code blocks become code cells with
"language": "biolang" metadata. The resulting notebook uses
nbformat v4 and can be opened in JupyterLab, VS Code, or any notebook viewer.
Terminal Rendering
When you run bl notebook file.bln in a terminal, prose sections are
rendered with ANSI styling:
- Headings — bold, underlined, with level indicators
- Inline code — cyan highlight
- Bold and italic — ANSI bold/italic
- Blockquotes — indented with
|prefix in dim text - Lists — bullet points with indentation
Code blocks are executed in order. Output is interleaved between prose sections, making it easy to follow an analysis step by step.
Example Notebook
Here's a complete .bln notebook demonstrating the key features:
# GC Content Analysis
This notebook analyzes GC content across a set of contigs
and identifies potential outliers.
## Setup
```biolang
# @hide
let min_gc = 0.3
let max_gc = 0.7
```
## Load Data
Read the FASTA file and compute per-sequence statistics.
```biolang
let seqs = read_fasta("contigs.fa")
println(f"Loaded {len(seqs)} sequences")
```
## Compute GC Content
```biolang
# @echo
let gc_values = seqs |> map(|s| gc_content(s.seq))
let mean_gc = mean(gc_values)
let std_gc = stdev(gc_values)
println(f"Mean GC: {mean_gc:.3f} +/- {std_gc:.4f}")
```
## Identify Outliers
Flag contigs with GC content more than 2 standard deviations
from the mean — these may indicate contamination or
horizontal gene transfer.
```biolang
let outliers = seqs
|> filter(|s| {
let gc = gc_content(s.seq)
abs(gc - mean_gc) > 2.0 * std_gc
})
println(f"Found {len(outliers)} outlier contigs")
outliers |> each(|s| println(f" {s.id}: GC={gc_content(s.seq):.3f}"))
```
## Summary
> The analysis identified potential contaminant contigs based
> on anomalous GC content. Review these sequences before
> downstream assembly or annotation.
Tips
- Use
# @hidefor configuration and imports to keep the narrative clean - Use
# @echofor key analysis steps so readers see both code and results - Use
# @skipto temporarily disable expensive computation during development - Use
# @hide-outputwhen you want to show the code but not its (verbose) output - State carries across cells — define variables once and reuse them throughout
- The HTML export is self-contained: share
report.htmldirectly - Use
--from-ipynbto migrate existing Jupyter notebooks to BioLang