JBrowse 2 combined guide
This document is a collection of all our documentation. It includes our quick start guide, user guide, configuration guide, CLI guide, developer guide, and FAQ. You can browse the other documents individually, but this page is to help simple ctrl+f searching and easy browsing. You can also download a pdf version of these same docs located at https://jbrowse.org/jb2/jbrowse2.pdf
Super-quick start guide for JBrowse web
This is a quick overview to get started running JBrowse 2 from scratch using the command line. It is helpful if you have some familiarity with the command line, and with some bioinformatics tools like samtools in general. This guide also assumes you have:
- a web server that reads files from /var/www/html/ e.g. Apache or nginx (not strictly necessary for jbrowse to run, see footnote)
- node 12+ installed
- genometools installed e.g.
sudo apt install genometools
orbrew install brewsci/bio/genometools
, used for sorting GFF3 for creating tabix GFF - samtools installed e.g.
sudo apt install samtools
orbrew install samtools
, used for creating FASTA index and BAM/CRAM processing - tabix installed e.g.
sudo apt install tabix
orbrew install htslib
, used for created tabix indexes for BED/VCF/GFF files
Super-quick overview for CLI
Initial setup
### Install JBrowse 2 CLI tools, note: if you want to use the jbrowse command
### under the sudo user, change this to `sudo npm install -g @jbrowse/cli`, but
### sometimes it is better to work under the principle of least priviledge and
### operate under a normal user so this guide does not use this
npm install -g @jbrowse/cli
### Use the `jbrowse create` command to download the latest release, and put it
### in a web server directory
jbrowse create /var/www/html/jbrowse2
### Alternatively, you may download to a directory, and then move it to the web
### directory
jbrowse create ~/mylocaljbrowse
mv ~/mylocaljbrowse /var/www/html/jbrowse2
Loading a FASTA file
### Create indexed FASTA file and load it using the add-assembly command
### Add your genome assembly to the config at /var/www/html/jbrowse2/config.json
### Also copies the files to this directory
samtools faidx genome.fa
jbrowse add-assembly genome.fa --out /var/www/html/jbrowse2 --load copy
Loading a BAM file
### Copies file.bam and file.bam.bai to /var/www/html/jbrowse2 and adds track to
### the config at /var/www/html/jbrowse2/config.json. Assumes that file.bam and
### file.bam.bai exist
samtools index file.bam
jbrowse add-track file.bam --out /var/www/html/jbrowse2/ --load copy
### Adds a url entry for a bam file to the config.json, the URL is stored in the
### config instead of downloading files, so no --load flag is needed
jbrowse add-track http://website.com/myfile.bam --out /var/www/html/jbrowse2
### If your BAM index (bai) is not filename+'.bai' then you can manually specify
### the --index flag. The --index flag also works with loading tabix tracks too
jbrowse add-track myfile.bam --index myfile.bai --out /var/www/html/jbrowse2 --load copy
Loading GFF3
### load gene annotations from a GFF, using "GenomeTools" (gt) to sort the gff
### and tabix to index the GFF3
gt gff3 -sortlines -tidy -retainids myfile.gff > myfile.sorted.gff
bgzip myfile.sorted.gff
tabix myfile.sorted.gff.gz
jbrowse add-track myfile.sorted.gff.gz --out /var/www/html/jbrowse2 --load copy
Note: as an alternative to gt gff3 -sortlines is awk+GNU sort
awk '$1 ~ /^#/ {print $0;next} {print $0 | "sort -t\"\t\" -k1,1 -k4,4n"}' file.gff > file.sorted.gff
bgzip file.sorted.gff
tabix file.sorted.gff.gz
The awk command is inspired by the method in the tabix documentation http://www.htslib.org/doc/tabix.html but avoids subshells and properly sets the tab delimiter for GNU sort in case there are spaces in the GFF
Miscellaneous tips
### Example of using --subDir to organize your data directory:
### copies myfile.bam and myfile.bam.bai to /var/www/html/jbrowse2/my_bams
### folder, which helps organize your data folder
jbrowse add-track myfile.bam --subDir my_bams --out /var/www/html/jbrowse2 --load copy
### Example without using the --out parameter:
### If you are in a directory with a config.json file, you can omit the --out parameter
cd /var/www/html/jbrowse2
jbrowse add-track /path/to/my/file.bam --load copy
### After you've had jbrowse for a while, you can upgrade to our latest release
jbrowse upgrade /var/www/html/jbrowse2
### Outputting to a specific config file instead of a config directory
### Alternative loading syntax where I specify a config file, and then this can
### be loaded via http://localhost/jbrowse2/?config=alt_config.json
jbrowse add-assembly mygenome.fa --out /var/www/html/jbrowse2/alt_config.json --load copy
Load a synteny track
### Demo for loading synteny data, both assemblies are outputted to a single
### config.json in /var/www/html/jbrowse2/config.json
minimap2 grape.fa peach.fa > peach_vs_grape.paf
jbrowse add-assembly grape.fa --load copy --out /var/www/html/jbrowse2/ -n grape
jbrowse add-assembly peach.fa --load copy --out /var/www/html/jbrowse2/ -n peach
### Use gt gff3 to make sorted tabixed gffs for each assembly, and then load to
### their respective ## assembly
jbrowse add-track grape.sorted.gff.gz -a grape --load copy --out /var/www/html/jbrowse2
jbrowse add-track peach.sorted.gff.gz -a peach --load copy --out /var/www/html/jbrowse2
### Load the synteny "track" from a PAF file. Note the order matters here for
### the --assemblyNames parameter. If minimap2 is run like `minimap2 grape.fa
### peach.fa` then you load --assemblyNames peach,grape. the order is reversed
### because the syntax is minimap2 ref.fa query.fa on the CLI and query (left side
### of PAF) and target (right hand side) in PAF output file
jbrowse add-track peach_vs_grape.paf --assemblyNames peach,grape --out /var/www/html/jbrowse2/ --load copy
Create a text index to let users search for gene names
### Finally create a text-index for your genes. By default it will index all
### tracks with Gff3TabixAdapter and VcfTabixAdapter. A progress bar will show
### indexing progress
jbrowse text-index --out /var/www/html/jbrowse2
### Index only a specific assembly
jbrowse text-index --out /var/www/html/jbrowse2 -a hg19
#### Index only some specific trackIds
jbrowse text-index --out /var/www/html/jbrowse2 --tracks=mygenes1,mygenes2
#### Index each track individually
jbrowse text-index --out /var/www/html/jbrowse2 --tracks=mygenes1,mygenes2 --perTrack
### If you already have a text-index, you have to use --force to overwrite the old one
jbrowse text-index --out /var/www/html/jbrowse2 --force
Conclusion
You can now visit http://localhost/jbrowse2 and your genome should be ready!
This guide is meant to be a super-quick conceptual overview for getting JBrowse 2 set up, but if you are new to the command line or to jbrowse in general, you might want to start with the slightly longer quick-start guide here.
Footnote
JBrowse doesn't strictly need Apache or nginx, it is "static site compatible" meaning it uses no server code and can run on any static website hosting. For example, you can upload the jbrowse folder that we prepared here in /var/www/html/jbrowse2 to Amazon S3, and it will work there too. See the FAQ for what webserver do I need for more info.
JBrowse web quick start
In this guide, we'll get an instance of JBrowse running on your computer.
Pre-requisites
- Ability to run commands on the command line
- Node.js 12+
caution
If you are using apt
as your package manager, we recommend not using it to
install Node.js. Good alternatives include
NodeSource or
NVM.
Download
You can download JBrowse 2 by using the JBrowse CLI or by downloading and unpacking it manually. We recommend using the JBrowse CLI since it also includes utilities to help you configure JBrowse 2 once it is set up.
Downloading using the JBrowse CLI
The JBrowse CLI can help perform many tasks to help you manage JBrowse 2, such as:
- create a new instance of JBrowse 2 automatically
- update an existing instance of JBrowse 2 with the latest released version
- configure your JBrowse 2 instance
Installing the CLI tools
To install the JBrowse CLI, run
npm install -g @jbrowse/cli
After running this command you can then test the installation with
jbrowse --version
This will output the current version of the JBrowse CLI.
note
If you can't or don't want to globally install the JBrowse CLI, you can also use
the npx command, which
is included with Node.js, to run JBrowse CLI without installing it. Simply
replace jbrowse
with npx @jbrowse/cli
in any command, e.g.
npx @jbrowse/cli --version
Using jbrowse create
to download JBrowse 2
In the directory where you would like to download JBrowse 2, run this command
jbrowse create jbrowse2
Downloading manually
You can also download JBrowse 2 manually. Go to the
releases page of the
JBrowse 2 GitHub repository and find the latest release that is tagged
@jbrowse/web
. Download the ZIP file from that release. Make sure it is the ZIP
file that starts with jbrowse-web-
and not the "Source code" ZIP file. Once
you have downloaded the ZIP file, extract it to the location you would like to
have JBrowse 2.
Checking the download
Whether you used the JBrowse CLI or downloaded manually, the directory where you downloaded JBrowse should look something like this:
jbrowse2/
├── a586bb28a5bad4a3aba2.worker.js
├── a586bb28a5bad4a3aba2.worker.js.LICENSE.txt
├── a586bb28a5bad4a3aba2.worker.js.map
├── asset-manifest.json
├── favicon.ico
├── index.html
├── manifest.json
├── precache-manifest.52c8ba3337cf7ae812b37d874b2de030.js
├── robots.txt
├── service-worker.js
├── static/
└── test_data/
Running JBrowse 2
JBrowse 2 requires a web server to run. It won't work if you try to directly
open the index.html
in your web browser. We can use a simple server to check
that JBrowse 2 has been downloaded properly. Run
cd jbrowse2/
npx serve . # use npx serve -S . if you want to refer to symlinked data later on
This will start a web server in our JBrowse 2 directory. Navigate to the
location specified in the tool's output. It will look something like
http://localhost:5000
. Once at that page, you should see a page that says that
the configuration is not found. That is expected, since we haven't configured
JBrowse 2 yet. It will look something like this:

Go ahead an click on the sample config to see a JBrowse 2 running with a demo configuration. It should look like this:

Congratulations! You're running JBrowse 2.
Next steps
Now that JBrowse 2 is set up, you can configure it with your own genomes and tracks. There are two ways you can configure JBrowse 2: with the JBrowse CLI (guide here) or with JBrowse 2's built-in graphical configuration editing (guide here).
Config editing quick start — command-line interface
In order to display your data, JBrowse 2 needs to know about the reference genome for your organism of interest and needs to have tracks created that reference your data sources. This guide will show you how to set those up using the JBrowse CLI.
note
You can also do this configuration with graphical configuration editing interface built into JBrowse 2. See that guide here.
Pre-requisites
Adding a genome assembly
info
For this step we configure JBrowse to use files being hosted at a URL. For an example of how to use files located on your computer, see the adding a track step.
First we will configure an assembly, or reference genome, for for JBrowse 2. This usually means providing a file that describes the reference sequence for the organism, such as a FASTA or 2BIT file.
You will want to use your own data for your organism, but for this example we provide a small example reference sequence for a simulated organism, volvox mythicus, that you can use.
## Make sure you are in the directory where you have downloaded JBrowse 2
jbrowse add-assembly http://jbrowse.org.s3.amazonaws.com/genomes/volvox/volvox.fa
caution
A FASTA must have an index to work in JBrowse 2. This command assumes that the
index file is the same as the FASTA but with .fai
appended to the file name.
This command will generate a config file if one does not exist yet and add an
assembly called "volvox" to the config file with the URLs of the FASTA and FASTA
index files. The name of the assembly was guessed from the file name, but you
can customize that and many other things with various flags passed to the
command. You can run jbrowse add-assembly --help
to get a list of all the
options.
JBrowse 2 also supports other assembly file formats, such as bgzip-compressed
indexed FASTA (e.g. .fa.gz
, .fa.gz.fai
, and .fa.gz.gzi
files) and 2BIT
files. See configuring assemblies for more info
on formats supported for the sequence file.
note
If your FASTA is not indexed, you can use the samtools
tool to index it.
samtools faidx volvox.fa
## generates volvox.fa.fai
Or if you want to compress your FASTA, you can use bgzip
as well.
bgzip volvox.fa
samtools faidx volvox.fa.gz
## compresses volvox.fa to volvox.fa.gz and generates volvox.fa.gz.fai and volvox.fa.gz.gzi
For more info about bgzip
and samtools
, see https://www.htslib.org/.
If you have your JBrowse 2 running as described in the JBrowse web quickstart, you can refresh the page and an add a linear genome view. You will now see your config in the Assembly dropdown.

Adding a track
Now we will show you how to add an alignments track and a variant track to JBrowse 2.
info
For this step we configure JBrowse to use files located on your computer. For an example of how to use files hosted at a URL, see the adding a genome assembly step.
Adding an alignments track
For this example we will use a BAM file to add an alignments track. Again, for this example we provide a small example BAM, but for your data you will replace the file name with the names of your data files.
For this track we will assume the data is on your computer at the locations
/data/volvox.bam
and /data/volvox.bam.bai
. You can download these file here
if you want to run this example:
BAM and
BAM index.
To add the track, run
## Replace with the location of your BAM file
jbrowse add-track /data/volvox.bam --load copy
This will copy the BAM and BAM index into the JBrowse 2 directory and add a
track pointing at those files to the config file. To see more options adding the
track, such as specifying a name, run jbrowse add-track --help
.
If you don't want to copy your BAM file, you can use --move
to move the file
into the JBrowse 2 directory or --symlink
to add a symlink to the file to the
JBrowse 2 directory. If you want more control over the location, you can use
inPlace
to point the track at the file where it is, but be careful with this
option because on a traditional server you will need to ensure that the file is
in a place where the web server is serving it.
note
If your BAM is not indexed, you can use the samtools
tool to index it.
samtools index volvox.bam
## generates volvox.bam.bai
For more info about samtools
, see https://www.htslib.org/.
If you have your JBrowse 2 running as described in the JBrowse web quickstart, you can refresh the page and an add a linear genome view of the volvox assembly. Then open track selector, and you will see the alignments track.

Adding a variant track
Adding a variant track is similar to adding an alignments track. For this
example, we will use a VCF file for the track. JBrowse 2 expects VCFs to be
compressed with bgzip
and indexed. Similar to the above example, we will
assume the files are at /data/volvox.vcf.gz
and /data/volvox.vcf.gz.tbi
. You
can download these file here:
VCF and
VCF index.
To add the track, run
jbrowse add-track /data/volvox.vcf.gz --load copy
note
If your VCF is not indexed, you can use the bgzip
and tabix
tools to
compress index it.
bgzip yourfile.vcf
tabix yourfile.vcf.gz
Alternatively, you can do the same thing with the bcftools
tool.
bcftools view volvox.vcf --output-type z > volvox.vcf.gz
rm volvox.vcf
bcftools index --tbi volvox.vcf.gz
Note if you get errors about your VCF file not being sorted when using tabix, you can use bcftools to sort your VCF.
bcftools sort file.vcf > file.sorted.vcf
bgzip file.sorted.vcf
tabix file.sorted.vcf.gz
For more info about bgzip
, tabix
, and bcftools
, see
https://www.htslib.org/.
If you have your JBrowse 2 running as described in the JBrowse web quickstart, you can refresh the page and an add a linear genome view of the volvox assembly. Then open track selector, and you will see the variant track.

Adding a BigWig/BigBed track
Probably one of the most simple track types to load is a BigWig/BigBed file since it does not have any external index file, it is just a single file
An example file is here https://jbrowse.org.s3.amazonaws.com/genomes/volvox/volvox-sorted.bam.coverage.bw
### Download bigwig or bigbed file
jbrowse add-track volvox-sorted.bam.coverage.bw --load copy
Adding a GFF3 file with GFF3Tabix
To load a GFF3 file, we can sort and index it with tabix
Sorting a GFF3 can be done with GenomeTools (to
install can use sudo apt install genometools
)
gt gff3 -sortlines -tidy -retainids yourfile.gff > yourfile.sorted.gff
bgzip yourfile.sorted.gff
tabix yourfile.sorted.gff.gz
jbrowse add-track yourfile.sorted.gff.gz --load copy
Note: as an alternative to gt gff3 -sortlines is awk+GNU sort
awk '$1 ~ /^#/ {print $0;next} {print $0 | "sort -t\"\t\" -k1,1 -k4,4n"}' file.gff > file.sorted.gff
bgzip file.sorted.gff
tabix file.sorted.gff.gz
The awk command is inspired by the method in the tabix documentation http://www.htslib.org/doc/tabix.html but avoids subshells and properly sets the tab delimiter for GNU sort in case there are spaces in the GFF
Indexing feature names for searching
The final step of loading you jbrowse instance may include adding a "search index" so that you can search by genes or other features by their name or ID
To do this we can use the jbrowse text-index
command
jbrowse text-index
This will index relevant track types e.g. any track with Gff3TabixAdapter (gene names and IDs) or VcfTabixAdapter (e.g. variant IDs). The command will print out a progress bar for each track that it is indexing.
This will also update your config.json so after it completes, you can type a gene name into the "search box" in the linear genome view or other views and quickly navigate to genes by gene name.
See the text-index command docs for more info. Also see the FAQ entries for text searching
Conclusion
Now that you have JBrowse configured with an assembly and a couple of tracks, you can start customizing it further. Check out the rest of the docs for more information, especially the JBrowse CLI docs for more details on some of the steps shown here.
Config editing quick start — graphical interface
In order to display your data, JBrowse 2 needs to know about the reference genome for your organism of interest and needs to have tracks created that reference your data sources. This guide will show you how to set those up using the JBrowse 2's graphical configuration editing.
note
You can also do this configuration with JBrowse CLI. See that guide here.
Pre-requisites
This tutorial requires having the following software installed
Starting JBrowse 2 admin server
The JBrowse CLI contains a tool called admin-server
. This will act as a web
server for JBrowse 2 and will write any changes made in JBrowse 2 to a config
file. The admin-server
is meant to be run only temporarily to help you set up
your config, it is not used for serving your jbrowse instance in production.
The admin-server
launches an instance of JBrowse 2 in "admin mode", which then
lets you
- Add and edit assemblies with the "Assembly manager"
- Add tracks and edit tracks
- Add and edit connections
All of these changes will be written by the server to the JBrowse config file
(usually config.json
) located in the JBrowse instance. This is something that
can only be done while the admin-server
is running, which again, is only meant
to be temporary!
To start the admin-server
, navigate into your JBrowse 2 directory and run
### Start the admin-server
jbrowse admin-server
This will then generate a link that you can visit in your web browser

