A Jekyll static site for BSidesNYC. Hosted on GitHub Pages. This site has been modernized to use Bootstrap 5.3.3 and native browser APIs, significantly reducing legacy dependencies like jQuery.
_config.yml ← single source of truth for event config (dates, venue, top nav)
_data/ ← YAML content files (speakers, sponsors, sessions, villages, archive/YYYY)
_includes/ ← reusable HTML partials
_layouts/ ← default.html (master layout) + compress.html (HTML minifier)
_sass/ ← modular SCSS
js/ ← custom JS (ES6+ standardized)
Pages are simple HTML files with YAML front matter (layout: default, permalink: /foo/).
Key sections:
year, date, location: Current conference metadata.navigationLinks: Top-nav items.sessionize.*: API endpoint URLs for schedule and speaker data._layouts/default.htmlMaster layout. Modernized features:
lib/bootstrap-5.3.3/ (byte-identical to the jsDelivr files). The JS loads async: it’s only needed once someone taps.fonts/roboto/ (@font-face in _sass/partials/_fonts.scss, font-display: swap). Deliberately not preloaded, so it doesn’t compete with the CSS on a thin connection.defer.Entry point: css/main.scss pulls from _sass/main.scss.
_sass/partials/_base.scss using CSS variables (--bs-primary).transform: scale() for card zooms.waves.js ripple with modern CSS :active feedback.<symbol> library in _includes/svg-icons.html for zero-request icon and logo loading.Dynamic pages fetch data via the Sessionize API using fetch(). The codebase uses ES6+ syntax (const, let, arrow functions, .forEach(), .find()).
| File | Responsibility |
|---|---|
js/scripts.js | Global behaviors: Sticky header (native scroll listener), IntersectionObserver for animations. |
js/schedule.js | Builds the schedule table and session modals. loadSchedule() uses the download the layout starts in <head> (window.earlyFetch), retries with fetchJson(), keeps the last good copy in localStorage and falls back to it with a note. On the event day it marks the slot that’s on now and scrolls to it (test with ?now=2026-10-17T13:20). |
js/speakers.js | Builds the speaker grid. Cards “fill in” individually as images load. |
js/utils.js | Centralized Utilities: Contains createBootstrapModal, addSessionContentToModal, and addSpeakerContentToModal to ensure UI consistency. |
js/archive.js | Video modal logic and URL parsing for the Archive page. Utilizes Plyr.js for unified playback. |
js/map.js | Google Maps initialization and configuration. |
.mp4 links from archive.org and handle YouTube embeds with a consistent UI.position: sticky instead of JavaScript plugins.Update conference date/venue: Edit _config.yml.
Add a sponsor: Add entry to _data/sponsors.yml under the correct tier. Update image in img/sponsors/.
Add a partner: Add an entry to _data/partners.yml (shown under the sponsor tiers on /sponsors/). imageUrl (in img/sponsors/) is optional; without it the card shows the name as text.
Add a new archive year:
_data/archive/YYYY.yml.archive.html and add ``.
Update track→room mapping: Edit trackToRoomElements() in js/utils.js.
Section background photos: Use background-image: url('/img/sections-background/'); for the inline style. If img/sections-background/<name>-sm.webp exists (828px wide, ~quality 60), phones get it instead. A page can drop its hero photo on phones with mobileHero: false in its front matter (the schedule does).
Update venue maps: The stacked all-floors overview on /map/ is drawn from _data/venue_overview.yml (rough west→east positions, not to scale). Each floor’s clean plan is an SVG fragment in _includes/floorplans/, listed under venueFloorMaps in _config.yml (svg, plus image for the original architectural plan in img/venue/); _includes/floorplan-svg.html wraps a fragment in the shared frame.
Printable venue map: img/venue-map-print.svg (plus -level-1 and -hound-square “YOU ARE HERE” versions) is built by Jekyll from the same _data/venue_overview.yml as the website’s map, 2:1 like the 2025 signs. Drawn by _includes/venue-map-print.svg; each sign version is a three-line page in img/ naming the floor, the spot the sign stands at and which side the label goes. Its colours mirror the SCSS ones, so keep them in step.
Room-map popup: Room names in the schedule and session popups open showRoomMap() (js/utils.js), which clones that floor from the <template>s in _includes/floorplan-templates.html (included on /schedule/ and /speakers/) and highlights the room. A track’s room in trackToRoomElements() must match a data-room attribute in the floor SVG; its directions text is shown above the plan.
Offline support (service worker): sw.js (Jekyll-built) caches the event-day pages, their CSS/JS/font and the Sessionize data so phones keep working with bad or no signal. Switch and notes: “Offline support” in _config.yml.
cache: "no-cache"), falling back to the saved copy only after a few seconds without an answer. Sessionize edits need no action; an open schedule page also re-checks every 10 minutes and when brought back to the front (recheckSchedule() in js/schedule.js).bsidesnyc-<build time>); old ones are deleted. Local CSS/JS URLs carry ?v=<build time> (assetVersion in the layout), so a page never runs with an older cached script. When adding a local CSS/JS tag, append assetVersion the same way.X-Saved-At header; the schedule shows “the copy saved on your phone at …” when it gets one.serviceWorker.enabled: false makes sw.js remove itself and its caches, and the layout unregisters it.Inline <script>s in layouts/includes: _layouts/compress.html minifies HTML onto one line, so use /* */ comments in inline scripts - a // comment swallows the rest of the script.
bundle install
bundle exec jekyll serve
GitHub Pages handles the production build automatically on push to master.