flowchart TD
A["Archive (raw scans, notes)"] -->|curation| B["raw_data/*.md"]
B -->|python pipeline| C[_photos/*.md]
C -->|jekyll build| D[_site/]
D -->|static HTML| E[Browser]
E -->|frontmatter injected| F[myscript.js]
F -->|reads config| G[Leaflet Map & Overlays]
B -->|frontmatter| F
C -->|frontmatter| F
F -->|URL params| G
Historical material is first collected from archival scans, social-history contributions, and manual research notes, then normalized by an editor into one Markdown file per photo object inside raw_data/.
Each raw_data entry represents a single historical record: descriptive text + structured metadata (date, labels, location geometry, and one primary image with optional variants).
Original research material is stored in archive/, then curated to production level in raw_data/ as input to the python pipeline to produce jekyll collection items in _photos/.
This site is a static Jekyll project with a Python preprocessing pipeline and a client-side JavaScript data layer for interactive maps and overlays.
General Data Flow:
raw_data/, each with YAML frontmatter for metadata (title, date, labels, location, images).scripts/process_research.py) processes these into normalized, runtime-ready Markdown in _photos/, generating image assets and GeoJSON overlays._photos/ and _topics/ collections.assets/js/myscript.js) powers interactive maps, overlays, and UI features, reading configuration from page frontmatter and URL parameters.Key Principles:
raw_data/ (never _photos/)._config.yml).The main interactive logic is handled by assets/js/myscript.js, which powers the Leaflet-based maps and overlays on photo, topic, and map pages. This script is designed to:
flowchart LR
subgraph Jekyll Build
B1[raw_data/*.md] --frontmatter--> C1[_photos/*.md]
C1 --frontmatter--> D1[HTML page]
end
D1 --JS vars--> E1[myscript.js]
E1 --config merge--> F1[Map Initialization]
F1 --overlays--> G1[Leaflet Map]
E1 --URL params--> F1
D1 --user interaction--> G1
G1 --UI events--> E1
Jekyll layouts inject frontmatter variables as global JS variables (e.g., centerLat, centerLng, zoomLevel, activeLayers, topicSlug, topicFeaturedPhotos, photoOriginGeoJson, etc.). These are read by myscript.js at runtime to configure the map:
centerLat, centerLng, zoomLevel (from frontmatter, can be overridden by ?center= and ?zoom= URL params)activeLayers (array from frontmatter, or ?layers= URL param)topicSlug, topicFeaturedPhotos (from topic page frontmatter)photoOriginGeoJson, photoFovGeoJson, photoLineGeoJson (from photo page frontmatter)All these variables are set in the page’s HTML by the Jekyll layout, using Liquid templating to output the frontmatter values as JS assignments before loading myscript.js.
myscript.jsflowchart TD
subgraph Page Render
A1["Frontmatter (YAML)"] -->|Liquid| B1[JS Variables]
B1 -->|window.*| C1[myscript.js]
C1 -->|LAYER_CONFIG| D1[Map Layers]
C1 -->|GeoJSON| E1[Photo Overlays]
C1 -->|Timeline| F1[Slider Control]
end
C1 -->|reads URL| G1[URL Params]
G1 -->|override| D1
G1 -->|override| F1
D1 -->|Leaflet| H1[Map]
E1 -->|Leaflet| H1
F1 -->|Leaflet| H1
LAYER_CONFIG object for all map layers (basemaps, overlays, rasters, images, GeoJSON), using asset paths resolved from the Jekyll base URL.location.*_geojson fields injected by the pipeline and passed via frontmatter.featured_photos and topic-specific GeoJSON.In a Jekyll layout (e.g., _layouts/photo.html):
<script>
var centerLat = 41.3551;
var centerLng = 14.3722;
var zoomLevel = 17;
var activeLayers = null;
var photoOriginGeoJson = null;
// ...etc
</script>
<script src="/piedimonte-matese-old-photos/assets/js/myscript.js"></script>
_config.yml.Markdown files frontmatter contains information to build the site ad the embedded leaflet maps :
raw_data/*md : human-curated metadata such as title, date, labels, location coordinates, map settings, original_url, and image references (images[] preferred, or legacy primary_image + variants)._photos/*md (processed/generated): keeps source fields and adds runtime fields generated by the Python pipeline: normalized image objects with final asset paths + thumbnails, processed_primary_image, processed_primary_thumb, processed_images, normalized variants, and map-ready location.*_geojson fields (when geometry is availableThe core pattern is:
raw_data/scripts/process_research.py)_site/The architecture is intentionally one-way: source data is edited in raw_data/, while _photos/ and generated assets are pipeline outputs.
archive/ (private historical backup)_config.yml.raw_data/ (authoritative editable source)Current supported image schemas:
images:
- file: "source-image.jpg"
is_primary: true
type: "original"
note: "Main shot"
alt: "Accessible alt text"
primary_image: "source-image.jpg"
variants:
- file: "variant-image.jpg"
type: "restoration"
note: "Edited version"
_photos/ (generated Jekyll collection)raw_data/*.md.Generated media outputs:
assets/images/[slug]-main.jpgassets/thumbs/[slug].jpgassets/images/variants/[slug]/...assets/thumbs/variants/[slug]/...Generated geospatial outputs:
assets/maps_data/photos_origin.geojsonassets/maps_data/photos_fov.geojsonassets/maps_data/photos_lov.geojsonscripts/process_research.py)The script is an ETL pipeline for markdown metadata + image assets.
raw_data/*.mdpython-frontmatter)title, date, location, labels + image schema)images[] structurePillow)_photos/[slug].mdgeopandas + shapely)The script enriches metadata with runtime-ready fields, including:
processed_primary_imageprocessed_primary_thumbprocessed_imagesvariants (normalized generated variant metadata)location.origin_geojson, location.fov_geojson, location.line_of_sight_geojsonpython scripts/process_research.py --log INFO
Useful dependencies (from requirements.txt):
python-frontmatter, Pillow, PyYAMLgeopandas, shapely, pandasphotos collection_config.yml with permalink /photos/:slug/._photos/ (generated by Python)._layouts/photo.html.Photo layout behavior:
processed_images (with fallbacks).topics collection_config.yml with permalink /topics/:slug/._topics/ and are editorial/manual._layouts/topic.html.Topic-photo join model:
featured_photos entries with id values.id against site.photos by slug.Example featured_photos pattern:
featured_photos:
- id: via-carmine-cotonificio
commentary: "Historical relation to the square."
Labels are not a separate Jekyll collection; they are derived from photo metadata.
labels in frontmatter.site.photos.labels.md mounts _layouts/label.html at /labels/./labels/?tag=label-slug.Related list/table behavior:
/photos/ (_layouts/photos_index.html) supports ?label= prefilter./labels/ supports ?tag= prefilter._config.yml defines site metadata, collections, base URL, and excluded folders.cdn_libs to avoid URL scattering.Most dependencies are loaded from pinned CDN versions. This keeps the project compatible with static hosting and avoids a JS build pipeline.
raw_data/ and/or _topics/scripts/process_research.py_site/ is generated output only._photos/ is generated collection output only.raw_data/, _topics/, layouts/includes, and config.This separation reduces drift and preserves reproducibility.
images[] + legacy fallback currently coexist)._config.yml over hardcoded URLs.raw_data/ before running the pipeline.location.*_geojson fields in generated _photos/*.md and check browser console for CDN load errors.featured_photos[].id exactly matches photo slug in _photos/.