Website hackertours.hamburg.ccc.de https://hackertours.hamburg.ccc.de
  • HTML 56.3%
  • CSS 27%
  • JavaScript 13.2%
  • Shell 3.2%
  • Dockerfile 0.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Stefan Bethke aae9018000
All checks were successful
/ build (pull_request) Successful in 26s
Sync 40C3 Hackertours tours from Hackertours-Admin (all tours)
2026-10-17 01:03:18 +02:00
.forgejo/workflows Upgrade to Hugo 0.16x and zen theme v7.1.0 2026-10-16 15:07:25 +02:00
archetypes First try 2023-12-07 19:37:47 +01:00
assets dd vendored icons for the tour-map 2026-10-16 20:35:02 +02:00
content Sync 40C3 Hackertours tours from Hackertours-Admin (all tours) 2026-10-16 19:51:14 +02:00
data/schedule Sync 40C3 Hackertours tours from Hackertours-Admin (all tours) 2026-10-17 01:03:18 +02:00
i18n Add a generic tour-map shortcode and a data format to supply the necessary info 2026-10-16 20:21:21 +02:00
layouts dd vendored icons for the tour-map 2026-10-16 20:35:02 +02:00
static Körperfunk added, corrected languages 2025-12-25 09:57:12 +01:00
themes Upgrade to Hugo 0.16x and zen theme v7.1.0 2026-10-16 15:07:25 +02:00
.gitignore First try 2023-12-07 19:37:47 +01:00
.gitmodules First try 2023-12-07 19:37:47 +01:00
.hugo_build.lock First try 2023-12-07 19:37:47 +01:00
Dockerfile Update docker.io/nginx Docker tag to v1.29.1 2026-05-18 22:18:40 +00:00
hugo.yaml Prepare for 40C3 2026-10-16 15:17:27 +02:00
README.md dd vendored icons for the tour-map 2026-10-16 20:35:02 +02:00
renovate.json Add renovate.json 2024-07-30 18:46:18 +00:00

Hackertours Web Site

Complete the checkout

We need the submodule for the theme, so update/clone the submodules:

git submodule update --init --recursive

Run in dev mode

hugo server --buildFuture --buildDrafts

Then open http://localhost:1313

Shortcode: Language badge

Use the lang shortcode to mark whether a tour is in German, English or bilingual. It renders a small superscript badge next to the text, with details when hovered over or parsed by a screenreader.

  • German: {{< lang de >}}
  • English: {{< lang en >}}
  • Bilingual: {{< lang deen >}}

Shortcode: Tour schedule