warning
Note: the admin-server is meant to be used temporarily for configuration, not in production
Adding a genome assembly
A key first step in configuring a genome browser is adding an assembly to view.
In order to do this, use the navigation bar to open up the Assembly Manager
(Admin > Open Assembly Manager
).
This opens up a table which can be used to create, edit, and delete assemblies in your application

Let's add the hg38 human reference genome to our JBrowse 2 application.
Press the "Add New Assembly" button, and enter the necessary information in the form:
- name:
hg38
- type:
BgzipFastaAdapter
- fasta:
https://jbrowse.org/genomes/GRCh38/fasta/hg38.prefix.fa.gz
- fasta index:
https://jbrowse.org/genomes/GRCh38/fasta/hg38.prefix.fa.gz.fai
- gzi:
https://jbrowse.org/genomes/GRCh38/fasta/hg38.prefix.fa.gz.gzi

Click on "Create New Assembly". Great, we've added an assembly! We can see that we have successfully added the hg38 assembly.

The assembly can be edited or deleted, but for now we will return to the application.
Editing a genome assembly
After you've added a genome assembly, you can use the pencil icon button in the Assembly manager to edit that assembly. You can also delete assemblies from the assembly manager.
Adding a track
To add a new track or connection, you can use the menu bar in the app to open
the form for adding a track File > Open Track
:

Alternatively, you can use the action button (circular "+") inside the track selector to access the "Add track" form.

In the "Add track" form, you can provide a URL to a file to load. Opening files from your local machine is not supported currently in the JBrowse 2 web app (JBrowse desktop does allow this, though, and this functionality may be added in some form in the future)
Paste a URL to a file and optionally provide an index file URL too. The following file formats are supported
tabix
-indexed VCFtabix
-indexed BEDtabix
-indexed GFF- indexed BAM
- indexed CRAM
- BigWig
- BigBed
- Hi-C (Juicebox)
For tabix files, TBI or CSI indexes are allowed. CSI or BAI is allowed for BAM. Only CRAI is allowed for CRAM. The index will be inferred for BAI or TBI files as e.g. filename+'.bai'. If it is different from this, make sure to specify the index file explicitly.
Editing a track
First we will open a Linear Genome View using the navigation bar
(File > Add > Linear Genome View
), and click on the "Select Tracks" button.
The configuration settings are accessible by clicking on the ellipses by each track.

Open the configuration editor for the track by clicking on the "Settings" button shown above. You can use the configuration editor to live-edit any configurable value for a given track.
Setting a default session
It is also possible to use the graphical admin server to set the default session
of your JBrowse 2 instance. This is the session that will appear when JBrowse 2
is first visited. To do so, open the form to set the default session
(Admin > Set default session
):

You can use the form to clear your default session, select the currently open session, or any of your previously saved sessions.
Additional resources
There are a number of additional features for configuring JBrowse 2. Make sure to refer to the config guide for topics such as adding tracks or adding an assembly with the CLI
Conclusion
This quickstart showed how to launch the admin-server
in the JBrowse CLI to
perform graphical configuration of your application. Specifically, we looked at
how to access and use the assembly manager, as well as how to access the
configuration editor for tracks. Importantly, all tracks have different
configuration options available in the configuration editor.
Make sure to take a look at any tracks you add to JBrowse 2 that you might want to further configure!
Quick start for JBrowse desktop
Installing JBrowse desktop
This guide will walk you through installing jbrowse 2 on the desktop
JBrowse 2 desktop does not require any pre-requisites for your installation, so we can jump right in
Installing on Linux
Visit http://github.com/gmod/jbrowse-components/releases/latest and find the latest Linux AppImage release. Download that file to wherever you would like to keep it and then start it in one of two ways:
In the terminal
Using the AppImage file on linux, all that is needed is to make the file executable which you can do in a terminal
## Make the AppImage file executable, only need to do this once
chmod a+x jbrowse-desktop-*-linux.AppImage
## Run!
./jbrowse-desktop-*-linux.AppImage
In your file explorer
This may vary slightly depending on your distribution but should basically follow these steps:
- Right-click on the AppImage file and select "Properties"
- Go to the "Permissions" tab
- Check "Allow executing file as program" and close
You can now double-click the AppImage file to launch JBrowse.
Installing on MacOS
Visit http://github.com/gmod/jbrowse-components/releases/latest and find the latest MacOS release artifact in our latest builds.
Download the .dmg file for MacOS, double click, and drag JBrowse 2 into 'applications'.
You can now open JBrowse 2 like any other application on your Mac.
Installing on Windows
Visit http://github.com/gmod/jbrowse-components/releases/latest and download the
latest Windows installer executable (will end with win.exe
).
Double-click the downloaded installer and it will install and open JBrowse. You can now open JBrowse like any other program.
JBrowse Desktop start screen
After you have installed and started JBrowse Desktop you will see a start screen like this

