Skip to content

The photographs and the videos, and the privacy policy that declares the player - #218

Merged
DZPM merged 6 commits into
editionfrom
archive/5-media
Oct 16, 2026
Merged

DZPM merged 6 commits into
editionfrom
archive/5-media

Conversation

@DZPM

@DZPM DZPM commented Oct 15, 2026

Copy link
Copy Markdown
Member

Part 5 of 5 of the Archive, #213, and the one that closes it. Stacked on #217: its base is archive/4-listings. Retarget it to edition when the one before it merges.

The photographs and the videos: what the days actually looked like.

What it adds

  • 231 photographs of eleven event days, from our own threads on X, each with the caption of its post, credited to the account that published it, and 107 of them naming the talk they show. A photograph the association only shared is never imported, because its copyright is somebody else's.
  • The gallery: one card per photograph, the caption as a quotation, a link to its own anchor, and a cap on the height so a portrait does not tower over the page.
  • 117 video links: 88 of the 89 our channel holds, and the 29 of PyData Barcelona 2017 that pyvideo kept. Six of those were missing from every playlist and were found by asking the channel itself.
  • data/channel_videos.yaml, the inventory, and a check that fails when a video of the channel reaches no page. A missing video used to be something a person noticed by eye.
  • A player on the page of a talk, in a youtube-nocookie frame, on 113 pages. A listing and an event page carry a link and no frame.

The part to read carefully

The frame changes what a reader's browser does, so content/pybcn_association/privacy-policy.md and legal-notice.md change with it. In short: Google serves the player, so it sees a reader's IP address and that they opened that page, before they press play; until they press play Google states the player stores nothing; and under every player there is the plain link to the same video on youtube.com, so the page reads fine with the frame blocked.

The last commit, "Minor fixes from the second validation round", is the result of walking the built site: column widths, the mark on every external link, the sticky jump bar, and the group photograph of four PyDay editions.

DZPM added 6 commits October 15, 2026 10:17
…os as rows

partials/photo_gallery.html renders the gallery of an event page, under
one Gallery heading, in two subsections. Photos (N): one figure per
photograph, in a card of its own, with the caption under it in italic
(it is the text of the post that published the photo, so it is marked as
a quotation), the talk and its speakers credited under a photograph of a
talk, the source credited as "Via @account" with the mark of the host in
front of the link, and a link to the anchor of each figure. A photograph
is capped at 675px high. Talks & Videos (N), on an edition page: one row
per recording of the day, in programme order, the row the Talks block of
a meetup page prints, with the title as the link to the page of the
talk and the Watch line to YouTube. A subsection with nothing in it is
not printed, and a page with neither has no gallery.

partials/gallery_content.html resolves the block once per page, with the
page as the cache key: the file of each item as an image resource, its
talk by id, and its position. It skips an item whose file it cannot
resolve and an item with no caption, on purpose: a missing asset would
stop the build, and an image with no accessible name is worse on the
page than one photo fewer. bin/check-content is what says those out
loud, in the commit that follows. partials/event_videos.html gives it
the videos of an edition: the agenda walked slot by slot, then the
talks the agenda does not place, so PyData Barcelona 2017, which has
talks and no grid, gets its videos from the second walk. David Arcos
decided on 2026-10-15 that a recording is material added after the day,
like a photograph, so it belongs in the Gallery at the end of the page
and not under the schedule, where PyDay BCN 2020 alone had a Videos
block for one day. partials/caption_links.html escapes a caption and
then makes its mentions, hashtags, and URLs into links: the one field
of the site that reaches a template through safeHTML, and the reason
the canary page gets a caption. partials/photo_anchor.html gives the
figure of a photo one id.