The tour overview of an event (content/*/<event>/_index.md) shows the schedule with {{< schedule >}}. It reads data/schedule/<event>.yaml, which is shared by both languages:

days:
  - day: 1
    date: "2025-12-27"
    tours:
      - { time: "11:30", tour: xfel, lang: deen }
      - { time: "12:00", tour: city-walk, lang: de }
  • tour is the slug of the tour page in the event section. The card shows that page's title, without the event prefix, and links to it.
  • lang is de, en or deen, or a list of these. It renders the same badge as the lang shortcode.
  • time is HH:MM with a leading zero (09:30). Tours are sorted by time, so their order in the file doesn't matter.

Wide screens get one column per day on an hour grid, with tours that start at the same time side by side. The first column shows the hour wherever the first day has no tour in it. On narrow screens a day picker shows one day at a time, starting with today's day during the event.

For a different event than the page's section, pass its name: {{< schedule 39c3 >}}.

Without a data file, or without any tours in it, the shortcode renders nothing and the build logs a warning. To silence it, for example for an upcoming event, add warning-schedule-empty to ignoreLogs in hugo.yaml.

Shortcode: Tour map

{{< tour-map >}} on an event's overview page shows a map of the tour locations, with the routes from the Congress, on OpenStreetMap. For a different event than the page's section, pass its name: {{< tour-map 39c3 >}}. It uses Leaflet, which is kept in assets/vendor/leaflet/.

  • Each tour gets a marker in its colour, with its icon in white, and its route as a line; walking legs are dotted. Clicking a marker or a route shows the tour title, linked to the tour page, and the directions.
  • The map shows all tours at once. Scroll-wheel zoom only starts after clicking into the map, so the page still scrolls normally.
  • Without JavaScript, and for screen readers, it shows a list of the tours with their directions and a link to each location on openstreetmap.org.
  • If a text is missing in the page's language, the other language is used.
  • Without any tours with geo, the shortcode renders nothing and the build logs a warning with the ID warning-tour-map-empty.

Map data in the schedule file

A map of an event shows where each tour takes place and how to get there from the Congress. The data for it goes into the same file as the schedule, data/schedule/<event>.yaml, next to days. Like the schedule, it is shared by both languages; anything that people read comes with a de and an en version.

map:
  origin:                          # where all routes start, shown with its own marker
    name: { de: "Congress (CCH)", en: "Congress (CCH)" }
    geo: { lat: 53.561450, lon: 9.986360 }
    icon: computer

tours:
  miniatur-wunderland:             # tour slug, as in days[].tours[].tour
    geo: { lat: 53.543843, lon: 9.988765 }
    color: "#32cd32"
    icon: tram-stop
    directions:
      de: |
        - Ab S Dammtor mit dem Bus 4 Richtung Osakaallee.
        - Am Rathausmarkt in die U3 Richtung Schlump umsteigen.
        - An der U Baumwall aussteigen, über den Kanal, links am Kanal entlang bis zum Eingang.
      en: |
        - From S Dammtor take bus 4 towards Osakaallee.
        - At Rathausmarkt change to the U3 towards Schlump.
        - Exit at U Baumwall, cross the canal and walk left alongside it to the entrance.
    route:                         # from map.origin to geo, one entry per leg
      - { mode: walk, polyline: "…" }
      - { mode: bus, line: "4", polyline: "…" }
      - { mode: subway, line: "U3", polyline: "…" }
      - { mode: walk, polyline: "…" }

days:
  # … as described under "Shortcode: Tour schedule"

tours has one entry per tour slug that should appear on the map. A slug can be in tours without being scheduled, and the other way round; scheduled tours without an entry simply don't appear on the map.

Field Required Content
geo yes Meeting point or venue: lat and lon in decimal degrees (WGS 84), six decimals are plenty. Write it even though the tour page has the same value in params.geo; the map only reads this file.
color no Colour of the marker and the route, as a CSS colour ("#32cd32" or LimeGreen). Pick colours that differ between tours.
icon no Name of an icon for the marker, see "Map icons" below. Without it, or with an unknown name, the marker is a plain coloured circle; an unknown name also logs a build warning.
directions no How to get there from the origin, per language (de, en) as Markdown, usually a short list of steps.
route no The way from map.origin to geo as a list of legs in travel order. Without it the tour only gets a marker.

Each leg in route has:

  • mode: walk, bus, subway (U-Bahn), train (S-Bahn, regional train), ferry or other. The map can draw walking legs differently from rides.
  • line (optional): the line name as signposted, for example "4", "U3" or "S2".
  • The geometry, in one of two forms:
    • polyline: an encoded polyline as returned by most routing services. Add precision: 6 if it was encoded with six decimals instead of the default five.
    • coordinates: a list of [lon, lat] pairs (GeoJSON order), handy for hand-drawn routes exported from uMap or geojson.io.

Legs should join up: each leg starts where the previous one ends, and the first leg starts at map.origin.

map.origin is usually the same for all tours of an event, so it is written once. It takes name (per language), geo and an optional icon.

Map icons

Marker icons come from three public-domain (CC0) icon sets for maps, kept in assets/vendor/icons/:

Set Icons Browse
osmic 154 OSMIC, or the files in assets/vendor/icons/osmic/
maki 211 Maki
temaki 557 Temaki

icon takes the file name without .svg, for example ferry or railway-halt. The name is looked up in osmic, then maki, then temaki; some names exist in more than one set, so to pick a specific set, put its name in front: maki:garden, temaki:binoculars. uMap's pictograms are OSMIC and Maki icons with the same names, and this lookup order picks the same icon as uMap for every one of them, so icon values copied from uMap work unchanged.

Only the icons a page uses end up in it, so the size of the sets doesn't matter. To update a set, replace its folder with the SVG files of a newer version; each folder has a README with the version it came from.

The 39C3 tour map (uMap)

The 39C3 overview pages embed a map with the map-39c3 shortcode (layouts/_shortcodes/map-39c3.html). It is an iframe of the uMap map 39c3 Hackertours, which was created by the uMap user WinstonS in December 2025. The map has no other editors, so only that account can change it. Nothing about the map is stored in this repository apart from the embed code.

How the map is built:

  • The background is the "Jawg Dark" tile layer.
  • Layer 1 holds a single marker for the Congress (CCH).
  • Each tour has its own layer, named after the tour (Alsterdampfer, MiWuLa, XFEL, …), with two features of the same colour:
    • A marker at the venue, with a pictogram icon. Its name is an HTML link to the English tour page, and its description lists the directions from the Congress (English only).
    • A line named "Way to …" from the Congress area (mostly S Dammtor) to the venue, with the same directions as its description.
  • The lines were most likely drawn by hand with uMap's line tool rather than calculated by a routing service: most of them start near S Dammtor, but each at a slightly different point, the vertices are spaced irregularly (30 to 100 m on average, up to several hundred metres), and the XFEL route consists of two separately drawn pieces. The routes combine walking, bus, U-Bahn and S-Bahn.

To change the map, edit it on uMap (as the owner, or after the owner adds you as an editor); the website picks up changes immediately because the iframe loads the live map. When adding a layer, its ID has to be added to the datalayers parameter in the embed URL, which uMap's "Share" panel generates.

The uMap data has been converted into this format in data/schedule/39c3.yaml, with English directions only and each route as one leg of mode other. To get the data out again, for example after changes on uMap:

  • A single layer as GeoJSON: https://umap.openstreetmap.fr/en/datalayer/1329184/<layer-id>/. The layer IDs are listed in the datalayers parameter of the embed URL.
  • The whole map: the "Download" option in uMap's share panel exports all layers as one GeoJSON file.

In the GeoJSON, coordinates are already in [lon, lat] order, the colour and icon are in each feature's properties._umap_options, and the directions are in properties.description.