The left hand panel, with "Launch new session" can quickly launch a new session using either your own custom genome (which you can load using an indexed FASTA or a twobit file). Also on the left hand panel is the "Quickstart list". Users can click the checkbox next to e.g. hg38 and hit Go.
On the right hand panel is the "Recently opened sessions". This includes sessions that you have specifically saved, and sessions that were autosaved (e.g. ones that you didn't explicitly use "Save as" on). You can re-open your sessions by clicking on the link.
Special features on the start screen
Converting a saved session into a quickstart entry
If you study a rare species, you might find it useful to customize your quickstart panel. We allow you to convert a session in the "Recently opened sessions" into an entry that appears in the quickstart list.
To do so: Click a checkbox next to a session in the "Recently opened sessions" table, and then hit the
icon next to the trash can icon. This is helpful if e.g. you want to make your own custom organism a template for quickstarts in the future.Selecting multiple entries from the quickstart panel
Users can also hit the checkbox for multiple species in the quickstart list, and then the sessions are combined which is helpful if e.g. you are doing comparative genomics of hg19 and mm10.
Next steps
Check out the user guide for more info on how to use JBrowse Desktop. This covers all the features that are available with screenshots and instructions.
User guide
Navigating the UI
Linear genome view usage
To start a linear genome view, use the menu bar
File->Add->Linear genome view
Using the location search box
- Use the search box in the LGV
- Enter syntax chr1:1-100 or chr1:1..100
- You can also specify an assembly name with the locstring {hg19}chr1:1-100
You can also use the search box to search by gene name (if it is configured)

In order to enable name searching, you or the admin on the instance will need to create a "text index". See the quickstart guide for more info.
Scrolling
Mouse wheel can scroll side to side, as well as click and drag. The pan buttons also exist in the header of the linear genome view
Zooming
The zoom buttons exist in the header of the linear genome view, and there is also a slider bar to zoom in and out.
Note: You can also hold the "Ctrl" key and use your mousewheel or trackpad to scroll and this will zoom in and out
Re-ordering tracks
There is a drag handle on the track labels indicating by the six dots, clicking and dragging on this part of the track label can reorder tracks
Adding tracks
To add a new track or connection, you can use the menu bar in the app to open the form for adding a track:
File->Open Track

Note: There is also a circular "+" button inside the track selector menu that can also be used to access the "Add track" form.

In the "Add track" form, you can provide a URL to a file to load, or you can also open files from your local machine. In some cases, you need to provide an index (bigwig files for example have no index, but BAM/CRAM or tabix filetypes like VCF/GFF/BED tabix do). In some cases we can automatically infer the index e.g. if you provide a URL for a BAM and the index filename is bamfilename +'.bai' but you may need to manually supply it in some cases (index inference can't be done with files from your local machine)
The following file formats are supported
- Tabixed VCF
- Tabixed BED
- Tabixed GFF
- BAM
- CRAM
- BigWig
- BigBed
- .hic file (Juicebox)
- PAF
For tabix files, TBI or CSI indexes are allowed. CSI or BAI is allowed for BAM. Only CRAI is allowed for CRAM. The index will be inferred for BAI or TBI files as filename+'.bai' for example, but if it is different than this, make sure to specify the index file explicitly.
Note: If you are an administrator, you can add tracks with the command line or with the admin server add-track or admin-server guide
Sharing sessions
On JBrowse Web, the main menu bar has a "Share" button to enable users to share their sessions with other people. The share button generates a URL that can be sent to other users.
Note: Share sessions is not available on JBrowse Desktop.
Also note: you can't copy the literal URL in your address bar and send it to other users, you must use the "Share" button to do that, but you can copy and paste the URL in your URL bar between different tabs in your local browser though

The session URL will contain
- what views are on the screen, and settings for the views (e.g. track labels overlapping or offset)
- what tracks are in the view
- extra tracks that you added with the "Add track workflow"
- for the alignments track, the show soft clipping and sort settings on the pileup
- etc
All this stuff gets included in the session
This means you can share links with your custom tracks with other users, without being a JBrowse admin!
Track menu
Users can access track-specific functions by using the track menu, which is accessible from the track selecter itself ("..." icon) or on the track label (vertical "..."). Some functions are only available when the track is open e.g. from the track label, but more basic options like "About track" are available from the track menu on the track selector.

About track dialog
Using the track menu as described above, you can access the "About track" dialog

Editing track configs
As a non-admin user, in order to edit a track config, you have to make a copy of the track. This will copy it to your "session tracks", which you can edit freely

Rubberband selection
The scale bars accept a click-and-drag action to select a region. Rubberband selection can be performed on both the main (lower) and overview (upper) scale bars.

Track label positioning
Track labels can be positioned on their own row or overlapping the data to save vertical screen space. They can also be hidden. This is done by clicking on the hamburger menu for a specific view.

Horizontally flip
The view can be horizontally flipped, or reverse complemented, to make the coordinates go from right to left instead of left to right
We use triangles pointing in the direction of the orientation in the overview bar to help indicate whether the app is horizontally flipped or not
Here is an example of before and after horizontally flipping the view

Sequence track
The sequence track shows the reference sequence and a three-frame translation. If the view is horizontally flipped, the sequence is "reverse complemented" so the bottom three translation frames go to the top, and the top frames go to the bottom.

Alignments tracks
Visualizing alignments is an important aspect of genome browsers. This guide will go over the main features of the "Alignments track"
The alignments track is a combination of a pileup and a coverage visualization
Pileup visualization
The pileup is the lower part of the alignments track and shows each of the reads as boxes positioned on the genome.
By default the reads are colored red if they aligned to the forward strand of the reference genome, or blue if they aligned to the reverse strand.
Coverage visualization
The coverage visualization shows the depth-of-coverage of the reads at each position on the genome, and also draws using colored boxes any occurrence of mismatches between the read and the reference genome, so if 50% of the reads had a T instead of the reference A, half the height of the coverage histogram would contain a 'red' box

Show soft clipping
If a read contains bases that do not map the the genome properly, they can either be removed from the alignment (hard clipping) or can be included, and not shown by default (soft clipping)
JBrowse 2 also contains an option to "show the soft clipping" that has occurred. This can be valuable to show the signal around a region that contains structural variation or difficult mappability

Sort by options
The alignments tracks can also be configured to "sort by" a specific attribute for reads that span the center line.
By default the center line is not shown, but by showing it (Go to the view's hamburger menu->Select "Show center line") then you will obtain a better idea of what the "sort by" option is doing
Showing the center line
Here is how to turn on the center line
- Open the hamburger menu in the top left of the linear genome view
- Select "Show center line"

Sorting by base
Sorting by base will re-arrange the pileup so that the reads that have a specific base-pair mutation at the position crossing the center line (which is 1bp wide) will be arranged in a sorted manner. To enable Sort by base
- Open the track menu for the specific track using the vertical '...' in the track label
- Select 'Sort by'->'Base pair'

Sort, color and filter by tag
We can now also do things like
- Sort by tag
- Filter by tag
- Color by tag
With these features, we can create very expressive views of alignments tracks. For example, in the below step-by-step guide, it shows how to color and sort the reads by the HP tag.

Color by modifications/methylation
If you have data that marks DNA/RNA modifications using the MM tag in BAM/CRAM format, then the alignments track can use these to color these. It uses two modes
- Modifications mode - draws the modifications as they are
- Methylation mode - draws both unmodified and modifified CpGs (unmodified positions are not indicated by the MM tag and this mode considers the sequence context)



Color by orientation
JBrowse uses the same color scheme as IGV for coloring by pair orientation. These pair orientations can be used to reveal complex patterns of structural variation
See https://software.broadinstitute.org/software/igv/interpreting_pair_orientations for a good guide on interpreting these pair orientations

Sashimi-style arcs
The alignments track will draw sashimi-track style arcs across spliced alignments (indicated by N in the CIGAR string). If the reads additionally are tagged with XS tags, it will try to draw the arcs using the strand indicated by the alignment

Note that you can disable these by clicking on the track menu (vertical ... next to track label, then hovering over SNPCoverage options, and unchecking "Draw arcs")
Insertion and clipping indicators
The alignments track will also draw a upside-down histogram of insertion and soft/hard clipped read counts at all positions, and mark significant positions (covering 30% of the reads) with a colored triangle.

Also, insertions that are larger than 10bp are marked with a special larger purple rectangle, seen in the below screenshot. Generally, long reads span larger insertions better, so this feature is more prominant with large reads.

Note that you can disable these by clicking on the track menu (vertical ... next to track label, then hovering over SNPCoverage options, and unchecking "Draw insertion/clipping indicators" and "Draw insertion/clipping counts")
Quantitative tracks
Visualizing genome signals, whether it is read depth-of-coverage or other signal, can often be done by using BigWig or other quantitative feature files

Example use case: viewing whole-genome coverage for profiling CNV
The latest JBrowse also allows refining the resolution of BigWig tracks, and viewing whole genome coverage. This allows us to get detailed global views of CNV for example from whole-genome coverage profiling.
Here is a short picture guide to setup a whole-genome view of a BigWig for CNV coverage visualization:
- Open your BigWig track
- Go to the view menu and select "Show all assembly regions"
- Adjust the "Autoscale type" to your liking, the new options for "Local +/- 3sd" allows the autoscaling to avoid outliers
- Go to the track menu and select "Turn off histogram fill", which then shows only a dot for each point on the graph
- Go to the track menu and select "Resolution->Finer resolution" a couple times until resolution looks nice
Also note: all tracks have a drag handle on the bottom of it which you can drag down to make the track taller.

Variant tracks
Visualizing variant tracks from the VCF format alongside the original alignment evidence track is a common workflow for validating your results. In JBrowse 2 we can open a variant track and an alignments track as shown below

Variant widget
The variant features have a specialized widget that contains a table indicating all the calls that were made in a multi-sample VCF. Some VCF files, like the 1000 genomes VCF, can contain thousands of samples in a single file. This table can display the details

Comparative views
The dotplot view is a 2D comparative view that can display alignments between different genome assemblies, or even compare a long-read or NGS short-read against the genome.
Opening a dotplot view
Currently the workflow for launching a dotplot is done by navigating in the header bar to the File->Add->Dotplot view
This will let you select the genome assemblies of interest
Then you can also provide a synteny file in the form of PAF via the Add track workflow
Then currently you must configuration edit the PAFAdapter to indicate the two assemblies in the PAFAdapter



See the dotplot configuration for more detailed descriptions
Opening a linear synteny view
Use the main menu bar to select
File->Add->Linear synteny view


See the linear synteny configuration for more details on manually configuring the synteny view
Opening a synteny view from a dotplot view
We have designed JBrowse 2 to be able to open up a synteny view from a dotplot view. This is enabled by "display modes" so that the same track can be displayed in different contexts.
Here is a short demo that shows opening a synteny view from a dotplot view selection

Long read vs reference plots
One can also launch a dotplot view that compares a long read to the reference genome by
- Right clicking an alignment
- Select "Dotplot read vs ref" or "Linear read vs ref" in the context menu


Hi-C tracks
Visualizing Hi-C data can be performed with .hic files which are generated by the Juicebox software suite. It uses the hic-straw module developed by the juicebox/igv.js team to visualize it in jbrowse.
Currently configuration options are basic for Hi-C tracks, see configuration for info about configuring Hi-C tracks

SV inspector
The SV inspector is a "workflow" that is designed to help users inspect structural variant calls
Opening the SV inspector
We can start the SV inspector by launching it from the App level menu bar

This will bring up an "import form" that asks you for your SV evidence. This can be provided opening a file locally or using a URL for files in the following formats:
- VCF or VCF.gz (plain text VCF, or (b)gzipped VCF)
- BEDPE
- STAR-fusion result file

Example SV inspector workflow
We can start the SV inspector workflow by opening up this file containing translocation events called from a breast cancer cell line SKBR3, based on these published data http://schatz-lab.org/publications/SKBR3/
## Example VCF for use in the SV inspector
https://jbrowse.org/genomes/hg19/skbr3/reads_lr_skbr3.fa_ngmlr-0.2.3_mapped.bam.sniffles1kb_auto_l8_s5_noalt.new.vcf
Copy this URL and paste it into the import form and select hg19

SV inspector results
After loading the user's requested file, you will have a tabular view with each row representing a row of the file you opened, along with a whole-genome overview of the SVs on the right

Now here is where things can become interesting
We can search and filter the table, with filtering and searching being reflected in the circular view as well.

Launching breakpoint split view
By clicking on the features in the circular view, or clicking on the triangle drop-down on the leftmost column of the table, we can dynamically launch a new view of the data that is called the "split view" or the "breakpoint split view"
This allows us to inspect the breakpoints of the structural variant, and compare each side to the alignments.

Getting the protein sequence for features
If you have a track with gene or transcript level features, then the feature detail sidebar will automatically stitch together the sequence for that feature. The options include:
- CDS - the coding sequences, spliced together
- Protein - performs protein translation on the CDS, currently assuming the default codon translation table
- cDNA - the CDS plus UTR, or just all exons if a non-coding gene
- Gene w/ introns - the entire gene region sequence with the introns included
- Gene w/ 10bp of introns - the spliced gene sequence with 10bp around the splice sites shown
- Gene w/ 500 up+down stream - the entire gene region with 500bp upstream and downstream (shown in light red)
- Gene w/ 500 up+down stream + 10bp of introns - the spliced gene sequence with 10bp around the splice sites shown and the up/down stream shown
Some of the params such as 500bp and 10bp are arbitrarily chosen, if you are interested in adjusting these parameters let us know

Using the plugin store
Users can add plugins to their session using the in-app plugin store. The plugin will be added to your "session" which can be shared with the share button (or if you are an admin running the admin-server, then it will be added to the config file).
This can add extra functions or tracks or many other interesting features. For example, if you add the CIVIC plugin, it will automatically add a track that contains the CIVIC cancer gene annotations to hg19.
Note that not all plugins are directly useful from being added (sometimes it needs extra work on the part of the plugin developer to make them useful in the GUI, some plugins require hand editing of configuration files).

Using the bookmark widget
JBrowse Web and JBrowse Desktop come with a "bookmark widget" that you can use to store lists of interesting regions that would would like to easily revisit.

The bookmark stores a list of single regions (chromosome, start, and end coordinate), and clicking on the regions in the bookmark widget will launch a linear genome view at that region.
You can also import a list of regions from a BED file

Note also that you can add "notes" for your list of regions, allowing a simple way to "annotate" your datasets

Finally, you can export your list of regions to a BED file or TSV
Config guide
Intro to the config.json
A JBrowse 2 configuration file, a config.json, is structured as follows
{
"configuration": {
/* global configs here */
},
"assemblies": [
/* list of assembly configurations, e.g. the genomes being viewed */
],
"tracks": [
/* array of tracks being loaded, contain reference to which assembl(y/ies)
they belong to */
],
"aggregateTextSearchAdapters": [
/* optional array of text search adapters */
],
"defaultSession": {
/* optional default session */
}
}
The most important thing to configure are your assemblies and your tracks
Configuring assemblies
An assembly configuration includes the "name" of your assembly, any "aliases" that might be associated with that assembly e.g. GRCh37 is sometimes seen as an alias for hg19, and then a "sequence" configuration containing a reference sequence track config. This is provides a special "track" that is outside the normal track config
Here is a complete config.json file containing only a hg19
{
"assemblies": [
{
"name": "hg19",
"aliases": ["GRCh37"],
"sequence": {
"type": "ReferenceSequenceTrack",
"trackId": "hg19_config",
"adapter": {
"type": "BgzipFastaAdapter",
"fastaLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz",
"locationType": "UriLocation"
},
"faiLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.fai",
"locationType": "UriLocation"
},
"gziLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.gzi",
"locationType": "UriLocation"
}
},
"rendering": {
"type": "DivSequenceRenderer"
}
},
"refNameAliases": {
"adapter": {
"type": "RefNameAliasAdapter",
"location": {
"uri": "https://s3.amazonaws.com/jbrowse.org/genomes/hg19/hg19_aliases.txt",
"locationType": "UriLocation"
}
}
}
}
]
}
Configuring reference name aliasing
Reference name aliasing is a process to make chromosomes that are named slightly differently but which refer to the same thing render properly
The refNameAliases in the above config provides this functionality
"refNameAliases": {
"adapter": {
"type": "RefNameAliasAdapter",
"location": {
"uri": "https://s3.amazonaws.com/jbrowse.org/genomes/hg19/hg19_aliases.txt",
"locationType": "UriLocation"
}
}
}
The hg19_aliases then is a tab delimited file that looks like this
The first column should be the names that are in your FASTA sequence, and the rest of the columns are aliases
1 chr1
2 chr2
3 chr3
4 chr4
5 chr5
6 chr6
7 chr7
8 chr8
9 chr9
10 chr10
11 chr11
12 chr12
13 chr13
14 chr14
15 chr15
16 chr16
17 chr17
18 chr18
19 chr19
20 chr20
21 chr21
22 chr22
X chrX
Y chrY
M chrM MT
Note that "chromAliases" files from UCSC match this format
https://hgdownload.soe.ucsc.edu/goldenPath/canFam6/bigZips/canFam6.chromAlias.txt
Adding an assembly with the CLI
Generally we add a new assembly with the CLI using something like
## use samtools to make a fasta index for your reference genome
samtools faidx myfile.fa
## install the jbrowse CLI
npm install -g @jbrowse/cli
## add the assembly using the jbrowse CLI, this will automatically copy the
myfile.fa and myfile.fa.fai to your data folder at /var/www/html/jbrowse2
jbrowse add-assembly myfile.fa --load copy --out /var/www/html/jbrowse2
See our CLI docs for the add-assembly for more details here -- add-assembly
Note: assemblies can also be added graphically using the assembly manager when you are using the admin-server. See the quickstart guide for more details.
Assembly config
Because JBrowse 2 can potentially have multiple assemblies loaded at once, it needs to make sure each track is associated with an assembly.
To do this, we make assemblies a special part of the config, and make sure each track refers to which genome assembly it uses
Example config with hg19 genome assembly loaded
Here is a complete config.json that has the hg19 genome loaded
{
"assemblies": [
{
"name": "hg19",
"aliases": ["GRCh37"],
"sequence": {
"type": "ReferenceSequenceTrack",
"trackId": "refseq_track",
"adapter": {
"type": "BgzipFastaAdapter",
"fastaLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz",
"locationType": "UriLocation"
},
"faiLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.fai",
"locationType": "UriLocation"
},
"gziLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.gzi",
"locationType": "UriLocation"
}
},
"rendering": {
"type": "DivSequenceRenderer"
}
},
"refNameAliases": {
"adapter": {
"type": "RefNameAliasAdapter",
"location": {
"uri": "https://s3.amazonaws.com/jbrowse.org/genomes/hg19/hg19_aliases.txt",
"locationType": "UriLocation"
}
}
}
}
]
}
The top level config is an array of assemblies
Each assembly contains
name
- a name to refer to the assembly by. each track that is related to this assembly references this namealiases
- sometimes genome assemblies have aliases like hg19, GRCh37, b37p5, etc. while there may be small differences between these different sequences, they often largely have the same coordinates, so you might want to be able to associate tracks from these different assemblies together. The assembly aliases are most helpful when loading from a UCSC trackHub which specifies the genome assembly names it uses, so you can connect to a UCSC trackHub if your assembly name or aliases match.sequence
- this is a complete "track" definition for your genome assembly. we specify that it is a track of type ReferenceSequenceTrack, give it a trackId, and an adapter configuration. an adapter configuration can specify IndexedFastaAdapter (fasta.fa and fasta.fai), BgzipFastaAdapter (fasta.fa.gz, fasta.fa.gz.fai, fasta.gz.gzi), ChromSizesAdapter (which fetches no sequences, just chromosome names)
ReferenceSequenceTrack
Example ReferenceSequenceTrack config, which as above, is specified as the child of the assembly section of the config
{
"type": "ReferenceSequenceTrack",
"trackId": "refseq_track",
"adapter": {
"type": "BgzipFastaAdapter",
"fastaLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz",
"locationType": "UriLocation"
},
"faiLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.fai",
"locationType": "UriLocation"
},
"gziLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.gzi",
"locationType": "UriLocation"
}
},
"rendering": {
"type": "DivSequenceRenderer"
}
}
BgzipFastaAdapter
A bgzip FASTA format file is generated by
bgzip -i sequence.fa
samtools faidx sequence.fa.gz
### above commands generates the following three files
sequence.fa.gz
sequence.fa.gz.gzi
sequence.fa.gz.fai
These are loaded into a BgzipFastaAdapter as follows
{
"type": "BgzipFastaAdapter",
"fastaLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz",
"locationType": "UriLocation"
},
"faiLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.fai",
"locationType": "UriLocation"
},
"gziLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.gzi",
"locationType": "UriLocation"
}
}
IndexedFastaAdapter
An indexed FASTA file is similar to the above, but the sequence is not compressed
samtools faidx sequence.fa
### above commands generate the .fa and .fai files
sequence.fa
sequence.fa.fai
These are loaded into a IndexedFastaAdapter as follows
{
"type": "IndexedFastaAdapter",
"fastaLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa",
"locationType": "UriLocation"
},
"faiLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.fai",
"locationType": "UriLocation"
}
}
FASTA Header Location
Meta-information on the assembly can be specified by adding the following section to either the IndexedFastaAdapter or BgzipFastaAdapter configuration. One option for the contents of this metadata is the FFRGS (Fair Formatted Reference Genome Standard) header specification for FASTA files can be found here, however, just the raw plaintext is displayed for this file so the format is not strict.
"metadataLocation": {
"uri": "https://raw.githubusercontent.com/FFRGS/FFRGS-Specification/main/examples/example.yaml",
"locationType": "UriLocation"
}
TwoBitAdapter
The UCSC twoBit adapter is also supported. Note however that the 2bit format has a longer startup time than other adapters because there is a larger upfront parsing time.
{
"type": "TwoBitAdapter",
"twoBitLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.2bit",
"locationType": "UriLocation"
}
}
Optionally you can specify a .chrom.sizes file which will speed up loading the 2bit especially if it has many chromosomes in it
{
"type": "TwoBitAdapter",
"twoBitLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.2bit",
"locationType": "UriLocation"
},
"chromSizesLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.chrom.sizes",
"locationType": "UriLocation"
}
}
Track configurations
All tracks can contain
- trackId - internal track ID, must be unique
- name - displayed track name
- assemblyNames - an array of assembly names a track is associated with, often just a single assemblyName
- category - (optional) array of categories to display in a hierarchical track selector
Example config.json containing a track config
{
"assemblies": [
{
"name": "hg19",
"aliases": ["GRCh37"],
"sequence": {
"type": "ReferenceSequenceTrack",
"trackId": "Pd8Wh30ei9R",
"adapter": {
"type": "BgzipFastaAdapter",
"fastaLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz",
"locationType": "UriLocation"
},
"faiLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.fai",
"locationType": "UriLocation"
},
"gziLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.gzi",
"locationType": "UriLocation"
}
}
}
}
],
"tracks": [
{
"type": "FeatureTrack",
"trackId": "repeats_hg19",
"name": "Repeats",
"assemblyNames": ["hg19"],
"category": ["Annotation"],
"adapter": {
"type": "BigBedAdapter",
"bigBedLocation": {
"uri": "https://jbrowse.org/genomes/hg19/repeats.bb",
"locationType": "UriLocation"
}
}
}
]
}
AlignmentsTrack config
Example AlignmentsTrack config
{
"trackId": "my_alignments_track",
"name": "My Alignments",
"assemblyNames": ["hg19"],
"type": "AlignmentsTrack",
"adapter": {
"type": "BamAdapter",
"bamLocation": {
"uri": "http://yourhost/file.bam",
"locationType": "UriLocation"
},
"index": {
"location": {
"uri": "http://yourhost/file.bam.bai",
"locationType": "UriLocation"
}
}
}
}
BamAdapter configuration options
- bamLocation - a 'file location' for the BAM
- index: a subconfiguration schema containing
- indexType: options BAI or CSI. default: BAI
- location: a 'file location' of the index
Example BamAdapter config
{
"type": "BamAdapter",
"bamLocation": {
"uri": "http://yourhost/file.bam",
"locationType": "UriLocation"
},
"index": {
"location": {
"uri": "http://yourhost/file.bam.bai",
"locationType": "UriLocation"
}
}
}
CramAdapter configuration options
- cramLocation - a 'file location' for the CRAM
- craiLocation - a 'file location' for the CRAI
Example CramAdapter config
{
"type": "CramAdapter",
"cramLocation": {
"uri": "http://yourhost/file.cram",
"locationType": "UriLocation"
},
"craiLocation": {
"uri": "http://yourhost/file.cram.crai",
"locationType": "UriLocation"
}
}
HicTrack config
Example Hi-C track config
{
"type": "HicTrack",
"trackId": "hic",
"name": "Hic Track",
"assemblyNames": ["hg19"],
"adapter": {
"type": "HicAdapter",
"hicLocation": {
"uri": "https://s3.amazonaws.com/igv.broadinstitute.org/data/hic/intra_nofrag_30.hic",
"locationType": "UriLocation"
}
}
}
HicAdapter config
We just simply supply a hicLocation currently for the HicAdapter
{
"type": "HicAdapter",
"hicLocation": {
"uri": "https://s3.amazonaws.com/igv.broadinstitute.org/data/hic/intra_nofrag_30.hic",
"locationType": "UriLocation"
}
}
HicRenderer config
baseColor
- the default baseColor of the Hi-C plot is red #f00, you can change it to blue so then the shading will be done in blue with #00fcolor
- this is a color callback that adapts the current Hi-C contact feature with the baseColor to generate a shaded block. The default color callback function isjexl:baseColor.alpha(Math.min(1,count/(maxScore/20))).hsl().string()
where it receives the count for a particular block, the maxScore over the region, and the baseColor from the baseColor config
VariantTrack config
- defaultRendering - options: 'pileup' or 'svg'. default 'svg'
- adapter - a variant type adapter config e.g. a VcfTabixAdapter
Example config
{
"type": "VariantTrack",
"trackId": "my track",
"name": "My Variants",
"assemblyNames": ["hg19"],
"adapter": {
"type": "VcfTabixAdapter",
"vcfGzLocation": {
"uri": "http://yourhost/file.vcf.gz",
"locationType": "UriLocation"
},
"index": {
"location": {
"uri": "http://yourhost/file.vcf.gz.tbi",
"locationType": "UriLocation"
}
}
}
}
VcfTabixAdapter configuration options
- vcfGzLocation - a 'file location' for the BigWig
- index: a subconfiguration schema containing
- indexType: options TBI or CSI. default TBI
- location: the location of the index
Example VcfTabixAdapter adapter config
{
"type": "VcfTabixAdapter",
"vcfGzLocation": {
"uri": "http://yourhost/file.vcf.gz",
"locationType": "UriLocation"
},
"index": {
"location": {
"uri": "http://yourhost/file.vcf.gz.tbi",
"locationType": "UriLocation"
}
}
}
QuantitativeTrack config
Example QuantitativeTrack config
{
"trackId": "my_wiggle_track",
"name": "My Wiggle Track",
"assemblyNames": ["hg19"],
"type": "QuantitativeTrack",
"adapter": {
"type": "BigWig",
"bigWigLocation": {
"uri": "http://yourhost/file.bw",
"locationType": "UriLocation"
}
}
}
General QuantitativeTrack options
- scaleType - options: linear, log, to display the coverage data. default: linear
- adapter - an adapter that returns numeric signal data, e.g. feature.get('score')
Autoscale options for QuantitativeTrack
Options for autoscale
- local - min/max values of what is visible on the screen
- global - min/max values in the entire dataset
- localsd - mean value +- N stddevs of what is visible on screen
- globalsd - mean value +/- N stddevs of everything in the dataset
Score min/max for QuantitativeTrack
These options overrides the autoscale options and provides a minimum or maximum value for the autoscale bar
- minScore
- maxScore
QuantitativeTrack drawing options
- inverted - draws upside down
- defaultRendering - can be density, xyplot, or line
- summaryScoreMode - options: min, max, whiskers
QuantitativeTrack renderer options
- filled - fills in the XYPlot histogram
- bicolorPivot - options: numeric, mean, none. default: numeric
- bicolorPivotValue - number at which the color switches from posColor to negColor. default: 0
- color - color or color callback for drawing the values. overrides posColor/negColor. default: none
- posColor - color to draw "positive" values. default: red
- negColor - color to draw "negative" values. default: blue
- clipColor - color to draw "clip" indicator. default: red
BigWigAdapter options
- bigWigLocation - a 'file location' for the bigwig
Example BigWig adapter config
{
"type": "BigWig",
"bigWigLocation": {
"uri": "http://yourhost/file.bw",
"locationType": "UriLocation"
}
}
SyntenyTrack config
Example SyntenyTrack config
{
"type": "SyntenyTrack",
"trackId": "dotplot_track",
"assemblyNames": ["YJM1447", "R64"],
"name": "dotplot",
"adapter": {
"type": "PAFAdapter",
"pafLocation": {
"uri": "https://s3.amazonaws.com/jbrowse.org/genomes/yeast/YJM1447_vs_R64.paf"
},
"assemblyNames": ["YJM1447", "R64"]
}
}
We can load a SyntenyTrack from PAF with the CLI e.g. with
jbrowse add-track myfile.paf --type SyntenyTrack --assemblyNames \
grape,peach --load copy --out /var/www/html/jbrowse2
The first assembly is the "target" and the second assembly is the "query"
See the super quickstart guide for more recipes on loading synteny tracks with the CLI.
PAFAdapter config
The PAF adapter reflects a pairwise alignment, and is outputted by tools like minimap2. It can be used for SyntenyTracks
{
"type": "PAFAdapter",
"pafLocation": {
"uri": "https://s3.amazonaws.com/jbrowse.org/genomes/yeast/YJM1447_vs_R64.paf"
},
"assemblyNames": ["YJM1447", "R64"]
}
Slots
- pafLocation - the location of the PAF file. The pafLocation can refer to a gzipped or unzipped delta file. It will be read into memory entirely as it is not an indexed file format.
- assemblyNames - list of assembly names, typically two (first in list is target, second is query)
- queryAssembly - alternative to assemblyNames: just the assemblyName of the query
- targetAssembly - alternative to assemblyNames: just the assemblyName of the query
DeltaAdapter config
The DeltaAdapter is used to load .delta files from MUMmer/nucmer. It can be used for SyntenyTracks
{
"type": "DeltaAdapter",
"deltaLocation": {
"uri": "https://s3.amazonaws.com/jbrowse.org/genomes/yeast/YJM1447_vs_R64.paf"
},
"assemblyNames": ["YJM1447", "R64"]
}
Slots
- deltaLocation - the location of the delta file. The deltaLocation can refer to a gzipped or unzipped delta file. It will be read into memory entirely as it is not an indexed file format.
- assemblyNames - list of assembly names, typically two (first in list is target, second is query)
- queryAssembly - alternative to assemblyNames: just the assemblyName of the query
- targetAssembly - alternative to assemblyNames: just the assemblyName of the query
ChainAdapter config
The ChainAdapter is used to load .chain files from MUMmer/nucmer. It can be used for SyntenyTracks
{
"type": "DeltaAdapter",
"deltaLocation": {
"uri": "https://s3.amazonaws.com/jbrowse.org/genomes/yeast/YJM1447_vs_R64.paf"
},
"assemblyNames": ["YJM1447", "R64"]
}
Slots
- chainLocation - the location of the UCSC chain file. The chainLocation can refer to a gzipped or unzipped delta file. It will be read into memory entirely as it is not an indexed file format.
- assemblyNames - list of assembly names, typically two (first in list is target, second is query)
- queryAssembly - alternative to assemblyNames: just the assemblyName of the query
- targetAssembly - alternative to assemblyNames: just the assemblyName of the query
MCScanAnchorsAdapter
The .anchors file from MCScan refers to pairs of homologous genes and can be loaded into synteny tracks in jbrowse 2
{
"type": "MCScanAnchorsAdapter",
"mcscanAnchorsLocation": {
"uri": "https://s3.amazonaws.com/jbrowse.org/genomes/synteny/grape.peach.anchors.gz"
},
"bed1Location": {
"uri": "https://s3.amazonaws.com/jbrowse.org/genomes/synteny/grape_vs_peach/grape.bed.gz"
},
"bed2Location": {
"uri": "https://s3.amazonaws.com/jbrowse.org/genomes/synteny/grape_vs_peach/peach.bed.gz"
},
"assemblyNames": ["grape", "peach"]
}
The guide at https://github.com/tanghaibao/jcvi/wiki/MCscan-(Python-version) shows a demonstration of how to create the anchors and bed files (the .bed files are intermediate steps in creating the anchors files and are required by the MCScanAnchorsAdapter)
Slots
- mcscanAnchorsLocation - the location of the .anchors file from the MCScan workflow. The .anchors file has three columns. It can be gzipped or ungzipped, and is read into memory whole
- bed1Location - the location of the first assemblies .bed file from the MCScan workflow. It can be gzipped or ungzipped, and is read into memory whole. This would refer to the gene names on the "left" side of the .anchors file.
- bed2Location - the location of the second assemblies .bed file from the MCScan workflow. It can be gzipped or ungzipped, and is read into memory whole. This would refer to the gene names on the "right" side of the .anchors file.
MCScanSimpleAnchorsAdapter
The "simple" .anchors.simple file from MCScan refers to pairs of homologous genes and can be loaded into synteny tracks in jbrowse 2
{
"type": "MCScanSimpleAnchorsAdapter",
"mcscanSimpleAnchorsLocation": {
"uri": "https://s3.amazonaws.com/jbrowse.org/genomes/synteny/grape.peach.anchors.simple.gz"
},
"bed1Location": {
"uri": "https://s3.amazonaws.com/jbrowse.org/genomes/synteny/grape_vs_peach/grape.bed.gz"
},
"bed2Location": {
"uri": "https://s3.amazonaws.com/jbrowse.org/genomes/synteny/grape_vs_peach/peach.bed.gz"
},
"assemblyNames": ["grape", "peach"]
}
The guide at https://github.com/tanghaibao/jcvi/wiki/MCscan-(Python-version) shows a demonstration of how to create the anchors and bed files (the .bed files are intermediate steps in creating the anchors.simple files and are required by the MCScanSimpleAnchorsAdapter)
Slots
mcscanSimpleAnchorsLocation
- the location of the .anchors.simple file from the MCScan workflow (this file has 5 columns, start and end gene from bed1, start and end genes from bed2, and score). It can be gzipped or ungzipped, and is read into memory wholebed1Location
- the location of the first assemblies .bed file from the MCScan workflow. It can be gzipped or ungzipped, and is read into memory whole. This would refer to the gene names on the "left" side of the .anchors file.bed2Location
- the location of the second assemblies .bed file from the MCScan workflow. It can be gzipped or ungzipped, and is read into memory whole. This would refer to the gene names on the "right" side of the .anchors file.
Advanced adapters
There are two useful adapter types that can be used for more advanced use
cases, such as generating configuration for data returned by an API. These are
the FromConfigAdapter
and FromConfigSequenceAdapter
. They can be used as the
adapter
value for any track type.
FromConfigAdapter
This adapter can be used to generate features directly from values stored in the configuration.
Example FromConfigAdapter
{
"type": "FromConfigAdapter",
"features": [
{
"refName": "ctgA",
"uniqueId": "alias1",
"aliases": ["A", "contigA"]
},
{
"refName": "ctgB",
"uniqueId": "alias2",
"aliases": ["B", "contigB"]
}
]
}
FromConfigSequenceAdapter
Similar behavior to FromConfigAdapter
, with a specific emphasis on performance
when the features are sequences.
Example FromConfigSequenceAdapter
{
"type": "FromConfigSequenceAdapter",
"features": [
{
"refName": "SEQUENCE_1",
"uniqueId": "firstId",
"start": 0,
"end": 33,
"seq": "CCAAGATCTAAGATGTCAACACCTATCTGCTCA"
},
{
"refName": "SEQUENCE_2",
"uniqueId": "secondId",
"start": 0,
"end": 44,
"seq": "CCGAACCACAGGCCTATGTTACCATTGGAAAGCTCACCTTCCCG"
}
]
}
Text searching
Text searching is now available on JBrowse 2.
Text searching appears in two forms: per-track indexes and aggregate indexes which search across multiple tracks
Aggregate indexes may look like this
{
"aggregateTextSearchAdapters": [
{
"type": "TrixTextSearchAdapter",
"textSearchAdapterId": "hg19-index",
"ixFilePath": {
"uri": "https://jbrowse.org/genomes/hg19/trix/hg19.ix",
"locationType": "UriLocation"
},
"ixxFilePath": {
"uri": "https://jbrowse.org/genomes/hg19/trix/hg19.ixx",
"locationType": "UriLocation"
},
"metaFilePath": {
"uri": "https://jbrowse.org/genomes/hg19/trix/meta.json",
"locationType": "UriLocation"
},
"assemblyNames": ["hg19"]
}
}
An example per-track config may look like this
{
"trackId":"yourtrack",
"name":"Track name",
"adapter":{
"type": "Gff3TabixAdapter",
"gffGzLocation": { "uri":"yourfile.gff.gz",
"locationType": "UriLocation" }
"index":{ "location": { "uri":"yourfile.gff.gz.tbi",
"locationType": "UriLocation" } }
},
"textSearching": {
"textSearchAdapter": {
"type": "TrixTextSearchAdapter",
"textSearchAdapterId": "hg19-index",
"ixFilePath": {
"uri": "https://jbrowse.org/genomes/hg19/trix/hg19.ix",
"locationType": "UriLocation"
},
"ixxFilePath": {
"uri": "https://jbrowse.org/genomes/hg19/trix/hg19.ixx",
"locationType": "UriLocation"
},
"metaFilePath": {
"uri": "https://jbrowse.org/genomes/hg19/trix/meta.json",
"locationType": "UriLocation"
},
"assemblyNames": ["hg19"]
},
"indexingAttributes": ["Name","ID"],
"indexingFeatureTypesToExclude": ["CDS","exon"]
}
}
Information on generating trix indexes via the cli can be found here
TrixTextSearchAdapter config
The trix search index is the current file format for name searching
It is based on the UCSC trix file format described here https://genome.ucsc.edu/goldenPath/help/trix.html
To create trix indexes you can use our command line tools. More info found at our jbrowse text-index guide. This tool will automatically generate a config like this. The config slots are described below for details
{
"textSearchAdapter": {
"type": "TrixTextSearchAdapter",
"textSearchAdapterId": "gff3tabix_genes-index",
"ixFilePath": {
"uri": "trix/gff3tabix_genes.ix",
"locationType": "UriLocation"
},
"ixxFilePath": {
"uri": "trix/gff3tabix_genes.ixx",
"locationType": "UriLocation"
},
"metaFilePath": {
"uri": "trix/gff3tabix_genes_meta.json",
"locationType": "UriLocation"
}
}
}
- ixFilePath - the location of the trix ix file
- ixxFilePath - the location of the trix ixx file
- metaFilePath - the location of the metadata json file for the trix index
JBrowse1TextSearchAdapter config
This is more uncommon, but allows back compatibility with a jbrowse 1 names index created by generate-names.pl
{
"textSearchAdapter": {
"type": "JBrowse1TextSearchAdapter",
"textSearchAdapterId": "generate-names-index",
"namesIndexLocation": {
"uri": "/names",
"locationType": "UriLocation"
}
}
}
- namesIndexLocation - the location of the JBrowse1 names index data directory
DotplotView config
It is recommended to use the DotplotView's importform or a session spec to initialize a dotplot view.
LinearSyntenyView config
It is recommended to use the LinearSyntenyView's importform or a session spec to initialize a dotplot view.
Configuring the theme
Color
The color scheme as well as some sizing options can be configured via the theme. This is done via a top-level configuration in the config file. For example:
{
"configuration": {
"theme": {
"palette": {
"primary": {
"main": "#4400a6"
}
}
}
}
}
JBrowse uses 4 colors that can be changed. For example, this is the default theme:


The customized theme screenshot uses the below configuration
Color code | Color | |
---|---|---|
Primary | #311b92 | Deep purple |
Secondary | #0097a7 | Cyan |
Tertiary | #f57c00 | Orange |
Quaternary | #d50000 | Red |
{
"configuration": {
"theme" :{
"palette": {
"primary": {
"main": "#311b92"
},
"secondary": {
"main": "#0097a7"
},
"tertiary": {
"main": "#f57c00"
},
"quaternary": {
"main": "#d50000"
}
}
}
}
Logo
It is also possible to supply a custom logo to be displayed in the top right corner of the app instead of the JBrowse 2 logo. To do this, store a SVG file containing your logo on your server, and specify the path in your configuration:
{
"configuration": {
"logoPath": {
"uri": "path/to/my/custom-logo.svg"
}
}
}
The dimensions of the logo should be 150x48px
.
Sizing
You can also change some sizing options by specifying the "typography" (to change font size) and "spacing" (to change the amount of space between elements) options:
{
"theme": {
"typography": { "fontSize": 10 },
"spacing": 2
}
}
Advanced
JBrowse uses Material-UI for its theming. You can read more about Material-UI
themes here. Generally, most
options you could pass to Material-UI's
createMuiTheme
should work in the theme configuration.
Disabling analytics
This is done via adding a field in the global configuration in the config file. For example:
{
"configuration": {
"disableAnalytics": true
}
}
Configuration callbacks
We use Jexl (see https://github.com/TomFrost/Jexl) for defining configuration callbacks.
An example of a Jexl configuration callback might look like this
"color": "jexl:get(feature,'strand')==-1?'red':'blue'"
The notation get(feature,'strand') is the same as feature.get('strand') in javascript code.
We have a number of other functions such as
Feature operations - get
jexl:get(feature,'start') // start coordinate, 0-based half open
jexl:get(feature,'end') // end coordinate, 0-based half open
jexl:get(feature,'refName') // chromosome or reference sequence name
jexl:get(feature,'CIGAR') // BAM or CRAM feature CIGAR string
jexl:get(feature,'seq') // BAM or CRAM feature sequence
jexl:get(feature,'type') // feature type e.g. mRNA or gene
Feature operations - getTag
The getTag function smooths over slight differences in BAM and CRAM features to access their tags
jexl:getTag(feature, 'MD') // fetches MD string from BAM or CRAM feature
jexl:getTag(feature, 'HP') // fetches haplotype tag from BAM or CRAM feature
String functions
jexl:charAt('abc',2) // c
jexl:charCodeAt(' ',0) // 32
jexl:codePointAt(' ',0) // 32
jexl:startsWith('kittycat','kit') // true
jexl:endsWith('kittycat','cat') // true
jexl:padStart('cat', 8, 'kitty') // kittycat
jexl:padEnd('kitty', 8, 'cat') // kittycat
jexl:replace('kittycat','cat','') // kitty
jexl:replaceAll('kittycatcat','cat','') // kitty
jexl:slice('kittycat',5) // cat
jexl:substring('kittycat',0,5) // kitty
jexl:trim(' kitty ') // kitty, whitespace trimmed
jexl:trimStart(' kitty ') // kitty, starting whitespace trimmed
jexl:trimEnd(' kitty ') // kitty, ending whitespace trimmed
jexl:toUpperCase('kitty') // KITTY
jexl:toLowerCase('KITTY') // kitty
jexl:split('KITTY KITTY', ' ') // ['KITTY', 'KITTY']
Math functions
jexl:max(0,2)
jexl:min(0,2)
jexl:sqrt(4)
jexl:ceil(0.5)
jexl:floor(0.5)
jexl:round(0.5)
jexl:abs(-0.5)
jexl:log10(50000)
jexl:parseInt('2')
jexl:parseFloat('2.054')
Console logging
jexl:log(feature) // console.logs output and returns value
jexl:cast({'mRNA':'green','pseudogene':'purple'})[get(feature,'type')] // returns either green or purple depending on feature type
Binary operators
jexl:get(feature,'flags')&2 // bitwise and to check if BAM or CRAM feature flags has 2 set
Customizing feature details panels
Every track has a configuration called formatDetails
Here is an example track with a formatter
{
"type": "FeatureTrack",
"trackId": "genes",
"assemblyNames": ["hg19"],
"name": "Genes",
"formatDetails": {
"feature": "jexl:{name:'<a href=https://google.com/?q='+feature.name+'>'+feature.name+'</a>',newfield:'Custom contents here: '+feature.name,type:undefined }"
},
"adapter": {
"type": "Gff3TabixAdapter",
"gffGzLocation": {
"uri": "volvox.sort.gff3.gz"
},
"index": {
"location": {
"uri": "volvox.sort.gff3.gz.tbi"
}
}
}
}

This feature formatter changes the "name"
field in the feature detail panel
to have a link to a google search for that feature's name. This can be used to
link to gene pages for example as well.
In addition, this example also adds a custom field called "newfield"
and
removes e.g. "type"
from being displayed.
The schema for formatDetails
is
feature
- customizes the top-level featuresubfeatures
- customizes the subfeatures, recursively up todepth
depth
- depth to customize the subfeatures to, default 1
The general way this is done is by making a jexl callback either or both of
feature
and subfeatures
(if you want both feature and subfeatures, you can copy the same thing to both config slots).
The callback returns an object where the keys of the object are what you want to replace
In the example above we return an object with:
name
- customizes the name field with a link in the feature detailstype
- we make this undefined, which removes it from the feature detailsnewfield
- this generates a new field in the feature details
Making sophisticated customizations to feature detail panels
If your feature detail panel customization is complex, you can create a custom javascript function in a plugin that is registered with the jexl system e.g.
class MyPlugin {
install() {}
configure(pluginManager: PluginManager) {
pluginManager.jexl.addFunction('formatName', feature => {
return `<a href="${feature.name}">${feature.name}</a>`
})
}
}
Then you can use the custom jexl function in your config callbacks as follows:
{
"type": "FeatureTrack",
"trackId": "genes",
"assemblyNames": ["hg19"],
"name": "Genes",
"formatDetails": {
"feature": "jexl:{name:formatName(feature)}"
},
...
}
Developer guide
In this guide, will introduce the JBrowse 2 ecosystem from the developer's point of view. We'll examine the core concepts of how code is packaged and structured, and then go over how to create new plugins and pluggable elements.
Introduction and overview
Let's get a high-level view of the JBrowse 2 ecosystem.
Products and plugins
The JBrowse 2 ecosystem has two main type of top-level artifacts that are published on their own: products and plugins.

A "product" is an application of some kind that is published on its own (a web
app, an electron app, a CLI app, etc). jbrowse-web
, jbrowse-desktop
, and
jbrowse-cli
are products.
A "plugin" is a package of functionality that is designed to "plug in" to a product at runtime to add functionality. These can be written and published by anyone, not just the JBrowse core team. Not all of the products use plugins, but most of them do.
Also, most of the products are pretty standard in the way they are constructed. For example, jbrowse-web is a React web application that is made with Create React App (CRA), and jbrowse-cli is a command-line tool implemented with OCLIF.

Example plugins
You can follow this guide for developing plugins, but you might also want to refer to working versions of plugins on the web now
This repo contains a template for creating new plugins https://github.com/GMOD/jbrowse-plugin-template.
Here are some examples of working plugins.
- jbrowse-plugin-ucsc-api probably the simplest plugin example, it demonstrates accessing data from UCSC REST API
- jbrowse-plugin-gwas a custom plugin to display manhattan plot GWAS data
- jbrowse-plugin-biothings-api demonstrates accessing data from mygene.info, part of the "biothings API" family
- jbrowse-plugin-msaview - demonstrates creating a custom view type that doesn't use any conventional tracks
- jbrowse-plugin-gdc demonstrates accessing GDC cancer data GraphQL API, plus a custom drawer and track type for coloring variants by impact score
- jbrowse-plugin-systeminformation demonstrates using desktop specific functionality, accessing system node libraries. This desktop specific functionality should use the CJS bundle type (electron doesn't support ESM yet)
You can use these to see how plugins are generally structured, and can use the pluggable elements in them as templates for your own pluggable elements.
Now, let's explore what plugins can do and how they are structured.
What's in a plugin
A plugin is an independently distributed package of code that is designed to "plug in" to a JBrowse application.
It's implemented as a class that extends @jbrowse/core/Plugin
. It gets
instantiated by the application that it plugs into, and it has an install
method and a configure
method that the application calls. This class is
distributed as a webpack bundle that exports it to a namespace on the browser's
window
object specifically for JBrowse plugins1.
It's common for a plugin to use its configure
method to set up mobx
autoruns or reactions that react to
changes in the application's state to modify its behavior.
Plugins often also have their install
method add "pluggable elements" into
the host JBrowse application. This is how plugins can add new kinds of views,
tracks, renderers, and so forth.
Pluggable elements
Pluggable elements are pieces of functionality that plugins can add to JBrowse. Examples of pluggable types include:
- Adapter types
- Track types
- View types
- Display types
- Renderer types
- Widgets
- RPC calls
- Extension points
- Internet account types
- Connection types
- Text search adapter types
- Extension points
In additional to creating plugins that create new adapters, track types, etc. note that you can also wrap the behavior of another track so these elements are composable
For example we can have adapters that perform calculations on the results of another adapter, views that contains other subviews, and tracks that contain other tracks, leading to a lot of interesting behavior. Details and examples below
Adapters
Adapters basically are parsers for a given data format. We will review what adapters the alignments plugin has (to write your own adapter, see creating adapters)
Example adapters: the @jbrowse/plugin-alignments
plugin creates
multiple adapter types
BamAdapter
- This adapter uses the@gmod/bam
NPM module, and adapts it for use by the browser.CramAdapter
- This adapter uses the@gmod/cram
NPM module. Note that CramAdapter also takes a sequenceAdapter as a subadapter configuration, and uses getSubAdapter to instantiate itSNPCoverageAdapter
- this adapter takes aBamAdapter
orCramAdapter
as a subadapter, and calculates feature coverage from it
Track types
Track types are a high level type that controls how features are drawn. In most cases, a track combines a renderer and an adapter, and can do additional things like
- Control what widget pops up on feature click
- Add extra menu items to the track menu
- Create subtracks (See
AlignmentsTrack
) - Choose "static-blocks" rendering styles, which keeps contents stable while the user scrolls, or "dynamic-blocks" that update on each scroll
Example tracks: the @jbrowse/plugin-alignments
exports multiple track
types
SNPCoverageTrack
- this track type actually derives from the WiggleTrack typePileupTrack
- a track type that draws alignment pileup resultsAlignmentsTrack
- combinesSNPCoverageTrack
andPileupTrack
as "subtracks"
Displays
A display is a method for displaying a particular track in a particular view
For example, we have a notion of a synteny track type, and the synteny track type has two display models
DotplotDisplay
, which is used in the dotplot viewLinearSyntenyDisplay
, which is used in the linear synteny view
This enables a single track entry to be used in multiple view types e.g. if I
run jbrowse add-track myfile.paf
, this automatically creates a SyntenyTrack
entry in the tracklist, and when this track is opened in the dotplot view, the
DotplotDisplay
is used for rendering
Another example of a track type with multiple display types is VariantTrack
,
which has two display methods
LinearVariantDisplay
- used in linear genome viewChordVariantDisplay
- used in the circular view to draw breakends and structural variants
Renderers
Renderers are a new concept in JBrowse 2, and are related to the concept of server side rendering (SSR), but can be used not just on the server but also in contexts like the web worker (e.g. the webworker can draw the features to an OffscreenCanvas). For more info see creating renderers
Example renderers: the @jbrowse/plugin-alignments
exports several
renderer types
PileupRenderer
- a renderer type that renders Pileup type display of alignments fetched from theBamAdapter
/CramAdapter
SNPCoverageRenderer
- a renderer that draws the coverage. Note that this renderer derives from the wiggle renderer, but does the additional step of drawing the mismatches over the coverage track
Widgets
Widgets are custom info panels that can show up in side panels, modals, or other places in an app
Widgets can do multiple types of things including
- Configuration widget
- Feature detail widget
- Add track widget
- Add connection widget
- etc.
These widgets can be extended via plugins, so for example, the
@jbrowse/plugin-alignments
extends the BaseFeatureDetailWidget
to
have custom display of the alignments
AlignmentsFeatureDetailWidget
- this provides a custom widget for viewing the feature details of alignments features that customizes the basic feature detail widget
View types
Creating view types is one of the most powerful features of JBrowse 2, because it allows us to put entirely different visualizations in the same context as the standard linear-genome-view.
We have demonstrated a couple new view types in JBrowse 2 already including
LinearGenomeView
- the classic linear view of a genomeCircularView
- a Circos-like circular whole genome viewDotplotView
- a comparative 2-D genome viewSvInspectorView
- superview containingCircularView
andSpreadsheetView
subviews- And more!
We think the boundaries for this are just your imagination, and there can also be interplay between view types e.g. popup dotplot from a linear view, etc.
RPC methods
Plugins can register their own RPC methods, which can allow them to offload custom behaviors to a web-worker or server side process.
The wiggle plugin, for example, registers two custom RPC method types
WiggleGetGlobalStats
WiggleGetMultiRegionStats
These methods can run in the webworker when available
Extension points
Extension points are a pluggable element type which allows users to add a callback that is called at an appropriate time.
See example for adding context menu items for an example of using extension points
The basic API is that producers can say
const ret = pluginManager.evaluateExtensionPoint('ExtensionPointName', {
value: 1,
})
And consumers can say
pluginManager.addToExtensionPoint('ExtensionPointName', arg => {
return arg.value + 1
})
pluginManager.addToExtensionPoint('ExtensionPointName', arg => {
return arg.value + 1
})
In this case, arg that is passed in evaluateExtensionPoint calls all the callbacks that have been registered by addToExtensionPoint. If multiple extension points are registered, the return value of the first extension point is passed as the new argument to the second and so on (they are chained together)
So in the example above, ret would be {value:3}
after evaluating the
extension point
Common plugin use cases
Adding a top-level menu
These are the menus that appear in the top bar of JBrowse Web and JBrowse
Desktop. By default there are File
and Help
menus. You can add your own
menu, or you can add menu items or sub-menus to the existing menus and
sub-menus.

You add menus in the configure
method of your plugin. Not all JBrowse
products will have top-level menus, though. JBrowse Web and JBrowse Desktop
have them, but something like JBrowse Linear View (which is an just a single
view designed to be embedded in another page) does not. This means you need to
check whether or not menus are supported using isAbstractMenuManager
in the
configure
method. This way the rest of the plugin will still work if there is
not a menu. Here's an example that adds an "Open My View" item to the File -> Add
menu.
import Plugin from '@jbrowse/core/Plugin'
import { isAbstractMenuManager } from '@jbrowse/core/util'
import InfoIcon from '@material-ui/icons/Info'
class MyPlugin extends Plugin {
name = 'MyPlugin'
install(pluginManager) {
// install MyView here
}
configure(pluginManager) {
if (isAbstractMenuManager(pluginManager.rootModel)) {
pluginManager.rootModel.appendToSubMenu(['File', 'Add'], {
label: 'Open My View',
icon: InfoIcon,
onClick: session => {
session.addView('MyView', {})
},
})
}
}
}
This example uses rootModel.appendToSubMenu
. See top-level menu
API for more details on available functions.
Adding menu items to a custom track
If you create a custom track, you can populate the track menu items in it using
the trackMenuItems
property in the track model. For example:
types
.model({
// model
})
.views(self => ({
trackMenuItems() {
return [
{
label: 'Menu Item',
icon: AddIcon,
onClick: () => {},
},
]
},
}))
Note that it is also common to use this scenario, because the base display may implement track menu items so this is like getting the superclasses track menu items
types
.model({
// model
})
.views(self => {
const { trackMenuItems: superTrackMenuItems } = self
return {
get trackMenuItems() {
return [
...superTrackMenuItems(),
{
label: 'Menu Item',
icon: AddIcon,
onClick: () => {},
},
]
},
}
})
Adding track context-menu items
When you right-click in a linear track, a context menu will appear if there are
any menu items defined for it. It's possible to add items to that menu, and you
can also have different menu items based on if the click was on a feature or
not, and based on what feature is clicked. This is done by extending the
contextMenuItems
view of the display model. Here is an example:
class SomePlugin extends Plugin {
name = 'SomePlugin'
install(pluginManager) {
pluginManager.addToExtensionPoint(
'Core-extendPluggableElement',
pluggableElement => {
if (pluggableElement.name === 'LinearPileupDisplay') {
const { stateModel } = pluggableElement
const newStateModel = stateModel.extend(self => {
const superContextMenuItems = self.contextMenuItems
return {
views: {
contextMenuItems() {
const feature = self.contextMenuFeature
if (!feature) {
// we're not adding any menu items since the click was not
// on a feature
return superContextMenuItems()
}
return [
...superContextMenuItems(),
{
label: 'Some menu item',
icon: SomeIcon,
onClick: () => {
// do some stuff
},
},
]
},
},
}
})
pluggableElement.stateModel = newStateModel
}
return pluggableElement
},
)
}
}
Configuration model concepts
Configuration slot types
Our configuration system is "typed" to facilitate graphical editing of the configuration. Each configuration has a "schema" that lists what "configuration slots" it has. Each configuration slot has a name, description, a type, and a value.
Here is a mostly comprehensive list of config types
stringEnum
- allows assigning one of a limited set of entries, becomes a dropdown box in the GUIcolor
- allows selecting a color, becomes a color picker in the GUInumber
- allows entering any numeric valuestring
- allows entering any stringinteger
- allows entering a integer value- `boolean
frozen
- an arbitrary JSON can be specified in this config slot, becomes textarea in the GUIfileLocation
- refers to a URL, local file path on desktop, or file blob object in the browsertext
- allows entering a string, becomes textarea in the GUIstringArray
- allows entering a list of strings, becomes a "todolist" style editor in the GUI where you can add or delete thingsstringArrayMap
- allows entering a list of key-value entries
Let's examine the PileupRenderer
configuration as an example.
Example config with multiple slot types
This PileupRenderer
config contains an example of several different slot types
import { types } from 'mobx-state-tree'
export default ConfigurationSchema('PileupRenderer', {
color: {
type: 'color',
description: 'the color of each feature in a pileup alignment',
defaultValue: `jexl:get(feature,'strand') == - 1 ? '#8F8FD8' : '#EC8B8B'`,
contextVariable: ['feature'],
},
displayMode: {
type: 'stringEnum',
model: types.enumeration('displayMode', ['normal', 'compact', 'collapse']),
description: 'Alternative display modes',
defaultValue: 'normal',
},
minSubfeatureWidth: {
type: 'number',
description: `the minimum width in px for a pileup mismatch feature. use for
increasing mismatch marker widths when zoomed out to e.g. 1px or
0.5px`,
defaultValue: 0,
},
maxHeight: {
type: 'integer',
description: 'the maximum height to be used in a pileup rendering',
defaultValue: 600,
},
})
Accessing config values
So instead of accessing config.displayMode
, we say
readConfObject(config, 'displayMode')
You might also see in the code like this
getConf(track, 'maxHeight')
Which would be equivalent to calling
readConfObject(track.configuration, 'maxHeight')`
Using config callbacks
Config callbacks allow you to have a dynamic color based on some function logic you provide. All config slots can actually become config callback. The arguments that are given to the callback are listed by the 'contextVariable' but must be provided by the calling code (the code reading the config slot). To pass arguments to the a callback we say
readConfObject(config, 'color', { feature })
That implies the color configuration callback will be passed a feature, so the config callback can be a complex function determining the color to use based on various feature attributes
Example of a config callback
We use Jexl to express callbacks. See https://github.com/TomFrost/Jexl for more details.
If you had an variant track in your config, and wanted to make a custom config callback for color, it might look like this
{
"type": "VariantTrack",
"trackId": "variant_colors",
"name": "volvox filtered vcf (green snp, purple indel)",
"category": ["VCF"],
"assemblyNames": ["volvox"],
"adapter": {
"type": "VcfTabixAdapter",
"vcfGzLocation": {
"uri": "volvox.filtered.vcf.gz",
"locationType": "UriLocation"
},
"index": {
"location": {
"uri": "volvox.filtered.vcf.gz.tbi",
"locationType": "UriLocation"
}
}
},
"displays": [
{
"type": "LinearVariantDisplay",
"displayId": "volvox_filtered_vcf_color-LinearVariantDisplay",
"renderer": {
"type": "SvgFeatureRenderer",
"color1": "jexl:get(feature,'type')=='SNV'?'green':'purple'"
}
}
]
}
This draws all SNV (single nucleotide variants) as green, and other types as purple (insertion, deletion, other structural variant).
Configuration internals
A configuration is a type of mobx-state-tree model, in which leaf nodes are ConfigSlot types, and other nodes are ConfigurationSchema types.
Schema
/ | \
Slot Schema Slot
| \
Slot Slot
Configurations are all descendants of a single root configuration, which is
root.configuration
.
Configuration types should always be created by the ConfigurationSchema
factory, e.g.
import { ConfigurationSchema } from '@jbrowse/core/utils/configuration'
const ThingStateModel = types.model('MyThingsState', {
foo: 42,
configuration: ConfigurationSchema('MyThing', {
backgroundColor: {
defaultValue: 'white',
type: 'string',
},
}),
})
An example of a config schema with a sub-config schema is the BamAdapter
, with
the index sub-config schema
ConfigurationSchema(
'BamAdapter',
{
bamLocation: {
type: 'fileLocation',
defaultValue: { uri: '/path/to/my.bam', locationType: 'UriLocation' },
},
// this is a sub-config schema
index: ConfigurationSchema('BamIndex', {
indexType: {
model: types.enumeration('IndexType', ['BAI', 'CSI']),
type: 'stringEnum',
defaultValue: 'BAI',
},
location: {
type: 'fileLocation',
defaultValue: {
uri: '/path/to/my.bam.bai',
locationType: 'UriLocation',
},
},
}),
},
{ explicitlyTyped: true },
)
Reading the sub-config schema is as follows
const indexType = readConfObject(config, ['index', 'indexType'])
Alternatively can use
const indexConf = readConfObject(config, ['index'])
indexConf.indexType
However, this may miss default values from the slot, the readConfObject has special logic to fill in the default value
Creating adapters
What is an adapter
An adapter is essentially a class that fetches and parses your data and returns it in a format JBrowse understands.
For example, if you have some data source that contains genes, and you want to display those genes using JBrowse's existing gene displays, you can write a custom adapter to do so. If you want to do a custom display of your data, though, you'll probably need to create a custom display and/or renderer along with your adapter.
What types of adapters are there
- Feature adapter - This is the most common type of adapter. Essentially, it takes a request for a region (a chromosome, starting position, and ending position) and returns the features (e.g. genes, reads, variants, etc.) that are in that region. Examples of this in JBrowse include adapters for BAM and VCF file formats.
- Regions adapter - This type of adapter is used to define what regions are in an assembly. It returns a list of chromosomes/contigs/scaffolds and their sizes. An example of this in JBrowse is an adapter for a chrome.sizes file.
- Sequence adapter - This is basically a combination of a regions adapter and a feature adapter. It can give the list of regions in an assembly, and can also return the sequence of a queried region. Examples of this in JBrowse include adapters for FASTA and .2bit file formats.
- RefName alias adapter - This type of adapter is used to return data about aliases for reference sequence names, for example to define that "chr1" is an alias for "1". An example of this in JBrowse is an adapter for (alias files)[http://software.broadinstitute.org/software/igv/LoadData/#aliasfile]
- Text search adapter - This type of adapter is used to search through text search indexes. Returns list of search results. An example of this in JBrowse is the trix text search adapter.
Note about refname alias adapter: the first column must match what is seen in your FASTA file
Skeleton of a feature adapter
A basic feature adapter might look like this (with implementation omitted for simplicity):
class MyAdapter extends BaseFeatureDataAdapter {
constructor(config) {
// config
}
async getRefNames() {
// return refNames used in your adapter, used for refName renaming
}
getFeatures(region, opts) {
// region: {
// refName:string, e.g. chr1
// start:number, 0-based half open start coord
// end:number, 0-based half open end coord
// assemblyName:string, assembly name
// originalRefName:string the name of the refName from the fasta file, e.g. 1 instead of chr1
// }
// opts: {
// signal?: AbortSignal
// ...rest: all the renderProps() object from the display type
// }
}
freeResources(region) {
// can be empty
}
}
So to make a feature adapter, you implement the getRefNames function (optional), the getFeatures function (returns an rxjs observable stream of features, discussed below) and freeResources (optional)
Example feature adapter
To take this a little slow let's look at each function individually
This is a more complete description of the class interface that you can implement
import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter'
import SimpleFeature from '@jbrowse/core/util/simpleFeature'
import { readConfObject } from '@jbrowse/core/configuration'
import { ObservableCreate } from '@jbrowse/core/util/rxjs'
class MyAdapter extends BaseFeatureDataAdapter {
// your constructor gets a config object that you can read with readConfObject
// if you use "subadapters" then you can initialize those with getSubAdapter
constructor(config, getSubAdapter) {
const fileLocation = readConfObject(config, 'fileLocation')
const subadapter = readConfObject(config, 'sequenceAdapter')
const sequenceAdapter = getSubAdapter(subadapter)
}
// use rxjs observer.next(new SimpleFeature(...your feature data....) for each
// feature you want to return
getFeatures(region, options) {
return ObservableCreate(async observer => {
try {
const { refName, start, end } = region
const response = await fetch(
'http://myservice/genes/${refName}/${start}-${end}',
options,
)
if (response.ok) {
const features = await result.json()
features.forEach(feature => {
observer.next(
new SimpleFeature({
uniqueID: `${feature.refName}-${feature.start}-${feature.end}`,
refName: feature.refName,
start: feature.start,
end: feature.end,
}),
)
})
observer.complete()
} else {
throw new Error(`${response.status} - ${response.statusText}`)
}
} catch (e) {
observer.error(e)
}
})
}
async getRefNames() {
// returns the list of refseq names in the file, used for refseq renaming
// you can hardcode this if you know it ahead of time e.g. for your own
// remote data API or fetch this from your data file e.g. from the bam header
return ['chr1', 'chr2', 'chr3'] /// etc
}
freeResources(region) {
// optionally remove cache resources for a region
// can just be an empty function
}
}
What is needed from a feature adapter
getRefNames
Returns the refNames that are contained in the file, this is used for "refname renaming" and is optional but highly useful in scenarios like human chromosomes which have, for example, chr1 vs 1.
Returning the refNames used by a given file or resource allows JBrowse to automatically smooth these small naming disparities over. See reference renaming
getFeatures
A function that returns features from the file given a genomic range query e.g.
getFeatures(region, options)
The region parameter contains
interface Region {
refName: string
start: number
end: number
originalRefName: string
assemblyName: string
}
The refName, start, end specify a simple genomic range. The "assemblyName" is used to query a specific assembly if your adapter responds to multiple assemblies e.g. for a synteny data file or a REST API that queries a backend with multiple assemblies.
The "originalRefName" are also passed, where originalRefName is the queried refname before ref renaming e.g. in BamAdapter, if the BAM file uses chr1, and your reference genome file uses 1, then originalRefName will be 1 and refName will be chr1
The options parameter to getFeatures can contain any number of things
interface Options {
bpPerPx: number
signal: AbortSignal
statusCallback: Function
headers: Record<string, string>
}
bpPerPx
- number: resolution of the genome browser when the features were fetchedsignal
- can be used to abort a fetch request when it is no longer needed, from AbortControllerstatusCallback
- not implemented yet but in the future may allow you to report the status of your loading operationsheaders
- set of HTTP headers as a JSON object
We return an rxjs Observable from getFeatures. This is similar to a JBrowse 1 getFeatures call, where we pass each feature to a featureCallback, tell it when we are done with finishCallback, and send errors to errorCallback, except we do all those things with the Observable
Here is a "conversion" of JBrowse 1 getFeatures callbacks to JBrowse 2 observable calls
featureCallback(new SimpleFeature(...))
->observer.next(new SimpleFeature(...))
finishCallback()
->observer.complete()
errorCallback(error)
->observer.error(error)
freeResources
This is uncommonly used, so most adapters make this an empty function
Most adapters in fact use an LRU cache to make resources go away over time instead of manually cleaning up resources
Writing your own plugin
JBrowse 2 plugins can be used to add new pluggable elements (views, tracks, adapters, etc), and to modify behavior of the application by adding code that watches the application's state. For the full list of what kinds of pluggable element types plugins can add, see the pluggable elements page.
The first thing that we have is a src/index.js
which exports a default class
containing the plugin registration code
src/index.js
import AdapterType from '@jbrowse/core/pluggableElementTypes/AdapterType'
import Plugin from '@jbrowse/core/Plugin'
import { AdapterClass, configSchema } from './UCSCAdapter'
export default class UCSCPlugin extends Plugin {
name = 'UCSCPlugin'
install(pluginManager) {
pluginManager.addAdapterType(
() =>
new AdapterType({
name: 'UCSCAdapter',
configSchema,
AdapterClass,
}),
)
}
}
src/UCSCAdapter/index.ts
import {
ConfigurationSchema,
readConfObject,
} from '@jbrowse/core/configuration'
import { ObservableCreate } from '@jbrowse/core/util/rxjs'
import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter'
import SimpleFeature from '@jbrowse/core/util/simpleFeature'
import stringify from 'json-stable-stringify'
export const configSchema = ConfigurationSchema(
'UCSCAdapter',
{
base: {
type: 'fileLocation',
description: 'base URL for the UCSC API',
defaultValue: {
uri: 'https://cors-anywhere.herokuapp.com/https://api.genome.ucsc.edu/',
locationType: 'UriLocation',
},
},
track: {
type: 'string',
description: 'the track to select data from',
defaultValue: '',
},
},
{ explicitlyTyped: true },
)
export class AdapterClass extends BaseFeatureDataAdapter {
constructor(config) {
super(config)
this.config = config
}
getFeatures(region) {
const { assemblyName, start, end, refName } = region
return ObservableCreate(async observer => {
const { uri } = readConfObject(this.config, 'base')
const track = readConfObject(this.config, 'track')
try {
const result = await fetch(
`${uri}/getData/track?` +
`genome=${assemblyName};track=${track};` +
`chrom=${refName};start=${start};end=${end}`,
)
if (result.ok) {
const data = await result.json()
data[track].forEach(feature => {
observer.next(
new SimpleFeature({
...feature,
start: feature.chromStart,
end: feature.chromEnd,
refName: feature.chrom,
uniqueId: stringify(feature),
}),
)
})
observer.complete()
}
} catch (e) {
observer.error(e)
}
})
}
async getRefNames() {
const arr = []
for (let i = 0; i < 23; i++) {
arr.push(`chr${i}`)
}
return arr
}
freeResources() {}
}
Adding this track to our configuration
We can create a track.json like this
track.json
{
"type": "FeatureTrack",
"trackId": "genehancer_ucsc",
"name": "UCSC GeneHancer",
"assemblyNames": ["hg38"],
"adapter": {
"type": "UCSCAdapter",
"track": "geneHancerInteractionsDoubleElite"
}
}
Then use the jbrowse CLI tool add-track-json
jbrowse add-track-json file.json
This will automatically add this track to the tracks array of our config.json
Alternatively, we can manually edit this JSON into the config.json.
When we open this track, we should see the GeneHancer regions are drawn as orange blocks.
Creating a custom renderer type
Let's say we want to create a track that connects a gene to it's enhancer. On UCSC the GeneHancer tracks do exactly this. An instance of the UCSC with the GeneHancer tracks is here.
We can see data that we can get for the GeneHancer interactions from the UCSC API like this
curl 'https://api.genome.ucsc.edu/getData/track?genome=hg19;\
track=geneHancerInteractionsDoubleElite;chrom=chr1;start=750000;\
end=505700000'|less
Given that the functionality of rendering arcs is so distinct from UCSC API adaptation, we can actually make this a new plugin. Let's imagine starting a new plugin from scratch again
src/index.js
import Plugin from '@jbrowse/core/Plugin'
import PluginManager from '@jbrowse/core/PluginManager'
import ArcRenderer, {
configSchema as ArcRendererConfigSchema,
ReactComponent as ArcRendererReactComponent,
} from './ArcRenderer'
export default class ArcRendererPlugin extends Plugin {
name = 'ArcPlugin'
install(pluginManager) {
pluginManager.addRendererType(
() =>
new ArcRenderer({
name: 'ArcRenderer',
ReactComponent: ArcRendererReactComponent,
configSchema: ArcRendererConfigSchema,
pluginManager,
}),
)
}
}
src/ArcRenderer/index.js
import React from 'react'
// prettier-ignore
import {
ServerSideRendererType
} from '@jbrowse/core/pluggableElementTypes/renderers/ServerSideRendererType'
import {
ConfigurationSchema,
readConfObject,
} from '@jbrowse/core/configuration'
import { PrerenderedCanvas } from '@jbrowse/core/ui'
import { bpSpanPx } from '@jbrowse/core/util'
import {
createCanvas,
createImageBitmap,
} from '@jbrowse/core/util/offscreenCanvasPonyfill'
// Our config schema for arc track will be basic, include just a color
export const configSchema = ConfigurationSchema(
'ArcRenderer',
{
color: {
type: 'color',
description: 'color for the arcs',
defaultValue: 'darkblue',
},
},
{ explicitlyTyped: true },
)
// This ReactComponent is the so called "rendering" which is the component
// that contains the contents of what was rendered.
export const ReactComponent = props => {
return (
<div style={{ position: 'relative' }}>
<PrerenderedCanvas {...props} />
</div>
)
}
// Our ArcRenderer class does the main work in it's render method
// which draws to a canvas and returns the results in a React component
export default class ArcRenderer extends ServerSideRendererType {
async render(renderProps) {
const { features, config, regions, bpPerPx, highResolutionScaling } =
renderProps
const region = regions[0]
const width = (region.end - region.start) / bpPerPx
const height = 500
const canvas = createCanvas(
width * highResolutionScaling,
height * highResolutionScaling,
)
const ctx = canvas.getContext('2d')
ctx.scale(highResolutionScaling, highResolutionScaling)
for (const feature of features.values()) {
const [left, right] = bpSpanPx(
feature.get('start'),
feature.get('end'),
region,
bpPerPx,
)
ctx.beginPath()
ctx.strokeStyle = readConfObject(config, 'color', { feature })
ctx.lineWidth = 3
ctx.moveTo(left, 0)
ctx.bezierCurveTo(left, 200, right, 200, right, 0)
ctx.stroke()
}
const imageData = await createImageBitmap(canvas)
const reactElement = React.createElement(
this.ReactComponent,
{
...renderProps,
width,
height,
imageData,
},
null,
)
return { reactElement, imageData, width, height }
}
}
The above code is relatively simple but it is fairly quirky. Here are some notes:
- renderers can be run in offscreen or even a node.js canvas, so we do not
assume the
document.createElement
exists to create our canvas, instead using a utility function that makes a OffscreenCanvas or node-canvas (depends on context, e.g. webworker or node.js) - the "rendering" component contains the results of our renderer. in this case
it delegates to the
PrerenderedCanvas
component, a component we use in other places throughout the codebase
Bringing the two together
We can bring these two contexts together with a new track in our config.json.
Remember our previous track.json? Now we can edit it to use our own ArcRenderer
track.json
{
"type": "BasicTrack",
"trackId": "genehancer_ucsc",
"name": "UCSC GeneHancer",
"assemblyNames": ["hg38"],
"adapter": {
"type": "UCSCAdapter",
"track": "geneHancerInteractionsDoubleElite"
},
"renderer": {
"type": "ArcRenderer"
}
}
Then add the track
jbrowse add-track-json track.json --update
Creating custom renderers
What is a renderer
In JBrowse 1, a track type typically would directly call the data parser and do it's own rendering. In JBrowse 2, the data parsing and rendering is offloaded to a web-worker or other RPC. This allows things to be faster in many cases. This is conceptually related to "server side rendering" or SSR in React terms.

Important note: you can make custom tracks types that do not use this workflow, but it is a built in workflow that works well for the core track types in JBrowse 2.
How to create a new renderer
The fundamental aspect of creating a new renderer is creating a class that implements the "render" function. A renderer is actually a pair of a React component that contains the renderer's output, which we call the "rendering" and the renderer itself
class MyRenderer implements ServerSideRendererType {
render(props) {
const { width, height, regions, features } = props
const canvas = createCanvas(width, height)
const ctx = canvas.getContext('2d')
ctx.fillStyle = 'red'
ctx.drawRect(0, 0, 100, 100)
const imageData = createImageBitmap(canvas)
return {
reactElement: React.createElement(this.ReactComponent, { ...props }),
imageData,
height,
width,
}
}
}
In the above simplified example, our renderer creates a canvas using width and
height that are supplied via arguments, and draw a rectangle. We then return a
React.createElement
call which creates a "rendering" component that will
contain the output
Note that the above canvas operations use an OffscreenCanvas
for Chrome, or in
other browsers serialize the drawing commands to be drawn in the main thread
What are the props passed to the renderer
The typical props that a renderer receives
export interface PileupRenderProps {
features: Map<string, Feature>
layout: { addRect: (featureId, leftBp, rightBp, height) => number }
config: AnyConfigurationModel
regions: Region[]
bpPerPx: number
height: number
width: number
highResolutionScaling: number
}
The layout is available on BoxRendererType renderers so that it can layout things in pileup format, and has an addRect function to get the y-coordinate to render your data at
The features argument is a map of feature ID to the feature itself. To iterate over the features Map, we can use an iterator or convert to an array
class MyRenderer extends ServerSideRendererType {
render(props) {
const { features, width, height } = props
// iterate over the ES6 map of features
for (const feature in features.values()) {
// render each feature to canvas or output SVG
}
// alternatively
const feats = Array.from(features.values())
feats.forEach(feat => {})
}
}
Adding custom props to the renderer
Note that track models themselves can extend this using their renderProps function
For example the WiggleTrack
has code similar to this, which adds a scaleOpts
prop that gets passed to the renderer
const model = types
.compose(
'WiggleTrack',
blockBasedTrack,
types.model({
type: types.literal('WiggleTrack'),
}),
)
.views(self => {
const { renderProps: superRenderProps } = self
return {
renderProps() {
return {
...superRenderProps(),
scaleOpts: {
domain: this.domain,
stats: self.stats,
autoscaleType: getConf(self, 'autoscale'),
scaleType: getConf(self, 'scaleType'),
inverted: getConf(self, 'inverted'),
},
}
},
}
})
Rendering SVG
Our SVG renderer is an example, where it extends the existing built in renderer type with a custom ReactComponent only
export default class SVGPlugin extends Plugin {
install(pluginManager: PluginManager) {
pluginManager.addRendererType(
() =>
new BoxRendererType({
name: 'SvgFeatureRenderer',
ReactComponent: SvgFeatureRendererReactComponent,
configSchema: svgFeatureRendererConfigSchema,
pluginManager,
}),
)
}
}
Then, we have our Rendering component just be plain React code. This is a highly simplified SVG renderer just to illustrate
export default function SvgFeatureRendering(props) {
const { width, features, regions, layout, bpPerPx } = props
const region = regions[0]
const feats = Array.from(features.values())
const height = readConfObject(config, 'height', { feature })
return (
<svg>
{feats.map(feature => {
// our layout determines at what y-coordinate to
// plot our feature, given all the other features
const top = layout.addRect(
feature.id(),
feature.get('start'),
feature.get('end'),
height,
)
const [left, right] = bpSpanPx(
feature.get('start'),
feature.get('end'),
region,
bpPerPx,
)
return <rect x={left} y={top} height={height} width={right - left} />
})}
</svg>
)
}
Notes:
- The above SVG renderer is highly simplified but serves an example, but it
shows that you can have a simple React component that leverages the existing
BoxRendererType
, so that you do not have to necessarily create your own renderer class - The renderers receive an array of regions to render, but if they are only
equipped to handle one region at a time then they can select only rendering
to
regions[0]
Overriding the renderer's getFeatures method
Normally, it is sufficient to override the getFeatures
function in your
dataAdapter
If you want to drastically modify the feature fetching behavior, you can modify the renderer's getFeatures call
The base ServerSideRendererType
class has a built-in getFeatures
function that,
in turn, calls your adapter's getFeatures function, but if you need
tighter control over how your adapter's getFeatures method is called then
your renderer. The Hi-C renderer type does not operate on conventional
features and instead works with contact matrices, so the Hi-C renderer has a
custom getFeatures function
import { toArray } from 'rxjs/operators'
class HicRenderer extends ServerSideRendererType {
async getFeatures(args) {
const { dataAdapter, regions } = args
const features = await dataAdapter
.getFeatures(regions[0])
.pipe(toArray())
.toPromise()
return features
}
}
Creating custom track types
At a high level the track types are just "ReactComponents" that contain rendered track contents. Oftentimes, for custom drawing, we create a renderer instead of a track, but here are some reasons you might want a custom track
- Drawing custom things over the rendered content (e.g. drawing the Y-scale bar in the wiggle track)
- Implementing custom track menu items (e.g. Show soft clipping in the alignments track)
- Adding custom widgets (e.g. custom
VariantFeatureWidget
in variant track) - You want to bundle your renderer and adapter as a specific thing that is
automatically initialized rather than the
BasicTrack
(which combines any adapter and renderer)
For examples of custom track types, refer to things like
HicTrack
, which uses a custom HicRenderer to draw contact matrixGDCPlugin
, which has a custom track type that registers custom feature detail widgetsVariantTrack
, which also registers custom widgets, and hasChordVariantDisplay
andLinearVariantDisplay
SyntenyTrack
, which can be displayed withDotplotDisplay
orLinearSyntenyDisplay
Embedded components
Our embedded components allow you to use individual JBrowse views in your application
JBrowse React Linear Genome View
This component consists of a single JBrowse 2 linear view.
- @jbrowse/react-linear-genome-view linear genome view React component on NPM
- Storybook - docs for the linear genome view React component
Here is a table of different usages of the @jbrowse/react-linear-genome-view
using different bundlers
Bundler | Demo | Source code | Note |
---|---|---|---|
create-react-app v4 | demo | source code (download) | no polyfills needed in create-react-app v4 |
create-react-app v5 | demo | source code (download) | for create-react-app v5, we use craco to update the webpack config to polyfill some node modules |
vite | demo | source code (download) | for vite, we use rollup to polyfill some node polyfills similar to craco in create-react-app v5 |
next.js | demo | source code (download) | uses next.js 11, may have trouble with building production builds on next.js 12 due to a webpack bug in 5.70+. Also see next.config.js to update basePath as needed |
vanilla js | demo | source code (download) | uses a script tag to include a UMD bundle, and doesn't require any transpilation or bundling |
JBrowse React Circular Genome View
This component consists of a single JBrowse 2 circular view.
- @jbrowse/react-circular-genome-view circular genome view React component on NPM
- Storybook - docs for the circular genome view React component
Here is a table of different usages of the
@jbrowse/react-circular-genome-view
using different bundlers
Syntax | Demo | Source code | Note |
---|---|---|---|
create-react-app v4 | demo | source code (download) | no polyfills needed in create-react-app v4 |
create-react-app v5 | demo | source code (download) | for create-react-app v5, we use craco to update the webpack config to polyfill some node modules |
vanilla js | demo | source code (download) | uses a script tag to include a UMD bundle, and doesn't require any transpilation or bundling |
API guide
In this guide, will cover API level documentation e.g. methods that can be called on different objects and data model formats
MenuItems objects
You can add menus or add items to existing menus in several places.
In these different places, a MenuItem
object defines the menu item's text,
icon, action, and other attributes.
Types of MenuItem
s:
- Normal: a standard menu item that performs an action when clicked
- Checkbox: a menu item that has a checkbox
- Radio: a menu item that has a radio button icon
- Divider: a horizontal line (not clickable) that can be used to visually divide menus
- SubHeader: text (not clickable) that can be used to visually label a section of a menu
- SubMenu: contains menu items, for making nested menus
Name | Description |
---|---|
type | Options are 'normal', 'radio', 'checkbox', 'subMenu', 'subHeader', or 'divider'. If not provided, defaults to 'normal', unless a subMenu attribute is present, in which case it defaults to 'subMenu'. |
label | The text for the menu item. Not applicable to 'divider', required for all others. |
subLabel | Additional descriptive text for the menu item. Not applicable to 'divider' or 'subHeader', optional for all others. |
icon | An icon for the menu item. Must be compatible with Material-UI's Icons. Not applicable to 'divider' or 'subHeader', optional for all others. |
disabled | Whether or not the menu item is disabled (meaning grayed out and not clickable). Not applicable to 'divider' or 'subHeader', optional for all others. |
checked | Whether or not the checkbox or radio button are selected. Only applicable to 'radio' and 'checkbox' |
onClick | Callback of action to perform on click. Function signature is (session) => undefined . Required for 'normal', 'radio', and 'checkbox', not applicable to any others. |
subMenu | An array of menu items. Applicable only to 'subMenu'. |
As an example, the here is an array of MenuItems and the resulting menu:
;[
{
label: 'Normal menu item',
icon: AddIcon,
onClick: () => {},
},
{
label: 'Normal',
subLabel: 'with subLabel',
icon: AddIcon,
onClick: () => {},
},
{
label: 'Disabled menu item',
disabled: true,
icon: AddIcon,
onClick: () => {},
},
{
type: 'radio',
label: 'Radio checked',
checked: true,
onClick: () => {},
},
{
type: 'radio',
label: 'Radio unchecked',
checked: false,
onClick: () => {},
},
{
type: 'checkbox',
label: 'Checkbox checked',
checked: true,
onClick: () => {},
},
{
type: 'checkbox',
label: 'Checkbox unchecked',
checked: false,
onClick: () => {},
},
{ type: 'divider' },
{ type: 'subHeader', label: 'This is a subHeader' },
{
label: 'SubMenu',
subMenu: [
{
label: 'SubMenu item one',
onClick: () => {},
},
{
label: 'SubMenu item two',
onClick: () => {},
},
],
},
]

rootModel Menu API
Users can customize the top-level menu items using these functions that are available on the rootModel:
appendMenu
Add a top-level menu
Parameters
Name | Description |
---|---|
menuName | Name of the menu to insert. |
Return Value
The new length of the top-level menus array
insertMenu
Insert a top-level menu
Parameters
Name | Description |
---|---|
menuName | Name of the menu to insert. |
position | Position to insert menu. If negative, counts from the end, e.g. insertMenu('My Menu', -1) will insert the menu as the second-to-last one. |
Return Value
The new length of the top-level menus array
appendToMenu
Add a menu item to a top-level menu
Parameters
Name | Description |
---|---|
menuName | Name of the top-level menu to append to. |
menuItem | Menu item to append. |
Return Value
The new length of the menu
insertInMenu
Insert a menu item into a top-level menu
Parameters
Name | Description |
---|---|
menuName | Name of the top-level menu to insert into. |
menuItem | Menu item to insert. |
position | Position to insert menu item. If negative, counts from the end, e.g. insertMenu('My Menu', -1) will insert the menu as the second-to-last one. |
Return Value
The new length of the menu
appendToSubMenu
Add a menu item to a sub-menu
Parameters
Name | Description |
---|---|
menuPath | Path to the sub-menu to add to, starting with the top-level menu (e.g. ['File', 'Insert'] ). |
menuItem | Menu item to append. |
Return value
The new length of the sub-menu
insertInSubMenu
Insert a menu item into a sub-menu
Parameters
Name | Description |
---|---|
menuPath | Path to the sub-menu to add to, starting with the top-level menu (e.g. ['File', 'Insert'] ). |
menuItem | Menu item to insert. |
position | Position to insert menu item. If negative, counts from the end, e.g. insertMenu('My Menu', -1) will insert the menu as the second-to-last one. |
Return value
The new length of the sub-menu
Extension points
In the core codebase, we have the concept of extension points that users can call or add to
The API is
pluginManager.evaluateExtensionPoint(extensionPointName, args)
There is also an async version
pluginManager.evaluateAsyncExtensionPoint(extensionPointName, args)
Users can additionall add to extension points, so that when they are evaluated, it runs a chain of callbacks that are registered to that extension point
This looks like
pluginManager.addToExtensionPoint(extensionPointName, callback => newArgs)
Here are the extension points in the core codebase
Core-extendPluggableElement
(sync) used to add extra functionality to existing state tree models, for example, extra right-click context menus
Core-guessAdapterForLocation
(sync) used to infer an adapter type given a location type from the "Add track" workflow
Core-guessTrackTypeForLocation
(sync) used to infer a track type given a location type from the "Add track workflow"
LaunchView-LinearGenomeView
(async) launches a linear genome view given parameters
- session:AbstractSessionModel - instance of the session which you can call actions on
- assembly:string - assembly name
- loc:string - a locstring
- tracks:string[] - array of trackIds
LaunchView-CircularView
- session:AbstractSessionModel - instance of the session which you can call actions on
- assembly:string - assembly name
- tracks:string[] - array of trackIds
Extension point footnote
Users that want to add further extension points can do so. The naming system, "Core-" just refers to the fact that these extension points are from our core codebase. Plugin developers may choose their own prefix to avoid collisions
URL query parameter API
JBrowse Web features the ability to automatically provide URL parameters to setup a session
Note that the embedded components like @jbrowse/react-linear-genome-view make no assumptions on how URL params are used, so would have to be implemented by the consumer of the library
Simple API for linear genome view
We provide a simplified URL format specifically designed for launching a single linear genome view
Example
http://host/jbrowse2/?config=test_data/config.json&loc=chr1:6000-7000&assembly=hg19&tracks=gene_track,vcf_track
Here are the query params used here
?config=
Example
?config=test_data/volvox/config.json
A path to a JBrowse 2 config file, relative to the current folder on the disk. Note that this just uses client side fetch to read the file, not server side file reads. If ?config= is not specified, it looks for a file named config.json e.g. http://host/jbrowse2/config.json which is what the @jbrowse/cli tool sets up by default
&assembly=
Example
&assembly=hg19
The &assembly parameter refers to an assembly's "name" field one of the "assemblies" array in the from the config.json. This is only used for launching a single linear genome view.
&loc=
Example
&loc=chr1:6000-7000
This performs a navigation to this region on load, which can be specified using the syntax. This is only used for launching a single linear genome view.
Example strings
chr1:6000-7000 // using - notation for range
chr1:6000..7000 // using .. notation for range
chr1:7000 // centered on this position
Note: Navigating via a text search query e.g. supply &loc=gene_name is not yet supported
&tracks=
Example
&tracks=gene_track,vcf_track
This is a comma separated list of trackIds. You can see your trackId's in the config.json. Note, you can also refer to a trackId added by &sessionTracks= here. This is only used for launching a single linear genome view.
More URL parameters
&sessionTracks=
If you want to dynamically add a track to the session, you can do so with
&sessionTracks=
You can also use this method to add a FromConfigAdapter
track, which let's you
specify features in JSON format, so you can e.g. add BLAST hits via the URL bar
Example
https://jbrowse.org/code/jb2/main/?config=test_data/volvox/config.json&loc=ctgA:1-800&assembly=volvox&tracks=gff3tabix_genes,volvox_filtered_vcf,volvox_microarray,volvox_cram,url_track&sessionTracks=[{"type":"FeatureTrack","trackId":"url_track","name":"URL track","assemblyNames":["volvox"],"adapter":{"type":"FromConfigAdapter","features":[{"uniqueId":"one","refName":"ctgA","start":100,"end":200,"name":"Boris"}]}}]
This creates a track dynamically that has a single feature at chr1:100-200
The data to supply to &sessionTracks=
is an array of track configs, and in the
above URL, looks like this when pretty-printed
[
{
"type": "FeatureTrack",
"trackId": "url_track",
"name": "URL track",
"assemblyNames": ["volvox"],
"adapter": {
"type": "FromConfigAdapter",
"features": [
{
"uniqueId": "one",
"refName": "ctgA",
"start": 190,
"end": 191,
"name": "Boris"
}
]
}
}
]
&session=
The session parameter, e.g. &session= has a number of different "input formats"
Local sessions
The local sessions look like this
https://host/jbrowse2/?session=local-Fjphq8kjY
By default, after a session is loaded, it is stored into localStorage, and then the URL bar uses the ?session=local- format to reflect the key of the localStorage entry.
Shared sessions
If you click the "Share button" in the header bar, it will generate a "shareable link" that you can give to other users
https://host/jbrowse2/?session=share-HShsEcnq3i&password=nYzTU
See this FAQ entry for more info about how shared sessions work
Session spec
Another useful session URL is called a "session spec" or "session specification". This provides a way to launch multiple views at once, including view types other than the linear genome view
Linear Genome View
https://jbrowse.org/code/jb2/main/?config=test_data/volvox/config.json&session=spec-{"views":[{"assembly":"volvox","loc":"ctgA:1-5100","type": "LinearGenomeView","tracks":["gff3tabix_genes","volvox_filtered_vcf","volvox_microarray","volvox_cram"]}]}
Expanded
{
"views": [
{
"assembly": "volvox",
"loc": "ctgA:1-5100",
"type": "LinearGenomeView",
"tracks": [
"gff3tabix_genes",
"volvox_filtered_vcf",
"volvox_microarray",
"volvox_cram"
]
}
]
}
As you can see, you can supply an array of views (so you can open multiple views at once) and can specify the loc, tracks, assembly, and view type, or other view specific parameters (different view types may accept different params, e.g. dotplot has two assemblies)
Circular view
Here is a session spec for a Circular View
https://jbrowse.org/code/jb2/main/?config=test_data/volvox/config.json&session=spec-{"views":[{"assembly":"volvox","loc":"ctgA:1-5100","type": "CircularView","tracks":["volvox_sv_test"]}]}
Expanded
{
"views": [
{
"assembly": "volvox",
"loc": "ctgA:1-5100",
"type": "CircularView",
"tracks": ["volvox_sv_test"]
}
]
}
Dotplot view
https://jbrowse.org/code/jb2/main/?config=test_data/volvox/config_main_thread.json&session=spec-%7B"views":%5B%7B"type":"DotplotView","views":%5B%7B"assembly":"volvox"%7D,%7B"assembly":"volvox"%7D%5D,"tracks":%5B"volvox_fake_synteny"%5D%7D%5D%7D
Expanded
{
"views": [
{
"type": "DotplotView",
"views": [{ "assembly": "volvox" }, { "assembly": "volvox" }],
"tracks": ["volvox_fake_synteny"]
}
]
}
Note that this dotplot session spec doesn't have the ability to navigate to specific regions on the assembly yet, it just navigates to a whole genome overview
Spreadsheet view
https://jbrowse.org/code/jb2/main/?config=test_data/volvox/config.json&session=spec-%7B%22views%22:%5B%7B%22type%22:%22SpreadsheetView%22,%20%22uri%22:%22test_data/volvox/volvox.filtered.vcf.gz%22,%22assembly%22:%22volvox%22%7D%5D%7D
Expanded
{
"views": [
{
"type": "SpreadsheetView",
"uri": "test_data/volvox/volvox.filtered.vcf.gz",
"assembly": "volvox"
}
]
}
SV inspector
https://jbrowse.org/code/jb2/main/?config=test_data/volvox/config.json&session=spec-%7B"views":%5B%7B"type":"SvInspectorView","uri":"test_data/volvox/volvox.dup.vcf.gz","assembly":"volvox"%7D%5D%7D
Expanded
{
views: [
{
type: "SvInspectorView",
uri: "test_data/volvox/volvox.dup.vcf.gz",
assembly: "volvox",
},
],
};
Linear synteny view
https://jbrowse.org/code/jb2/main/?config=test_data%2Fvolvox%2Fconfig.json&session=spec-{"views":[{"type":"LinearSyntenyView","tracks":["volvox_fake_synteny"],"views":[{"loc":"ctgA:1-100","assembly":"volvox"},{"loc":"ctgA:300-400","assembly":"volvox"}]}]}
Expanded
{
"views": [
{
"type": "LinearSyntenyView",
"tracks": ["volvox_fake_synteny"],
"views": [
{ "loc": "ctgA:1-100", "assembly": "volvox" },
{ "loc": "ctgA:300-400", "assembly": "volvox" }
]
}
]
}
JSON sessions
Similar to encoded sessions, but more readable, JSON session let you specify the input a JSON snapshot of a session session. This is slightly different from a session spec, which has extra logic that loads the session. JSON sessions are literal session snapshots, like those that might come from the "Export session..." process
Example
&session=json-{"session":{"id":"xSHu7qGJN","name":"test","sessionPlugins":[{"url":"https://unpkg.com/jbrowse-plugin-msaview/dist/jbrowse-plugin-msaview.umd.production.min.js"}]}}
This loads a session with an extra plugin loaded
Encoded sessions
This is similar to JSON sessions but uses a URL encoding (base64+gzip)
Example
https://jbrowse.org/code/jb2/v1.5.9/?session=encoded-eJyNU2FzmkAQ_SvOfaaNIKDyLbFN0xlrTWRqnU4mc8ACm8BB7k6NdfjvXcCiZpq23-Dt2923u-_2DCPmsevHMn0ePT2umMEEz4GgGWx7C1AKC9EzzQv7wupbpkGfntX3HKt3-YW4OZcJCub1DRZJvgW5xEinzBuMbINtELaKeT_2bY98E0ym_PvdR8rTu7LuMUUBXH4CUeTwjdgUKeJYgZ6_MM-yLWtsGiwo5yBrwBkO3w9dx3b7I3fsuI5FTVGVGd9BdAcJCW27SYhn7QxDKqg0l7pRCIJkmM7YHIxcd2AQbwNSAYExzxQYjCsFeZDtDtlpYo5ZdU9qJQ-fTiZxxrPVYGrf-sdJroHrtQS_ZhIaFiLGZC25JlUUFmGAD0kcPzQ1O90nNQe72dU0eC716vV6rrjC8EObQLEUMElpINu0_tHn3R_yq_t6oBQjuAEegexmP0JfaSv16bpQM_4CMgh1If1WWooguQxTDHnGDpQpDyCjkVhBFTJeliiS-gBpsZ2A0CBrPV3VBt7pIuAiUgvQumZ7Wq6hVrjFKAFNxfZnrfxTKXWw2d3bjG6VN29Rlk2j5mQZaW7ssK8MFmNGin14oVUz1pr5zMQVkXiocQPL_9L6l1jVHFLQD13xsyDHihBqb9AiVPsE_d8WPEKTLuUcv2xdjK8qzLM1PdUDlqPAHH-eeL99vvNC4cFKsrFZ9QuCGmjL
Note that the "Share" button has a gear icon that let's you select "Long URL" that produces these URLs. The encoded share links can be used without the central session sharing system in place, as the entire session is encoded in the URL.
Command line tools
This document covers the CLI tools. Note: for @jbrowse/img static export tool, see https://www.npmjs.com/package/@jbrowse/img
Installation
The command line tools can be installed globally using npm
as follows
$ npm install -g @jbrowse/cli
A CLI tool called jbrowse
should then be available in the path. You can test
your installation with
$ jbrowse --version
It is also possible to do one-off executions using npx, e.g.
npx @jbrowse/cli create myfolder
It is likely preferable in most cases to install the tools globally with npm install @jbrowse/cli -g
however
Commands
jbrowse add-assembly SEQUENCE
jbrowse add-connection CONNECTIONURLORPATH
jbrowse add-track TRACK
jbrowse add-track-json TRACK
jbrowse admin-server
jbrowse create LOCALPATH
jbrowse help [COMMAND]
jbrowse set-default-session
jbrowse text-index
jbrowse upgrade [LOCALPATH]
jbrowse add-assembly SEQUENCE
Add an assembly to a JBrowse 2 configuration
USAGE
$ jbrowse add-assembly SEQUENCE
ARGUMENTS
SEQUENCE
sequence file or URL
If TYPE is indexedFasta or bgzipFasta, the index file defaults to <location>.fai
and can be optionally specified with --faiLocation
If TYPE is bgzipFasta, the gzip index file defaults to <location>.gzi and can be
optionally specified with --gziLocation
OPTIONS
-a, --alias=alias
An alias for the assembly name (e.g. "hg38" if the name of the assembly is "GRCh38");
can be specified multiple times
-f, --force
Equivalent to `--skipCheck --overwrite`
-h, --help
show CLI help
-l, --load=copy|symlink|move|inPlace
Required flag when using a local file. Choose how to manage the data directory. Copy, symlink, or move the data
directory to the JBrowse directory. Or use inPlace to modify the config without doing any file operations
-n, --name=name
Name of the assembly; if not specified, will be guessed using the sequence file name
-t, --type=indexedFasta|bgzipFasta|twoBit|chromSizes|custom
type of sequence, by default inferred from sequence file
indexedFasta An index FASTA (e.g. .fa or .fasta) file;
can optionally specify --faiLocation
bgzipFasta A block-gzipped and indexed FASTA (e.g. .fa.gz or .fasta.gz) file;
can optionally specify --faiLocation and/or --gziLocation
twoBit A twoBit (e.g. .2bit) file
chromSizes A chromosome sizes (e.g. .chrom.sizes) file
custom Either a JSON file location or inline JSON that defines a custom
sequence adapter; must provide --name if using inline JSON
--displayName=displayName
The display name to specify for the assembly, e.g. "Homo sapiens (hg38)" while the name can be a shorter identifier
like "hg38"
--faiLocation=faiLocation
[default: <fastaLocation>.fai] FASTA index file or URL
--gziLocation=gziLocation
[default: <fastaLocation>.gzi] FASTA gzip index file or URL
--out=out
synonym for target
--overwrite
Overwrite existing assembly if one with the same name exists
--refNameAliases=refNameAliases
Reference sequence name aliases file or URL; assumed to be a tab-separated aliases
file unless --refNameAliasesType is specified
--refNameAliasesType=aliases|custom
Type of aliases defined by --refNameAliases; if "custom", --refNameAliases is either
a JSON file location or inline JSON that defines a custom sequence adapter
--refNameColors=refNameColors
A comma-separated list of color strings for the reference sequence names; will cycle
through colors if there are fewer colors than sequences
--skipCheck
Don't check whether or not the sequence file or URL exists or if you are in a JBrowse directory
--target=target
path to config file in JB2 installation directory to write out to.
Creates ./config.json if nonexistent
EXAMPLES
# add assembly to installation in current directory. assumes .fai file also exists, and copies GRCh38.fa and
GRCh38.fa.fai to current directory
$ jbrowse add-assembly GRCh38.fa --load copy
# add assembly to a specific jb2 installation path using --out, and copies the .fa and .fa.fai file to /path/to/jb2
$ jbrowse add-assembly GRCh38.fa --out /path/to/jb2/ --load copy
# force indexedFasta for add-assembly without relying on file extension
$ jbrowse add-assembly GRCh38.xyz --type indexedFasta --load copy
# add displayName for an assembly
$ jbrowse add-assembly myFile.fa.gz --name hg38 --displayName "Homo sapiens (hg38)"
# use chrom.sizes file for assembly instead of a fasta file
$ jbrowse add-assembly GRCh38.chrom.sizes --load inPlace
# add assembly from preconfigured json file, expert option
$ jbrowse add-assembly GRCh38.config.json --load copy
# add assembly from a 2bit file, also note pointing direct to a URL so no --load flag needed
$ jbrowse add-assembly https://example.com/data/sample.2bit
# add a bgzip indexed fasta inferred by fa.gz extension. assumes .fa.gz.gzi and .fa.gz.fai files also exists
$ jbrowse add-assembly myfile.fa.gz --load copy
See code: src/commands/add-assembly.ts
jbrowse add-connection CONNECTIONURLORPATH
Add a connection to a JBrowse 2 configuration
USAGE
$ jbrowse add-connection CONNECTIONURLORPATH
ARGUMENTS
CONNECTIONURLORPATH URL of data directory
For hub file, usually called hub.txt
For JBrowse 1, location of JB1 data directory similar to http://mysite.com/jbrowse/data/
OPTIONS
-a, --assemblyName=assemblyName Assembly name of the connection If none, will default to the assembly in your config
file
-c, --config=config Any extra config settings to add to connection in JSON object format, such as
'{"uri":"url":"https://sample.com"}, "locationType": "UriLocation"}'
-f, --force Equivalent to `--skipCheck --overwrite`
-h, --help show CLI help
-n, --name=name Name of the connection. Defaults to connectionId if not provided
-t, --type=type type of connection, ex. JBrowse1Connection, UCSCTrackHubConnection, custom
--connectionId=connectionId Id for the connection that must be unique to JBrowse. Defaults to
'connectionType-assemblyName-currentTime'
--out=out synonym for target
--overwrite Overwrites any existing connections if same connection id
--skipCheck Don't check whether or not the data directory URL exists or if you are in a JBrowse
directory
--target=target path to config file in JB2 installation directory to write out to.
EXAMPLES
$ jbrowse add-connection http://mysite.com/jbrowse/data/
$ jbrowse add-connection http://mysite.com/jbrowse/custom_data_folder/ --type JBrowse1Connection
$ jbrowse add-connection http://mysite.com/path/to/hub.txt --assemblyName hg19
$ jbrowse add-connection http://mysite.com/path/to/custom_hub_name.txt --type UCSCTrackHubConnection --assemblyName
hg19
$ jbrowse add-connection http://mysite.com/path/to/custom --type custom --config
'{"uri":{"url":"https://mysite.com/path/to/custom"}, "locationType": "UriLocation"}' --assemblyName hg19
$ jbrowse add-connection https://mysite.com/path/to/hub.txt --connectionId newId --name newName --target
/path/to/jb2/installation/config.json
See code: src/commands/add-connection.ts
jbrowse add-track TRACK
Add a track to a JBrowse 2 configuration
USAGE
$ jbrowse add-track TRACK
ARGUMENTS
TRACK Track file or URL
OPTIONS
-a, --assemblyNames=assemblyNames Assembly name or names for track as comma separated string. If none, will
default to the assembly in your config file
-d, --description=description Optional description of the track
-f, --force Equivalent to `--skipCheck --overwrite`
-h, --help show CLI help
-l, --load=copy|symlink|move|inPlace Required flag when using a local file. Choose how to manage the track. Copy,
symlink, or move the track to the JBrowse directory. Or inPlace to leave track
alone
-n, --name=name Name of the track. Will be defaulted to the trackId if none specified
-t, --trackType=trackType Type of track, by default inferred from track file
--category=category Optional Comma separated string of categories to group tracks
--config=config Any extra config settings to add to a track. i.e '{"defaultRendering":
"density"}'
--indexFile=indexFile Optional index file for the track
--out=out synonym for target
--overwrite Overwrites existing track if it shares the same trackId
--protocol=protocol [default: uri] Force protocol to a specific value
--skipCheck Skip check for whether or not the file or URL exists or if you are in a JBrowse
directory
--subDir=subDir when using --load a file, output to a subdirectory of the target dir
--target=target path to config file in JB2 installation to write out to.
--trackId=trackId trackId for the track, by default inferred from filename, must be unique
throughout config
EXAMPLES
# copy /path/to/my.bam and /path/to/my.bam.bai to current directory and adds track to config.json
$ jbrowse add-track /path/to/my.bam --load copy
# copy my.bam and my.bam.bai to /path/to/jb2/bam and adds track entry to /path/to/jb2/bam/config.json
$ jbrowse add-track my.bam --load copy --out /path/to/jb2 --subDir bam
# same as above, but specify path to bai file. needed for if the bai file does not have the extension .bam.bai
$ jbrowse add-track my.bam --indexFile my.bai --load copy
# creates symlink for /path/to/my.bam and adds track to config.json
$ jbrowse add-track /path/to/my.bam --load symlink
# add track from URL to config.json, no --load flag needed
$ jbrowse add-track https://mywebsite.com/my.bam
# --load inPlace adds a track without doing file operations
$ jbrowse add-track /url/relative/path.bam --load inPlace
See code: src/commands/add-track.ts
jbrowse add-track-json TRACK
Add a track configuration directly from a JSON hunk to the JBrowse 2 configuration
USAGE
$ jbrowse add-track-json TRACK
ARGUMENTS
TRACK track JSON file or command line arg blob
OPTIONS
-u, --update update the contents of an existing track, matched based on trackId
--out=out synonym for target
--target=target path to config file in JB2 installation directory to write out to.
Creates ./config.json if nonexistent
EXAMPLES
$ jbrowse add-track-json track.json
$ jbrowse add-track-json track.json --update
See code: src/commands/add-track-json.ts
jbrowse admin-server
Start up a small admin server for JBrowse configuration
USAGE
$ jbrowse admin-server
OPTIONS
-h, --help show CLI help
-p, --port=port Specifified port to start the server on;
Default is 9090.
--bodySizeLimit=bodySizeLimit [default: 25mb] Size limit of the update message; may need to increase if config is
large.
Argument is passed to bytes library for parsing: https://www.npmjs.com/package/bytes.
--root=root path to the root of the JB2 installation.
Creates ./config.json if nonexistent. note that you can navigate to
?config=path/to/subconfig.json in the web browser and it will write to
rootDir/path/to/subconfig.json
EXAMPLES
$ jbrowse admin-server
$ jbrowse admin-server -p 8888
See code: src/commands/admin-server.ts
jbrowse create LOCALPATH
Downloads and installs the latest JBrowse 2 release
USAGE
$ jbrowse create LOCALPATH
ARGUMENTS
LOCALPATH Location where JBrowse 2 will be installed
OPTIONS
-f, --force Overwrites existing JBrowse 2 installation if present in path
-h, --help show CLI help
-l, --listVersions Lists out all versions of JBrowse 2
-t, --tag=tag Version of JBrowse 2 to install. Format is v1.0.0.
Defaults to latest
-u, --url=url A direct URL to a JBrowse 2 release
--branch=branch Download a development build from a named git branch
--nightly Download the latest development build from the main branch
EXAMPLES
# Download latest release from github, and put in specific path
$ jbrowse create /path/to/new/installation
# Download latest release from github and force overwrite existing contents at path
$ jbrowse create /path/to/new/installation --force
# Download latest release from a specific URL
$ jbrowse create /path/to/new/installation --url url.com/directjbrowselink.zip
# Download a specific tag from github
$ jbrowse create /path/to/new/installation --tag v1.0.0
# List available versions
$ jbrowse create --listVersions
See code: src/commands/create.ts
jbrowse help [COMMAND]
display help for jbrowse
USAGE
$ jbrowse help [COMMAND]
ARGUMENTS
COMMAND command to show help for
OPTIONS
--all see all commands in CLI
See code: @oclif/plugin-help
jbrowse set-default-session
Set a default session with views and tracks
USAGE
$ jbrowse set-default-session
OPTIONS
-c, --currentSession List out the current default session
-h, --help show CLI help
-n, --name=name [default: New Default Session] Give a name for the default session
-s, --session=session set path to a file containing session in json format
-t, --tracks=tracks Track id or track ids as comma separated string to put into default session
-v, --view=view View type in config to be added as default session, i.e LinearGenomeView, CircularView,
DotplotView.
Must be provided if no default session file provided
--delete Delete any existing default session.
--out=out synonym for target
--target=target path to config file in JB2 installation directory to write out to
--viewId=viewId Identifier for the view. Will be generated on default
EXAMPLES
$ jbrowse set-default-session --session /path/to/default/session.json
$ jbrowse set-default-session --target /path/to/jb2/installation/config.json --view LinearGenomeView --tracks track1,
track2, track3
$ jbrowse set-default-session --view LinearGenomeView, --name newName --viewId view-no-tracks
$ jbrowse set-default-session --currentSession # Prints out current default session
See code: src/commands/set-default-session.ts
jbrowse text-index
Make a text-indexing file for any given track(s).
USAGE
$ jbrowse text-index
OPTIONS
-a, --assemblies=assemblies Specify the assembl(ies) to create an index for. If unspecified, creates an index for
each assembly in the config
-h, --help show CLI help
-q, --quiet Hide the progress bars
--attributes=attributes [default: Name,ID] Comma separated list of attributes to index
--dryrun Just print out tracks that will be indexed by the process, without doing any indexing
--exclude=exclude [default: CDS,exon] Adds gene type to list of excluded types
--file=file File or files to index (can be used to create trix indexes for embedded component use
cases not using a config.json for example)
--fileId=fileId Set the trackId used for the indexes generated with the --file argument
--force Overwrite previously existing indexes
--out=out Synonym for target
--perTrack If set, creates an index per track
--prefixSize=prefixSize [default: 6] Specify the prefix size for the ixx index, increase size if many of your
gene IDs have same prefix e.g. Z000000001, Z000000002
--target=target Path to config file in JB2 installation directory to read from.
--tracks=tracks Specific tracks to index, formatted as comma separated trackIds. If unspecified, indexes
all available tracks
EXAMPLES
# indexes all tracks that it can find in the current directory's config.json
$ jbrowse text-index
# indexes specific trackIds that it can find in the current directory's config.json
$ jbrowse text-index --tracks=track1,track2,track3
# indexes all tracks in a directory's config.json or in a specific config file
$ jbrowse text-index --out /path/to/jb2/
# indexes only a specific assembly, and overwrite what was previously there using force (which is needed if a previous
index already existed)
$ jbrowse text-index -a hg19 --force
# create index for some files for use in @jbrowse/react-linear-genome-view or similar
$ jbrowse text-index --file myfile.gff3.gz --file myfile.vcfgz --out indexes
See code: src/commands/text-index.ts
jbrowse upgrade [LOCALPATH]
Upgrades JBrowse 2 to latest version
USAGE
$ jbrowse upgrade [LOCALPATH]
ARGUMENTS
LOCALPATH [default: .] Location where JBrowse 2 is installed
OPTIONS
-h, --help show CLI help
-l, --listVersions Lists out all versions of JBrowse 2
-t, --tag=tag Version of JBrowse 2 to install. Format is v1.0.0.
Defaults to latest
-u, --url=url A direct URL to a JBrowse 2 release
--branch=branch Download a development build from a named git branch
--clean Removes old js,map,and LICENSE files in the installation
--nightly Download the latest development build from the main branch
EXAMPLES
# Upgrades current directory to latest jbrowse release
$ jbrowse upgrade
# Upgrade jbrowse instance at a specific filesystem path
$ jbrowse upgrade /path/to/jbrowse2/installation
# Upgrade to a specific tag
$ jbrowse upgrade /path/to/jbrowse2/installation --tag v1.0.0
# List versions available on github
$ jbrowse upgrade --listVersions
# Upgrade from a specific URL
$ jbrowse upgrade --url https://sample.com/jbrowse2.zip
# Get nightly release from main branch
$ jbrowse upgrade --nightly
See code: src/commands/upgrade.ts
Debugging
Debug logs (provided by debug) can be
printed by setting the DEBUG
environment variable. Setting DEBUG=*
will
print all debug logs. Setting DEBUG=jbrowse*
will print only logs from this
tool, and setting e.g. DEBUG=jbrowse:add-assembly
will print only logs from
the add-assembly
command.
FAQ
Developers
How can I start the JBrowse 2 app as a developer
We recommend that you have the following
- Node v12+
- Git
- Yarn
Then you can follow steps from our README
It basically boils down to
git clone https://github.com/GMOD/jbrowse-components
cd jbrowse-components
yarn
cd products/jbrowse-web
yarn start
This will boot up a development instance of jbrowse-web
on port 3000
You can use PORT=8080 yarn start
to manually specify a different port
You can also instead go to the products/jbrowse-desktop
directory to do this
on desktop
For the embedded components e.g. products/jbrowse-react-linear-genome-view
,
use yarn storybook
instead of yarn start
General
What is special about JBrowse 2
One thing that makes JBrowse 2 special is that we can create new view types via our plugin system, e.g. circular, dotplot, etc. Anything you want can be added as a view, and can be shown alongside our other views
This makes JBrowse 2 more than just a genome browser-- it is really a platform that can be built on.
What are new features in JBrowse 2
See the https://jbrowse.org/jb2/features page for an overview of features
Setup
What web server do I need to run JBrowse 2
JBrowse 2 by itself is just a set of JS, CSS, and HTML files that can be statically hosted on a webserver without any backend services running.
Therefore, running JBrowse 2 generally involves just copying the JBrowse 2
folder to your web server html folder e.g. /var/www/html/
.
If you use a different platform such as Django, you may want to put it in the static resources folder.
Note that the server that you use should support byte-range requests (e.g. the Range HTTP header so that JBrowse can get small slices of large binary data files.
BAM files do not work on my server
If you are using Apache then you will probably want to disable mime_magic. If mime_magic is enabled, you may see that your server responds with the HTTP header Content-Encoding: gzip which JBrowse does NOT want, because this instructs the browser to unzip the data but JBrowse should be in charge of this.
How can I setup JBrowse 2 on my web server
We recommend following the steps in the quickstart web guide.
The general procedure is using the jbrowse create /var/www/html/jb2
and this
will download the latest version of jbrowse to your web folder e.g. in
/var/www/html
You can also use jbrowse upgrade /var/www/html/jb2
to get the latest version
How do I install or update the @jbrowse/cli tool
To install the @jbrowse/cli tool, you can use npm install -g @jbrowse/cli
You can use this same command to upgrade the tool too
This command will give you a command named jbrowse
which should automatically
be in your path if you have a standard installation of nodejs. We recommend
using nodesource or nvm to get your nodejs for this.
Also note that the @jbrowse/cli tool is just made for preparing your config.json, it is not used to run any server-side code
How do I update my instance of jbrowse-web
You can use the command, after installing
jbrowse upgrade /path/to/your/jbrowse2
This will download the latest release from github and overwrite it onto your jbrowse-web instance
How can I setup JBrowse 2 without the CLI tools
The jbrowse CLI tools are basically a convenience, and are not strictly required
Simple tasks can be done without it
For example, for jbrowse create, you can visit the blog and download the latest jbrowse-web release tag, and unzip it into your web directory
For other things, like add-assembly and add-track, you can manually edit the config.json, reviewing the config docs and sample configs will be valuable
Understanding the config basics will come in handy also because you can manually edit in advanced configs after your tracks are loaded however be careful because corrupt configs can produce hard to understand errors, because our config system is strongly typed
Feel free to message the team if you encounter these
How do I load a track into JBrowse 2
If you have followed the above steps and installed jbrowse 2 on your webserver and loaded the assembly, and have the CLI tools installed
jbrowse add-track myfile.bw -a hg19
This will setup a bigwig track on the hg19 assembly in your config.json. Make sure to run the command inside your current jbrowse2 folder e.g. /var/www/html/jbrowse2 or wherever you are currently setting up a config.json (you can have multiple configs)
Note that you can also use remote URLs
jbrowse add-track http://yourremote/myfile.bam
The add-track command will do as much as possible to infer from the file extension how to configure this track, and automatically infer the index to be myfile.bam.bai
Curiosities
Why do all the tracks need an assembly specified
We require that all tracks have a specific genome assembly specified in their config. This is because jbrowse 2 is a multi-genome-assembly browser (and can compare genomes given the data). This may be different to using say jbrowse 1 where it knows which genome assembly you are working with at any given time
How are the menus structured in the app
In JBrowse 1, the app level menu operated on the single linear genome view, but with JBrowse 2, the top level menu only performs global operations and the linear genome view has it's own hamburger menu. Note that each track also has it's own track level menu.
Why do some of my reads not display soft clipping
Some reads, such as secondary reads, do not have a SEQ field on their records, so they will not display softclipping.
The soft clipping indicators on these reads will appear black.
Do you have any tips for learning React and mobx-state-tree
Here is a short guide to React and mobx-state-tree that could help get you oriented
https://gist.github.com/cmdcolin/94d1cbc285e6319cc3af4b9a8556f03f
What technologies does JBrowse 2 use
We build on a lot of great open source technology, some main ones include
- React
- mobx-state-tree
- web-workers
- Typescript
- Electron (for desktop specifically)
Should I configure gzip on my web server
Yes! JBrowse 2 may load ~5MB of JS resources (2.5MB for main thread bundle, 2.5MB for worker bundle). If you have gzip enabled, the amount of data the user has to download though is only 1.4MB. We have worked on making bundle size small with lazy loading and other methods but adding gzip will help your users.
It will depend on your particular server setup e.g. apache, nginx, cloudfront, etc. how this may be done, but it is recommended to look into this.
How does JBrowse know when to display the "Zoom in to see more features" message
The rules that JBrowse uses to determine when to display the "Zoom in to see more features" message are called stats estimation rules
The general outline is:
- It doesn't display a zoom in message if zoomed in closer than 20kb
- It performs byte size estimation for BAM and CRAM type files (you will see a byte size estimation displayed alongside the "Zoom in to see features" message
- Other data types that don't use byte size estimation use feature density based calculation
- Hi-C, BigWig, and sequence adapters are hardcoded to return
{ featureDensity:0 }
to always render
If you need to customize your particular track, you can set config variables on the "display" section of your config
maxFeatureScreenDensity
- number of features times bpPerPxfetchSizeLimit
- this config variable exists on the adapters (can increase size limit)
Example config with a small feature screen density
{
"type": "VariantTrack",
"trackId": "variant_density",
"name": "test variants (small featuredensity limit)",
"assemblyNames": ["volvox"],
"adapter": {
"type": "VcfTabixAdapter",
"vcfGzLocation": {
"uri": "volvox.filtered.vcf.gz"
},
"index": {
"location": {
"uri": "volvox.filtered.vcf.gz.tbi"
}
}
},
"displays": [
{
"type": "LinearVariantDisplay",
"maxFeatureScreenDensity": 0.0006,
"displayId": "volvox_filtered_vcf_color-LinearVariantDisplay"
}
]
}
Example config for a CRAM file with a small fetchSizeLimit configured
{
"type": "AlignmentsTrack",
"trackId": "volvox_cram",
"name": "test track (small fetch size limit)",
"assemblyNames": ["volvox"],
"adapter": {
"type": "CramAdapter",
"cramLocation": {
"uri": "volvox-sorted-altname.cram"
},
"craiLocation": {
"uri": "volvox-sorted-altname.cram.crai"
},
"sequenceAdapter": {
"type": "TwoBitAdapter",
"twoBitLocation": {
"uri": "volvox.2bit"
}
},
"fetchSizeLimit": 1000
}
}
Text searching
Why I am running out of disk space while trix is running
The jbrowse text-index
program will output data to a TMP directory while
indexing. If your filesystem has low diskspace for /tmp you can set an
alternative temporary directory using the environment variable
TMPDIR=~/alt_tmp_dir/ jbrowse text-index
.
How does the jbrowse text-index trix format work
The jbrowse text-index
command creates text searching indexes using trix. The
trix indexes are based on the format described by UCSC here
https://genome.ucsc.edu/goldenPath/help/trix.html but we reimplemented the code
the create these index formats in the JBrowse CLI so you do not have to install
the UCSC tools.
The main idea is that you give trix
GENEID001 Wnt signalling
GENEID002 ey Pax6
Then this will generate a new file, the .ix file, sorted in alphabetical order
ey GENE002
signalling GENE001
Pax6 GENE002
Wnt GENE001
Then a second file, the .ixx file, tells us at what byte offset certain lines in the file are e.g.
signa000000435
Note that JBrowse creates a specialized trix index also. Instead of creating a ix file with just the gene names, it also provides their name and location in an encoded format.
URL params
Why can't I copy and paste my URL bar to share it with another user
In JBrowse Web, the current session can become too long to store in the URL bar, so instead, we store it in localStorage and only keep the key to the localStorage entry in the URL var. This is because otherwise URLs can get prohibitively long, and break server side navigations, intermediate caches, etc. Therefore, we make "sharing a session" a manual step that generates a shortened URL by default
Note 1: user's of @jbrowse/react-linear-genome-view have to re-implement any URL query param logic themselves, as this component makes no attempt to access URL query params
Note 2: You can copy and paste your URL bar and put it in another tab on your own computer, and JBrowse will restore the session using BroadcastChannel (supported on Firefox and Chrome)
How does the session sharing work with shortened URLs work in JBrowse Web
We have a central database hosted as a AWS dynamoDB that stores encrypted session snapshots that users create when they use the "Share" button. The "Share" button creates a random key on the client side (which becomes the &password= component of the share URL), encrypts the session client side, and sends the encrypted session without the key to the AWS dynamoDB.
This process, generates a URL with the format
&session=share-<DYNAMODBID>&password=<DECODEKEY>
The DECODEKEY is never transmitted to the server, but you can copy and paste the share URL, the person you shared automatically downloads the DynamoDB entry, and decodes it with the DECODEKEY from the URL that you provide
With this system, the contents of the dynamoDB are safe and unable to be read, even by JBrowse administrators.
Troubleshooting
Doing things like:
- Changing trackIds
- Deleting tracks
Can make user's saved sessions fail to load. If part of a session is inconsistent, currently, the entire session will fail to load. Therefore, make decisions to delete or change IDs carefully.
What should I do if the Share system isn't working?
If for any reason the session sharing system isn't working, e.g. you are behind a firewall or you are not able to connect to the central share server, you can click the "Gear" icon in the "Share" button pop-up, and it will give you the option to use "Long URL" instead of "Short URL" which let's you create share links without the central server
Also, if you are implementing JBrowse Web on your own server and would like to create your own URL shortener, you can use the shareURL parameter in the config.json file to point at your own server instead of ours.
- This means it's only possible to have one version of a particular plugin loaded on any given webpage, even if multiple products are loaded and using it on the same page.↩