Unofficial fork: this is an unofficial, unapproved fork of the original NUKnightLab/StoryMapJS repository and a proof of concept for an AI-based renovation using the model GLM 5.3 Flash. It is not endorsed by Northwestern University Knight Lab.
StoryMapJS tells stories on the web that highlight the locations of a series of events. This is a TypeScript rewrite of the original Knight Lab viewer: it renders storymap JSON (and IIIF manifests) on modern web maps — the authoring tool is not part of this repository.
There are a couple ways you can use a StoryMap.
-
Maps
Add a slide for each place in your story. The viewer draws cartography from OpenStreetMap or custom tile servers, and renders the route between your places.
-
Really big images
You can tell stories with large photographs, works of art, historic maps and other image files. Because it works best with pixel-dense files served over the IIIF Image API.
Tips & tricks
- Keep it short. We recommend not having more than 20 slides for a reader to click through.
- Pick stories that have a strong location narrative. It does not work well for stories that need to jump around in the map.
- Write each event as a part of a larger narrative.
- Include events that build up to major occurrences — not just the major events.
Media sources
The viewer can pull in media from a variety of sources: Twitter/X, Flickr, YouTube, Vimeo, Dailymotion, Wikipedia, SoundCloud, Facebook, DocumentCloud, Juxtapose, Google Docs, images, audio, video, quotes and more.
Examples
Help
Need help? Start with the frequently asked questions below, then check the README and the migration guide.
If you don't find an answer there, open a GitHub issue. Please be clear with your question, include the storymap JSON you are loading and, if appropriate, a link to a page which shows the issue.
Find a bug? If you are confident you have found a bug, please report it as a GitHub issue. Be sure to include detailed instructions on how to reproduce it. Upstream bugs go to NUKnightLab/StoryMapJS.
Technical documentation
Go further with StoryMap:
Frequently asked questions
-
How do I install the viewer?
npm install @projektemacher/storymapjs, then import the module and the stylesheet:import { StoryMap } from "@projektemacher/storymapjs"; import "@projektemacher/storymapjs/css/storymap.css"; new StoryMap("mapdiv", "my-storymap.json"); -
How do I embed a published storymap?
Use the embed page in an iframe; the
urlparameter is resolved against the site root:<iframe src="/embed/index.html?url=my-storymap.json" width="100%" height="800"></iframe> -
How can I link to a specific slide?
The viewer keeps the current slide in the URL as a
#slide-Nhash. Open a storymap at…#slide-5to start there, or use thestart_at_slideoption (also available as an embed URL parameter). Copy the URL at any time — it always points at the slide you are viewing. -
Can the storymap play automatically?
Set the
autoplayoption to the number of milliseconds each slide stays on screen (also available as an embed URL parameter):/embed/index.html?url=my-storymap.json&autoplay=5000Playback stops at the last slide, and any click, tap or keypress hands control back to the viewer.
-
How can I have a map without lines between points?
Setshow_lines: falsein the storymap options (or usemap_as_imagefor IIIF image stories, where lines are off by default). -
How can I use a custom map?
Set
map_typeto a tile URL template (e.g."https://tile.example.org/{z}/{x}/{y}.png") or pass raw OpenLayers options viamap_options— view, controls and interactions are all configurable. -
How can I adjust the zoom?
The viewer fits the map to all markers and zooms between places as the reader navigates (
calculate_zoom). Withcalculate_zoom: true(the default) the calculated zoom overrides per-slidelocation.zoomvalues; setcalculate_zoom: falseto use your ownlocation.zoomper slide.map_options.viewaccepts raw OpenLayers view options. -
Can I change the fonts?
Yes — ship a font theme with your storymap (
font_cssin the data, relative to the script) or reference a stock theme withfont_css: "stock:knightlab". The compiled stock themes are resolved from the library'scss/fonts/directory (next to the bundled JS). -
Can I use custom HTML in a slide?
Yes — the slide
textrenders as HTML: links, images, lists andvco-notespans all work. Text without a<p>tag is wrapped in one automatically. The markup is sanitized first: formatting survives, scripts and event handlers are dropped, URLs are checked to be web URLs, and pasted<iframe>embeds are rebuilt sandboxed. Still, only load storymaps from sources you trust. -
Can I limit the map to an area?
Setmap_bbox: [west, south, east, north](lon/lat) in the options — the view center is constrained to the box, so the map cannot pan away from it. For IIIF image stories the coordinates are raw image pixels. To also limit the map to the left, visible area (opaque slide panel, no gradient over the map), setmap_area: "left". -
Does the viewer load external services by default?
Yes, but set
consent_required: trueto ask for permission before anything is loaded from external services (media embeds, map tiles, external fonts). One dialog lists every service the story uses and offers allow all, decline all or a decision per service; services discovered later still ask on their slide. Denied services show a placeholder instead. Decisions are stored in your browser's local storage — clearing site data asks again.