Repository navigation
Content fixes after the archive: privacy policy, glossary, event listings, and meta description - #222
Conversation
A link with target="_blank" and no rel="noopener" hands the opened page a handle on this one (window.opener), which a hostile page can use to send the reader somewhere else. Modern browsers imply noopener, older ones do not, and the security audit counted 7 such links on the home page. Five templates (the footer, the people summary, the contact page, the event detail, and the agenda) and two pages with raw HTML (PyDay BCN 2018, 7 links, and the 2022 Django workshop of PyLadies BCN, 1 link) get rel="noopener", next to any rel value they already had. Measured on a -D build, the frozen pages under archives/ left out: no link with target="_blank" lacks noopener. bin/check-content: 0 errors, 79 warnings. bin/check-html-safety and bin/check-rendered: PASS.
The policy and humans.txt described the site before phases 3 and 4. Measured on a -D build, the frozen pages under archives/ left out: - Unsplash: the policy said the page headers load images from unsplash.com. Phase 4 removed the headers, and no page loads anything from Unsplash now. The sentence now says that scripts, styles, fonts, and images come from this site, except the PayPal button of the membership pages and the Eventbrite button of PyDay BCN 2018. - Eventbrite: it was missing from "Who else sees your data". It is there now, next to the other companies. - No photograph: the policy said a person page shows a silhouette. A person page shows the initials of the name on a colour (246 of the 370 person records have no photograph); only the grids of organizers or speakers on four event pages show a silhouette. - Where a person page comes from: the policy said every person sent their photograph and text, under their consent. The 204 person records that the archive built from our Meetup announcements were not sent by anybody. For those pages the basis is now the legitimate interest of the association in keeping the history of the community (GDPR article 6.1.f), and the reader can object and have the page removed. - Event photographs: the 530 photographs of the galleries come from the posts of the association on X and were not in the policy. A new section says where they come from, that they show the event in general, the basis (GDPR article 6.1.f), and that a person can object to a photograph and we remove it. - humans.txt said that no page asks another site for anything to draw itself. False: 218 pages carry the youtube-nocookie player, the two talk proposal pages embed a Google Form, PyDay BCN 2019 embeds a Google Calendar, and PayPal and Eventbrite serve one button each. The line now names them and points at the policy for the whole list. bin/check-content: 0 errors, 79 warnings. bin/check-html-safety and bin/check-rendered: PASS.
No page had a <meta name="description">, so a search engine showed whatever text it picked from the page: often the bar and the first menu items. og:description and twitter:description read .Summary, which is the start of a bio on a person page and a slice of a table on a page with raw HTML. The meta description now comes, in order, from the description of the front matter; for a talk, who gave it, at which event, and on which day; for an event, its type, its date, and its venue; for a person, the name and the roles the archive credits, with a serial comma; and else the new site description in config.toml. It is cut at 160 characters on a word. The two share tags read the same sentence. Measured on a -D build: 1309 of 1321 pages carry the meta description, and the 12 without it are alias redirects. 1309 carry og:description. Samples: "Talk by David Arcos at Python July Meetup, 28 July 2016.", "Monthly meetup on 16 September 2026 at Dow Jones.", and "David Arcos: Permanent Committee, Organizer, Speaker, and Mentor at Python Barcelona." bin/check-content: 0 errors, 79 warnings. bin/check-html-safety and bin/check-rendered: PASS.
…tendees, RSVPs One vocabulary for the words the site uses about people and numbers, decided on 2026-10-25: - Board: the junta is "Board" in visible text. The levels of the Who we are page are "Board (2026)" and "Former Board (2018 - 2025)" (they were "Management Board"). The addresses of the two role pages do not move: the people adapter keeps management-board-2026 and former-management-board-2018-2025, because a published release links the first one. The Information, Legal notice, and Privacy policy pages and the association-identity shortcode say "Board" as well. - Committee: the Comitè Permanent keeps its full name, "Permanent Committee", where it is named as a role (its tab, the roles of a person). Nothing changed there. - Event organizer: the role of the people an event page credits under Organizers (23 of them today, the PyLadies BCN organizers included) is "Event organizer", and its page is titled "Event organizers". Its address stays /people/role/organizer/. - Who we are: the menu entry and title of /pybcn_association/organizers/ (it was "Organizers", which now names a role). The address stays, and the intro of /people/ links the page by its new name. - Members: only the paying members of the association. Three sentences used the word for a Meetup group (Information, Promote your event) or a Google Group (Privacy policy) and say "people" or "belong to" now. - Attendees: the tab that was "Assistants" (a calque of the Catalan assistent). Its page moved to /people/role/attendees/, and the adapter declares the old address as an alias: Hugo 0.139.4 accepts "aliases" in AddPage and wrote the redirect. - RSVPs: the yes count of Meetup, which the meetup pages printed as "Registrations". The visible word is "RSVPs" on the meetup pages, the meetups listing, Monthly Events, and the Attendees page, and in the docs and bin/new-meetup. The front matter key stays attendance, and the meaning stays: an RSVP is a promise to come, not a seat filled. The tabs of /people/ read the title of each page, as the tabs of /talks/ do, so a tab says "Speakers" and "Event organizers", not the singular label of a row. The home page counts six things instead of four, and the number of a tile is the number of the page it leads to: Events 281 (the h1 of /events/), Talks 607 (/talks/), People 371 (the h1 of /people/, every record of the archive, with the caption "Speakers, organizers, and others" under the label), Board and Committee 11 (the people under the two home_faces levels of Who we are, Board (2026) 5 and Permanent Committee 6, nobody on both; the tile lands on #board-2026, because the level headings of partials/people-grid.html carry an id from their name now), Meetup RSVPs 8,917 (the sum of attendance over the 267 meetup pages that carry it, of 268), and Sponsors 82 (the h1 of /sponsors/). The RSVPs tile leads to the Attendees page, which prints the same sum from the same partial (partials/meetup_rsvps.html, through partials/attendees_note.html) and says in plain words what it is: the "RSVP: yes" answers on Meetup, not who came, which nobody recorded. All the figures are computed at build time and printed with a thousands separator; the grid of the tiles is two rows of three from 992px (it was one row of four), the rows of one height. Measured with Playwright at 1440 and 390 px: no overflow, every label on one line, the caption of People on a second. Measured on a -D build before and after (static/archives/ excluded): pages with "registrations" 270 to 0, pages with "Assistants" 19 to 0, pages with "Management Board" 4 to 0, pages with "RSVPs" 0 to 271. 1379 HTML pages (1378 before: the alias). bin/check-content 0 errors and 79 pre-existing warnings, bin/check-html-safety and bin/check-rendered pass. Left as they are, for a decision: "PyLadies BCN Organizers", the title and menu entry of /pyladies_bcn/organizers-and-speakers/; the "Organising Committee" credits of the PyDay and PyData programmes (credited_as, a fact of the record); "work group members" on the Information page, which is about the work groups and not about Meetup.
The index pages of the four series under /events/ (meetups, pyday_bcn,
pydatabcn, other_events) took the fallback layouts/_default/list.html,
a list of titles in alphabetical order: /events/meetups/ read "Python
Meetup April" of one year before "Python Meetup August" of another,
268 times. They now draw the table of /events/, grouped by year and by
month, newest first, with the same six columns, the jump bar of their
years (when there are two or more), and the legend of their types, cut
to the events of the series. The h1 carries the number of rows,
"Monthly meetups (268)", as "Events (281)" does.
Where the code went. The body of layouts/_default/events_index.html
(the intro, the rows, the jump bar, the legend, and the call to
partials/event_table.html) is partials/event_listing.html, which that
layout and the new layouts/events/list.html both call, so a series
page cannot list an event differently from /events/. Hugo picks
events/list.html for the nested section pages by their type and looks
up the events_index layout of /events/ before it, so /events/ did not
move. partials/event_row.html returns the type token of a row, which
the legend counts rows by: on /events/ that gives the figures
partials/listing_counts.html gave before, checked below, and on a
series page the figures of that page alone. partials/listing_total.html
counts the rows of a section page of events for its h1.
No PyLadies BCN section lists events: /pyladies_bcn/meetups/ is the
Meetup link page (monthly_events layout), and the PyLadies BCN meetups
are rows of /events/meetups/, 71 of them, marked in its legend.
Measured on a -D build before and after. Rows: /events/ 281 and 281,
with the same legend (155 monthly meetups, 72 PyLadies BCN meetups, 23
coding dojos, 9 practice sessions, 9 PyDay BCN editions, 6 barbecues, 2
PyDataBCN editions, 2 sprints, 1 coderetreat, 1 hackathon, 1 workshop).
/events/meetups/ 268 titles to 268 rows under 20 years;
/events/pyday_bcn/ 9 to 9; /events/pydatabcn/ 1 to 1 (no jump bar);
/events/other_events/ 3 to 3. Pages with a section_index list under
/events/ 4 to 0. 1379 HTML pages before and after. bin/check-content 0
errors and 79 pre-existing warnings, bin/check-html-safety and
bin/check-rendered pass. Playwright at 1440 and 390 px on
/events/meetups/ and /events/pyday_bcn/: no horizontal overflow, the
rows reflow as on /events/.
The tabs.
/events/ and the index of each series under it (/events/meetups/,
/events/pyday_bcn/, /events/pydatabcn/, /events/other_events/) draw
one bar of tabs above their rows, All and the four series with their
counts, the current one marked with aria-current="page":
[ All 281 ] [ Monthly meetups 268 ] [ PyDay BCN 9 ] [ PyDataBCN 1 ] [ Other events 3 ]
The bar is partials/filter_tabs.html, the one /talks/ and /people/
draw, called from the new partials/events_tabs.html out of
partials/event_listing.html, so the two layouts that share that body
share the tabs. No new page and no script: the views were already the
section pages, so the tabs are read from the sections of /events/
(a section with no event gets no tab), their text is the title of the
section page, and the URLs do not move.
The count of a tab is the count the h1 of its page prints, both from
the one test of a row, a page of the events section with a year, filed
under its CurrentSection. The order is the one of the Events menu, by
the weight of the section page, with the meetups (no weight, 268 of
the 281 rows) in front. No glyph on a tab: a series is not a type, the
meetups hold eleven of them, so the legend under the tabs keeps that
job.
Measured on a -D build and on the dev server. On each of the five
pages the bar lists the five tabs above, exactly one tab carries
aria-current and it is the page itself, and each count equals the
number in the h1 of the page the tab leads to (281, 268, 9, 1, 3; the
four add up to 281). Playwright at 1440 and 390 px on the five pages:
scrollWidth equals clientWidth, the tabs take one line at 1440 and
three at 390. 1379 HTML pages before and after. bin/check-content 0
errors and 79 pre-existing warnings; bin/check-html-safety and
bin/check-rendered pass.
config.toml declares en-us, og:locale is en_US, the URLs and the role ids say "organizer", and CSS and Hugo write color and center, while the text of the site mixed both spellings: 142 -ize forms against 18 -ise, but "programme" 71 times against "program" once, and "colour" 26 against "color" 20. The visible text of a -D build, archives excluded, carried 377 "programme", 22 "organis-", 10 "colour", 5 "behaviour", 2 "favourite", and 1 "licence"; it now carries 0, 6, 9, 5, 0, and 0. What changed: templates and partials (text and comments), the section intros and the association and PyLadies pages, the comments of the event front matter, data/event_emoji.yaml, the SCSS comments, AGENTS.md, README.md, CONTRIBUTING.md, LICENSING.md, the comments and messages of bin/, and one workflow comment. organise, programme, colour, licence, centre, favourite, behaviour, recognise, normalise, labelled, neighbour, honours, and learnt take their American forms. The credited_as strings "<Edition> Organising Committee" and "Organizing Committee" (PyDay BCN 2021 to 2025, PyDataBCN 2023), written by the association when it made each page, read "<Edition> organizers". What stays: imported talk titles, descriptions, and captions, event announcements, the bios people wrote, the prompt in bin/prompts/, every URL, slug, id, and identifier (site_licence, centre_x, normalise_scheme, PALETTE_COLOURS, aria-labelledby, the "grey" palette token), and the LICENSE file. The six remaining "organis-" and nine "colour" of the build are all in imported text or a bio. Verified: bin/check-content (0 errors, 79 warnings, the photo warnings of before), bin/check-html-safety, bin/check-rendered on the -D build (1379 pages, as before), and bin/check-extraction --selftest (7 of 7).
| Some event pages show photographs from the posts of the association on X, with the caption they were posted with. Only photographs that the association published itself are on the site. They show the event in general: a speaker gave the talk in public and accepted that it was recorded, and the audience appears in the background and from a distance. | ||
|
|
||
| - **Where it comes from**: the public posts of the association on X. | ||
| - **Why we have it**: our legitimate interest in keeping the history of the community (GDPR article 6.1.f). You can object to a photograph in which you appear, and we remove it. |
There was a problem hiding this comment.
Check the last line: https://pybcn.org/people/daniel-mesejo-leon/
To change or remove anything on it, edit that file on GitHub and open a pull request, or write to pybcn@googlegroups.com.
It's in the privacy policy too, but in each person's url is more convenient, right?
| - **Where it comes from**: the person. Each one sent the photograph and wrote or approved the text for publication here. Someone who did not want a photograph did not send one, and the page shows a silhouette instead. | ||
| - **Why we have it**: with the person's consent (GDPR article 6.1.a). You can withdraw it at any time, and we remove the page. Withdrawing consent does not affect what was published before. | ||
| - **Where it comes from**: for most people, the person. They sent the photograph and wrote or approved the text for publication here. For speakers that the archive credits, the public announcements of our own Meetup events: the page then shows the name, the talks, and the events. A page with no photograph shows the initials of the name on a colour instead; the grid of organizers or speakers on an event page shows a silhouette. | ||
| - **Why we have it**: for a page that the person sent, their consent (GDPR article 6.1.a). You can withdraw it at any time, and we remove the page. Withdrawing consent does not affect what was published before. For a page built from our announcements, our legitimate interest in keeping the history of the community (GDPR article 6.1.f). You can object to it, and we remove the page. |
There was a problem hiding this comment.
Do we have a link to a reputable source confirming that this is the actual (and best) GDPR article we want to reference?
There was a problem hiding this comment.
Good question. The official text is the GDPR on EUR-Lex: https://eur-lex.europa.eu/eli/reg/2016/679/oj. Article 6(1)(f) is the legitimate interest basis, and Article 21 gives the right to object to it, which the policy now links from both bullets (83c39af). Consent (6(1)(a)) does not fit here: nobody asked the 204 speakers built from our announcements, or the people in the 530 photographs. I am not a lawyer, so if the board wants a second opinion, this is the paragraph to show.
|
|
||
| ## Past Management Boards | ||
| * Management Board 2018 - 2025 | ||
| ## Past Boards |
There was a problem hiding this comment.
So this was the only board from 2018 to 2025? @DZPM, weren't you the president at some point? Or does this refer to the board of the nonprofit organization?
There was a problem hiding this comment.
No, I was never president. The association was founded in 2018, and there was only one board before the current one, from 2018 to 2025, with Laura as president. Before 2018 there was no association, so no board: just the meetup group.
| partials/filter_tabs.html. | ||
|
|
||
| [ All 371 ] [ 📋 Management Board (2026) 4 ] [ 🧭 Permanent Committee 6 ] [ 🧭 Organizer 21 ] ... [ Assistants ] | ||
| [ All 371 ] [ 🎤 Speakers 356 ] [ 🧭 Event organizers 23 ] ... [ 📋 Board (2026) 5 ] ... [ 🪑 Attendees ] |
There was a problem hiding this comment.
Is there a way to have this automated? Otherwise, do we have to update this figure every time a new event is made?
There was a problem hiding this comment.
No manual updates: the tabs count their rows at build time. Those numbers were only in a comment that draws the tab bar as an example, and I see how they read as something to maintain. They are now N in all five comments (83c39af).
…m comments Two points from the review by @mesejo: - The privacy policy says a person can object to a page built from our announcements, or to an event photograph, but not how. Both bullets now link to "Your rights", which says to write to pybcn@googlegroups.com. - The comments that draw the tab bars of /talks/, /people/, and /events/ carried the counts of the day (All 371, Speakers 356, ...), which read as numbers to update by hand. The tabs count their rows at build time; the comments now show N. The /people/ example also used the old role name, Organizer, and now says Event organizers. bin/check-content: 0 errors, 79 warnings. bin/check-html-safety: PASS. The anchor #your-rights is the id Hugo gives the heading "Your rights", the same one the live policy has.
Content fixes after the archive went live: the privacy policy, the words the site uses, the event listings, and the meta description. Six commits, each one with its reasons and measured figures in its message.
🚧 For the board: the privacy policy changes
The policy said that every person page was sent by the person, under their consent. That is no longer true, so the policy now says:
I validated it, but the policy belongs to the association: please say so here if something is wrong.
What changes
/people/role/assistants/redirects to/people/role/attendees/./events/meetups/and the other series were in alphabetical order. They now use the table of/events/, by year and month, and the five pages share one bar of tabs, as/people/does.rel="noopener"on every link that opens a new tab.languageCode, the URLs, and the code already are. Imported text (talk titles and descriptions) does not change.Checks
Built with
-D: 1379 pages.bin/check-content0 errors (79 old photo warnings),bin/check-html-safetyPASS,bin/check-renderedPASS.Not in this PR
Bootstrap, jQuery, and Hugo upgrades go in a separate PR, to keep content and layout apart.