The pages that draw it: layouts/_default/event.html prints the gallery
last, after the sponsors and the people of the day, and lists it in the
section index; layouts/_default/single.html prints it too, for the
archived pages of 2016 to 2019 that are raw HTML on that layout;
layouts/_default/meetup.html prints the photographs under the talks.
The row of /events/ counts the photos of the day and the row of /talks/
the photos of the talk (partials/listing_counts.html); the page of a
talk shows every photo that names it, each linked to its figure, under
a Photos heading with the count (partials/talk_record.html returns the
list, layouts/talks/single.html prints it), and talks.scss gets the
rules of that card. photo_gallery.scss holds the rest, and the cap on
the height.
PyBCN posted photographs live from each PyDay on X, and those posts are
the only record of the day the association still owns. bin/import-x-photos
staged them, one photo per post so no two share a caption, and a human
curated each set: what the gallery does not want was dropped, and each
photo that shows a talk points at that talk by id. The photos block of
each page carries the thread, the items, and the comment that says where
they came from.

Eleven pages, 235 photographs, 101 of them naming a talk: PyDay BCN 2016
(4), PyData Barcelona 2017 (19), PyDay BCN 2018 (16), PyDay BCN 2019
(20), PyDay BCN 2021 (31), Hands-on Django with PyLadies BCN 2022 (11),
PyDay BCN 2022 (32), PyDataBCN 2023 (25), PyDay BCN 2023 (33), PyDay BCN
2024 (23), and PyDay BCN 2025 (21). Four of them are the group
photograph the association posted once the day was over, on PyDay BCN
2019, 2021, 2024, and 2025, last in its gallery. PyDay BCN 2020 was held
on YouTube and has no photograph.

The files sit under themes/pybcn_theme/assets/images/photos/<event>/,
capped at 1000px wide by bin/fit-sources (IMPORTED_PHOTO_CAP), and the
header image of the Django page is the one of the set. A photograph the
association only shared, rather than took, is not here: its copyright
belongs to whoever took it (LICENSING.md says so in the commit that
follows).
…he canary

bin/check-content gains check_gallery: every item of a photos block must
reach the page it declares. It rejects a block that is not a block, an
item with no file, a file in none of the asset directories or with a ".."
segment, an item with no caption (the caption is the alt text, so the
gallery leaves such a photo out rather than publish an image nobody can
read), a photo that points at a talk of another file, and a source that
is not an https URL (the credit reads the account out of its path). A
photo wider than the gallery asks for is a warning that points at
bin/fit-sources. The gallery of one event points only at the talks of its
own file, so talk_ids_of is shared with check_agenda and reports each
mistake once.

bin/check-rendered gains a third canary. The caption of a gallery photo
is the one field that reaches a template through safeHTML, so
content/canary.md gets a photos block whose caption carries markup and
a protocol relative address, //canary.invalid/caption, which the partial
leaves alone and a template that printed the caption as markup would
turn into a link to the canary host. The check fails if the caption did
not reach the page as text. README.md describes the three canaries.

LICENSING.md says where the event photographs come from, that the
account credited is not the photographer, that a photograph the
association only shared is never imported, and how to ask for one to
come down.
partials/video_frame.html embeds one video in a frame from
www.youtube-nocookie.com, the player that sets no cookie until the
reader presses play. The id is read from the URL and checked against the
shape of a YouTube id before it is written into the src: the URL is
content, and no content field reaches the page through safeHTML.
loading=lazy defers the request, referrerpolicy keeps the path of the
page out of it, and the wrapper holds a 16:9 box (talks.scss) so the
page does not move when the player arrives. The caller prints the plain
link to YouTube under the frame in every case, so the page reads fine
with the frame blocked.

Where a player goes: on a page about one video. The page of the talk
(layouts/talks/single.html, its Video section); the Recordings block of
the page of a meetup or an edition (partials/session_videos.html), one
player per recording of a whole session, because a recording that
belongs to no talk has no page of its own and the page of its day is
the page about it; and the Videos block of the page of a person
(layouts/people/single.html), one player per talk of theirs that has
one, with the link and the day under each. A listing or a programme
grid prints a link and no frame, because PyDay BCN 2020 has a video on
almost every row and would make one request to Google per row before a
reader asked for any of them. Every heading over a list of recordings
carries the count. bin/check-rendered allows the frame under talks/,
events/meetups/, and people/ with that one src prefix and nowhere else.

