# JBrowse web quick start

This guide sets up a self-hosted JBrowse web instance: you'll use the
`@jbrowse/cli` command-line tool to download JBrowse, add an assembly and
tracks, and serve the result as a folder of files on a web server.

Other ways to run JBrowse:

- [JBrowse desktop](https://jbrowse.org/jb2-staging/docs/quickstart_desktop) - open local files without a web
  server
- [](https://jbrowse.org/jb2-staging/docs/embedded_components) - embed a view in your own web app

The `config.json` directory you build in this guide opens directly in JBrowse
Desktop as well. See [](https://jbrowse.org/jb2-staging/docs/tutorials/cli_desktop).

## TLDR

- Install Node.js 18+, samtools, tabix
- `npm install -g @jbrowse/cli`
- `jbrowse create jbrowse2 && cd jbrowse2`
- `samtools faidx genome.fa && jbrowse add-assembly genome.fa --load copy`
- `samtools index file.bam && jbrowse add-track file.bam --load copy`
- `bgzip file.vcf && tabix file.vcf.gz && jbrowse add-track file.vcf.gz --load copy`
- `jbrowse text-index`
- `npx serve -S .`

## Reproduce it end to end

The TLDR above uses placeholder filenames (`genome.fa`, `file.bam`, `file.vcf`)
that you supply.
[`build_quickstart_web.sh`](https://github.com/GMOD/jbrowse-components/blob/main/scripts/build_quickstart_web.sh)
runs the same flow against the volvox sample data JBrowse ships:

```bash
curl -fO https://raw.githubusercontent.com/GMOD/jbrowse-components/main/scripts/build_quickstart_web.sh
bash build_quickstart_web.sh               # builds ./quickstart_web_build/jbrowse2
npx serve -S quickstart_web_build/jbrowse2 # then open the printed URL
```

It downloads a FASTA, a BAM, a BigWig, a VCF, and a GFF3, runs the same
`samtools faidx` / `samtools index` / `bgzip` + `tabix` indexing and
`add-assembly` / `add-track` / `text-index` commands, and writes a `config.json`
with an alignments track, a coverage track, a variant track, and a searchable
gene track. Every input is pinned, so re-running reproduces the same config. It
needs `samtools`, htslib's `bgzip` and `tabix`, `curl`, and node (for the
JBrowse CLI).

## Prerequisites

- Node.js 18+ - use [NodeSource](https://github.com/nodesource) or
  [NVM](https://github.com/nvm-sh/nvm), not `apt` (tends to install old
  versions)
- [samtools](http://www.htslib.org/): `sudo apt install samtools` or
  `brew install samtools`
- [tabix](http://www.htslib.org/doc/tabix.html): `sudo apt install tabix` or
  `brew install htslib`
- [bcftools](https://samtools.github.io/bcftools/) (optional, for VCF
  sorting/indexing): `sudo apt install bcftools` or `brew install bcftools`

## Installing the JBrowse CLI

```bash
npm install -g @jbrowse/cli
jbrowse --version
```

To avoid a global install, replace `jbrowse` with `npx @jbrowse/cli` in any
command below.

## Download JBrowse 2

```bash
jbrowse create jbrowse2
```

This downloads and unzips jbrowse-web into a folder named `jbrowse2`. Run
`cd jbrowse2` before any further commands. Alternatively, download the zip
manually from https://github.com/GMOD/jbrowse-components/releases.

## Running JBrowse 2

JBrowse 2 requires a web server. Opening `index.html` directly in your browser
won't work.

To verify locally:

```bash
cd jbrowse2/
npx serve -S .
```

The `-S` flag tells `serve` to resolve symlinks, relevant if you later add
tracks with `--load symlink`.

Navigate to `http://localhost:3000`. Click the sample config to confirm the
install works.

For production, place the folder in your web server's static directory (e.g.
`/var/www/html/jbrowse2/`) and visit `http://yourserver/jbrowse2`.

<Figure caption="The JBrowse 2 fresh-install screen, shown when no config.json is present yet. An 'It worked!' banner plus a list of sample configs and demo sessions to try." src="/img/config_not_found.png"/>

<Figure caption="JBrowse 2 screen with a sample configuration" src="/img/sample_config.png"/>

## Adding tracks

The examples below run from inside `jbrowse2/`, so they omit `--out` (which
defaults to the current directory). To write elsewhere, add
`--out /var/www/html/jbrowse2`, either a directory containing `config.json` or a
path to a specific config file. Run `jbrowse add-track --help` for all options.

For the full list of supported formats and the adapter each maps to, see
[](https://jbrowse.org/jb2-staging/docs/config_guides/file_types).

Every example below uses `--load copy`, which puts the data file next to
`config.json` so one server serves both. For data your lab already hosts
somewhere else, pass the URL in place of a path and the track records that URL;
see the [hosting section](#hosting-your-own-data) below.

```bash
jbrowse add-track https://data.myuniversity.edu/rnaseq/sample1.bam
```

### Genome assembly (FASTA)

```bash
samtools faidx genome.fa
jbrowse add-assembly genome.fa --load copy
```

This writes an assembly entry to `config.json` and copies `genome.fa` and
`genome.fa.fai` into the output directory. Use `--load symlink` to symlink
instead of copying.

Use `--name` (shorthand `-n`) to set a human-readable assembly name (defaults to
the filename).

JBrowse 2 also supports bgzip-compressed indexed FASTA and 2bit files.

<Figure caption="JBrowse 2 linear genome view setup with volvox in assembly dropdown" src="/img/lgv_assembly.png"/>

### BAM / CRAM

```bash
samtools index file.bam   # or file.cram
jbrowse add-track file.bam --load copy
```

See the [alignments track guide](https://jbrowse.org/jb2-staging/docs/user_guides/alignments_track).

<Figure caption="JBrowse 2 linear genome view with alignments track" src="/img/volvox_alignments.png"/>

### VCF

VCFs must be bgzip-compressed and tabix-indexed:

```bash
bgzip file.vcf
tabix file.vcf.gz
jbrowse add-track file.vcf.gz --load copy
```

If tabix reports the VCF is unsorted, sort it first:

```bash
bcftools sort file.vcf > file.sorted.vcf
bgzip file.sorted.vcf
tabix file.sorted.vcf.gz
```

See https://www.htslib.org/ for more on `bgzip`, `tabix`, and `bcftools`.

<Figure caption="JBrowse 2 linear genome view with variant track" src="/img/volvox_variants.png"/>

For multi-sample VCFs, see the
[multi-sample variant guide](https://jbrowse.org/jb2-staging/docs/user_guides/multivariant_track).

### BigWig / BigBed

No external index needed:

```bash
jbrowse add-track file.bw --load copy
```

See the [quantitative track guide](https://jbrowse.org/jb2-staging/docs/user_guides/quantitative_track).

### GFF3

```bash
jbrowse sort-gff yourfile.gff | bgzip > yourfile.sorted.gff.gz
tabix yourfile.sorted.gff.gz
jbrowse add-track yourfile.sorted.gff.gz --load copy
```

See the [gene track guide](https://jbrowse.org/jb2-staging/docs/user_guides/gene_track).

### GTF

GTF shares GFF3's refname and start columns, so `sort-gff` sorts it too:

```bash
jbrowse sort-gff yourfile.gtf | bgzip > yourfile.sorted.gtf.gz
tabix yourfile.sorted.gtf.gz
jbrowse add-track yourfile.sorted.gtf.gz --load copy
```

A plain `.gtf` loads without any of this, but the whole file is read at once, so
sort and index anything genome-scale.

GTF has no `Name` or `ID` attribute, so transcripts are grouped into a gene by
`gene_id`, and
[`aggregateField`](https://jbrowse.org/jb2-staging/docs/config/gtftabixadapter/#slot-aggregatefield) names the
attribute that labels the gene. `jbrowse text-index` matches the GTF spellings —
`gene_name`, `transcript_name`, `gene_id`, `transcript_id` — alongside its GFF3
defaults, so searching by gene name works on a GTF track without passing
`--attributes`.

See the [gene track guide](https://jbrowse.org/jb2-staging/docs/user_guides/gene_track).

### Synteny (PAF)

Use [minimap2](https://github.com/lh3/minimap2) to align two assemblies and load
the result as a synteny track:

```bash
minimap2 -cx asm20 grape.fa peach.fa > peach_vs_grape.paf

jbrowse add-assembly grape.fa --load copy -n grape
jbrowse add-assembly peach.fa --load copy -n peach
```

Note: `--assemblyNames` takes `query,target`, the **reverse** of minimap2's
`target query` order. Above, `minimap2 grape.fa peach.fa` makes peach the query,
so load with `--assemblyNames peach,grape`:

```bash
jbrowse add-track peach_vs_grape.paf --assemblyNames peach,grape --load copy
```

Setting the named `queryAssembly` and `targetAssembly` fields on the adapter in
`config.json` avoids the ordering question (see the
[synteny track config guide](https://jbrowse.org/jb2-staging/docs/config_guides/synteny_track)).

Pick the `-cx` preset by how far apart the two assemblies are:

- `asm5` - closely related assemblies, up to ~5% divergence
- `asm10` - moderately diverged assemblies
- `asm20` - divergent / cross-species comparisons, up to ~20% divergence, used
  above

See the [minimap2 docs](https://github.com/lh3/minimap2) for details.

Other supported synteny formats:

- `.delta` (MUMmer/NUCmer)
- `.chain` (UCSC)
- `.anchors` and `.anchors.simple` (MCScan)
- `.out` (MashMap)

Add them the same way:
`jbrowse add-track alignment.delta --assemblyNames query,target ...`. For large
alignments, convert to indexed PIF first with `jbrowse make-pif`.

See also the [linear synteny view](https://jbrowse.org/jb2-staging/docs/user_guides/linear_synteny_view),
[dotplot view](https://jbrowse.org/jb2-staging/docs/user_guides/dotplot_view),
[synteny visualization tutorial](https://jbrowse.org/jb2-staging/docs/tutorials/synteny_visualization),
[all-vs-all synteny](https://jbrowse.org/jb2-staging/docs/tutorials/allvsall_synteny), and
[multi-way synteny](https://jbrowse.org/jb2-staging/docs/tutorials/multiway_synteny_grape_peach_cacao).

## Hosting your own data

The folder you just built is a **static site**: plain files that a web server
hands out unchanged, with no server-side program or database. All the work
happens in the visitor's browser, which fetches the pieces of your data files it
needs.

Any web server, S3 or GCS bucket, or institutional file host can serve it. See
[](https://jbrowse.org/jb2-staging/docs/config_guides/deploying) for the full picture, including generating
`config.json` from a samplesheet.

Two properties decide whether a host works, and both fail quietly:

- **Byte-range requests.** JBrowse reads slices of a BAM, CRAM, BigWig, or tabix
  file rather than downloading it, so the host has to answer a `Range` header
  with `206 Partial Content`. A host that returns the whole file with `200`
  instead is the usual reason a track that works locally shows nothing in
  production. See
  [](https://jbrowse.org/jb2-staging/docs/config_guides/serving_data#indexed-binary-files-do-not-work-on-my-server).
- **No re-compression of compressed files.** Serving a `.bam` or `.bgz` through
  gzip corrupts the byte offsets the index depends on. See
  [](https://jbrowse.org/jb2-staging/docs/config_guides/serving_data#configure-gzip-for-text-never-for-bgzf).

Object storage satisfies both out of the box, which is why S3 and GCS are common
homes for the data even when the app itself is served elsewhere. Data on a
different domain than the app needs a
[CORS policy](https://jbrowse.org/jb2-staging/docs/config_guides/serving_data#cors-errors-on-remote-files) as
well.

For data that cannot be public, JBrowse authenticates per file host. See
[](https://jbrowse.org/jb2-staging/docs/config_guides/authentication).

## Indexing feature names for searching

Optionally, build a text index so users can search by gene name or feature ID:

```bash
jbrowse text-index
```

This indexes the GFF3, GTF and VCF tracks in your config, tabix-indexed or
plain. Every other track is skipped, and a bare `text-index` run skips silently
— name a track with `--tracks` and it says why that one was left out. Once
complete, names can be typed directly into the location search box. See
[](https://jbrowse.org/jb2-staging/docs/config_guides/text_searching) for which attributes are indexed and how
to narrow the set, the [text-index docs](https://jbrowse.org/jb2-staging/docs/cli#jbrowse-text-index) for the
flags, and
[the trix index format](https://jbrowse.org/jb2-staging/docs/config_guides/text_searching#the-trix-index-format)
for how the index files work.

## Tutorials

- [](https://jbrowse.org/jb2-staging/docs/tutorials/cli_desktop)
- [Synteny visualization](https://jbrowse.org/jb2-staging/docs/tutorials/synteny_visualization)
- [Cancer structural variants](https://jbrowse.org/jb2-staging/docs/tutorials/sv_visualization_cgiab)
- [](https://jbrowse.org/jb2-staging/docs/tutorials/population_genomics)
- [Long-read methylation](https://jbrowse.org/jb2-staging/docs/tutorials/methylation)
- [RNA-seq](https://jbrowse.org/jb2-staging/docs/tutorials/rnaseq)
- [All tutorials](https://jbrowse.org/jb2-staging/docs/tutorials)

## See also

- [](https://jbrowse.org/jb2-staging/docs/user_guide)
- [](https://jbrowse.org/jb2-staging/docs/config_guides/file_types)
- [](https://jbrowse.org/jb2-staging/docs/config_guide)
- [CLI reference](https://jbrowse.org/jb2-staging/docs/cli)
- [](https://jbrowse.org/jb2-staging/docs/faq)
- [CORS errors](https://jbrowse.org/jb2-staging/docs/config_guides/serving_data#cors-errors-on-remote-files)

## Tips

**Organize data into subdirectories:**

```bash
jbrowse add-track myfile.bam --subDir my_bams --load copy --out /var/www/html/jbrowse2
```

**Upgrade JBrowse to the latest release:**

```bash
jbrowse upgrade /var/www/html/jbrowse2
```

**Upgrade the CLI:**

```bash
npm install -g @jbrowse/cli
```

**Use a custom config filename:**

```bash
jbrowse add-assembly mygenome.fa --out /path/to/jbrowse2/alt_config.json --load copy
# Access at: http://localhost/jbrowse2/?config=alt_config.json
```