It is not nothing: the frame still asks Google for the player when the
page loads, and Google sees the IP address and the browser of the reader
at that moment, before play. The privacy policy says what the frame does
and does not do, names the YouTube player among the Google services the
site uses, and carries the registered address of the association; the
legal notice names the player among the frames Google serves. David
Arcos decided for the frame on 2026-10-14, after a first decision for a
click-to-load facade, and for the players of the Recordings block on
2026-10-15.
The PyBCN YouTube channel holds 89 videos. bin/import-videos wrote each
one as a link of type video on the talk record of the event that held
it: 65 links on the talks of 34 meetup pages, and 29 on the talks of
PyData Barcelona 2017, the form the 20 links of PyDay BCN 2020 already
had. The row of a talk prints the link with the YouTube mark in front,
the page of the talk plays it under its Video heading, and the gallery
of PyData Barcelona 2017 lists its 29 recordings together.

A recording of a whole session, a block of lightning talks or the
introduction of an evening, belongs to no talk, so three meetup pages
carry it as an entry of session_videos, title and url, which
partials/session_videos.html plays under a Recordings heading after the
talks, on the meetup page and on an edition page alike. Not "videos":
Hugo reads that key as the og:video URLs of the page.

data/channel_videos.yaml is the inventory of the channel, the list this
site maintains: one entry per video with the id, the title, and the
decision, placed or not and why, plus the 29 videos of other channels
the pages link. 88 are placed and 1 is unplaced with a reason.
bin/check-content reads it against the pages and never the network: a
placed entry no page carries, a YouTube link no entry lists, an unplaced
entry with no reason, a session video with no title or no url or listed
twice on its page, and the reserved videos key are errors. Its summary
line reports 117 YouTube links to 117 videos. AGENTS.md says how a new
video gets noticed, through bin/list-channel, and what to write where.

bin/check-content on this tree: 373 people, 74 sponsors, 607 talks on
224 pages, 87 venues, 0 errors, 81 warnings.
David Arcos walked the built site and reported a list. These are the
fixes, kept together because each is small and none changes what the
archive holds.

The listings: the Day column shows the first day only, Venue, Gallery,
Month, and Event are narrower, the venue hover appears only when the
full name says more than the short one, and a speaker name on /talks/
reads and behaves like the link it is.

The marks: one grey mark per link destination, on every external link
including the ones in the body of a page and the edit link of the About
block, with Flickr added to the table. "Watch on YouTube" is "Watch",
because the mark already says where it goes.

The person page: the bio and the social links sit beside the portrait,
the roles moved onto the Events heading, the portrait zooms inside its
frame the way the organizers cards do, and the generic avatar shows
here too. Collaborator prints in the singular, and the board of 2018 to
2025 is the Former Management Board.

The rest: the jump bar pins under the navigation as the page scrolls,
PyData Barcelona 2017 lists its talks once with both counts, the feed
sorts by the day the event happened rather than the day it was
committed, Hacktoberfest 2018 takes the day and the organizers its own
frozen archive records, and four PyDay editions get the group
photograph of their closing post.
@DZPM
DZPM requested a review from a team as a code owner October 15, 2026 10:04
@DZPM DZPM self-assigned this Oct 15, 2026
@DZPM DZPM mentioned this pull request Oct 15, 2026
24 tasks done

@ber2 ber2 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good stuff

@DZPM
DZPM changed the base branch from archive/4-listings to edition October 16, 2026 06:36
@DZPM DZPM closed this Oct 16, 2026
@DZPM DZPM reopened this Oct 16, 2026
@DZPM
DZPM merged commit efcaba3 into edition Oct 16, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants