From 3cb22a57da621481f25270d88ce28641993ce4fa Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 00:35:55 +0200
Subject: [PATCH 01/39] Point every social link at the host that answers it,
and check its shape
Nothing checked the four link fields (linkedin, github, twitter, site)
in the person and sponsor files. The link checker in CI reads the built
pages, and a URL broken badly enough never becomes a link at all, so it
is invisible to both. Three kinds of drift had accumulated, three links
had never worked, and four organizers had no GitHub account on file.
**Four GitHub accounts recorded.** 80 of the 139 person files carried a
`github` field and these four did not, so there was no way to go from a
name on the organizers page to the account that reviews pull requests.
That gap cost real time this week: I read `ber2` as one person when it
is another, and could not tell whether a member of the Permanent
Committee had ever been invited to the organisation, because nothing
connected his name to `mrswats`. Each handle comes from the name the
account itself declares on GitHub, matched against the name in the
person file. Nothing is guessed:
alberto.md ber2 Alberto Camara
nuria.md llevaNEUS Nuria Pujol Vilanova
ferran-jovell.md mrswats Ferran Jovell
daniel-mesejo.md mesejo Daniel Mesejo
Daniel's is the odd one: the orphan duplicate `daniel_mesejo.md`, which
no page lists, already had the field, while the file the organizers page
actually uses did not. Five members of the organisation have no person
file at all and are left alone: areski, chdoig, mikanchu, paulinus and
tris-sondon.
**88 Twitter links, now x.com.** Both `twitter.com` and `www.twitter.com`
redirect there, so every one of them cost a redirect and showed a brand
that no longer exists. The two association accounts in config.toml and
the archetype that generates a new sponsor file go with them.
**11 GitHub links carried `www.`**, which `github.com` redirects away.
They now match the other 81.
**120 LinkedIn links, now `www.linkedin.com`.** One was broken and had
been for as long as it has existed: patricia-lamadrid.md began
`ttps://`, a missing h in the scheme. Four pointed at `es.linkedin.com`,
which serves the same profile but pins the reader to one interface
language, and one at `linkedin.com` without `www`. All 120 now use
`www.linkedin.com`, which is the host LinkedIn itself serves and which
115 already used. No LinkedIn URL carries query parameters, which is
worth stating because a profile URL copied from a browser usually does.
`/in/`, `/company/` and `/school/` all stay: they are different kinds of
LinkedIn page, not an inconsistency.
**One personal site pointed at a subdirectory**, `davidarcos.net/blog/`,
rather than at the site. The other personal sites are left alone. Three of
them are written with `www`, and none of the three needs it:
paulaszewach.com answers with it and without it, and netbcn.cat and
enricdomingo.com answer nothing either way, so they are down rather than
www-only. They keep the form their owner gave us. A URL somebody chose for
themselves is not a cosmetic inconsistency to tidy up.
**check-content now holds the shape.** It rejects a github, linkedin or
twitter link that does not start with the one host each service serves,
rejects query parameters in any of them, and warns about a personal site
served over http. A twitter link has to be https://x.com/USERNAME and
nothing else. It found six things on the first run:
patricia-lamadrid linkedin began "ttps://", missing the h
alejandro-nicolas linkedin had no scheme at all
amalia_vradi linkedin had no scheme at all
colorsensing twitter carried ?lang=es
eduard_cespedes site carried ?lang=en
juan-luis-cano twitter held a Mastodon address
The first three had never worked. A browser reads "ttps://www.linkedin.com"
as a path relative to the current page, so those three people have had a
dead link on their card for as long as the file has existed. Juan Luis's
Mastodon address moves to `site`, where it renders a globe: it was
drawing an X icon over a profile on the network he left. An empty
`twitter:` key in the CodeOp sponsor file is gone too: it rendered
nothing and meant nothing.
**The icons are ordered by how many people have each.** They came out
twitter, github, linkedin, site. Counting the person files, that is
close to backwards:
linkedin 114 of the 139 person files
github 84
twitter 64
site 23
The network four in five people have was third, and the one fewer than
half of them have was first, so the first icon on most cards was the one
least likely to be there, and the row opened with a gap on more than half
of them. The order is now linkedin, github, twitter, site, in the
card and in the dialog. It is fixed in the template rather than
computed, because the shape of this list changes about once a decade and
a sort at build time would cost more to read than it saves. The order of
the keys in a person's front matter has no effect on any of this and is
left alone: the template decides.
Verified: each new account renders its icon on the organizers page;
x.com/PyBCN, x.com/PyLadiesBCN, davidarcos.net and github.com/ber2 all
answer 200 with no redirect; and the three content checks pass.
---
bin/check-content | 48 +++++++++++++++++++
config.toml | 4 +-
content/people/albert-franzi.md | 2 +-
content/people/alberto-labarga.md | 2 +-
content/people/alberto.md | 3 +-
content/people/alejandro-nicolas.md | 4 +-
content/people/alex-molas.md | 2 +-
content/people/alexandre-savio.md | 2 +-
content/people/alicia-morales.md | 2 +-
content/people/alvaro-duran-barata.md | 2 +-
content/people/amalia_vradi.md | 2 +-
content/people/angel.md | 4 +-
content/people/ankit-mahato.md | 2 +-
content/people/anton-caceres.md | 2 +-
content/people/antonio-molina.md | 2 +-
content/people/biel-stela-ballester.md | 2 +-
content/people/camilo-chacon.md | 2 +-
content/people/carlton-gibson.md | 2 +-
content/people/carmen-iniesta-lopez.md | 2 +-
content/people/cheuk-ting-ho.md | 2 +-
content/people/christian-adell.md | 2 +-
content/people/daniel-mesejo.md | 1 +
content/people/daniel-sanchez-santolaya.md | 2 +-
content/people/david-de-la-iglesia-castro.md | 2 +-
content/people/david.md | 6 +--
content/people/edgar-riba.md | 2 +-
content/people/eduard_cespedes.md | 4 +-
content/people/elisabeth-ortega-carrasco.md | 2 +-
content/people/eloi.md | 4 +-
content/people/enric-domingo.md | 2 +-
content/people/esperanza-buitrago.md | 4 +-
content/people/esteve.md | 4 +-
content/people/ferran-fabregas.md | 2 +-
content/people/ferran-jovell.md | 1 +
content/people/francesco-faraone.md | 2 +-
content/people/gabriel-de-maeztu.md | 4 +-
content/people/gajendra-deshpande.md | 2 +-
content/people/gema-parreno.md | 2 +-
content/people/ifosch.md | 2 +-
content/people/israel-saeta.md | 2 +-
content/people/jimena-escobar.md | 2 +-
content/people/johanna-sanchez.md | 2 +-
content/people/jordi.md | 2 +-
content/people/jose-riera.md | 2 +-
content/people/jose_haro.md | 2 +-
content/people/josep.md | 4 +-
content/people/juan-bernardo-lince.md | 2 +-
content/people/juan-luis-cano.md | 2 +-
content/people/julio-martinez.md | 2 +-
content/people/kemalcan-bora.md | 2 +-
content/people/laysa-uchoa.md | 2 +-
content/people/loris.md | 2 +-
content/people/lpmayos-president.md | 2 +-
content/people/lpmayos.md | 2 +-
content/people/marc-pous.md | 2 +-
content/people/mariana-meireles.md | 4 +-
content/people/miquel-sarrias.md | 2 +-
content/people/miroslav_sedivy.md | 2 +-
content/people/monica-dominguez.md | 2 +-
content/people/natalia-secretary.md | 2 +-
content/people/natalia.md | 2 +-
content/people/noe-casas.md | 2 +-
content/people/nuria.md | 3 +-
content/people/patricia-lamadrid.md | 2 +-
content/people/patricio-reyes.md | 2 +-
content/people/pavel-lonkin.md | 2 +-
content/people/pere-miquel-brull.md | 2 +-
content/people/rberenguel.md | 4 +-
content/people/ricardo-ander-egg.md | 2 +-
content/people/ruben-afonso.md | 2 +-
content/people/sonia-estrade.md | 2 +-
content/people/vivek-sharma.md | 2 +-
content/people/xavi.md | 2 +-
content/sponsors/affectv.md | 2 +-
content/sponsors/aimsun.md | 2 +-
content/sponsors/apsl.md | 2 +-
content/sponsors/casadelmig.md | 2 +-
content/sponsors/codelytv.md | 2 +-
content/sponsors/codeop.md | 1 -
content/sponsors/colorsensing.md | 2 +-
content/sponsors/coopdevs.md | 2 +-
content/sponsors/holaluz.md | 2 +-
content/sponsors/isdieducation.md | 2 +-
content/sponsors/kiwi.md | 2 +-
content/sponsors/letgo.md | 2 +-
content/sponsors/marfeel.md | 2 +-
content/sponsors/nuclia.md | 2 +-
content/sponsors/okta.md | 2 +-
content/sponsors/preply.md | 2 +-
content/sponsors/psf.md | 2 +-
content/sponsors/pybcn.md | 2 +-
content/sponsors/pyladiesbcn.md | 2 +-
content/sponsors/pythones.md | 2 +-
content/sponsors/qida.md | 2 +-
content/sponsors/satellogic.md | 2 +-
content/sponsors/shimoku.md | 2 +-
content/sponsors/somenergia.md | 2 +-
content/sponsors/travelperk.md | 2 +-
content/sponsors/typeform.md | 2 +-
content/sponsors/ub.md | 2 +-
content/sponsors/upf.md | 2 +-
content/sponsors/veriff.md | 2 +-
content/sponsors/verse.md | 2 +-
themes/pybcn_theme/archetypes/sponsors.md | 2 +-
.../layouts/partials/people_summary.html | 16 +++----
105 files changed, 173 insertions(+), 122 deletions(-)
diff --git a/bin/check-content b/bin/check-content
index f6048491..4896f921 100755
--- a/bin/check-content
+++ b/bin/check-content
@@ -214,6 +214,53 @@ def report_small(small):
f"the grid. Smallest: {shown}. Replacing the file is the only fix.")
+# One form per network, so a reader of the files can tell at a glance that two
+# links point at the same place, and so nobody has to wonder whether
+# es.linkedin.com and www.linkedin.com are the same profile. The hosts are the
+# ones each service itself serves: github.com redirects www away, LinkedIn
+# serves www, and twitter.com has redirected to x.com since the rename.
+SOCIAL_PREFIX = {
+ "github": "https://github.com/",
+ "linkedin": "https://www.linkedin.com/",
+ "twitter": "https://x.com/",
+}
+
+
+def check_social(people, sponsors):
+ """Check the shape of every social link in a person or sponsor file.
+
+ Nothing else checks these. The link checker in CI reads the built pages,
+ and a URL broken badly enough is not rendered as a link at all: one
+ person's LinkedIn was `ttps://www.linkedin.com/...`, missing the h, which
+ a browser treats as a relative path. It had never worked and nobody had
+ noticed.
+ """
+ for page_id, path in sorted({**people, **sponsors}.items()):
+ data = front_matter(path) or {}
+ for field, prefix in SOCIAL_PREFIX.items():
+ value = data.get(field)
+ if not value:
+ continue
+ value = str(value).strip()
+ if "?" in value:
+ error(path, f"{field} carries query parameters: '{value}'. "
+ f"Copy the profile URL, not the one the browser "
+ f"was showing.")
+ elif not value.startswith(prefix):
+ error(path, f"{field} is '{value}', which does not start with "
+ f"{prefix}")
+
+ site = data.get("site")
+ if site:
+ site = str(site).strip()
+ if "?" in site:
+ error(path, f"site carries query parameters: '{site}'")
+ elif not site.startswith(("https://", "http://")):
+ error(path, f"site is '{site}', which is not an http or https URL")
+ elif site.startswith("http://"):
+ warn(path, f"site is served over http, not https: '{site}'")
+
+
def check_logos(sponsors):
"""A sponsor whose declared logo file is missing renders a broken image, and
the Hugo build does not notice. A sponsor with no logo_image at all is only
@@ -383,6 +430,7 @@ def main():
sponsors = collect_ids("sponsors")
check_photos(people)
check_logos(sponsors)
+ check_social(people, sponsors)
listed_people = check_listings(people, sponsors)
check_agenda()
check_orphans(people, listed_people)
diff --git a/config.toml b/config.toml
index d16a15de..482bf2ca 100644
--- a/config.toml
+++ b/config.toml
@@ -76,7 +76,7 @@ unsafe=true
[params.social_items.twitter]
name = "X"
icon = "icon_x fa-2x"
- link = "https://twitter.com/PyBCN"
+ link = "https://x.com/PyBCN"
[params.social_items.youtube]
name = "YouTube"
link = "https://www.youtube.com/c/PythonBarcelona"
@@ -102,7 +102,7 @@ unsafe=true
[params.social_items_pyladies.twitter]
name = "X"
icon = "icon_x fa-2x"
- link = "https://twitter.com/PyLadiesBCN"
+ link = "https://x.com/PyLadiesBCN"
[params.social_items_pyladies.meetup]
name = "Meetup"
link = "https://www.meetup.com/PyLadies-BCN"
diff --git a/content/people/albert-franzi.md b/content/people/albert-franzi.md
index adbebb52..27425030 100644
--- a/content/people/albert-franzi.md
+++ b/content/people/albert-franzi.md
@@ -5,6 +5,6 @@ short_bio: "Fell so in love with data that ended up as Head of Data Platform at
photo: albert-franzi-cros.jpg
photo_anchor: Left
-twitter: https://twitter.com/franzicros
+twitter: https://x.com/franzicros
linkedin: https://www.linkedin.com/in/albertfranzi/
---
diff --git a/content/people/alberto-labarga.md b/content/people/alberto-labarga.md
index 7ca4511c..eb8750cb 100644
--- a/content/people/alberto-labarga.md
+++ b/content/people/alberto-labarga.md
@@ -4,7 +4,7 @@ name: "Alberto Labarga"
photo: "alberto-labarga.jpg"
linkedin: "https://www.linkedin.com/in/albertolabarga"
github: "https://github.com/alabarga"
-twitter: "https://twitter.com/alabarga"
+twitter: "https://x.com/alabarga"
---
With a background in Biomedical Engineering and Bioinformatics, for the last fifteen years I have been involved in biomedical data science projects and systems administration, both at University and research centers, and as professional activity at several start-ups company which I contributed to create.
diff --git a/content/people/alberto.md b/content/people/alberto.md
index a0416ba4..87178cb0 100644
--- a/content/people/alberto.md
+++ b/content/people/alberto.md
@@ -1,10 +1,11 @@
---
id: alberto
name: "Alberto Cámara"
+github: https://github.com/ber2
short_bio: "Senior Data Scientist at Hybrid Theory"
photo: alberto-camara.jpg
pybcn_position: PyBCN Organizer
-twitter: "https://twitter.com/b3r2s"
+twitter: "https://x.com/b3r2s"
linkedin: "https://www.linkedin.com/in/alberto-camara/"
---
diff --git a/content/people/alejandro-nicolas.md b/content/people/alejandro-nicolas.md
index 7e963e6a..d734ae28 100644
--- a/content/people/alejandro-nicolas.md
+++ b/content/people/alejandro-nicolas.md
@@ -5,7 +5,7 @@ short_bio: "Alejandro is a Full Stack developer who has seen his career graduall
photo: alejandro-nicolas.jpg
photo_anchor: Bottom
-twitter: https://twitter.com/sander_pm
-linkedin: www.linkedin.com/in/alejandro-nicolàs-ruiz-73915711a
+twitter: https://x.com/sander_pm
+linkedin: https://www.linkedin.com/in/alejandro-nicolàs-ruiz-73915711a
github: https://github.com/Qouter
---
diff --git a/content/people/alex-molas.md b/content/people/alex-molas.md
index 4e1f5d9a..d7b40606 100644
--- a/content/people/alex-molas.md
+++ b/content/people/alex-molas.md
@@ -4,7 +4,7 @@ name: Alex Molas
short_bio: ""
photo: alex-molas.png
-github: https://www.github.com/alexmolas
+github: https://github.com/alexmolas
twitter: https://x.com/molasalex
linkedin: https://www.linkedin.com/in/alex-molas
---
diff --git a/content/people/alexandre-savio.md b/content/people/alexandre-savio.md
index e7b8765a..ecdf5b6f 100644
--- a/content/people/alexandre-savio.md
+++ b/content/people/alexandre-savio.md
@@ -5,6 +5,6 @@ short_bio: Freelance Software Engineer, specializing in Python, Cloud, DevOps, n
photo: alexandre-savio.jpg
photo_anchor: Top
-twitter: https://twitter.com/alex_savio
+twitter: https://x.com/alex_savio
linkedin: https://www.linkedin.com/in/alexsavio
---
diff --git a/content/people/alicia-morales.md b/content/people/alicia-morales.md
index 7dff20f0..8d2574d6 100644
--- a/content/people/alicia-morales.md
+++ b/content/people/alicia-morales.md
@@ -8,7 +8,7 @@ photo_anchor: Top
pybcn_position: PyBCN Organizer
-twitter: https://twitter.com/amoralca16
+twitter: https://x.com/amoralca16
github: https://github.com/amoralca16
linkedin: https://www.linkedin.com/in/%F0%9F%91%A9%E2%80%8D%F0%9F%92%BB-alicia-morales-carrasco-81a3ba89/
site: https://amoralca16.github.io/
diff --git a/content/people/alvaro-duran-barata.md b/content/people/alvaro-duran-barata.md
index 9fdfebfe..e2137f0a 100644
--- a/content/people/alvaro-duran-barata.md
+++ b/content/people/alvaro-duran-barata.md
@@ -5,7 +5,7 @@ short_bio: NLP/ML engineer
photo: alvaro-duran-barata.jpeg
photo_anchor: Top
-linkedin: https://es.linkedin.com/in/alvaroduranbarata
+linkedin: https://www.linkedin.com/in/alvaroduranbarata
github: https://github.com/ohduran
---
diff --git a/content/people/amalia_vradi.md b/content/people/amalia_vradi.md
index 6a39fc60..afaf140b 100644
--- a/content/people/amalia_vradi.md
+++ b/content/people/amalia_vradi.md
@@ -4,7 +4,7 @@ name: "Amalia Vradi"
short_bio: "Data Scientist"
photo: amalia-vradi.jpg
pybcn_position: PyLadiesBCN Collaborator
-linkedin: "www.linkedin.com/in/amaliavradi"
+linkedin: "https://www.linkedin.com/in/amaliavradi"
github: "https://github.com/amaliavr"
---
diff --git a/content/people/angel.md b/content/people/angel.md
index c0a32d63..70a2d67f 100644
--- a/content/people/angel.md
+++ b/content/people/angel.md
@@ -2,9 +2,9 @@
id: angel
name: Àngel Fernández Ibáñez
short_bio: "Software Engineer at Holaluz, with experience in web applications and data pipelines. Trying to leave the world better than I found it."
-twitter: "https://twitter.com/anxodio"
+twitter: "https://x.com/anxodio"
linkedin: "https://www.linkedin.com/in/anxodio/"
-github: "https://www.github.com/anxodio"
+github: "https://github.com/anxodio"
photo: angel-fernandez-ibanez.jpg
photo_anchor: Right
pybcn_position: PyBCN Collaborator
diff --git a/content/people/ankit-mahato.md b/content/people/ankit-mahato.md
index c240424a..efcfbfeb 100644
--- a/content/people/ankit-mahato.md
+++ b/content/people/ankit-mahato.md
@@ -4,7 +4,7 @@ name: Ankit Mahato
short_bio: Ankit is a die hard Pythonista & an open source contributor (titus2, numba) with more than 8 years of experience in scientific computing, ML, visualization and the entire data analytics pipeline.
photo: ankit-mahato.png
-twitter: https://twitter.com/ankitmahato
+twitter: https://x.com/ankitmahato
linkedin: https://www.linkedin.com/in/ankitmahato/
github: https://github.com/animator
site: https://realworldpython.guide
diff --git a/content/people/anton-caceres.md b/content/people/anton-caceres.md
index 1473b40f..d61eb947 100644
--- a/content/people/anton-caceres.md
+++ b/content/people/anton-caceres.md
@@ -5,6 +5,6 @@ short_bio: Python dev running an agency in Munich and organizing tech events.
photo: anton-caceres.jpg
photo_anchor: Top
-twitter: https://twitter.com/anton_caceres
+twitter: https://x.com/anton_caceres
linkedin: https://www.linkedin.com/in/antoncaceres
---
diff --git a/content/people/antonio-molina.md b/content/people/antonio-molina.md
index 800539e5..4f2c89b9 100644
--- a/content/people/antonio-molina.md
+++ b/content/people/antonio-molina.md
@@ -3,7 +3,7 @@ id: antonio-molina
name: Antonio Molina
photo: antonio-molina.jpg
-twitter: https://twitter.com/aydevosotros
+twitter: https://x.com/aydevosotros
linkedin: https://www.linkedin.com/in/amolinag/
github: https://github.com/aydevosotros
---
diff --git a/content/people/biel-stela-ballester.md b/content/people/biel-stela-ballester.md
index d377ec53..b7571fc9 100644
--- a/content/people/biel-stela-ballester.md
+++ b/content/people/biel-stela-ballester.md
@@ -3,7 +3,7 @@ id: biel-stela-ballester
name: "Biel Stela Ballester"
photo: biel-stela-ballester.jpg
github: "https://github.com/BielStela"
-twitter: "https://twitter.com/batx00"
+twitter: "https://x.com/batx00"
---
diff --git a/content/people/camilo-chacon.md b/content/people/camilo-chacon.md
index d2c4c0a6..f47c4f13 100644
--- a/content/people/camilo-chacon.md
+++ b/content/people/camilo-chacon.md
@@ -2,7 +2,7 @@
id: camilo-chacon
name: Camilo Chacón Sartori
photo: camilo-chacon-sartori.jpg
-twitter: https://twitter.com/camilo_chacon_s
+twitter: https://x.com/camilo_chacon_s
linkedin: https://www.linkedin.com/in/camilo-chacon-sartori/
---
diff --git a/content/people/carlton-gibson.md b/content/people/carlton-gibson.md
index 3cb0c1fa..8cc0fae2 100644
--- a/content/people/carlton-gibson.md
+++ b/content/people/carlton-gibson.md
@@ -2,7 +2,7 @@
id: carlton-gibson
name: "Carlton Gibson"
photo: carlton-gibson.jpg
-twitter: "https://twitter.com/carltongibson"
+twitter: "https://x.com/carltongibson"
---
Long-time Django user, current Django Fellow, and maintainer of several key packages in the Django ecosystem. Husband and father of four.
\ No newline at end of file
diff --git a/content/people/carmen-iniesta-lopez.md b/content/people/carmen-iniesta-lopez.md
index 4e2468b3..be4daef6 100644
--- a/content/people/carmen-iniesta-lopez.md
+++ b/content/people/carmen-iniesta-lopez.md
@@ -5,7 +5,7 @@ short_bio: NLP/ML engineer
photo: carmen-iniesta-lopez.jpg
linkedin: https://www.linkedin.com/in/carmen-iniesta-lopez/
github: https://github.com/Ciniesta
-twitter: https://twitter.com/Carmenisst
+twitter: https://x.com/Carmenisst
---
NLP/ML engineer @ Nuclia. Passionate about nlp, data and ethics. Find me in the mountains :)
\ No newline at end of file
diff --git a/content/people/cheuk-ting-ho.md b/content/people/cheuk-ting-ho.md
index dee66fb2..8e5a8880 100644
--- a/content/people/cheuk-ting-ho.md
+++ b/content/people/cheuk-ting-ho.md
@@ -4,7 +4,7 @@ name: "Cheuk Ting Ho"
photo: "cheuk-ting-ho.jpg"
linkedin: "https://www.linkedin.com/in/cheukting-ho"
github: "https://github.com/Cheukting"
-twitter: "https://twitter.com/cheukting_ho"
+twitter: "https://x.com/cheukting_ho"
---
After having a career in data science, Cheuk now brings her knowledge in data and passion for the tech community as the developer advocate for Anaconda. Cheuk constantly contributes to the open-source community by giving free talks and tutorials and organize sprints to encourage diversity contributions.
diff --git a/content/people/christian-adell.md b/content/people/christian-adell.md
index 90bd8c6d..d46a4599 100644
--- a/content/people/christian-adell.md
+++ b/content/people/christian-adell.md
@@ -3,7 +3,7 @@ id: christian-adell
name: Christian Adell
photo: christian-adell.jpg
-twitter: https://twitter.com/chadell0
+twitter: https://x.com/chadell0
linkedin: https://www.linkedin.com/in/christianadell/
github: https://github.com/chadell
site: https://www.netbcn.cat/
diff --git a/content/people/daniel-mesejo.md b/content/people/daniel-mesejo.md
index 9e4d2fbf..69f59466 100644
--- a/content/people/daniel-mesejo.md
+++ b/content/people/daniel-mesejo.md
@@ -1,6 +1,7 @@
---
id: daniel-mesejo
name: "Daniel Mesejo Leon"
+github: https://github.com/mesejo
photo: daniel-mesejo-leon.jpg
photo_anchor: Top
diff --git a/content/people/daniel-sanchez-santolaya.md b/content/people/daniel-sanchez-santolaya.md
index 1559faba..934e56e6 100644
--- a/content/people/daniel-sanchez-santolaya.md
+++ b/content/people/daniel-sanchez-santolaya.md
@@ -3,7 +3,7 @@ id: daniel-sanchez-santolaya
name: Daniel Sanchez Santolaya
short_bio: Data Scientist
photo: daniel-sanchez-santolaya.jpg
-twitter: https://twitter.com/danisbd89
+twitter: https://x.com/danisbd89
linkedin: https://www.linkedin.com/in/daniel-sanchez-santolaya/
github: https://github.com/DaniSanchezSantolaya
---
diff --git a/content/people/david-de-la-iglesia-castro.md b/content/people/david-de-la-iglesia-castro.md
index 03cb5674..01dcbda4 100644
--- a/content/people/david-de-la-iglesia-castro.md
+++ b/content/people/david-de-la-iglesia-castro.md
@@ -4,7 +4,7 @@ name: David de la Iglesia Castro
short_bio: "David is a `Software Engineer` at https://iterative.ai/, where he mainly works on open source tools like [DVC](https://github.com/iterative/dvc) and [DVCLive](https://github.com/iterative/dvclive). Before that, he was a `Senior Computer Vision Researcher` at [Gradiant](https://www.gradiant.org/)"
photo: david-de-la-iglesia-castro.jpg
-twitter: https://twitter.com/daviddelachurch
+twitter: https://x.com/daviddelachurch
github: https://github.com/daavoo
linkedin: https://www.linkedin.com/in/david-de-la-iglesia-castro-b4b67b20a/
---
diff --git a/content/people/david.md b/content/people/david.md
index ad71a017..df4596bf 100644
--- a/content/people/david.md
+++ b/content/people/david.md
@@ -5,8 +5,8 @@ short_bio: Distributed systems, scalability, security, Python
photo: david-arcos.jpg
pybcn_position: PyBCN Organizer
-twitter: https://twitter.com/DZPM
+twitter: https://x.com/DZPM
linkedin: https://www.linkedin.com/in/davidarcos/
-github: https://www.github.com/DZPM
-site: https://davidarcos.net/blog/
+github: https://github.com/DZPM
+site: https://davidarcos.net/
---
diff --git a/content/people/edgar-riba.md b/content/people/edgar-riba.md
index aabb8709..807e5c2d 100644
--- a/content/people/edgar-riba.md
+++ b/content/people/edgar-riba.md
@@ -4,7 +4,7 @@ name: Edgar Riba
short_bio: Edgar Riba is a research scientist at Institut de Robòtica i Informàtica Industrial, Barcelona (CSIC-UPC) and PhD candidate at the Computer Vision Center at Universitat Autònoma de Barcelona. His interests are in Geometric Computer Vision for Scene Reconstruction using deep learning technologies, and developing useful tools for researchers. Enthusiastic about the free and open-source software culture, he became an active member and contributor of the OpenCV community after his participation in the Google Summer of Code 2014-2020 as a student and later as a mentor. Currently, he is a member of the Technical Committee of the OpenCV.org and founding member and main contributor of Kornia, an open source differentiable computer vision library for PyTorch.
photo: edgar-riba.jpg
-twitter: https://twitter.com/edgarriba
+twitter: https://x.com/edgarriba
linkedin: https://www.linkedin.com/in/edgarriba/
github: https://github.com/edgarriba
site: https://kornia.github.io/
diff --git a/content/people/eduard_cespedes.md b/content/people/eduard_cespedes.md
index 2a57904b..8ee7fefc 100644
--- a/content/people/eduard_cespedes.md
+++ b/content/people/eduard_cespedes.md
@@ -3,8 +3,8 @@ id: eduard_cespedes
name: Eduard Céspedes Borràs
short_bio: I'm a passionate Software Architect that loves to learn and that enjoys being out of the comfort zone, being faced with a great challenge and having to overcome it to achieve the goal! That's why I've been CTO in Belgium, I've created and streaming platform for an Australian company, I've worked as a senior frontend developer for a New Zealand company, I've done trainings for an Argentinian company and I've advised one of the biggest companies in Singapore. I'm good at what I do because I love what I do, and you can see it in how I work.
photo: eduard-cespedes-borras.jpg
-twitter: https://twitter.com/haduart
+twitter: https://x.com/haduart
linkedin: https://www.linkedin.com/in/eduardcespedesborras/
github: https://github.com/haduart/
-site: http://orkei.com/?lang=en
+site: http://orkei.com/
---
diff --git a/content/people/elisabeth-ortega-carrasco.md b/content/people/elisabeth-ortega-carrasco.md
index dda99cd4..14c7cfda 100644
--- a/content/people/elisabeth-ortega-carrasco.md
+++ b/content/people/elisabeth-ortega-carrasco.md
@@ -7,7 +7,7 @@ photo: elisabeth-ortega-carrasco.jpg
pybcn_position: PyLadiesBCN Collaborator
-twitter: https://twitter.com/draentropia
+twitter: https://x.com/draentropia
github: https://github.com/draentropia
---
diff --git a/content/people/eloi.md b/content/people/eloi.md
index a03943f1..c957f201 100644
--- a/content/people/eloi.md
+++ b/content/people/eloi.md
@@ -5,7 +5,7 @@ short_bio: "Teaching Software Engineering, Distributed Software and Robotics in
pybcn_position: "PyBCN organizer"
photo: eloi-puertas-prats.jpg
photo_anchor: Bottom
-twitter: "https://twitter.com/eloipuertas"
+twitter: "https://x.com/eloipuertas"
linkedin: "https://www.linkedin.com/in/eloipuertas/"
-github: "https://www.github.com/eloipuertas"
+github: "https://github.com/eloipuertas"
---
diff --git a/content/people/enric-domingo.md b/content/people/enric-domingo.md
index 5b67e96f..748f60c7 100644
--- a/content/people/enric-domingo.md
+++ b/content/people/enric-domingo.md
@@ -4,6 +4,6 @@ name: "Enric Domingo"
short_bio: ""
photo: "enric-domingo.jpg"
linkedin: "https://www.linkedin.com/in/e-domingo/"
-github: "https://www.github.com/enricd"
+github: "https://github.com/enricd"
site: "https://www.enricdomingo.com"
---
\ No newline at end of file
diff --git a/content/people/esperanza-buitrago.md b/content/people/esperanza-buitrago.md
index 853ef027..f1f8392b 100644
--- a/content/people/esperanza-buitrago.md
+++ b/content/people/esperanza-buitrago.md
@@ -5,7 +5,7 @@ short_bio: "Esperanza is a mathematician with a specialty in logic. She has been
photo: esperanza-buitrago.jpg
photo_anchor: Top
-twitter: https://twitter.com/ebuitragod
+twitter: https://x.com/ebuitragod
linkedin: https://www.linkedin.com/in/ebuitragod/
-github: https://www.github.com/ebuitragod
+github: https://github.com/ebuitragod
---
diff --git a/content/people/esteve.md b/content/people/esteve.md
index 5d00c4f8..247c2d06 100644
--- a/content/people/esteve.md
+++ b/content/people/esteve.md
@@ -5,7 +5,7 @@ short_bio: "Robots, art, running, movies, theatre and cheese, in no
particular order"
photo: esteve-fernandez.jpg
pybcn_position: "PyBCN Collaborator"
-twitter: "https://twitter.com/esteve"
+twitter: "https://x.com/esteve"
linkedin: "https://www.linkedin.com/in/estevefernandez"
-github: "https://www.github.com/esteve"
+github: "https://github.com/esteve"
---
diff --git a/content/people/ferran-fabregas.md b/content/people/ferran-fabregas.md
index ef65ac57..76c09116 100644
--- a/content/people/ferran-fabregas.md
+++ b/content/people/ferran-fabregas.md
@@ -3,7 +3,7 @@ id: ferran-fabregas
name: "Ferran Fàbregas"
short_bio: Computer scientist and programmer by profession, I started in the "maker" world 7 years ago, in which I have developed a cross-disciplinary knowledge in different disciplines of digital manufacturing, electronics, robotics, micro-controller programming and education, trying to turn my passion into a full-time job.
photo: ferran-fabregas.png
-twitter: https://twitter.com/ferrithemaker
+twitter: https://x.com/ferrithemaker
linkedin: https://www.linkedin.com/in/ferran-fabregas-94a68525/
github: https://github.com/ferrithemaker
site: https://ferranfabregas.me/
diff --git a/content/people/ferran-jovell.md b/content/people/ferran-jovell.md
index 02f94910..c8109000 100644
--- a/content/people/ferran-jovell.md
+++ b/content/people/ferran-jovell.md
@@ -1,6 +1,7 @@
---
id: ferran-jovell
name: "Ferran Jovell"
+github: https://github.com/mrswats
photo: "ferran-jovell.jpg"
pybcn_position: PyBCN Organizer
diff --git a/content/people/francesco-faraone.md b/content/people/francesco-faraone.md
index 1e45a642..73c078a5 100644
--- a/content/people/francesco-faraone.md
+++ b/content/people/francesco-faraone.md
@@ -5,7 +5,7 @@ short_bio: "Neapolitan by birth, Barcelonian by adoption, I started programming
photo: francesco-faraone.png
photo_anchor: Bottom
-twitter: https://twitter.com/cicfaraone
+twitter: https://x.com/cicfaraone
linkedin: https://www.linkedin.com/in/francesco-faraone-01568a8/
github: https://github.com/ffaraoneim
site: https://github.com/ffaraone
diff --git a/content/people/gabriel-de-maeztu.md b/content/people/gabriel-de-maeztu.md
index 9cb4af1a..390a14f5 100644
--- a/content/people/gabriel-de-maeztu.md
+++ b/content/people/gabriel-de-maeztu.md
@@ -5,9 +5,9 @@ short_bio: Medical doctor and mathematician, during my work as a researcher, I f
photo: gabriel-de-maeztu.jpg
photo_anchor: Bottom
-twitter: https://twitter.com/gabimaeztu
+twitter: https://x.com/gabimaeztu
github: https://github.com/merqurio
xxxgitlab: https://gitlab.com/merqurio
-linkedin: https://linkedin.com/in/gabrieldemaeztu
+linkedin: https://www.linkedin.com/in/gabrieldemaeztu
---
diff --git a/content/people/gajendra-deshpande.md b/content/people/gajendra-deshpande.md
index c2f25a0c..a269677d 100644
--- a/content/people/gajendra-deshpande.md
+++ b/content/people/gajendra-deshpande.md
@@ -4,7 +4,7 @@ name: Gajendra Deshpande
short_bio: I have delivered talks at SciPy India, PyCon FR, PyCon HK and JuliaCon. I use Python extensively for teaching and research. My major work includes using Python to develop prototypes in the field of Cyber Security. I lead PyData Belagavi and OWASP Belagavi chapters. I love to mentor students and volunteer at Free and Open Source events.
photo: gajendra-deshpande.jpg
-twitter: https://twitter.com/gcdeshpande
+twitter: https://x.com/gcdeshpande
linkedin: https://www.linkedin.com/in/gajendradeshpande
github: https://github.com/gcdeshpande
site: https://gcdeshpande.github.io/
diff --git a/content/people/gema-parreno.md b/content/people/gema-parreno.md
index 3725cba5..1c65e4cf 100644
--- a/content/people/gema-parreno.md
+++ b/content/people/gema-parreno.md
@@ -4,7 +4,7 @@ name: "Gema Parreño"
photo: gema-parreno.jpg
linkedin: "https://www.linkedin.com/in/gemaparreno/"
github: "https://github.com/SoyGema"
-twitter: "https://twitter.com/SoyGema"
+twitter: "https://x.com/SoyGema"
---
Gema is a data scientist that has created Deep Asteroid, a program that detect Asteroids impact on earth . Besides, she has contributed to StarCraft II pySC2 Open Source library. She likes everything data and machine learning related.
diff --git a/content/people/ifosch.md b/content/people/ifosch.md
index 0d1366e0..e9369bce 100644
--- a/content/people/ifosch.md
+++ b/content/people/ifosch.md
@@ -5,7 +5,7 @@ short_bio: UN*X Sysadmin and Infra automation with Ruby at Devex, Python and Go
photo: ignasi-fosch.jpg
pybcn_position: PyBCN Practice sessions organizer
-twitter: https://twitter.com/ifosch
+twitter: https://x.com/ifosch
linkedin: https://www.linkedin.com/in/ifosch/
github: https://github.com/ifosch
site: https://natx.cat
diff --git a/content/people/israel-saeta.md b/content/people/israel-saeta.md
index b5204ac9..970e3076 100644
--- a/content/people/israel-saeta.md
+++ b/content/people/israel-saeta.md
@@ -2,7 +2,7 @@
id: israel-saeta
name: "Israel Saeta Pérez"
photo: israel-saeta-perez.jpg
-twitter: "https://twitter.com/dukebody"
+twitter: "https://x.com/dukebody"
---
Fan de Python, el software libre en general y organizar saraos. Socio fundador de PyBCN y ex-presidente de Python España.
diff --git a/content/people/jimena-escobar.md b/content/people/jimena-escobar.md
index d1c266ee..3b4765a5 100644
--- a/content/people/jimena-escobar.md
+++ b/content/people/jimena-escobar.md
@@ -4,7 +4,7 @@ name: "Jimena Escobar Bermúdez"
photo: jimena-escobar-bermudez.jpg
linkedin: "https://www.linkedin.com/in/jimena-eb/"
github: "https://github.com/JimenaEB"
-twitter: "https://twitter.com/Jimena_y_yo"
+twitter: "https://x.com/Jimena_y_yo"
---
I'm Jimena, president of Python Spain, and a woman happy and proud to be a computer engineer. If I had to summarize my role in one sentence, it would be "Full Stack developer working on diversity, equity and inclusion (DEI) from a technical perspective and happy to be part of the community.
diff --git a/content/people/johanna-sanchez.md b/content/people/johanna-sanchez.md
index eb4f8a89..1e414af0 100644
--- a/content/people/johanna-sanchez.md
+++ b/content/people/johanna-sanchez.md
@@ -2,7 +2,7 @@
id: johanna-sanchez
name: "Johanna Sanchez"
photo: johanna-sanchez.jpg
-twitter: "https://twitter.com/EllaQuimica"
+twitter: "https://x.com/EllaQuimica"
---
Química & Junior FullStack Developer. Me apasiona
diff --git a/content/people/jordi.md b/content/people/jordi.md
index 9bb59651..d324761d 100644
--- a/content/people/jordi.md
+++ b/content/people/jordi.md
@@ -7,7 +7,7 @@ short_bio: I love music, computers, cinema, photography and mixing them
pybcn_position: PyBCN Organizer
-twitter: https://twitter.com/jordixou
+twitter: https://x.com/jordixou
linkedin: https://www.linkedin.com/in/jsoucheiron
github: https://github.com/jsoucheiron
---
diff --git a/content/people/jose-riera.md b/content/people/jose-riera.md
index 700ec517..837e8eb0 100644
--- a/content/people/jose-riera.md
+++ b/content/people/jose-riera.md
@@ -8,7 +8,7 @@ short_bio: Engineering Manager. Building Product + Tech + Data. Colaborador de l
pybcn_position: PyBCN Organizer
twitter: https://x.com/jhrs21
-linkedin: https://es.linkedin.com/in/josehriera
+linkedin: https://www.linkedin.com/in/josehriera
diff --git a/content/people/jose_haro.md b/content/people/jose_haro.md
index 14a33c17..0351f963 100644
--- a/content/people/jose_haro.md
+++ b/content/people/jose_haro.md
@@ -5,7 +5,7 @@ short_bio: Jose Haro Peralta is a full-stack software consultant specialising in
photo: jose-haro-peralta.png
photo_anchor: Top
-twitter: https://twitter.com/JoseHaroPeralta
+twitter: https://x.com/JoseHaroPeralta
linkedin: https://www.linkedin.com/in/jose-haro-peralta/
github: https://github.com/abunuwas
---
diff --git a/content/people/josep.md b/content/people/josep.md
index 65ee9d94..64d3654d 100644
--- a/content/people/josep.md
+++ b/content/people/josep.md
@@ -3,8 +3,8 @@ id: josep
name: "Josep Martínez Vilà"
short_bio: "Photography, opera, read, table tennis"
pybcn_position: "PyBCN Organizer"
-twitter: "https://twitter.com/jmartinezvila"
-linkedin: "https://es.linkedin.com/in/josepmartinezvila"
+twitter: "https://x.com/jmartinezvila"
+linkedin: "https://www.linkedin.com/in/josepmartinezvila"
github: "https://github.com/josepmv"
photo: josep-martinez-vila.jpg
---
diff --git a/content/people/juan-bernardo-lince.md b/content/people/juan-bernardo-lince.md
index 95e5a471..b12dc9fd 100644
--- a/content/people/juan-bernardo-lince.md
+++ b/content/people/juan-bernardo-lince.md
@@ -3,7 +3,7 @@ id: juan-bernardo-lince
name: Juan Bernardo Lince
short_bio: City Manager
photo: juan-bernardo-lince.jpg
-twitter: https://twitter.com/LinceCabal
+twitter: https://x.com/LinceCabal
linkedin: https://www.linkedin.com/in/juanblince/
github: https://github.com/jblince
---
diff --git a/content/people/juan-luis-cano.md b/content/people/juan-luis-cano.md
index 39d9355a..75976335 100644
--- a/content/people/juan-luis-cano.md
+++ b/content/people/juan-luis-cano.md
@@ -3,9 +3,9 @@ id: juan-luis-cano
name: Juan Luis Cano Rodríguez
short_bio: Aerospace Engineer with a passion for STEM, programming, outreach, and sustainability
photo: juan-luis-cano-rodriguez.jpg
-twitter: https://social.juanlu.space/@astrojuanlu
linkedin: https://www.linkedin.com/in/juanluiscanor/
github: https://github.com/astrojuanlu/
+site: https://social.juanlu.space/@astrojuanlu
---
Juan Luis (he/him/él) is an Aerospace Engineer with a passion for STEM, programming, outreach, and sustainability. He works as Developer Advocate for Kedro, an opinionated data science framework, at QuantumBlack, AI by McKinsey. He has worked as Developer Advocate at Read the Docs, as software engineer in the space, consulting, and banking industries, and as a Python trainer for several private and public entities.
diff --git a/content/people/julio-martinez.md b/content/people/julio-martinez.md
index 7cbdcf06..28985bde 100644
--- a/content/people/julio-martinez.md
+++ b/content/people/julio-martinez.md
@@ -4,7 +4,7 @@ name: Julio Martinez
short_bio: Julio is a senior developer, who has been working in the retail and advertisement industries since 2001 in different roles, while he's been speaker in several conferences. With a master in Natural Language Processing, he tries to keep his skills updated with the last NLP novelties.
photo: julio-martinez.jpg
-twitter: https://twitter.com/liopic
+twitter: https://x.com/liopic
linkedin: https://www.linkedin.com/in/liopic/
github: https://github.com/liopic
site: http://www.liopic.me/
diff --git a/content/people/kemalcan-bora.md b/content/people/kemalcan-bora.md
index 00fa978a..aa9460e7 100644
--- a/content/people/kemalcan-bora.md
+++ b/content/people/kemalcan-bora.md
@@ -4,7 +4,7 @@ name: "Kemalcan Bora"
photo: "kemalcan-bora.jpg"
linkedin: "https://www.linkedin.com/in/kemalcanbora/"
github: "https://github.com/kemalcanbora"
-twitter: "https://twitter.com/KemalcanBora"
+twitter: "https://x.com/KemalcanBora"
---
Software Architect with over a decade of experience in cloud computing and distributed systems. Currently combining work as a Software Architect at AGCO with pursuing a Ph.D. in Information and Communication Technologies at Universitat Pompeu Fabra. As an AWS Community Builder and AWS Certified Machine Learning Specialist, brings deep expertise in cloud-native solutions, particularly in Go and Python development. Career highlights include leading major system modernization projects that achieved significant cost reductions and implementing microservices architectures. Passionate about open-source contributions and actively participates in the developer community.
diff --git a/content/people/laysa-uchoa.md b/content/people/laysa-uchoa.md
index 4186e038..d52e6650 100644
--- a/content/people/laysa-uchoa.md
+++ b/content/people/laysa-uchoa.md
@@ -4,7 +4,7 @@ name: Laysa Uchoa
short_bio: "Python dev and Pyladies Munich organizer. I believe that technology can make the world more democratic and just better - let's contribute to this."
photo: laysa-uchoa.jpg
-twitter: https://twitter.com/laysauchoa
+twitter: https://x.com/laysauchoa
linkedin: https://www.linkedin.com/in/laysauchoa/
github: https://github.com/laysauchoa
diff --git a/content/people/loris.md b/content/people/loris.md
index b04cef13..bab8af57 100644
--- a/content/people/loris.md
+++ b/content/people/loris.md
@@ -6,7 +6,7 @@ short_bio: bioinformatics
pybcn_position: PyBCN Meetup organizer
-twitter: https://twitter.com/LorisMularoni
+twitter: https://x.com/LorisMularoni
github: https://github.com/batterio
linkedin: https://www.linkedin.com/in/mularoni-loris-a67094a
---
diff --git a/content/people/lpmayos-president.md b/content/people/lpmayos-president.md
index a4f166e5..e4ff9304 100644
--- a/content/people/lpmayos-president.md
+++ b/content/people/lpmayos-president.md
@@ -8,7 +8,7 @@ site: https://lpmayos.github.io/
pybcn_position: "PyBCN Former President"
linkedin: "https://www.linkedin.com/in/lpmayos/"
-github: "https://www.github.com/lpmayos"
+github: "https://github.com/lpmayos"
---
diff --git a/content/people/lpmayos.md b/content/people/lpmayos.md
index cca939e4..d0407561 100644
--- a/content/people/lpmayos.md
+++ b/content/people/lpmayos.md
@@ -8,7 +8,7 @@ site: https://lpmayos.github.io/
pybcn_position: "PyLadiesBCN Organizer"
linkedin: "https://www.linkedin.com/in/lpmayos/"
-github: "https://www.github.com/lpmayos"
+github: "https://github.com/lpmayos"
---
diff --git a/content/people/marc-pous.md b/content/people/marc-pous.md
index c3289993..cfef91d6 100644
--- a/content/people/marc-pous.md
+++ b/content/people/marc-pous.md
@@ -4,7 +4,7 @@ name: Marc Pous
short_bio: "Marc is currently the balena.io Developer Advocate. Former co-founder of the IoT platform thethings.iO startup. He has more than 15 years of experience connecting things to the Internet.
Marc is a co-founder of the IoT Coffee Talk and member of the Internet of Things Council. He is also responsible for managing the IoT communities in Barcelona and Munich, organizing meetups and inviting up-and-coming IoT companies to pitch their products. Furthermore, he is responsible for co-organizing the international event IoT Stars during the MWC at Barcelona.
He creates IoT products as a hobby, from a connected sofa for a music festival, ATMs for a research project, beer mugs in Munich’s Oktoberfest to Christmas lights that light up when you tweet. His advocacy efforts for the Internet of Things and his stature (6,9 feet) has earned him the nickname IoT Giant. You can follow and ping him at his Twitter account @gy4nt."
photo: marc-pous.jpg
-twitter: https://twitter.com/gy4nt
+twitter: https://x.com/gy4nt
linkedin: https://www.linkedin.com/in/marcpous/
github: https://github.com/mpous
site: http://marcpous.com
diff --git a/content/people/mariana-meireles.md b/content/people/mariana-meireles.md
index b40f5cec..c9758263 100644
--- a/content/people/mariana-meireles.md
+++ b/content/people/mariana-meireles.md
@@ -4,8 +4,8 @@ name: Mariana Meireles
short_bio: "I care deeply about the impacts that technology has in the world and try my best to be the change I want to see by contributing to open source projects that stand upon libre and diverse standards. I’m currently focusing on the Jupyter ecosystem and advocating for open science and open knowledge whenever I can."
photo: mariana-meireles.png
-twitter: https://twitter.com/mari_meir
+twitter: https://x.com/mari_meir
linkedin: https://www.linkedin.com/in/mariana-meireles
-github: https://www.github.com/marimeireles
+github: https://github.com/marimeireles
site: https://psychonautgirl.space
---
diff --git a/content/people/miquel-sarrias.md b/content/people/miquel-sarrias.md
index c34433d4..8af100e3 100644
--- a/content/people/miquel-sarrias.md
+++ b/content/people/miquel-sarrias.md
@@ -6,7 +6,7 @@ photo: miquel-sarrias.jpg
photo_anchor: Top
linkedin: https://www.linkedin.com/in/miquel-s%C3%A0rrias-mont%C3%B3n-aa5067129/
-twitter: https://twitter.com/MiquelSarrias
+twitter: https://x.com/MiquelSarrias
---
Python enthusiast, innovating in the water sector for cetaqua, the Spanish water technology center.
\ No newline at end of file
diff --git a/content/people/miroslav_sedivy.md b/content/people/miroslav_sedivy.md
index 117a8176..e39c55e2 100644
--- a/content/people/miroslav_sedivy.md
+++ b/content/people/miroslav_sedivy.md
@@ -3,7 +3,7 @@ id: miroslav_sedivy
name: "Miroslav Šedivý"
short_bio: "Greedy polyglot, data & open source rhymer, python3 charmer, sustainable urbanist, unicode collector, wandering openstreetmapper, and an hjkl juggler."
photo: miroslav-sedivy.jpg
-twitter: "https://twitter.com/eumiro"
+twitter: "https://x.com/eumiro"
linkedin: "https://www.linkedin.com/in/eumiro/"
github: "https://github.com/eumiro"
site: https://eumiro.github.io
diff --git a/content/people/monica-dominguez.md b/content/people/monica-dominguez.md
index babb23b5..da61f64c 100644
--- a/content/people/monica-dominguez.md
+++ b/content/people/monica-dominguez.md
@@ -5,7 +5,7 @@ short_bio: PhD in Computer Science
photo: monica-dominguez.jpg
linkedin: https://www.linkedin.com/in/monikadominguezbajo
github: https://github.com/monikaUPF
-twitter: https://twitter.com/monikaUPF
+twitter: https://x.com/monikaUPF
---
Monica Dominguez has a PhD in Computer Science and joined the Research Project's department at Aimsun in 2022. She collaborates with the Data Science Department developing data-driven experiments, data analysis and processing related to European Projects and proof of concepts for product development. Her main research line is in Graph Neural Networks applied to traffic forecasting and demand prediction.
\ No newline at end of file
diff --git a/content/people/natalia-secretary.md b/content/people/natalia-secretary.md
index cf77d1b4..51116b0f 100644
--- a/content/people/natalia-secretary.md
+++ b/content/people/natalia-secretary.md
@@ -5,7 +5,7 @@ short_bio: "Research software engineer"
photo: natalia-padilla.jpg
pybcn_position: "PyBCN Former Secretary"
-twitter: "https://twitter.com/nataliasirera"
+twitter: "https://x.com/nataliasirera"
linkedin: "https://www.linkedin.com/in/natàlia-padilla-sirera-8112305a/"
github: "https://github.com/NataliaSirera"
diff --git a/content/people/natalia.md b/content/people/natalia.md
index f1347d1c..5b6db836 100644
--- a/content/people/natalia.md
+++ b/content/people/natalia.md
@@ -5,7 +5,7 @@ short_bio: "Research software engineer"
photo: natalia-padilla.jpg
pybcn_position: "PyLadiesBCN Organizer"
-twitter: "https://twitter.com/nataliasirera"
+twitter: "https://x.com/nataliasirera"
linkedin: "https://www.linkedin.com/in/natàlia-padilla-sirera-8112305a/"
github: "https://github.com/NataliaSirera"
diff --git a/content/people/noe-casas.md b/content/people/noe-casas.md
index 8515dbd9..7d1bfba4 100644
--- a/content/people/noe-casas.md
+++ b/content/people/noe-casas.md
@@ -3,7 +3,7 @@ id: noe-casas
name: " Noé Casas"
photo: noe-casas.png
linkedin: "https://www.linkedin.com/in/noecasas/"
-twitter: "https://twitter.com/noecasas"
+twitter: "https://x.com/noecasas"
---
Noé Casas holds a PhD in deep learning applied to machine translation from Universitat Politècnica de Catalunya (UPC). With 18 years of experience as a software developer, including 2 years dedicated to data science, and a background spanning 5 years in natural language processing and deep learning technologies. He is also an enthusiast of language learning and is currently embarking on his entrepreneurial journey as the founder of Langtern (https://langtern.com), a platform aimed at helping language teachers and students achieve their respective goals more effectively.
\ No newline at end of file
diff --git a/content/people/nuria.md b/content/people/nuria.md
index ea4a2928..d05a63b4 100644
--- a/content/people/nuria.md
+++ b/content/people/nuria.md
@@ -1,10 +1,11 @@
---
id: nuria
name: "Núria Pujol Vilanova"
+github: https://github.com/llevaNEUS
short_bio: ""
photo: nuria-pujol-vilanova.jpg
pybcn_position: "PyLadiesBCN Organizer"
-twitter: "https://twitter.com/llevaneus"
+twitter: "https://x.com/llevaneus"
linkedin: "https://www.linkedin.com/in/n%C3%BAria-pujol-780a145/"
---
diff --git a/content/people/patricia-lamadrid.md b/content/people/patricia-lamadrid.md
index 7cc74947..be46a843 100644
--- a/content/people/patricia-lamadrid.md
+++ b/content/people/patricia-lamadrid.md
@@ -6,7 +6,7 @@ short_bio: Data Engineer - Coding lover - Dressmaker
photo: patricia-lamadrid-robles.jpg
pybcn_position: PyBCN Collaborator
-linkedin: ttps://www.linkedin.com/in/patricia-lamadrid/
+linkedin: https://www.linkedin.com/in/patricia-lamadrid/
github: https://github.com/plamadridr/
---
diff --git a/content/people/patricio-reyes.md b/content/people/patricio-reyes.md
index 97d3068f..6f41474b 100644
--- a/content/people/patricio-reyes.md
+++ b/content/people/patricio-reyes.md
@@ -3,7 +3,7 @@ id: patricio-reyes
name: "Patricio Reyes Valenzuela"
short_bio: "Senior researcher at Barcelona Supercomputing Center (BSC), the National Center for Supercomputing in Spain."
photo: patricio-reyes-valenzuela.jpg
-twitter: "https://twitter.com/pareyesv"
+twitter: "https://x.com/pareyesv"
linkedin: "https://www.linkedin.com/in/patricioreyes"
github: "https://github.com/pareyesv"
---
diff --git a/content/people/pavel-lonkin.md b/content/people/pavel-lonkin.md
index 9766f838..d22b8b9c 100644
--- a/content/people/pavel-lonkin.md
+++ b/content/people/pavel-lonkin.md
@@ -4,7 +4,7 @@ name: "Pavel Lonkin"
photo: "pavel-lonkin.jpg"
linkedin: "https://www.linkedin.com/in/plonkin/"
github: "https://github.com/d3rky"
-twitter: "https://twitter.com/pavel_lonkin"
+twitter: "https://x.com/pavel_lonkin"
---
Hey! I'm Pavel, but, please, call me just Pasha. I relocated just 2 years ago to Barcelona. I'm using python already for 10 years and really love the flexibility of this language. But if you'll ask me what are my most loved programming languages, Python won't be in my top 2. I can explain you why so after several beers in the bar. Now I'm working as a Team Leader, but I never stop writing code and practicing Python. See you on PyDay BCN 2022!
diff --git a/content/people/pere-miquel-brull.md b/content/people/pere-miquel-brull.md
index bd65bbe0..439c3303 100644
--- a/content/people/pere-miquel-brull.md
+++ b/content/people/pere-miquel-brull.md
@@ -4,7 +4,7 @@ name: "Pere Miquel Brull"
photo: pere-miquel-brull.jpg
linkedin: "https://www.linkedin.com/in/pmbrull/"
github: "https://github.com/pmbrull"
-twitter: "https://twitter.com/perembrull"
+twitter: "https://x.com/perembrull"
---
Pere Miquel is a Founding Engineer at Collate, the company behind OpenMetadata. After working as a Data Engineer in different sectors and living through the lack of management and control behind metadata, he's now building a metadata management platform focusing on the collaboration between people and data.
diff --git a/content/people/rberenguel.md b/content/people/rberenguel.md
index 0b7ad9f7..bea0c5c7 100644
--- a/content/people/rberenguel.md
+++ b/content/people/rberenguel.md
@@ -5,9 +5,9 @@ short_bio: "Lead Data Engineer (Python, Scala, Apache Spark) at Hybrid Theory"
photo: ruben-berenguel.png
pybcn_position: PyBCN Organizer
-twitter: "https://twitter.com/berenguel"
+twitter: "https://x.com/berenguel"
linkedin: "https://www.linkedin.com/in/rberenguel/"
-github: https://www.github.com/rberenguel
+github: https://github.com/rberenguel
site: https://mostlymaths.net
---
diff --git a/content/people/ricardo-ander-egg.md b/content/people/ricardo-ander-egg.md
index 72d0672e..e465cf60 100644
--- a/content/people/ricardo-ander-egg.md
+++ b/content/people/ricardo-ander-egg.md
@@ -4,7 +4,7 @@ name: Ricardo Ander-Egg Aguilar
photo: ricardo-ander-egg-aguilar.jpg
photo_anchor: Top
-twitter: https://twitter.com/ricardoanderegg
+twitter: https://x.com/ricardoanderegg
linkedin: https://www.linkedin.com/in/ricardoanderegg/
github: https://github.com/polyrand
---
diff --git a/content/people/ruben-afonso.md b/content/people/ruben-afonso.md
index de2ce15c..7259f83c 100644
--- a/content/people/ruben-afonso.md
+++ b/content/people/ruben-afonso.md
@@ -5,7 +5,7 @@ short_bio: Solutions Architect with AWS
photo: ruben-afonso.png
photo_anchor: Bottom
-twitter: https://twitter.com/rubenafo
+twitter: https://x.com/rubenafo
linkedin: https://www.linkedin.com/in/rubenafonso/
github: https://github.com/rubenafo
---
diff --git a/content/people/sonia-estrade.md b/content/people/sonia-estrade.md
index 16c3afe4..5c360a2b 100644
--- a/content/people/sonia-estrade.md
+++ b/content/people/sonia-estrade.md
@@ -2,7 +2,7 @@
id: sonia-estrade
name: "Sònia Estradé Albiol"
photo: sonia-estrade-albiol.jpg
-twitter: "https://twitter.com/estrade_sonia"
+twitter: "https://x.com/estrade_sonia"
---
Sònia Estradé Albiol is a physicist specializing in electron energy loss spectroscopy and transmission electron microscopy. President of AMIT-Cat and member of the board of PRISMA.
\ No newline at end of file
diff --git a/content/people/vivek-sharma.md b/content/people/vivek-sharma.md
index 1a68da2f..c7a2be16 100644
--- a/content/people/vivek-sharma.md
+++ b/content/people/vivek-sharma.md
@@ -5,7 +5,7 @@ short_bio: "Vivek (They/Them/Theirs) is a Research Assistant at Instituto de Bio
photo: vivek-sharma.jpg
photo_anchor: Top
-twitter: https://twitter.com/Chaotic_Neuron
+twitter: https://x.com/Chaotic_Neuron
linkedin: https://www.linkedin.com/in/vivek-sharma-2715b6129
github: https://github.com/ChaoticNeurons
---
diff --git a/content/people/xavi.md b/content/people/xavi.md
index 2881ab7d..93ed2cda 100644
--- a/content/people/xavi.md
+++ b/content/people/xavi.md
@@ -5,7 +5,7 @@ short_bio: "[passion for passion in ('Python', 'Free Software', 'Privacy', 'Huma
photo: xavi-francisco-gilabert.jpg
pybcn_position: PyBCN Organizer
-twitter: https://twitter.com/srxavi/
+twitter: https://x.com/srxavi/
github: https://github.com/srxavi
linkedin: https://www.linkedin.com/in/xavifrancisco/
---
diff --git a/content/sponsors/affectv.md b/content/sponsors/affectv.md
index 18b275a5..e74026d5 100644
--- a/content/sponsors/affectv.md
+++ b/content/sponsors/affectv.md
@@ -3,6 +3,6 @@ id: affectv
name: affectv
logo_image: affectv.png
web: https://www.affectv.com/
-twitter: https://twitter.com/affectv
+twitter: https://x.com/affectv
---
diff --git a/content/sponsors/aimsun.md b/content/sponsors/aimsun.md
index f6e16b19..cb026d81 100644
--- a/content/sponsors/aimsun.md
+++ b/content/sponsors/aimsun.md
@@ -3,5 +3,5 @@ id: aimsun
name: Aimsun
logo_image: aimsun.jpg
web: https://www.aimsun.com
-twitter: https://twitter.com/aimsun
+twitter: https://x.com/aimsun
---
diff --git a/content/sponsors/apsl.md b/content/sponsors/apsl.md
index ff303c85..1facbb5b 100644
--- a/content/sponsors/apsl.md
+++ b/content/sponsors/apsl.md
@@ -3,5 +3,5 @@ id: apsl
name: APSL
logo_image: apsl.svg
web: https://apsl.tech
-twitter: https://twitter.com/apsl_web
+twitter: https://x.com/apsl_web
---
diff --git a/content/sponsors/casadelmig.md b/content/sponsors/casadelmig.md
index ab1fea5f..7021fe12 100644
--- a/content/sponsors/casadelmig.md
+++ b/content/sponsors/casadelmig.md
@@ -3,5 +3,5 @@ id: casadelmig
name: FAB Casa del Mig - Punt Multimèdia
logo_image: casadelmig.jpg
web: https://www.puntmultimedia.org/
-twitter: https://twitter.com/Puntmultimedia
+twitter: https://x.com/Puntmultimedia
---
diff --git a/content/sponsors/codelytv.md b/content/sponsors/codelytv.md
index 803edde7..9ebade35 100644
--- a/content/sponsors/codelytv.md
+++ b/content/sponsors/codelytv.md
@@ -3,5 +3,5 @@ id: codelytv
name: Codely TV
logo_image: codely.png
web: https://codely.tv/
-twitter: https://twitter.com/CodelyTV
+twitter: https://x.com/CodelyTV
---
diff --git a/content/sponsors/codeop.md b/content/sponsors/codeop.md
index 6ad8cd72..6a201b21 100644
--- a/content/sponsors/codeop.md
+++ b/content/sponsors/codeop.md
@@ -3,6 +3,5 @@ id: codeop
name: CodeOp
logo_image: codeop.png
web: https://codeop.tech/
-twitter:
---
diff --git a/content/sponsors/colorsensing.md b/content/sponsors/colorsensing.md
index ac20d1db..006c3875 100644
--- a/content/sponsors/colorsensing.md
+++ b/content/sponsors/colorsensing.md
@@ -3,5 +3,5 @@ id: colorsensing
name: ColorSensing
logo_image: colorsensing.svg
web: https://www.color-sensing.com/en
-twitter: https://twitter.com/colorsensing?lang=es
+twitter: https://x.com/colorsensing
---
diff --git a/content/sponsors/coopdevs.md b/content/sponsors/coopdevs.md
index 6e2175e1..671160e6 100644
--- a/content/sponsors/coopdevs.md
+++ b/content/sponsors/coopdevs.md
@@ -3,7 +3,7 @@ id: coopdevs
name: Coopdevs
logo_image: coopdevs.svg
web: https://coopdevs.org/
-twitter: https://twitter.com/coopdevs
+twitter: https://x.com/coopdevs
linkedin: https://www.linkedin.com/company/coopdevs/
mastodont: https://mastodon.economiasocial.org/@Coopdevs/
---
diff --git a/content/sponsors/holaluz.md b/content/sponsors/holaluz.md
index 457d272f..19dbf563 100644
--- a/content/sponsors/holaluz.md
+++ b/content/sponsors/holaluz.md
@@ -3,6 +3,6 @@ id: holaluz
name: Holaluz
logo_image: holaluz.png
web: https://www.holaluz.com/
-twitter: https://twitter.com/holaluzcom
+twitter: https://x.com/holaluzcom
---
diff --git a/content/sponsors/isdieducation.md b/content/sponsors/isdieducation.md
index 4903be0c..d49b6cdf 100644
--- a/content/sponsors/isdieducation.md
+++ b/content/sponsors/isdieducation.md
@@ -3,7 +3,7 @@ id: isdieducation
name: ISDI Education
logo_image: isdi.png
web: https://www.isdi.education/es
-linkedin: https://es.linkedin.com/school/isdi/
+linkedin: https://www.linkedin.com/school/isdi/
instagram: https://www.instagram.com/isdi_edu/
---
diff --git a/content/sponsors/kiwi.md b/content/sponsors/kiwi.md
index 2dbf5f75..b68de39a 100644
--- a/content/sponsors/kiwi.md
+++ b/content/sponsors/kiwi.md
@@ -3,5 +3,5 @@ id: kiwi
name: Kiwi.com
logo_image: kiwi.png
web: https://www.kiwi.com/en/
-twitter: https://twitter.com/kiwi
+twitter: https://x.com/kiwi
---
diff --git a/content/sponsors/letgo.md b/content/sponsors/letgo.md
index 6085ef82..fdf7b664 100644
--- a/content/sponsors/letgo.md
+++ b/content/sponsors/letgo.md
@@ -3,6 +3,6 @@ id: letgo
name: letgo
logo_image: letgo.png
web: https://www.letgo.com/
-twitter: https://twitter.com/letgo
+twitter: https://x.com/letgo
---
diff --git a/content/sponsors/marfeel.md b/content/sponsors/marfeel.md
index c0e635f3..c1494a2f 100644
--- a/content/sponsors/marfeel.md
+++ b/content/sponsors/marfeel.md
@@ -3,5 +3,5 @@ id: marfeel
name: Marfeel
logo_image: marfeel.png
web: https://www.marfeel.com/
-twitter: https://twitter.com/marfeel
+twitter: https://x.com/marfeel
---
diff --git a/content/sponsors/nuclia.md b/content/sponsors/nuclia.md
index 621c6200..3772c3d7 100644
--- a/content/sponsors/nuclia.md
+++ b/content/sponsors/nuclia.md
@@ -3,5 +3,5 @@ id: nuclia
name: Nuclia
logo_image: Nuclia.png
web: https://nuclia.com/
-twitter: https://twitter.com/nucliaAI
+twitter: https://x.com/nucliaAI
---
diff --git a/content/sponsors/okta.md b/content/sponsors/okta.md
index 638008ee..0acbbe0b 100644
--- a/content/sponsors/okta.md
+++ b/content/sponsors/okta.md
@@ -3,6 +3,6 @@ id: okta
name: Okta
logo_image: okta.png
web: https://auth0.com/careers
-twitter: https://twitter.com/auth0
+twitter: https://x.com/auth0
linkedin: https://www.linkedin.com/company/auth0/
---
diff --git a/content/sponsors/preply.md b/content/sponsors/preply.md
index 3ab805e9..a9824cb0 100644
--- a/content/sponsors/preply.md
+++ b/content/sponsors/preply.md
@@ -3,5 +3,5 @@ id: preply
name: Preply
logo_image: preply.png
web: https://preply.com/
-twitter: https://twitter.com/PreplyCom
+twitter: https://x.com/PreplyCom
---
diff --git a/content/sponsors/psf.md b/content/sponsors/psf.md
index a699b7dd..df3abb7f 100644
--- a/content/sponsors/psf.md
+++ b/content/sponsors/psf.md
@@ -3,5 +3,5 @@ id: psf
name: Python Software Foundation
logo_image: psf.png
web: https://www.python.org/psf
-twitter: https://twitter.com/psf
+twitter: https://x.com/psf
---
diff --git a/content/sponsors/pybcn.md b/content/sponsors/pybcn.md
index 5459ae64..8058b808 100644
--- a/content/sponsors/pybcn.md
+++ b/content/sponsors/pybcn.md
@@ -3,5 +3,5 @@ id: pybcn
name: PyBCN
logo_image: pybcn.png
web: https://pybcn.org
-twitter: https://twitter.com/PyBCN
+twitter: https://x.com/PyBCN
---
diff --git a/content/sponsors/pyladiesbcn.md b/content/sponsors/pyladiesbcn.md
index 5b1e350a..cf217fd7 100644
--- a/content/sponsors/pyladiesbcn.md
+++ b/content/sponsors/pyladiesbcn.md
@@ -3,5 +3,5 @@ id: pyladiesbcn
name: PyLadiesBCN
logo_image: pyladiesbcn.jpeg
web: https://pybcn.org/pyladies_bcn/
-twitter: https://twitter.com/PyLadiesBCN
+twitter: https://x.com/PyLadiesBCN
---
diff --git a/content/sponsors/pythones.md b/content/sponsors/pythones.md
index 6e1ab28a..834c75a9 100644
--- a/content/sponsors/pythones.md
+++ b/content/sponsors/pythones.md
@@ -3,5 +3,5 @@ id: pythones
name: Python España
logo_image: pythonES.png
web: https://es.python.org
-twitter: https://twitter.com/python_es
+twitter: https://x.com/python_es
---
diff --git a/content/sponsors/qida.md b/content/sponsors/qida.md
index 76dfb0e7..c34b73db 100644
--- a/content/sponsors/qida.md
+++ b/content/sponsors/qida.md
@@ -3,5 +3,5 @@ id: qida
name: Qida
logo_image: Qida.png
web: https://qida.es/
-twitter: https://twitter.com/qidacare
+twitter: https://x.com/qidacare
---
diff --git a/content/sponsors/satellogic.md b/content/sponsors/satellogic.md
index 8749c4e4..00a0d66d 100644
--- a/content/sponsors/satellogic.md
+++ b/content/sponsors/satellogic.md
@@ -3,5 +3,5 @@ id: satellogic
name: Satellogic
logo_image: satellogic.png
web: https://satellogic.com/
-twitter: https://twitter.com/satellogic
+twitter: https://x.com/satellogic
---
diff --git a/content/sponsors/shimoku.md b/content/sponsors/shimoku.md
index 67479790..fab98899 100644
--- a/content/sponsors/shimoku.md
+++ b/content/sponsors/shimoku.md
@@ -3,6 +3,6 @@ id: shimoku
name: Shimoku
logo_image: shimoku.png
web: https://www.shimoku.com
-twitter: https://twitter.com/AiShimoku
+twitter: https://x.com/AiShimoku
---
diff --git a/content/sponsors/somenergia.md b/content/sponsors/somenergia.md
index f88e2206..f11e9b08 100644
--- a/content/sponsors/somenergia.md
+++ b/content/sponsors/somenergia.md
@@ -3,6 +3,6 @@ id: somenergia
name: Som Energia
logo_image: somenergia.jpg
web: https://www.somenergia.coop
-twitter: https://twitter.com/SomEnergia
+twitter: https://x.com/SomEnergia
---
diff --git a/content/sponsors/travelperk.md b/content/sponsors/travelperk.md
index b0600bcb..f013a3ff 100644
--- a/content/sponsors/travelperk.md
+++ b/content/sponsors/travelperk.md
@@ -3,6 +3,6 @@ id: travelperk
name: TravelPerk
logo_image: travelperk.png
web: https://www.travelperk.com/
-twitter: https://twitter.com/travelperk
+twitter: https://x.com/travelperk
---
diff --git a/content/sponsors/typeform.md b/content/sponsors/typeform.md
index de43f354..cd60e71b 100644
--- a/content/sponsors/typeform.md
+++ b/content/sponsors/typeform.md
@@ -3,5 +3,5 @@ id: typeform
name: Typeform
logo_image: typeform.png
web: https://typeform.com
-twitter: https://www.twitter.com/typeform/
+twitter: https://x.com/typeform/
---
diff --git a/content/sponsors/ub.md b/content/sponsors/ub.md
index 435007bd..9fa7d79a 100644
--- a/content/sponsors/ub.md
+++ b/content/sponsors/ub.md
@@ -3,5 +3,5 @@ id: ub
name: Universitat de Barcelona
logo_image: ub.jpg
web: https://www.ub.edu
-twitter: https://www.twitter.com/UniBarcelona
+twitter: https://x.com/UniBarcelona
---
diff --git a/content/sponsors/upf.md b/content/sponsors/upf.md
index b04a0ba7..09a82abb 100644
--- a/content/sponsors/upf.md
+++ b/content/sponsors/upf.md
@@ -3,5 +3,5 @@ id: upf
name: Universitat Pompeu Fabra
logo_image: upf.png
web: https://upf.edu
-twitter: https://twitter.com/upfbarcelona
+twitter: https://x.com/upfbarcelona
---
diff --git a/content/sponsors/veriff.md b/content/sponsors/veriff.md
index 1ab90ff2..c6aec435 100644
--- a/content/sponsors/veriff.md
+++ b/content/sponsors/veriff.md
@@ -3,6 +3,6 @@ id: veriff
name: Veriff
logo_image: veriff.png
web: https://veriff.com
-twitter: https://twitter.com/Veriff
+twitter: https://x.com/Veriff
---
diff --git a/content/sponsors/verse.md b/content/sponsors/verse.md
index 2a6db25f..4a7391c6 100644
--- a/content/sponsors/verse.md
+++ b/content/sponsors/verse.md
@@ -3,5 +3,5 @@ id: verse
name: Verse
logo_image: verse.jpg
web: https://verse.me
-twitter: http://www.twitter.com/joinverse/
+twitter: https://x.com/joinverse/
---
diff --git a/themes/pybcn_theme/archetypes/sponsors.md b/themes/pybcn_theme/archetypes/sponsors.md
index 9435c6d4..1860fbac 100644
--- a/themes/pybcn_theme/archetypes/sponsors.md
+++ b/themes/pybcn_theme/archetypes/sponsors.md
@@ -4,6 +4,6 @@ name: {{ .Name }}
logo: https://{{ .Name }}.com/logo.png
logo_image: {{ .Name }}.png
web: https://{{ .Name }}.com
-twitter: https://twitter.com/{{ .Name }}
+twitter: https://x.com/{{ .Name }}
---
diff --git a/themes/pybcn_theme/layouts/partials/people_summary.html b/themes/pybcn_theme/layouts/partials/people_summary.html
index a2184eba..9090621e 100644
--- a/themes/pybcn_theme/layouts/partials/people_summary.html
+++ b/themes/pybcn_theme/layouts/partials/people_summary.html
@@ -47,14 +47,14 @@
- {{ if $.person.Params.twitter }}
-
+ {{ if $.person.Params.linkedin }}
+
{{ end }}
{{ if $.person.Params.github }}
{{ end }}
- {{ if $.person.Params.linkedin }}
-
+ {{ if $.person.Params.twitter }}
+
{{ end }}
{{ if $.person.Params.site }}
@@ -72,14 +72,14 @@
{{ $.person.Params.name }}
- {{ if $.person.Params.twitter }}
-
+ {{ if $.person.Params.linkedin }}
+
{{ end }}
{{ if $.person.Params.github }}
{{ end }}
- {{ if $.person.Params.linkedin }}
-
+ {{ if $.person.Params.twitter }}
+
{{ end }}
{{ if $.person.Params.site }}
From e61b462100c8b0aca2f51f6af95c7dfa9f18fc7e Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 00:55:00 +0200
Subject: [PATCH 02/39] Move three people from the Permanent Committee to
Collaborators
Loris Mularoni, Ruben Berenguel and Xavi Francisco are listed as the
Permanent Committee and are not in it. The page had gone stale: the
committee that meets today is six people, and the site showed nine.
They move to Collaborators rather than off the page, which is what has been
done with everyone who stepped back from the committee before them. The
association owes them the listing either way.
Permanent Committee goes from 9 to 6, Collaborators from 5 to 8. Nobody is
removed and the Management Board is untouched.
Checked against the committee's own membership, not against the site.
---
content/pybcn_association/organizers.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/content/pybcn_association/organizers.md b/content/pybcn_association/organizers.md
index 6ca787e7..5822225f 100644
--- a/content/pybcn_association/organizers.md
+++ b/content/pybcn_association/organizers.md
@@ -14,10 +14,10 @@ people_levels:
people: [jordi-bosch, daniel-mesejo, yago-tafalla, mauricio-volcanes, sergi-ramirez]
name: Management Board (2026)
- people_per_line: 5
- people: [alberto, david, ifosch, loris, natalia, rberenguel, xavi, alicia-morales, ferran-jovell]
+ people: [alberto, david, ifosch, natalia, alicia-morales, ferran-jovell]
name: Permanent Committee
- people_per_line: 5
- people: [elisabeth-ortega-carrasco, josep, lpmayos, nuria, jose-riera]
+ people: [elisabeth-ortega-carrasco, josep, loris, lpmayos, nuria, jose-riera, rberenguel, xavi]
name: Collaborators
- people_per_line: 5
people: [lpmayos-president, mireia, natalia-secretary]
From 2ef979ad56eb0c8567f70448be347c2c249b3eec Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 00:56:32 +0200
Subject: [PATCH 03/39] Serve the three personal sites over https, and give the
committee two rows
The three sites that the content linked over http all answer over https:
http://marcpous.com https://marcpous.com/
http://orkei.com/ https://orkei.com/
http://www.liopic.me/ https://liopic.me/
Nothing on the site is linked over http any more.
The Permanent Committee is six people at five per row, which left one card
alone on the second row. Three per row gives two even rows and larger cards.
The other three sections keep five, which is what their counts suit.
Two people are left with a dead link on their card: netbcn.cat and
enricdomingo.com answer nothing, with `www` or without. Repairing those
means asking them, so it is not done here.
---
content/people/eduard_cespedes.md | 2 +-
content/people/julio-martinez.md | 2 +-
content/people/marc-pous.md | 2 +-
content/pybcn_association/organizers.md | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/content/people/eduard_cespedes.md b/content/people/eduard_cespedes.md
index 8ee7fefc..152169ec 100644
--- a/content/people/eduard_cespedes.md
+++ b/content/people/eduard_cespedes.md
@@ -6,5 +6,5 @@ photo: eduard-cespedes-borras.jpg
twitter: https://x.com/haduart
linkedin: https://www.linkedin.com/in/eduardcespedesborras/
github: https://github.com/haduart/
-site: http://orkei.com/
+site: https://orkei.com/
---
diff --git a/content/people/julio-martinez.md b/content/people/julio-martinez.md
index 28985bde..f20b3b79 100644
--- a/content/people/julio-martinez.md
+++ b/content/people/julio-martinez.md
@@ -7,5 +7,5 @@ photo: julio-martinez.jpg
twitter: https://x.com/liopic
linkedin: https://www.linkedin.com/in/liopic/
github: https://github.com/liopic
-site: http://www.liopic.me/
+site: https://liopic.me/
---
diff --git a/content/people/marc-pous.md b/content/people/marc-pous.md
index cfef91d6..4d350dfa 100644
--- a/content/people/marc-pous.md
+++ b/content/people/marc-pous.md
@@ -7,5 +7,5 @@ photo: marc-pous.jpg
twitter: https://x.com/gy4nt
linkedin: https://www.linkedin.com/in/marcpous/
github: https://github.com/mpous
-site: http://marcpous.com
+site: https://marcpous.com/
---
diff --git a/content/pybcn_association/organizers.md b/content/pybcn_association/organizers.md
index 5822225f..e37b1fb2 100644
--- a/content/pybcn_association/organizers.md
+++ b/content/pybcn_association/organizers.md
@@ -13,7 +13,7 @@ people_levels:
- people_per_line: 5
people: [jordi-bosch, daniel-mesejo, yago-tafalla, mauricio-volcanes, sergi-ramirez]
name: Management Board (2026)
- - people_per_line: 5
+ - people_per_line: 3
people: [alberto, david, ifosch, natalia, alicia-morales, ferran-jovell]
name: Permanent Committee
- people_per_line: 5
From c0ba7a0062c161430e78974ca505cefc88bff4db Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 01:11:58 +0200
Subject: [PATCH 04/39] Give every person card the same 200px width, and take
out its white frame
The number of cards on a row used to be a fraction of the row, so three
cards in the Permanent Committee sat 180px apart while five cards in the
Board sat shoulder to shoulder, and the sections did not read as one
page.
The card is now a fixed 200px and the gutter a fixed 20px in every
section. The per_line_N class moves from the card to the row and caps
the width of the row at N slots, so the row itself decides how many
cards it holds. The last row of a section is centred. The Permanent
Committee goes 3+3 and the Collaborators 4+4.
Inside the card, 10px of padding inside the border put the photo in a
white frame that took a tenth of the 200px width, and 25px of margin
under the photo plus 1rem under the role plus 10px over the icons spread
the text over the card. The card is now 311px tall where it was 346px.
The photo reaches the border. The text block keeps 10px at each side and
5px over the name, the same as between the name and the role, and the
icons start where the role ends. The icons grow from 32px to 40px, which
is the largest size at which four of them fit on one line with 6px of
margin each: 176px of the 188px the row allows. The size is set in the
stylesheet, not with the fa-2x class, because it follows from the card
width. line-height: 1 on each link drops the 3px of empty line box that
the strut of the link's own text left under every icon.
---
content/pybcn_association/organizers.md | 2 +-
themes/pybcn_theme/assets/scss/people.scss | 99 ++++++++++++-------
.../layouts/partials/people-grid.html | 4 +-
.../layouts/partials/people_summary.html | 8 +-
4 files changed, 73 insertions(+), 40 deletions(-)
diff --git a/content/pybcn_association/organizers.md b/content/pybcn_association/organizers.md
index e37b1fb2..1d74f819 100644
--- a/content/pybcn_association/organizers.md
+++ b/content/pybcn_association/organizers.md
@@ -16,7 +16,7 @@ people_levels:
- people_per_line: 3
people: [alberto, david, ifosch, natalia, alicia-morales, ferran-jovell]
name: Permanent Committee
- - people_per_line: 5
+ - people_per_line: 4
people: [elisabeth-ortega-carrasco, josep, loris, lpmayos, nuria, jose-riera, rberenguel, xavi]
name: Collaborators
- people_per_line: 5
diff --git a/themes/pybcn_theme/assets/scss/people.scss b/themes/pybcn_theme/assets/scss/people.scss
index 0dc69305..16532c5f 100644
--- a/themes/pybcn_theme/assets/scss/people.scss
+++ b/themes/pybcn_theme/assets/scss/people.scss
@@ -2,50 +2,54 @@
// people section, so there is no single id to target.
.people_grid {
- // One row of N cards. Bootstrap's twelve columns cannot express five, so
- // the width is a fraction of the row instead. Below the medium breakpoint
- // every card takes the full width, as the Bootstrap classes used to do.
- //
- // The count steps up with the viewport. A row of five on a 768 px screen
- // gives each card 114 px, which is too narrow for the name and pushes the
- // social icons onto a second line. Three fit at 768 px, four at 992 px,
- // and the full count from 1200 px, where a card is about 200 px wide.
- @for $n from 1 through 8 {
- $md: if($n > 3, 3, $n);
- $lg: if($n > 4, 4, $n);
-
- .per_line_#{$n} {
- flex: 0 0 100%;
- max-width: 100%;
+ // The last row of a section rarely fills. Centring it puts the remainder
+ // in the middle instead of leaving one card alone on the left, and it
+ // means every section can keep the same cards per row, so no section ends
+ // up with wider cards than another and reads as more important.
+ .row.level {
+ justify-content: center;
+ }
- @media (min-width: 768px) {
- flex: 0 0 percentage(1 / $md);
- max-width: percentage(1 / $md);
- }
+ // Every card is the same width in every section, and so is the space
+ // between them. The number of cards on a row comes from capping the width
+ // of the row itself, not from making each slot a fraction of it: a slot
+ // that is a third of the row puts 180px of air between three cards while
+ // five cards sit shoulder to shoulder, and the two sections stop looking
+ // like the same page.
+ $card: 200px;
+ $gutter: 20px;
- @media (min-width: 992px) {
- flex: 0 0 percentage(1 / $lg);
- max-width: percentage(1 / $lg);
- }
+ .person_wrapper {
+ flex: 0 0 auto;
+ width: $card + $gutter;
+ }
- @media (min-width: 1200px) {
- flex: 0 0 percentage(1 / $n);
- max-width: percentage(1 / $n);
- }
+ @for $n from 1 through 8 {
+ .row.level.per_line_#{$n} {
+ max-width: ($card + $gutter) * $n;
+ margin-left: auto;
+ margin-right: auto;
}
}
.person_wrapper {
display: flex;
+ justify-content: center;
margin-bottom: 20px;
- padding-right: 15px;
- padding-left: 15px;
+ padding-right: $gutter / 2;
+ padding-left: $gutter / 2;
.person_item {
+ width: 100%;
+
border: 1px solid black;
- padding: 10px;
+ // No padding on the card itself: the photo has to reach the
+ // border. The text and the icons below set their own side
+ // padding. A padding here used to frame the photo in 10px of
+ // white, which on a 200px card is a tenth of its width.
+ padding: 0;
// A column, so every card in a row is as tall as the tallest and
// the social links sit on the bottom edge whatever the length of
@@ -58,7 +62,6 @@
height: 100%;
.img-wrap {
- margin-bottom: 25px;
position: relative;
// Keeps the zoom on hover inside the frame.
overflow: hidden;
@@ -92,12 +95,23 @@
.person_data {
line-height: 1rem;
+ // 5px above the name, the same as between the name and the
+ // role, so the text block reads as one unit under the photo.
+ // The side padding keeps the text off the border now that
+ // the card has none.
+ padding: 5px 10px 0;
h3 {
color: black;
font-size: 1.2em;
margin-bottom: 5px;
}
+
+ // Bootstrap gives a paragraph 1rem below it, which opened a
+ // 16px gap between the role and the icons.
+ p {
+ margin-bottom: 0;
+ }
}
.social_links {
@@ -107,7 +121,12 @@
// up the page, because this box has no positioned ancestor of
// its own, so the icons were only in the right place by luck.
margin-top: auto;
- padding-top: 10px;
+ // No space over the icons: the role above has none under it
+ // either. 5px on each side is the limit the icon row can
+ // wrap at, which is 188px of the 198px inside the border. A
+ // little under the row, because the icons are the bottom of
+ // the card and the border would otherwise touch them.
+ padding: 0 5px 6px;
// Flex, not text-align: inline-block icons are separated by the
// whitespace between the tags, about 4 px each, which is enough
@@ -119,13 +138,27 @@
justify-content: center;
// A small gap still widens the target each icon offers to a
- // pointer, which the 2x size alone does not.
+ // pointer, which the icon size alone does not.
+ //
+ // line-height: 1 drops the strut of the link's own 16px text,
+ // which hung 3px of empty line box under every icon.
a {
display: block;
margin: 0 3px;
+ line-height: 1;
}
+ // The size is set here, not with a fa-Nx class in the markup,
+ // because it follows from the card width. Four icons have to
+ // fit on one line inside the 188px the padding leaves. At
+ // 2.5em (40px) the four glyphs are 35, 39, 40 and 39px wide
+ // (LinkedIn, GitHub, X, globe: Font Awesome glyphs are not
+ // all a full em), plus 6px of margin each, 176px in all. The
+ // next class up, fa-3x (48px), gives 207px, which wraps. The
+ // X is a mask sized in em (see .icon_x in main.scss), so it
+ // scales with the same rule.
i {
+ font-size: 2.5em;
color: black;
&:hover {
color: $blue-pybcn;
diff --git a/themes/pybcn_theme/layouts/partials/people-grid.html b/themes/pybcn_theme/layouts/partials/people-grid.html
index 5b3555dd..9e066ca4 100644
--- a/themes/pybcn_theme/layouts/partials/people-grid.html
+++ b/themes/pybcn_theme/layouts/partials/people-grid.html
@@ -21,7 +21,7 @@
{{ $pages := where .Site.Pages "Section" "people" }}
{{ range $idx, $level := .levels }}
-
+
{{ if $level.name }}
{{ $level.name }}
@@ -29,7 +29,7 @@
{{ $level.name }}
{{ end }}
{{ range $pidx, $person := $level.people }}
{{ range $page := where $pages ".Params.id" "eq" $person }}
-
{{ end }}
diff --git a/themes/pybcn_theme/layouts/partials/people_summary.html b/themes/pybcn_theme/layouts/partials/people_summary.html
index 9090621e..593d8991 100644
--- a/themes/pybcn_theme/layouts/partials/people_summary.html
+++ b/themes/pybcn_theme/layouts/partials/people_summary.html
@@ -48,16 +48,16 @@
-
+ {{/* long_name: a smaller font, so the name stays on one line (see
+ people.scss). RuneCount, not len: len counts bytes, and an
+ accented name would count one character high per accent. */}}
+
{{ $.person.Params.pybcn_position }}
From 6ad138c9a4c081cc408c334a34fd3f368a6363e0 Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 01:37:46 +0200
Subject: [PATCH 07/39] Name every PyLadiesBCN Collaborator an Organizer, and
drop the qualifier from two Organizer roles
The four people with pybcn_position PyLadiesBCN Collaborator are
organizers of PyLadiesBCN, so the role says so and keeps the prefix.
Practice sessions organizer and Meetup organizer become Organizer, the
role every other organizer carries, so one card does not read as a
different kind of organizer from the next.
---
content/people/amalia_vradi.md | 2 +-
content/people/ariadna_fernandez_estevez.md | 2 +-
content/people/elisabeth-ortega-carrasco.md | 2 +-
content/people/ifosch.md | 2 +-
content/people/loris.md | 2 +-
content/people/paula_szewach.md | 2 +-
6 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/content/people/amalia_vradi.md b/content/people/amalia_vradi.md
index afaf140b..c29124eb 100644
--- a/content/people/amalia_vradi.md
+++ b/content/people/amalia_vradi.md
@@ -3,7 +3,7 @@ id: amalia_vradi
name: "Amalia Vradi"
short_bio: "Data Scientist"
photo: amalia-vradi.jpg
-pybcn_position: PyLadiesBCN Collaborator
+pybcn_position: PyLadiesBCN Organizer
linkedin: "https://www.linkedin.com/in/amaliavradi"
github: "https://github.com/amaliavr"
diff --git a/content/people/ariadna_fernandez_estevez.md b/content/people/ariadna_fernandez_estevez.md
index 6f9b660b..e2c249ea 100644
--- a/content/people/ariadna_fernandez_estevez.md
+++ b/content/people/ariadna_fernandez_estevez.md
@@ -3,7 +3,7 @@ id: ariadna_fernandez_estevez
name: Ariadna Fernández
photo: ariadna-fernandez.jpg
short_bio: "MLOps Engineer"
-pybcn_position: PyLadiesBCN Collaborator
+pybcn_position: PyLadiesBCN Organizer
linkedin: "https://www.linkedin.com/in/ariadna-fernandez-estevez/"
github: "https://github.com/afernaes"
---
diff --git a/content/people/elisabeth-ortega-carrasco.md b/content/people/elisabeth-ortega-carrasco.md
index 14c7cfda..c8dc7643 100644
--- a/content/people/elisabeth-ortega-carrasco.md
+++ b/content/people/elisabeth-ortega-carrasco.md
@@ -5,7 +5,7 @@ short_bio: "R&D&i Manager (HPC)"
photo: elisabeth-ortega-carrasco.jpg
-pybcn_position: PyLadiesBCN Collaborator
+pybcn_position: PyLadiesBCN Organizer
twitter: https://x.com/draentropia
github: https://github.com/draentropia
diff --git a/content/people/ifosch.md b/content/people/ifosch.md
index 2caa769b..a5066dec 100644
--- a/content/people/ifosch.md
+++ b/content/people/ifosch.md
@@ -3,7 +3,7 @@ id: ifosch
name: Ignasi Fosch
short_bio: UN*X Sysadmin and Infra automation with Ruby at Devex, Python and Go developer at home and blogger at http://entredevyops.es
photo: ignasi-fosch.jpg
-pybcn_position: Practice sessions organizer
+pybcn_position: Organizer
twitter: https://x.com/ifosch
linkedin: https://www.linkedin.com/in/ifosch/
diff --git a/content/people/loris.md b/content/people/loris.md
index dbc58363..9b594b40 100644
--- a/content/people/loris.md
+++ b/content/people/loris.md
@@ -4,7 +4,7 @@ name: Loris Mularoni
photo: loris-mularoni.jpg
short_bio: bioinformatics
-pybcn_position: Meetup organizer
+pybcn_position: Organizer
twitter: https://x.com/LorisMularoni
github: https://github.com/batterio
diff --git a/content/people/paula_szewach.md b/content/people/paula_szewach.md
index 3b056251..f9a8f001 100644
--- a/content/people/paula_szewach.md
+++ b/content/people/paula_szewach.md
@@ -2,7 +2,7 @@
id: paula_szewach
name: "Paula Szewach"
short_bio: "Computational social scientist"
-pybcn_position: PyLadiesBCN Collaborator
+pybcn_position: PyLadiesBCN Organizer
site: "https://www.paulaszewach.com/"
linkedin: "https://www.linkedin.com/in/paulaszewach/"
github: "https://github.com/pszewach"
From 865045d73912fdf399b76d58525791fa9411b6d7 Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 01:50:32 +0200
Subject: [PATCH 08/39] Size the card type and icons as a share of the card,
and let the grid fill its column
The card is not the same width on every page. The organizers page gives
it 200px and an event page 186px, and the window widths between the
breakpoints give down to 150px. A fixed type size has to serve the
narrowest card, so the previous rule put every long name at 13px, which
is smaller than the role above it and reads as the wrong hierarchy.
The name, the role and the social icons are now a share of the card,
through a container query unit on .person_wrapper. 9.6cqi is the 19.2px
the name has always had on a 200px card, 6.8cqi is 13.6px for the role
and 16cqi is 32px for the icons, and each has a clamp so a card that
takes the whole row on a phone does not scale the type with it.
A container query on inline-size measures the content box, which is the
card itself and not the slot that holds it. An earlier version keyed on
210px to catch the 179px card and caught the 200px one as well.
The grid also loses its horizontal padding from the md breakpoint up. A
Bootstrap container adds 15px inside the padding the column already has,
so on an event page the level heading band spanned the full width of the
col-md-9 while the first card sat 15px inside it. The card there goes
from 179px to 186px. The phone keeps the padding, because the card would
otherwise touch the edge of the screen.
Measured on the organizers page, PyDay 2025, Hands-on Django and the
PyLadies page, at 1440, 992, 860, 768 and 390: no name, role or icon row
on two lines, except one 26-character name on the 2022 Django page below
992px.
---
themes/pybcn_theme/assets/scss/people.scss | 65 +++++++++++++++-------
1 file changed, 44 insertions(+), 21 deletions(-)
diff --git a/themes/pybcn_theme/assets/scss/people.scss b/themes/pybcn_theme/assets/scss/people.scss
index 7ef8e6a3..68bde2d6 100644
--- a/themes/pybcn_theme/assets/scss/people.scss
+++ b/themes/pybcn_theme/assets/scss/people.scss
@@ -2,6 +2,17 @@
// people section, so there is no single id to target.
.people_grid {
+ // A Bootstrap container adds its own 15px of padding inside the padding
+ // the column already has. On an event page the level heading band spans
+ // the full width of the col-md-9 while the row of cards sat 15px inside
+ // it, which showed as a step between the band and the first card. The
+ // phone keeps the padding, because there the card would otherwise touch
+ // the edge of the screen.
+ @media (min-width: 768px) {
+ padding-left: 0;
+ padding-right: 0;
+ }
+
// The last row of a section rarely fills. Centring it puts the remainder
// in the middle instead of leaving one card alone on the left, and it
// means every section can keep the same cards per row, so no section ends
@@ -29,6 +40,11 @@
.person_wrapper {
flex: 0 0 auto;
+ // The card is the container the type sizes against, at the end of
+ // this file. inline-size contains the width only, so the equal-height
+ // rule on .person_item still resolves.
+ container-type: inline-size;
+ container-name: person_card;
// One card a row on a phone, whatever the section asks for. This is
// what the old col-md-N classes did: md means the fraction applies
// from 768px up and the slot is full width below it. Four cards a
@@ -146,7 +162,16 @@
h3 {
color: black;
- font-size: 1.2em;
+ // The type is a share of the card, not a fixed size,
+ // because the card is not the same width on every page:
+ // the organizers page gives it 200px and an event page
+ // 186px, and the intermediate window widths give less
+ // still. cqi is 1% of the card, which is the container
+ // declared on .person_wrapper. 9.6cqi is 19.2px on a
+ // 200px card, the size the name has always had, and the
+ // upper clamp holds it there when one card takes the
+ // whole row on a phone.
+ font-size: clamp(13px, 9.6cqi, 19.2px);
margin-bottom: 5px;
// A long name gets a smaller font, so it stays on one
@@ -165,20 +190,8 @@
// (18) is 170px at 19.2px and wraps on an event card, and
// no name of 17 or fewer wraps on either page.
//
- // The size comes from the narrowest card the site makes.
- // An event page puts the grid in a col-md-9, so a
- // four-card row there is 179px a card and 157px for the
- // name inside the border and the padding. The longest
- // name on those pages, "Elisabeth Ortega Carrasco", is
- // 226px at 19.2px and 153px at 13px, which fits.
- //
- // From the md breakpoint up only. Below 768px one card
- // takes the whole row, 318px for the name on a 390px
- // screen, and every name fits at the full size.
&.long_name {
- @media (min-width: 768px) {
- font-size: 13px;
- }
+ font-size: clamp(10px, 6.9cqi, 15px);
}
}
@@ -189,6 +202,11 @@
// Italic sets the role apart from the name above it,
// which is the same colour and only a little larger.
font-style: italic;
+ // Smaller than the name, including a long name. At the
+ // inherited 16px the role was larger than any name that
+ // had to shrink, which read as the wrong hierarchy.
+ // 6.8cqi is 13.6px on a 200px card.
+ font-size: clamp(9px, 6.8cqi, 13.6px);
}
}
@@ -225,22 +243,27 @@
// which hung 3px of empty line box under every icon.
a {
display: block;
- margin: 0 6px;
+ // The gap scales with the card like the glyph does, so
+ // the row keeps its proportions on a narrow card.
+ margin: 0 clamp(3px, 3cqi, 6px);
line-height: 1;
}
// The size is set here, not with a fa-Nx class in the markup,
// because it follows from the card width. Four icons have to
// fit on one line inside the 188px the padding leaves. At
- // 2em (32px) the four glyphs are 28, 31, 32 and 31px wide
+ // 32px the four glyphs are 28, 31, 32 and 31px wide
// (LinkedIn, GitHub, X, globe: Font Awesome glyphs are not
// all a full em), 122px in all, plus the 6px of margin on
- // each side of every link, so 170px of the 188px. The spare
- // 18px is what keeps the row off the padding when a browser
- // rounds a glyph up. The X is a mask sized in em (see
- // .icon_x in main.scss), so it scales with the same rule.
+ // each side of every link, so 170px of the 188px a 200px card
+ // leaves. The size is a share of the card, like the name and
+ // the role above: an event page card is 186px and the window
+ // widths between the breakpoints give down to 150px, where
+ // four icons at a fixed 32px wrapped onto a second line.
+ // 16cqi is 32px on a 200px card. The X is a mask sized in em
+ // (see .icon_x in main.scss), so it follows the same rule.
i {
- font-size: 2em;
+ font-size: clamp(18px, 16cqi, 32px);
color: black;
&:hover {
color: $blue-pybcn;
From ad7770d4cf941e2b2f52f1bf10e5c4427629c97e Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 01:56:04 +0200
Subject: [PATCH 09/39] Add a year to every event page that lists people, and
name the PyLadies level
No event page had a date field. The year lived only in the title and in
the file name, so no template could order the events. The eight pages
with people_sections now carry year in the front matter, taken from the
title. The Hands-on Django page has no year in its title: the value comes
from the file name and the photo paths, and 11 June 2022, the date the
page gives, was a Saturday as the page says.
The level on the PyLadies page was named Main organizers. The page is
the PyLadiesBCN organizers page, so the heading now says which group the
people organize: PyLadiesBCN Organizers. The same heading is the label
the person modal shows for an appearance on this page, where Main
organizers said nothing.
---
content/events/other_events/django_pyladies_2022.md | 1 +
content/events/pydatabcn/pydatabcn_2023.md | 1 +
content/events/pyday_bcn/pyday_bcn_2020.md | 1 +
content/events/pyday_bcn/pyday_bcn_2021.md | 1 +
content/events/pyday_bcn/pyday_bcn_2022.md | 1 +
content/events/pyday_bcn/pyday_bcn_2023.md | 1 +
content/events/pyday_bcn/pyday_bcn_2024.md | 1 +
content/events/pyday_bcn/pyday_bcn_2025.md | 1 +
content/pyladies_bcn/organizers-and-speakers.md | 2 +-
9 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/content/events/other_events/django_pyladies_2022.md b/content/events/other_events/django_pyladies_2022.md
index 63332ab4..e61c0fad 100644
--- a/content/events/other_events/django_pyladies_2022.md
+++ b/content/events/other_events/django_pyladies_2022.md
@@ -1,5 +1,6 @@
---
title: "Hands-on Django with PyLadiesBCN"
+year: 2022
description: "From zero to hero 🤘 Learn how to code your own web application!"
menu:
main:
diff --git a/content/events/pydatabcn/pydatabcn_2023.md b/content/events/pydatabcn/pydatabcn_2023.md
index 1761053f..7c6f12e0 100644
--- a/content/events/pydatabcn/pydatabcn_2023.md
+++ b/content/events/pydatabcn/pydatabcn_2023.md
@@ -1,5 +1,6 @@
---
title: "PyDataBCN 2023"
+year: 2023
description: "The annual gathering for Pythonists in love with data!"
menu:
main:
diff --git a/content/events/pyday_bcn/pyday_bcn_2020.md b/content/events/pyday_bcn/pyday_bcn_2020.md
index 4375fd64..1ff5bc53 100644
--- a/content/events/pyday_bcn/pyday_bcn_2020.md
+++ b/content/events/pyday_bcn/pyday_bcn_2020.md
@@ -1,5 +1,6 @@
---
title: "PyDay BCN 2020"
+year: 2020
description: "The fourth edition!"
menu:
main:
diff --git a/content/events/pyday_bcn/pyday_bcn_2021.md b/content/events/pyday_bcn/pyday_bcn_2021.md
index 0d1296cc..443a8ad3 100644
--- a/content/events/pyday_bcn/pyday_bcn_2021.md
+++ b/content/events/pyday_bcn/pyday_bcn_2021.md
@@ -1,5 +1,6 @@
---
title: "PyDay BCN 2021"
+year: 2021
description: "Post-pandemic edition!"
menu:
main:
diff --git a/content/events/pyday_bcn/pyday_bcn_2022.md b/content/events/pyday_bcn/pyday_bcn_2022.md
index 0d4f14a3..7cb850f9 100644
--- a/content/events/pyday_bcn/pyday_bcn_2022.md
+++ b/content/events/pyday_bcn/pyday_bcn_2022.md
@@ -1,5 +1,6 @@
---
title: "PyDay BCN 2022"
+year: 2022
description: "For the community, by the community!"
menu:
main:
diff --git a/content/events/pyday_bcn/pyday_bcn_2023.md b/content/events/pyday_bcn/pyday_bcn_2023.md
index 544f1eb1..d6d6c627 100644
--- a/content/events/pyday_bcn/pyday_bcn_2023.md
+++ b/content/events/pyday_bcn/pyday_bcn_2023.md
@@ -1,5 +1,6 @@
---
title: "PyDay BCN 2023"
+year: 2023
description: "For the community, by the community!"
menu:
main:
diff --git a/content/events/pyday_bcn/pyday_bcn_2024.md b/content/events/pyday_bcn/pyday_bcn_2024.md
index f00a2f0a..9b2ffe99 100644
--- a/content/events/pyday_bcn/pyday_bcn_2024.md
+++ b/content/events/pyday_bcn/pyday_bcn_2024.md
@@ -1,5 +1,6 @@
---
title: "PyDay BCN 2024"
+year: 2024
description: "For the community, by the community!"
menu:
main:
diff --git a/content/events/pyday_bcn/pyday_bcn_2025.md b/content/events/pyday_bcn/pyday_bcn_2025.md
index fbe2acc6..8070bf16 100644
--- a/content/events/pyday_bcn/pyday_bcn_2025.md
+++ b/content/events/pyday_bcn/pyday_bcn_2025.md
@@ -1,5 +1,6 @@
---
title: "PyDay BCN 2025"
+year: 2025
description: "For the community, by the community!"
menu:
main:
diff --git a/content/pyladies_bcn/organizers-and-speakers.md b/content/pyladies_bcn/organizers-and-speakers.md
index 5d7f497c..9c4a576b 100644
--- a/content/pyladies_bcn/organizers-and-speakers.md
+++ b/content/pyladies_bcn/organizers-and-speakers.md
@@ -12,5 +12,5 @@ heroBackground: /images/photos/pyladies/header/header2.jpeg
people_levels:
- people_per_line: 4
people: [nuria, lpmayos, natalia, elisabeth-ortega-carrasco]
- name: Main organizers
+ name: PyLadiesBCN Organizers
---
From 72b82b91cbf6d1dc301593a8cda1a5b9e0679e2c Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 01:59:10 +0200
Subject: [PATCH 10/39] List the social links with their text at the foot of
the person modal
The modal showed the links as a row of bare icons next to the name. The
row says which networks the person is on, and nothing more: a reader had
to follow a link to learn the handle. The new person_links.html partial
lists the same links at the foot of the modal, each with its icon and
the text that says where it goes: the LinkedIn path, the GitHub or X
user name, or the whole address of a personal site. The icon row by the
name stays as it was.
The text is cut from the stored URL. The person files carry one form per
network, which bin/check-content enforces, so the prefix is known and a
second copy of the handle stays out of the front matter.
A person with no link gets no list, not an empty one. Checked on
/organizers/ with david, who has all four, and on PyDay BCN 2023 with
emanuel-frazao, who has none.
---
themes/pybcn_theme/assets/scss/people.scss | 26 ++++++++++++++
.../layouts/partials/people_summary.html | 1 +
.../layouts/partials/person_links.html | 36 +++++++++++++++++++
3 files changed, 63 insertions(+)
create mode 100644 themes/pybcn_theme/layouts/partials/person_links.html
diff --git a/themes/pybcn_theme/assets/scss/people.scss b/themes/pybcn_theme/assets/scss/people.scss
index 68bde2d6..524ca904 100644
--- a/themes/pybcn_theme/assets/scss/people.scss
+++ b/themes/pybcn_theme/assets/scss/people.scss
@@ -312,6 +312,32 @@
color: $blue-pybcn;
}
}
+
+ // The same links as the icon row by the name, listed
+ // with their text at the foot of the modal, so a
+ // reader can see the handle or the host without
+ // leaving the page. See person_links.html.
+ .modal_links {
+ list-style: none;
+ padding: 0;
+ margin: 15px 0 0;
+
+ li {
+ margin-bottom: 4px;
+ }
+
+ // One column for the icon whatever its width, so
+ // the text starts on one line down the list. The
+ // LinkedIn glyph is narrower than the globe, and
+ // the X mark is a box of its own (see .icon_x in
+ // main.scss) that sets neither width nor gap.
+ i {
+ display: inline-block;
+ width: 1.5em;
+ margin-right: 6px;
+ text-align: center;
+ }
+ }
}
}
diff --git a/themes/pybcn_theme/layouts/partials/people_summary.html b/themes/pybcn_theme/layouts/partials/people_summary.html
index f4c93cc5..ad365fd5 100644
--- a/themes/pybcn_theme/layouts/partials/people_summary.html
+++ b/themes/pybcn_theme/layouts/partials/people_summary.html
@@ -91,6 +91,7 @@
diff --git a/themes/pybcn_theme/layouts/partials/person_links.html b/themes/pybcn_theme/layouts/partials/person_links.html
new file mode 100644
index 00000000..ad748fb5
--- /dev/null
+++ b/themes/pybcn_theme/layouts/partials/person_links.html
@@ -0,0 +1,36 @@
+{{- /*
+ The social links of one person as a list, each with its icon and the
+ text a reader needs to know where the link goes: the LinkedIn path, the
+ GitHub or X user name, or the address of a personal site.
+
+ Argument: the person page.
+
+ The modal title shows the same links as a row of bare icons. That row
+ says which networks the person is on and nothing more, so a reader
+ had to follow a link to learn the handle. This list is in addition to
+ that row, at the foot of the modal.
+
+ The text comes from the stored URL, not from a separate field. The
+ person files carry one form per network, which bin/check-content
+ enforces: https://www.linkedin.com/..., https://github.com/ and
+ https://x.com/. Cutting the known prefix is therefore safe, and
+ it keeps a second copy of the handle out of the front matter, where
+ it would drift from the URL. A site is a free URL and is shown whole.
+*/ -}}
+{{- $p := .Params -}}
+{{- if or $p.linkedin $p.github $p.twitter $p.site -}}
+
+{{- end -}}
From b3003d79875fdf7b88c5311b21a7a03a38f670ca Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 02:00:44 +0200
Subject: [PATCH 11/39] Record the personal site of Alberto Camara
---
content/people/alberto.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/content/people/alberto.md b/content/people/alberto.md
index 05273af3..af12f46f 100644
--- a/content/people/alberto.md
+++ b/content/people/alberto.md
@@ -7,6 +7,7 @@ photo: alberto-camara.jpg
pybcn_position: Organizer
twitter: "https://x.com/b3r2s"
linkedin: "https://www.linkedin.com/in/alberto-camara/"
+site: https://ber2.github.io
---
I work across the data spectrum in many places, from big data processing using tools such as Apache Spark, to training Machine Learning models and visualizing their outputs, using tools such as scikit-learn or tensorflow.
From 0871a63dc4b2fdb039775fabdf4b15cc059894bf Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 08:04:53 +0200
Subject: [PATCH 12/39] Show the links once in the modal, where each one says
where it goes
The modal listed the links twice: a row of bare icons next to the name,
and the list at the foot that also prints the handle or the host. The
bare row said less and came first, so it read as the real one.
The list is the only copy now, and its icons go up from 16px to 20px,
since they no longer compete with a larger row above them.
---
themes/pybcn_theme/assets/scss/people.scss | 16 +++++++++++-----
.../layouts/partials/people_summary.html | 19 ++++---------------
2 files changed, 15 insertions(+), 20 deletions(-)
diff --git a/themes/pybcn_theme/assets/scss/people.scss b/themes/pybcn_theme/assets/scss/people.scss
index 524ca904..7f47625a 100644
--- a/themes/pybcn_theme/assets/scss/people.scss
+++ b/themes/pybcn_theme/assets/scss/people.scss
@@ -313,10 +313,12 @@
}
}
- // The same links as the icon row by the name, listed
- // with their text at the foot of the modal, so a
- // reader can see the handle or the host without
- // leaving the page. See person_links.html.
+ // The links of the card, listed with their text at the
+ // foot of the modal, so a reader can see the handle or
+ // the host without leaving the page. This is the only
+ // place the modal shows them: a bare icon row next to
+ // the name said the same thing with less. See
+ // person_links.html.
.modal_links {
list-style: none;
padding: 0;
@@ -333,9 +335,13 @@
// main.scss) that sets neither width nor gap.
i {
display: inline-block;
+ // Larger than the text beside it, because these
+ // are now the only icons in the modal.
+ font-size: 1.25em;
width: 1.5em;
- margin-right: 6px;
+ margin-right: 8px;
text-align: center;
+ vertical-align: -2px;
}
}
}
diff --git a/themes/pybcn_theme/layouts/partials/people_summary.html b/themes/pybcn_theme/layouts/partials/people_summary.html
index ad365fd5..eff6b088 100644
--- a/themes/pybcn_theme/layouts/partials/people_summary.html
+++ b/themes/pybcn_theme/layouts/partials/people_summary.html
@@ -73,21 +73,10 @@
{{/* alt is empty here: the name is in the modal heading next to it. */}}
-
- {{ $.person.Params.name }}
- {{ if $.person.Params.linkedin }}
-
- {{ end }}
- {{ if $.person.Params.github }}
-
- {{ end }}
- {{ if $.person.Params.twitter }}
-
- {{ end }}
- {{ if $.person.Params.site }}
-
- {{ end }}
-
+ {{/* The name only. The links used to sit next to it as
+ bare icons, which repeated the list at the foot of the
+ modal, where each one also says where it goes. */}}
+
{{ $.person.Params.name }}
{{ $.person.Params.short_bio | markdownify }}
{{ $.person.Params.pybcn_position }}
{{ $.person.Content }}
From 6045c59852378f2fc4d2a7469a6453e7f6ee88d2 Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 08:09:04 +0200
Subject: [PATCH 13/39] Keep one name size on every card and cut what does not
fit
The name size was a share of the card, so a long name came out visibly
smaller than its neighbours on the same row and read as a different
heading level rather than as the same name in less room. It is one size
on every card again, and a name wider than the card is cut with an
ellipsis. The whole name is in the title of the button and in the modal
the button opens, so nothing is lost.
The ellipsis needs a box with a width to overflow, so the button is a
block of the full width. An inline button takes the width of its text
and never overflows.
The role also gets the same space above and below it. It had 5px over it
and none under, because margin-top: auto on the icon row leaves no gap
of its own on a card whose content fills it.
The role and the icons stay a share of the card. There the scaling fixes
real defects: four icons wrapped onto a second line on a 150px card, and
PyLadiesBCN Organizer wrapped on an event page.
Measured on the organizers page and PyDay 2025 at 1440, 992 and 390: the
name is 19.2px everywhere, no name, role or icon row is on two lines,
and the gap above and below the role is 5px on every card.
---
themes/pybcn_theme/assets/scss/people.scss | 56 +++++++++----------
.../layouts/partials/people_summary.html | 8 +--
2 files changed, 29 insertions(+), 35 deletions(-)
diff --git a/themes/pybcn_theme/assets/scss/people.scss b/themes/pybcn_theme/assets/scss/people.scss
index 7f47625a..d7d0da07 100644
--- a/themes/pybcn_theme/assets/scss/people.scss
+++ b/themes/pybcn_theme/assets/scss/people.scss
@@ -162,36 +162,26 @@
h3 {
color: black;
- // The type is a share of the card, not a fixed size,
- // because the card is not the same width on every page:
- // the organizers page gives it 200px and an event page
- // 186px, and the intermediate window widths give less
- // still. cqi is 1% of the card, which is the container
- // declared on .person_wrapper. 9.6cqi is 19.2px on a
- // 200px card, the size the name has always had, and the
- // upper clamp holds it there when one card takes the
- // whole row on a phone.
- font-size: clamp(13px, 9.6cqi, 19.2px);
+ // One size on every card. The size used to be a share of
+ // the card so a long name could stay on one line, but
+ // that made a long name visibly smaller than its
+ // neighbours and read as a different heading level
+ // rather than as the same name in less room.
+ font-size: 1.2em;
margin-bottom: 5px;
- // A long name gets a smaller font, so it stays on one
- // line. No ellipsis: a clipped surname reads badly, and
- // these are real people. Only the long names shrink, so
- // the other cards keep the heading size.
- //
- // The template adds the class from the character count,
- // because the template knows the name and CSS cannot
- // measure text. The count is a proxy for the width:
- // "Monica Dominguez" (16 characters) needs 164px and
- // "Albert Pujol Torras" (19) needs 156px, so a few names
- // on each side of the threshold shrink without need or
- // wrap. The threshold is 18 characters, measured on the
- // organizers page and on PyDay 2025: "Daniel Mesejo Leon"
- // (18) is 170px at 19.2px and wraps on an event card, and
- // no name of 17 or fewer wraps on either page.
- //
- &.long_name {
- font-size: clamp(10px, 6.9cqi, 15px);
+ // A name wider than the card is cut rather than wrapped.
+ // The whole name is in the title of the button and in the
+ // modal the button opens, so nothing is lost. The button
+ // has to be a block of the full width: the ellipsis needs
+ // a box with a width to overflow, and an inline button
+ // takes the width of its text.
+ button {
+ display: block;
+ width: 100%;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
}
@@ -217,15 +207,19 @@
// up the page, because this box has no positioned ancestor of
// its own, so the icons were only in the right place by luck.
margin-top: auto;
- // No space over the icons: the role above has none under it
- // either. The side padding is 2px rather than 5px because the
+ // 5px over the icons, the same as the gap over the role, so
+ // the role has equal space above and below it. It had 5px
+ // above and none below, because margin-top: auto leaves no
+ // gap of its own on a card whose content fills it.
+ //
+ // The side padding is 2px rather than 5px because the
// row has to survive the narrowest card on the site: an event
// page puts the grid in a col-md-9, so a four-card row there
// is 179px wide, 175px inside the border and the padding, and
// the four icons need 170px. A little under the row, because
// the icons are the bottom of the card and the border would
// otherwise touch them.
- padding: 0 2px 6px;
+ padding: 5px 2px 6px;
// Flex, not text-align: inline-block icons are separated by the
// whitespace between the tags, about 4 px each, which is enough
diff --git a/themes/pybcn_theme/layouts/partials/people_summary.html b/themes/pybcn_theme/layouts/partials/people_summary.html
index eff6b088..b4c4328f 100644
--- a/themes/pybcn_theme/layouts/partials/people_summary.html
+++ b/themes/pybcn_theme/layouts/partials/people_summary.html
@@ -43,10 +43,10 @@
- {{/* long_name: a smaller font, so the name stays on one line (see
- people.scss). RuneCount, not len: len counts bytes, and an
- accented name would count one character high per accent. */}}
-
+ {{/* title carries the whole name, because a name too long for the
+ card is cut with an ellipsis (see people.scss). The modal shows
+ it in full as well. */}}
+
{{ $.person.Params.pybcn_position }}
From 0a620483cb5ff2460c83fb686f754dc1474ce6d1 Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 08:18:32 +0200
Subject: [PATCH 14/39] List the pages each organizer appears on in the modal
The modal of most organizers held a photo, a role and the links, and
nothing a reader could follow to the events the person took part in.
Every event page already lists its speakers and organizers by id, so
the modal now inverts that index: one row per role, with a link to each
page, newest first.
Speaker PyDay BCN 2025
Organizer PyDay BCN 2024, PyDay BCN 2021, PyDay BCN 2020
Volunteer Hands-on Django with PyLadiesBCN
The index is built once per build, in appearances_index.html through
partialCached with a constant variant, from people_sections on the event
pages and people_levels on the association pages. Only the people listed
on /pybcn_association/organizers/ are indexed; every other person is a
speaker or a volunteer of one event, whose modal would list that one
event and nothing else.
The page the modal is on is left out. Everyone on /organizers/ would
otherwise get a link back to the page they are reading, which says
nothing their role line does not. Six organizers then have no
appearance at all, and the block emits nothing for them.
An appearance is one (heading, page) pair. Ferran Jovell is listed
under two levels of one section of the Django page, and the modal would
otherwise link that page twice under one label.
The heading a page uses, such as "Speakers", goes through
data/roles.yaml to become the singular role the modal shows. The
heading itself is the fallback, so a new heading shows up unmapped
rather than not at all, and the map is a plain data file that anyone
can edit. "Mentors, speakers & volunteers" names three roles under one
heading, so the single word it maps to, Volunteer, is an approximation
for the people listed there.
---
data/roles.yaml | 14 ++++
themes/pybcn_theme/assets/scss/people.scss | 19 +++++
.../pybcn_theme/layouts/_default/event.html | 2 +-
.../pybcn_theme/layouts/_default/people.html | 2 +-
.../layouts/partials/appearances_index.html | 76 +++++++++++++++++++
.../layouts/partials/people-grid.html | 4 +-
.../layouts/partials/people_summary.html | 6 ++
.../layouts/partials/person_appearances.html | 45 +++++++++++
8 files changed, 165 insertions(+), 3 deletions(-)
create mode 100644 data/roles.yaml
create mode 100644 themes/pybcn_theme/layouts/partials/appearances_index.html
create mode 100644 themes/pybcn_theme/layouts/partials/person_appearances.html
diff --git a/data/roles.yaml b/data/roles.yaml
new file mode 100644
index 00000000..90e2f8c9
--- /dev/null
+++ b/data/roles.yaml
@@ -0,0 +1,14 @@
+# The role a person modal shows for each heading an event page lists people
+# under. Left side: the heading as it is written in the page front matter
+# (people_sections[].title on an event page, people_levels[].name on an
+# association page). Right side: the singular role the modal prints next to
+# the links to those pages. A heading that is not in this list is printed as
+# it is, so a new heading works before anyone adds it here.
+#
+# "Mentors, speakers & volunteers" names three roles under one heading, so
+# any single word for it is an approximation. Volunteer is the one that is
+# true of everyone listed there.
+Speakers: Speaker
+Organizers: Organizer
+PyLadiesBCN Organizers: PyLadiesBCN Organizer
+"Mentors, speakers & volunteers": Volunteer
diff --git a/themes/pybcn_theme/assets/scss/people.scss b/themes/pybcn_theme/assets/scss/people.scss
index d7d0da07..5caf14ae 100644
--- a/themes/pybcn_theme/assets/scss/people.scss
+++ b/themes/pybcn_theme/assets/scss/people.scss
@@ -307,6 +307,25 @@
}
}
+ // The pages the person appears on, one row per role:
+ // the role in the first column, the linked page titles
+ // in the second. A grid rather than a table, so the
+ // role column is as wide as its longest word and no
+ // wider. See person_appearances.html.
+ .appearances {
+ display: grid;
+ grid-template-columns: max-content 1fr;
+ gap: 4px 12px;
+ margin: 15px 0 0;
+
+ dt {
+ font-weight: bold;
+ }
+ dd {
+ margin: 0;
+ }
+ }
+
// The links of the card, listed with their text at the
// foot of the modal, so a reader can see the handle or
// the host without leaving the page. This is the only
diff --git a/themes/pybcn_theme/layouts/_default/event.html b/themes/pybcn_theme/layouts/_default/event.html
index 3b43d4e5..a1692d3a 100644
--- a/themes/pybcn_theme/layouts/_default/event.html
+++ b/themes/pybcn_theme/layouts/_default/event.html
@@ -73,7 +73,7 @@
{{ end }}
diff --git a/themes/pybcn_theme/layouts/_default/people.html b/themes/pybcn_theme/layouts/_default/people.html
index 492e4303..379cfd86 100644
--- a/themes/pybcn_theme/layouts/_default/people.html
+++ b/themes/pybcn_theme/layouts/_default/people.html
@@ -1,5 +1,5 @@
{{ define "main" }}
-{{ partial "people-grid.html" (dict "levels" .Params.people_levels "Site" .Site)}}
+{{ partial "people-grid.html" (dict "levels" .Params.people_levels "Site" .Site "page" .)}}
{{ end }}
diff --git a/themes/pybcn_theme/layouts/partials/appearances_index.html b/themes/pybcn_theme/layouts/partials/appearances_index.html
new file mode 100644
index 00000000..aa2e42a0
--- /dev/null
+++ b/themes/pybcn_theme/layouts/partials/appearances_index.html
@@ -0,0 +1,76 @@
+{{- /*
+ The pages each organizer appears on, inverted from the pages themselves.
+
+ Returns a map from person id to a list of appearances, each a dict with
+ label, title, url and year. No argument is read: the data comes from
+ site.RegularPages and from data/roles.yaml.
+
+ Call it through partialCached with a constant variant, so the site is
+ walked once per build and not once per modal:
+
+ partialCached "appearances_index.html" site "appearances-index"
+
+ Two front matter shapes list people. An event page has people_sections,
+ each with a title and a list of levels; the section title is the heading.
+ An association page has people_levels, each with a name; the level name
+ is the heading. A level entry is a bare id, or a map with an id when the
+ page overrides the role for that entry (see people-grid.html).
+
+ Only the people listed on /pybcn_association/organizers/ are indexed.
+ Every other person is a speaker or a volunteer of one event, whose modal
+ would list that one event and nothing else. The Archive will widen this.
+
+ The heading goes through data/roles.yaml, which turns "Speakers" into
+ "Speaker". The heading itself is the fallback, so a new heading shows
+ up unmapped rather than not at all.
+
+ An appearance is one (heading, page) pair. Ferran Jovell is listed under
+ two levels of one section of the Django page, Mentors and Speakers, and
+ the modal would otherwise link that page twice under one label.
+
+ Drafts are skipped by name as well: site.RegularPages drops them in a
+ normal build, but a server run with -D would index content/canary.md.
+*/ -}}
+{{- $scope := dict -}}
+{{- with site.GetPage "/pybcn_association/organizers" -}}
+ {{- range .Params.people_levels -}}
+ {{- range .people -}}
+ {{- $id := . -}}
+ {{- if reflect.IsMap . }}{{ $id = .id }}{{ end -}}
+ {{- $scope = merge $scope (dict $id true) -}}
+ {{- end -}}
+ {{- end -}}
+{{- end -}}
+
+{{- $index := dict -}}
+{{- range $pg := site.RegularPages -}}
+ {{- if $pg.Draft }}{{ continue }}{{ end -}}
+ {{- /* heading -> list of ids, in the order the page lists them */ -}}
+ {{- $headings := slice -}}
+ {{- range $pg.Params.people_sections -}}
+ {{- $ids := slice -}}
+ {{- range .levels }}{{ range .people }}{{ $ids = $ids | append . }}{{ end }}{{ end -}}
+ {{- $headings = $headings | append (dict "heading" .title "ids" $ids) -}}
+ {{- end -}}
+ {{- range $pg.Params.people_levels -}}
+ {{- $headings = $headings | append (dict "heading" .name "ids" .people) -}}
+ {{- end -}}
+ {{- if not $headings }}{{ continue }}{{ end -}}
+
+ {{- $seen := dict -}}
+ {{- range $headings -}}
+ {{- $heading := .heading -}}
+ {{- $label := default $heading (index site.Data.roles $heading) -}}
+ {{- range .ids -}}
+ {{- $id := . -}}
+ {{- if reflect.IsMap . }}{{ $id = .id }}{{ end -}}
+ {{- if not (index $scope $id) }}{{ continue }}{{ end -}}
+ {{- $key := printf "%s|%s" $label $id -}}
+ {{- if index $seen $key }}{{ continue }}{{ end -}}
+ {{- $seen = merge $seen (dict $key true) -}}
+ {{- $entry := dict "label" $label "title" $pg.Title "url" $pg.RelPermalink "year" (int (default 0 $pg.Params.year)) -}}
+ {{- $index = merge $index (dict $id (append $entry (default slice (index $index $id)))) -}}
+ {{- end -}}
+ {{- end -}}
+{{- end -}}
+{{- return $index -}}
diff --git a/themes/pybcn_theme/layouts/partials/people-grid.html b/themes/pybcn_theme/layouts/partials/people-grid.html
index 9e066ca4..0cdea7e5 100644
--- a/themes/pybcn_theme/layouts/partials/people-grid.html
+++ b/themes/pybcn_theme/layouts/partials/people-grid.html
@@ -4,6 +4,8 @@
Arguments:
levels the list of levels, each with a name, people and people_per_line
Site the site, to look the people pages up
+ page the page the grid is on. The modal lists the other pages
+ the person appears on and leaves this one out
key a name unique to this grid on the page, "people" by default
An event page renders this partial once per people section, and the same
@@ -30,7 +32,7 @@
{{ $level.name }}
{{ range $pidx, $person := $level.people }}
{{ range $page := where $pages ".Params.id" "eq" $person }}
{{ end }}
{{ end }}
diff --git a/themes/pybcn_theme/layouts/partials/people_summary.html b/themes/pybcn_theme/layouts/partials/people_summary.html
index b4c4328f..862c8489 100644
--- a/themes/pybcn_theme/layouts/partials/people_summary.html
+++ b/themes/pybcn_theme/layouts/partials/people_summary.html
@@ -6,6 +6,11 @@
image at 400 px, so one 400 px WebP serves both, with an 800 px variant
for a 2x screen. A person with no photo falls back to anon_member.png.
+ Arguments:
+ person the person page
+ page the page the card is on, for the appearance list in the modal
+ key the grid key, so the modal id is unique on the page
+
A remote photo is not supported. The template used to accept photo_url
and print it in a plain img, which made every page that lists the person
load an image from a third party and tell that party who viewed it. No
@@ -80,6 +85,7 @@
diff --git a/themes/pybcn_theme/layouts/partials/person_appearances.html b/themes/pybcn_theme/layouts/partials/person_appearances.html
new file mode 100644
index 00000000..a829f034
--- /dev/null
+++ b/themes/pybcn_theme/layouts/partials/person_appearances.html
@@ -0,0 +1,45 @@
+{{- /*
+ The pages one person appears on, grouped by role, as links.
+
+ Speaker PyDay BCN 2025
+ Organizer PyDay BCN 2024, PyDay BCN 2021, PyDay BCN 2020
+
+ Arguments:
+ person the person page
+ page the page the modal is on
+
+ The index comes from appearances_index.html, built once per build.
+
+ The page the modal is on is left out. Everyone on /organizers/ would
+ otherwise get a link back to the page the reader is looking at, and the
+ role line above already says what that link would say. Six organizers
+ then have no appearance at all, and the block emits nothing for them:
+ no heading, no empty list.
+
+ Order: the role with the most recent appearance first, and inside a
+ role the most recent page first. A page with no year, such as the
+ PyLadies organizers page, goes last. Ties fall back to the label and
+ the title, so two builds give the same order.
+*/ -}}
+{{- $here := .page.RelPermalink -}}
+{{- $index := partialCached "appearances_index.html" site "appearances-index" -}}
+{{- $groups := dict -}}
+{{- range index $index .person.Params.id -}}
+ {{- if eq .url $here }}{{ continue }}{{ end -}}
+ {{- $item := merge . (dict "key" (printf "%04d %s" (sub 9999 .year) .title)) -}}
+ {{- $groups = merge $groups (dict .label (append $item (default slice (index $groups .label)))) -}}
+{{- end -}}
+{{- $list := slice -}}
+{{- range $label, $items := $groups -}}
+ {{- $items = sort $items "key" -}}
+ {{- $newest := (index $items 0).year -}}
+ {{- $list = $list | append (dict "label" $label "items" $items "key" (printf "%04d %s" (sub 9999 $newest) $label)) -}}
+{{- end -}}
+{{- with $list -}}
+
+ {{- range sort . "key" }}
+
{{ .label }}
+
{{ range $i, $it := .items }}{{ if $i }}, {{ end }}{{ $it.title }}{{ end }}
+ {{- end }}
+
+{{- end -}}
From e09231a9ac9862abbc53e1053748a36e9e74de3c Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 08:20:48 +0200
Subject: [PATCH 15/39] Keep one file per person, with the role set per page
entry
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Laura Pérez Mayos and Natàlia Padilla each had two person files,
lpmayos and lpmayos-president, natalia and natalia-secretary, so that
/organizers/ could show them twice with a different role: Organizer
under Collaborators and Former President or Former Secretary under the
old board. The split meant neither file told the whole story. The modal
of the Collaborators card listed seven events, and the modal of the
board card listed none, because no event page referenced the second id.
The ids that stay are the ones the event pages already reference:
lpmayos in 8 files against 1 for lpmayos-president, natalia in 9 files
against 1 for natalia-secretary. The two extra files go, and the only
page that listed them, organizers.md, now lists the surviving id.
To keep the two roles, an entry of a people list can now be a map with
an id and a role, next to the bare ids:
people:
- id: lpmayos
role: Former President
- mireia
The role replaces the pybcn_position of the person file on that page
only, on the card and in the modal. people-grid.html reads the shape
and documents it. bin/check-content reads the id out of a map entry,
which used to raise a TypeError, and rejects a map without an id, a
misspelt key, or a map in a sponsor list, which the template would drop
in silence.
/organizers/ renders the same people in the same sections with the same
role text as before, and both merged people now show their full
appearance list on both of their cards.
---
bin/check-content | 37 ++++++++++++++++++-
content/people/lpmayos-president.md | 15 --------
content/people/natalia-secretary.md | 12 ------
content/pybcn_association/organizers.md | 9 ++++-
.../layouts/partials/people-grid.html | 21 ++++++++++-
.../layouts/partials/people_summary.html | 7 +++-
6 files changed, 68 insertions(+), 33 deletions(-)
delete mode 100644 content/people/lpmayos-president.md
delete mode 100644 content/people/natalia-secretary.md
diff --git a/bin/check-content b/bin/check-content
index 4896f921..0b33a67e 100755
--- a/bin/check-content
+++ b/bin/check-content
@@ -296,6 +296,38 @@ LISTING_KEYS = {
}
+# The keys an entry of a people list may carry when it is a map rather than
+# a bare id. people-grid.html reads both; anything else is a misspelling the
+# template would drop in silence.
+ENTRY_KEYS = {"id", "role"}
+
+
+def entry_id(path, key, entry):
+ """Return the id of one entry of a listing, or None if it has none.
+
+ A people entry is a bare id, or a map with an id and a role that the page
+ shows instead of the person's pybcn_position (see people-grid.html). The
+ check used to compare the entry itself against the known ids, which
+ raised a TypeError on a map.
+ """
+ if isinstance(entry, str):
+ return entry
+ if not isinstance(entry, dict):
+ error(path, f"'{key}' lists {entry!r}, which is not an id")
+ return None
+ if key != "people_levels" and key != "people_sections":
+ error(path, f"'{key}' lists {entry!r}, but only a people list may hold a map")
+ return None
+ unknown = set(entry) - ENTRY_KEYS
+ if unknown:
+ error(path, f"'{key}' entry {entry!r} has unknown key(s) "
+ f"{', '.join(sorted(unknown))}; allowed: id, role")
+ if not entry.get("id"):
+ error(path, f"'{key}' entry {entry!r} has no id")
+ return None
+ return entry["id"]
+
+
def referenced_ids(path, data, key):
"""Pull every id out of one listing key of a page.
@@ -311,7 +343,10 @@ def referenced_ids(path, data, key):
if not isinstance(level, dict):
error(path, f"'{key}' holds {level!r}, which is not a level")
continue
- out.extend(level.get(LISTING_KEYS[key]) or [])
+ for entry in level.get(LISTING_KEYS[key]) or []:
+ ref = entry_id(path, key, entry)
+ if ref is not None:
+ out.append(ref)
return out
diff --git a/content/people/lpmayos-president.md b/content/people/lpmayos-president.md
deleted file mode 100644
index 3d31ad91..00000000
--- a/content/people/lpmayos-president.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-id: lpmayos-president
-name: "Laura Pérez Mayos"
-short_bio: "Books, nature and NLP"
-photo: laura-perez-mayos.jpg
-site: https://lpmayos.github.io/
-
-pybcn_position: "Former President"
-
-linkedin: "https://www.linkedin.com/in/lpmayos/"
-github: "https://github.com/lpmayos"
-
----
-
-Bookworm. Scuba diver. Mountain lover. Photography enthusiast. Urban cyclist. Research Scientist. Engineer.
diff --git a/content/people/natalia-secretary.md b/content/people/natalia-secretary.md
deleted file mode 100644
index 6d146b36..00000000
--- a/content/people/natalia-secretary.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-id: natalia-secretary
-name: "Natàlia Padilla"
-short_bio: "Research software engineer"
-photo: natalia-padilla.jpg
-pybcn_position: "Former Secretary"
-
-twitter: "https://x.com/nataliasirera"
-linkedin: "https://www.linkedin.com/in/natàlia-padilla-sirera-8112305a/"
-github: "https://github.com/NataliaSirera"
-
----
diff --git a/content/pybcn_association/organizers.md b/content/pybcn_association/organizers.md
index 1d74f819..64371b8a 100644
--- a/content/pybcn_association/organizers.md
+++ b/content/pybcn_association/organizers.md
@@ -20,6 +20,13 @@ people_levels:
people: [elisabeth-ortega-carrasco, josep, loris, lpmayos, nuria, jose-riera, rberenguel, xavi]
name: Collaborators
- people_per_line: 5
- people: [lpmayos-president, mireia, natalia-secretary]
name: Management Board (2018 - 2025)
+ # An entry with a role shows that role on this page instead of the
+ # pybcn_position of the person file. See people-grid.html.
+ people:
+ - id: lpmayos
+ role: Former President
+ - mireia
+ - id: natalia
+ role: Former Secretary
---
diff --git a/themes/pybcn_theme/layouts/partials/people-grid.html b/themes/pybcn_theme/layouts/partials/people-grid.html
index 0cdea7e5..84468f47 100644
--- a/themes/pybcn_theme/layouts/partials/people-grid.html
+++ b/themes/pybcn_theme/layouts/partials/people-grid.html
@@ -13,6 +13,21 @@
grid emits, so the row ids and the modal ids stay unique on the page.
Styles hook on the people_grid class, not on an id.
+ An entry of a people list is a bare id, or a map with an id and a role:
+
+ people:
+ - mireia
+ - id: lpmayos
+ role: Former President
+
+ The role replaces the pybcn_position of the person file on this page
+ only, on the card and in the modal. It exists so that one person file
+ can sit in two sections of /organizers/ with a different role in each:
+ Laura Pérez Mayos is an Organizer under Collaborators and the Former
+ President under the old board. Before this, each role was a second
+ person file with its own id, and the modal of the second one listed
+ none of the events the first one was in.
+
The column width comes from a per_line_N class rather than from Bootstrap's
col-md-N. Twelve columns divide by 1, 2, 3, 4, 6 and 12, so people_per_line
was silently rounded for any other value: 5 gave col-md-2, which is six
@@ -30,9 +45,11 @@
{{ $level.name }}
{{ end }}
{{ range $pidx, $person := $level.people }}
- {{ range $page := where $pages ".Params.id" "eq" $person }}
+ {{ $id := $person }}{{ $role := "" }}
+ {{ if reflect.IsMap $person }}{{ $id = $person.id }}{{ $role = $person.role }}{{ end }}
+ {{ range $page := where $pages ".Params.id" "eq" $id }}
{{ end }}
{{ end }}
diff --git a/themes/pybcn_theme/layouts/partials/people_summary.html b/themes/pybcn_theme/layouts/partials/people_summary.html
index 862c8489..3c35e528 100644
--- a/themes/pybcn_theme/layouts/partials/people_summary.html
+++ b/themes/pybcn_theme/layouts/partials/people_summary.html
@@ -9,6 +9,8 @@
Arguments:
person the person page
page the page the card is on, for the appearance list in the modal
+ role optional, the role to show instead of pybcn_position, when
+ the page lists the person with one (see people-grid.html)
key the grid key, so the modal id is unique on the page
A remote photo is not supported. The template used to accept photo_url
@@ -16,6 +18,7 @@
load an image from a third party and tell that party who viewed it. No
person used the field, and bin/check-content now rejects it.
*/ -}}
+{{- $role := default $.person.Params.pybcn_position $.role -}}
{{- $modal := printf "modal_%s" $.person.Params.id -}}
{{- with $.key -}}{{- $modal = printf "modal_%s_%s" . $.person.Params.id -}}{{- end -}}
{{- $photo := $.person.Params.photo -}}
@@ -52,7 +55,7 @@
card is cut with an ellipsis (see people.scss). The modal shows
it in full as well. */}}
-
{{ $.person.Content }}
{{ partial "person_appearances.html" (dict "person" $.person "page" $.page) }}
{{ partial "person_links.html" $.person }}
From 80b1c69361edd9c19a5f4b8fea763075e2571fd4 Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 09:56:57 +0200
Subject: [PATCH 16/39] Label an appearance by its level name, not the section
title
The appearance index took the section title as the heading of every
person in a people_sections entry. The Django page has one section titled
"Mentors, speakers & volunteers" with three named levels, so the index
called every mentor and speaker of that page a Volunteer, which was true
only of Mireia.
A level with a name is now its own heading, and a level without one falls
back to the section title. The Speakers and Organizers sections of the
event pages have one unnamed level each, so nothing changes for them.
data/roles.yaml maps Mentors and Volunteers to their singular role and
drops the combined title, which no level falls back to any more.
On /organizers/, David, Elisabeth, Natalia, Nuria and Xavi go from
Volunteer to Mentor on the Django page, and Ferran gets that page under
both Mentor and Speaker: the (label, page) dedup keeps two rows when the
labels differ.
---
data/roles.yaml | 25 +++++++++------
.../layouts/partials/appearances_index.html | 32 +++++++++++++------
2 files changed, 38 insertions(+), 19 deletions(-)
diff --git a/data/roles.yaml b/data/roles.yaml
index 90e2f8c9..23f6975b 100644
--- a/data/roles.yaml
+++ b/data/roles.yaml
@@ -1,14 +1,21 @@
# The role a person modal shows for each heading an event page lists people
-# under. Left side: the heading as it is written in the page front matter
-# (people_sections[].title on an event page, people_levels[].name on an
-# association page). Right side: the singular role the modal prints next to
-# the links to those pages. A heading that is not in this list is printed as
-# it is, so a new heading works before anyone adds it here.
+# under. Left side: the heading as it is written in the page front matter:
+# the level name (people_sections[].levels[].name on an event page,
+# people_levels[].name on an association page), or the section title
+# (people_sections[].title) when the level has no name. Right side: the
+# singular role the modal prints next to the links to those pages. A heading
+# that is not in this list is printed as it is, so a new heading works
+# before anyone adds it here.
#
-# "Mentors, speakers & volunteers" names three roles under one heading, so
-# any single word for it is an approximation. Volunteer is the one that is
-# true of everyone listed there.
+# Mentors and Volunteers are two of the three level names of the Django
+# page (Speakers is the third, already mapped), whose section title is
+# "Mentors, speakers & volunteers". The index used to map that title, and
+# so called every mentor and speaker of that page a Volunteer. The title
+# itself is not mapped: no level falls back to it,
+# and a new unnamed level under it would show the title as written, which
+# is the signal to name the level.
Speakers: Speaker
Organizers: Organizer
+Mentors: Mentor
+Volunteers: Volunteer
PyLadiesBCN Organizers: PyLadiesBCN Organizer
-"Mentors, speakers & volunteers": Volunteer
diff --git a/themes/pybcn_theme/layouts/partials/appearances_index.html b/themes/pybcn_theme/layouts/partials/appearances_index.html
index aa2e42a0..5a482bd0 100644
--- a/themes/pybcn_theme/layouts/partials/appearances_index.html
+++ b/themes/pybcn_theme/layouts/partials/appearances_index.html
@@ -11,10 +11,18 @@
partialCached "appearances_index.html" site "appearances-index"
Two front matter shapes list people. An event page has people_sections,
- each with a title and a list of levels; the section title is the heading.
- An association page has people_levels, each with a name; the level name
- is the heading. A level entry is a bare id, or a map with an id when the
- page overrides the role for that entry (see people-grid.html).
+ each with a title and a list of levels. An association page has
+ people_levels, each with a name. A level entry is a bare id, or a map
+ with an id when the page overrides the role for that entry (see
+ people-grid.html).
+
+ The heading is the level name when the level has one, and the section
+ title when it does not. The Django page has one section titled
+ "Mentors, speakers & volunteers" with three named levels, Mentors,
+ Speakers and Volunteers. Indexing the section title made everyone in it
+ a Volunteer; the level name says which of the three each person was.
+ The Speakers and Organizers sections of the event pages have one level
+ each and no level name, so they fall back to the section title.
Only the people listed on /pybcn_association/organizers/ are indexed.
Every other person is a speaker or a volunteer of one event, whose modal
@@ -24,9 +32,12 @@
"Speaker". The heading itself is the fallback, so a new heading shows
up unmapped rather than not at all.
- An appearance is one (heading, page) pair. Ferran Jovell is listed under
- two levels of one section of the Django page, Mentors and Speakers, and
- the modal would otherwise link that page twice under one label.
+ An appearance is one (heading, page) pair. The same person can be
+ listed twice on a page under one heading, by two entries or by a level
+ with no name that repeats the section title, and the modal would then
+ link that page twice under one label. Two different headings on one
+ page stay two appearances: Ferran Jovell is a Mentor and a Speaker of
+ the Django page, and the modal lists that page once under each.
Drafts are skipped by name as well: site.RegularPages drops them in a
normal build, but a server run with -D would index content/canary.md.
@@ -48,9 +59,10 @@
{{- /* heading -> list of ids, in the order the page lists them */ -}}
{{- $headings := slice -}}
{{- range $pg.Params.people_sections -}}
- {{- $ids := slice -}}
- {{- range .levels }}{{ range .people }}{{ $ids = $ids | append . }}{{ end }}{{ end -}}
- {{- $headings = $headings | append (dict "heading" .title "ids" $ids) -}}
+ {{- $title := .title -}}
+ {{- range .levels -}}
+ {{- $headings = $headings | append (dict "heading" (default $title .name) "ids" .people) -}}
+ {{- end -}}
{{- end -}}
{{- range $pg.Params.people_levels -}}
{{- $headings = $headings | append (dict "heading" .name "ids" .people) -}}
From 536017147a7789971e7cc8f9db3d25a954561916 Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 10:17:27 +0200
Subject: [PATCH 17/39] Add a year to the five event pages that had none
The person modal sorts appearances by the year of the page, most recent
first, and a page with no year goes last as year 0. Only the eight pages
that list people carried the field. The other five single events now
carry it too, taken from the title, so the same field is on every event
and a page that starts to list people sorts in its place at once.
The section pages and the monthly events page are not single events and
get no year.
---
content/events/other_events/hacktoberfest_2018.md | 1 +
content/events/other_events/pydata_2017_barcelona.md | 1 +
content/events/pyday_bcn/pyday_bcn_2016.md | 1 +
content/events/pyday_bcn/pyday_bcn_2018.md | 1 +
content/events/pyday_bcn/pyday_bcn_2019.md | 1 +
5 files changed, 5 insertions(+)
diff --git a/content/events/other_events/hacktoberfest_2018.md b/content/events/other_events/hacktoberfest_2018.md
index da0fc358..0ec30428 100644
--- a/content/events/other_events/hacktoberfest_2018.md
+++ b/content/events/other_events/hacktoberfest_2018.md
@@ -1,5 +1,6 @@
---
title: "Hacktoberfest 2018"
+year: 2018
description: ""
menu:
main:
diff --git a/content/events/other_events/pydata_2017_barcelona.md b/content/events/other_events/pydata_2017_barcelona.md
index d196e861..03d12482 100644
--- a/content/events/other_events/pydata_2017_barcelona.md
+++ b/content/events/other_events/pydata_2017_barcelona.md
@@ -1,5 +1,6 @@
---
title: "PyData 2017 - Barcelona edition"
+year: 2017
description: "The Data Science conference from NumFOCUS"
menu:
main:
diff --git a/content/events/pyday_bcn/pyday_bcn_2016.md b/content/events/pyday_bcn/pyday_bcn_2016.md
index daaef738..1027da2e 100644
--- a/content/events/pyday_bcn/pyday_bcn_2016.md
+++ b/content/events/pyday_bcn/pyday_bcn_2016.md
@@ -1,5 +1,6 @@
---
title: "PyDay BCN 2016"
+year: 2016
description: ""
menu:
main:
diff --git a/content/events/pyday_bcn/pyday_bcn_2018.md b/content/events/pyday_bcn/pyday_bcn_2018.md
index 80ce9f80..8bebda13 100644
--- a/content/events/pyday_bcn/pyday_bcn_2018.md
+++ b/content/events/pyday_bcn/pyday_bcn_2018.md
@@ -1,5 +1,6 @@
---
title: "PyDay BCN 2018"
+year: 2018
description: ""
menu:
main:
diff --git a/content/events/pyday_bcn/pyday_bcn_2019.md b/content/events/pyday_bcn/pyday_bcn_2019.md
index 1d9f53e6..a45dd974 100644
--- a/content/events/pyday_bcn/pyday_bcn_2019.md
+++ b/content/events/pyday_bcn/pyday_bcn_2019.md
@@ -1,5 +1,6 @@
---
title: "PyDay BCN 2019"
+year: 2019
description: ""
menu:
main:
From c8a332bbf8a777b7d4820c1e6e020226ba336bc4 Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 10:20:42 +0200
Subject: [PATCH 18/39] List every appearance in the person modal, whatever
page it is on
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The list left out the page the modal was opened from, which made the
modal depend on the page around it, and on /organizers/ hid the level of
the page, which is the information: the modal of Jordi Bosch did not say
Management Board (2026), the one of Laura Pérez Mayos did not say
Collaborators and Management Board (2018 - 2025), and the one of David
Arcos did not say Permanent Committee.
The modal is on its way to becoming a page per person with its own URL,
and for that its content has to be the same from everywhere: a list
that changes with the page it was opened from cannot become one page.
Every appearance is now shown with its link, on every page. On
/organizers/ the first row links to the page the reader is on; that is
the price of one list, and it stops being odd the day the modal is a
page.
A page with no year is a role held now, not an event, and sorts before
every dated event, so the current board heads the list. The rule used to
send it last, which put Management Board (2026) under the events of
2025.
The page argument went with the exclusion. It was threaded through
event.html, people.html, people-grid.html and people_summary.html for
this one partial and nothing else read it.
The empty branch stays: the index covers only the people listed on
/organizers/, so a speaker who is not an organizer still has no
appearance.
---
.../pybcn_theme/layouts/_default/event.html | 2 +-
.../pybcn_theme/layouts/_default/people.html | 2 +-
.../layouts/partials/people-grid.html | 4 +-
.../layouts/partials/people_summary.html | 3 +-
.../layouts/partials/person_appearances.html | 49 ++++++++++++-------
5 files changed, 35 insertions(+), 25 deletions(-)
diff --git a/themes/pybcn_theme/layouts/_default/event.html b/themes/pybcn_theme/layouts/_default/event.html
index a1692d3a..3b43d4e5 100644
--- a/themes/pybcn_theme/layouts/_default/event.html
+++ b/themes/pybcn_theme/layouts/_default/event.html
@@ -73,7 +73,7 @@
{{ end }}
diff --git a/themes/pybcn_theme/layouts/_default/people.html b/themes/pybcn_theme/layouts/_default/people.html
index 379cfd86..492e4303 100644
--- a/themes/pybcn_theme/layouts/_default/people.html
+++ b/themes/pybcn_theme/layouts/_default/people.html
@@ -1,5 +1,5 @@
{{ define "main" }}
-{{ partial "people-grid.html" (dict "levels" .Params.people_levels "Site" .Site "page" .)}}
+{{ partial "people-grid.html" (dict "levels" .Params.people_levels "Site" .Site)}}
{{ end }}
diff --git a/themes/pybcn_theme/layouts/partials/people-grid.html b/themes/pybcn_theme/layouts/partials/people-grid.html
index 84468f47..439c1f79 100644
--- a/themes/pybcn_theme/layouts/partials/people-grid.html
+++ b/themes/pybcn_theme/layouts/partials/people-grid.html
@@ -4,8 +4,6 @@
Arguments:
levels the list of levels, each with a name, people and people_per_line
Site the site, to look the people pages up
- page the page the grid is on. The modal lists the other pages
- the person appears on and leaves this one out
key a name unique to this grid on the page, "people" by default
An event page renders this partial once per people section, and the same
@@ -49,7 +47,7 @@
{{ $level.name }}
{{ if reflect.IsMap $person }}{{ $id = $person.id }}{{ $role = $person.role }}{{ end }}
{{ range $page := where $pages ".Params.id" "eq" $id }}
{{ end }}
{{ end }}
diff --git a/themes/pybcn_theme/layouts/partials/people_summary.html b/themes/pybcn_theme/layouts/partials/people_summary.html
index 3c35e528..dfb6a680 100644
--- a/themes/pybcn_theme/layouts/partials/people_summary.html
+++ b/themes/pybcn_theme/layouts/partials/people_summary.html
@@ -8,7 +8,6 @@
Arguments:
person the person page
- page the page the card is on, for the appearance list in the modal
role optional, the role to show instead of pybcn_position, when
the page lists the person with one (see people-grid.html)
key the grid key, so the modal id is unique on the page
@@ -88,7 +87,7 @@
diff --git a/themes/pybcn_theme/layouts/partials/person_appearances.html b/themes/pybcn_theme/layouts/partials/person_appearances.html
index a829f034..c62757fb 100644
--- a/themes/pybcn_theme/layouts/partials/person_appearances.html
+++ b/themes/pybcn_theme/layouts/partials/person_appearances.html
@@ -1,39 +1,52 @@
{{- /*
The pages one person appears on, grouped by role, as links.
- Speaker PyDay BCN 2025
- Organizer PyDay BCN 2024, PyDay BCN 2021, PyDay BCN 2020
+ Management Board (2026) Organizers
+ Speaker PyDay BCN (2025)
+ Organizer PyDay BCN (2024), PyDay BCN (2021), PyDay BCN (2020)
- Arguments:
- person the person page
- page the page the modal is on
+ Argument: the person page.
The index comes from appearances_index.html, built once per build.
- The page the modal is on is left out. Everyone on /organizers/ would
- otherwise get a link back to the page the reader is looking at, and the
- role line above already says what that link would say. Six organizers
- then have no appearance at all, and the block emits nothing for them:
- no heading, no empty list.
+ The list is the same whatever page the modal is opened from. It used
+ to leave out that page, so that nobody got a link back to the page
+ they were reading, and on /organizers/ that hid the level of the page,
+ which is the information: that Jordi Bosch is on the Management Board
+ (2026), that Laura Pérez Mayos is a Collaborator and was on the
+ Management Board (2018 - 2025). The modal is on its way to becoming a
+ page per person with its own URL, and for that its content has to be
+ the same from everywhere: a list that depends on the page it was
+ opened from cannot become one page. So the current page stays in, link
+ and all. On /organizers/ the first row links to the page the reader is
+ on. That is the price of one list, and it stops being odd the day the
+ modal is a page.
Order: the role with the most recent appearance first, and inside a
- role the most recent page first. A page with no year, such as the
- PyLadies organizers page, goes last. Ties fall back to the label and
- the title, so two builds give the same order.
+ role the most recent page first. A page with no year is a role that
+ is held now, not an event: the organizers pages of PyBCN and of
+ PyLadies BCN. It sorts before every dated event, so the current board
+ heads the list and the events follow, newest first. Ties fall back to
+ the label and the title, so two builds give the same order.
+
+ A person with no appearance gets nothing: no heading, no empty list.
+ Everyone on /organizers/ has at least that page, but the index covers
+ only the people listed there, so a speaker of one event who is not an
+ organizer still has an empty list. The Archive will widen this.
*/ -}}
-{{- $here := .page.RelPermalink -}}
{{- $index := partialCached "appearances_index.html" site "appearances-index" -}}
{{- $groups := dict -}}
-{{- range index $index .person.Params.id -}}
- {{- if eq .url $here }}{{ continue }}{{ end -}}
- {{- $item := merge . (dict "key" (printf "%04d %s" (sub 9999 .year) .title)) -}}
+{{- range index $index .Params.id -}}
+ {{- $rank := 0 -}}{{- if .year }}{{ $rank = sub 9999 .year }}{{ end -}}
+ {{- $item := merge . (dict "key" (printf "%04d %s" $rank .title)) -}}
{{- $groups = merge $groups (dict .label (append $item (default slice (index $groups .label)))) -}}
{{- end -}}
{{- $list := slice -}}
{{- range $label, $items := $groups -}}
{{- $items = sort $items "key" -}}
{{- $newest := (index $items 0).year -}}
- {{- $list = $list | append (dict "label" $label "items" $items "key" (printf "%04d %s" (sub 9999 $newest) $label)) -}}
+ {{- $rank := 0 -}}{{- if $newest }}{{ $rank = sub 9999 $newest }}{{ end -}}
+ {{- $list = $list | append (dict "label" $label "items" $items "key" (printf "%04d %s" $rank $label)) -}}
{{- end -}}
{{- with $list -}}
From e89b0d3f1cb2d911e76f300dfe7af40a0000b56f Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 10:24:58 +0200
Subject: [PATCH 19/39] End every event title with its year in parentheses
The titles named the year in three ways: at the end (PyDay BCN 2025), in
the middle (PyData 2017 - Barcelona edition) or not at all (Hands-on
Django with PyLadiesBCN). The modal lists several events in one row, and
the navigation menu lists them in a column, so the shapes sat side by
side. Every single event now reads Name (Year): PyDay BCN (2025),
PyDataBCN (2023), Hacktoberfest (2018), Hands-on Django with PyLadiesBCN
(2022), PyData Barcelona (2017).
The URLs come from the file names and do not change. The full list of
output paths is the same before and after, and the aliases still point
at the same pages.
---
content/events/other_events/django_pyladies_2022.md | 2 +-
content/events/other_events/hacktoberfest_2018.md | 2 +-
content/events/other_events/pydata_2017_barcelona.md | 2 +-
content/events/pydatabcn/pydatabcn_2023.md | 2 +-
content/events/pyday_bcn/pyday_bcn_2016.md | 2 +-
content/events/pyday_bcn/pyday_bcn_2018.md | 2 +-
content/events/pyday_bcn/pyday_bcn_2019.md | 2 +-
content/events/pyday_bcn/pyday_bcn_2020.md | 2 +-
content/events/pyday_bcn/pyday_bcn_2021.md | 2 +-
content/events/pyday_bcn/pyday_bcn_2022.md | 2 +-
content/events/pyday_bcn/pyday_bcn_2023.md | 2 +-
content/events/pyday_bcn/pyday_bcn_2024.md | 2 +-
content/events/pyday_bcn/pyday_bcn_2025.md | 2 +-
13 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/content/events/other_events/django_pyladies_2022.md b/content/events/other_events/django_pyladies_2022.md
index e61c0fad..f04af2a1 100644
--- a/content/events/other_events/django_pyladies_2022.md
+++ b/content/events/other_events/django_pyladies_2022.md
@@ -1,5 +1,5 @@
---
-title: "Hands-on Django with PyLadiesBCN"
+title: "Hands-on Django with PyLadiesBCN (2022)"
year: 2022
description: "From zero to hero 🤘 Learn how to code your own web application!"
menu:
diff --git a/content/events/other_events/hacktoberfest_2018.md b/content/events/other_events/hacktoberfest_2018.md
index 0ec30428..0ab3d45b 100644
--- a/content/events/other_events/hacktoberfest_2018.md
+++ b/content/events/other_events/hacktoberfest_2018.md
@@ -1,5 +1,5 @@
---
-title: "Hacktoberfest 2018"
+title: "Hacktoberfest (2018)"
year: 2018
description: ""
menu:
diff --git a/content/events/other_events/pydata_2017_barcelona.md b/content/events/other_events/pydata_2017_barcelona.md
index 03d12482..f121c13c 100644
--- a/content/events/other_events/pydata_2017_barcelona.md
+++ b/content/events/other_events/pydata_2017_barcelona.md
@@ -1,5 +1,5 @@
---
-title: "PyData 2017 - Barcelona edition"
+title: "PyData Barcelona (2017)"
year: 2017
description: "The Data Science conference from NumFOCUS"
menu:
diff --git a/content/events/pydatabcn/pydatabcn_2023.md b/content/events/pydatabcn/pydatabcn_2023.md
index 7c6f12e0..db0d27d9 100644
--- a/content/events/pydatabcn/pydatabcn_2023.md
+++ b/content/events/pydatabcn/pydatabcn_2023.md
@@ -1,5 +1,5 @@
---
-title: "PyDataBCN 2023"
+title: "PyDataBCN (2023)"
year: 2023
description: "The annual gathering for Pythonists in love with data!"
menu:
diff --git a/content/events/pyday_bcn/pyday_bcn_2016.md b/content/events/pyday_bcn/pyday_bcn_2016.md
index 1027da2e..dd0c5352 100644
--- a/content/events/pyday_bcn/pyday_bcn_2016.md
+++ b/content/events/pyday_bcn/pyday_bcn_2016.md
@@ -1,5 +1,5 @@
---
-title: "PyDay BCN 2016"
+title: "PyDay BCN (2016)"
year: 2016
description: ""
menu:
diff --git a/content/events/pyday_bcn/pyday_bcn_2018.md b/content/events/pyday_bcn/pyday_bcn_2018.md
index 8bebda13..3233b8dd 100644
--- a/content/events/pyday_bcn/pyday_bcn_2018.md
+++ b/content/events/pyday_bcn/pyday_bcn_2018.md
@@ -1,5 +1,5 @@
---
-title: "PyDay BCN 2018"
+title: "PyDay BCN (2018)"
year: 2018
description: ""
menu:
diff --git a/content/events/pyday_bcn/pyday_bcn_2019.md b/content/events/pyday_bcn/pyday_bcn_2019.md
index a45dd974..c0e2b490 100644
--- a/content/events/pyday_bcn/pyday_bcn_2019.md
+++ b/content/events/pyday_bcn/pyday_bcn_2019.md
@@ -1,5 +1,5 @@
---
-title: "PyDay BCN 2019"
+title: "PyDay BCN (2019)"
year: 2019
description: ""
menu:
diff --git a/content/events/pyday_bcn/pyday_bcn_2020.md b/content/events/pyday_bcn/pyday_bcn_2020.md
index 1ff5bc53..589ef091 100644
--- a/content/events/pyday_bcn/pyday_bcn_2020.md
+++ b/content/events/pyday_bcn/pyday_bcn_2020.md
@@ -1,5 +1,5 @@
---
-title: "PyDay BCN 2020"
+title: "PyDay BCN (2020)"
year: 2020
description: "The fourth edition!"
menu:
diff --git a/content/events/pyday_bcn/pyday_bcn_2021.md b/content/events/pyday_bcn/pyday_bcn_2021.md
index 443a8ad3..ac0af524 100644
--- a/content/events/pyday_bcn/pyday_bcn_2021.md
+++ b/content/events/pyday_bcn/pyday_bcn_2021.md
@@ -1,5 +1,5 @@
---
-title: "PyDay BCN 2021"
+title: "PyDay BCN (2021)"
year: 2021
description: "Post-pandemic edition!"
menu:
diff --git a/content/events/pyday_bcn/pyday_bcn_2022.md b/content/events/pyday_bcn/pyday_bcn_2022.md
index 7cb850f9..1645d6c7 100644
--- a/content/events/pyday_bcn/pyday_bcn_2022.md
+++ b/content/events/pyday_bcn/pyday_bcn_2022.md
@@ -1,5 +1,5 @@
---
-title: "PyDay BCN 2022"
+title: "PyDay BCN (2022)"
year: 2022
description: "For the community, by the community!"
menu:
diff --git a/content/events/pyday_bcn/pyday_bcn_2023.md b/content/events/pyday_bcn/pyday_bcn_2023.md
index d6d6c627..7d9a3259 100644
--- a/content/events/pyday_bcn/pyday_bcn_2023.md
+++ b/content/events/pyday_bcn/pyday_bcn_2023.md
@@ -1,5 +1,5 @@
---
-title: "PyDay BCN 2023"
+title: "PyDay BCN (2023)"
year: 2023
description: "For the community, by the community!"
menu:
diff --git a/content/events/pyday_bcn/pyday_bcn_2024.md b/content/events/pyday_bcn/pyday_bcn_2024.md
index 9b2ffe99..1f2441c5 100644
--- a/content/events/pyday_bcn/pyday_bcn_2024.md
+++ b/content/events/pyday_bcn/pyday_bcn_2024.md
@@ -1,5 +1,5 @@
---
-title: "PyDay BCN 2024"
+title: "PyDay BCN (2024)"
year: 2024
description: "For the community, by the community!"
menu:
diff --git a/content/events/pyday_bcn/pyday_bcn_2025.md b/content/events/pyday_bcn/pyday_bcn_2025.md
index 8070bf16..5f70a966 100644
--- a/content/events/pyday_bcn/pyday_bcn_2025.md
+++ b/content/events/pyday_bcn/pyday_bcn_2025.md
@@ -1,5 +1,5 @@
---
-title: "PyDay BCN 2025"
+title: "PyDay BCN (2025)"
year: 2025
description: "For the community, by the community!"
menu:
From c795f3686f0f1344c364376790bc03b62fb4b04e Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 10:45:32 +0200
Subject: [PATCH 20/39] Fit six cards on a row, at 178px with a 12px gutter
The Permanent Committee has six people and sat as three and three. Six
cards of 200px with a 20px gutter need 1320px and the grid is 1140, the
Bootstrap container width the rest of the page uses, so the card goes to
178px and the gutter to 12px.
Every card on the site changes, not only this section: the rule is that
a card is the same width everywhere, so no section reads as more
important than another.
The alternative was to widen the people grid to 1320px and keep the
200px card. That made the section wider than the heading bands and the
rest of the page, which looked worse than the smaller card.
Measured on the organizers page and PyDay 2025 at 1440, 992 and 390: no
name, role or icon row on two lines.
---
content/pybcn_association/organizers.md | 2 +-
themes/pybcn_theme/assets/scss/people.scss | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/content/pybcn_association/organizers.md b/content/pybcn_association/organizers.md
index 64371b8a..2737f170 100644
--- a/content/pybcn_association/organizers.md
+++ b/content/pybcn_association/organizers.md
@@ -13,7 +13,7 @@ people_levels:
- people_per_line: 5
people: [jordi-bosch, daniel-mesejo, yago-tafalla, mauricio-volcanes, sergi-ramirez]
name: Management Board (2026)
- - people_per_line: 3
+ - people_per_line: 6
people: [alberto, david, ifosch, natalia, alicia-morales, ferran-jovell]
name: Permanent Committee
- people_per_line: 4
diff --git a/themes/pybcn_theme/assets/scss/people.scss b/themes/pybcn_theme/assets/scss/people.scss
index 5caf14ae..ae076569 100644
--- a/themes/pybcn_theme/assets/scss/people.scss
+++ b/themes/pybcn_theme/assets/scss/people.scss
@@ -32,8 +32,8 @@
// so a fixed slot width dropped that page from four cards a row to
// three. The cards there are a little narrower than on the organizers
// page, which has the room, and the count is the same as before.
- $card: 200px;
- $gutter: 20px;
+ $card: 178px;
+ $gutter: 12px;
// A literal divisor is not a division in Dart Sass, which emits
// width: 100%/3 and the browser drops the rule. A variable divides.
$tablet_per_line: 3;
From 3d46a200cddfebc3353e84eb8c773d04a1197488 Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 10:47:24 +0200
Subject: [PATCH 21/39] Order the current roles by the page that lists them,
and balance the role line
Two fixes in the person card and its modal.
The headings of a page with no year sorted by label, so a reader saw
Management Board (2018 - 2025) above Permanent Committee, and the
PyLadies page above both. They now sort by the page and then by the
order the page itself lists its levels, which organizers.md writes
current board first. The index carries that position as ord.
The role also had 5px of box above and below it but did not look it. The
person data block set line-height: 1rem, so the 19.2px name overflowed
its own 16px line box by about 3px top and bottom while the smaller role
sat inside its box with room to spare. A reader saw 2px over the role
and 7px under it. A ratio of 1.2 makes each box track its own text.
Measured on the organizers page at 1440px: 5px above and below the role
on every card, and the modal reads Permanent Committee, Management Board
(2018 - 2025), PyLadiesBCN Organizer, then the events newest first.
---
themes/pybcn_theme/assets/scss/people.scss | 8 +++++++-
.../layouts/partials/appearances_index.html | 16 +++++++++++-----
.../layouts/partials/person_appearances.html | 17 +++++++++++------
3 files changed, 29 insertions(+), 12 deletions(-)
diff --git a/themes/pybcn_theme/assets/scss/people.scss b/themes/pybcn_theme/assets/scss/people.scss
index ae076569..98cc39e2 100644
--- a/themes/pybcn_theme/assets/scss/people.scss
+++ b/themes/pybcn_theme/assets/scss/people.scss
@@ -148,7 +148,13 @@
}
.person_data {
- line-height: 1rem;
+ // A ratio, not a fixed 1rem. At 1rem the 19.2px name
+ // overflowed its own 16px line box by about 3px at the top
+ // and the bottom, while the smaller role sat inside its box
+ // with room to spare. The boxes above and below the role
+ // were 5px apart each, but what a reader saw was 2px over
+ // the role and 7px under it.
+ line-height: 1.2;
// 5px above the name, the same as between the name and the
// role, so the text block reads as one unit under the photo.
// The side padding keeps the text off the border now that
diff --git a/themes/pybcn_theme/layouts/partials/appearances_index.html b/themes/pybcn_theme/layouts/partials/appearances_index.html
index 5a482bd0..bd23bdd1 100644
--- a/themes/pybcn_theme/layouts/partials/appearances_index.html
+++ b/themes/pybcn_theme/layouts/partials/appearances_index.html
@@ -2,7 +2,7 @@
The pages each organizer appears on, inverted from the pages themselves.
Returns a map from person id to a list of appearances, each a dict with
- label, title, url and year. No argument is read: the data comes from
+ label, title, url, year and ord. No argument is read: the data comes from
site.RegularPages and from data/roles.yaml.
Call it through partialCached with a constant variant, so the site is
@@ -70,17 +70,23 @@
{{- if not $headings }}{{ continue }}{{ end -}}
{{- $seen := dict -}}
- {{- range $headings -}}
- {{- $heading := .heading -}}
+ {{- range $ord, $h := $headings -}}
+ {{- $heading := $h.heading -}}
{{- $label := default $heading (index site.Data.roles $heading) -}}
- {{- range .ids -}}
+ {{- range $h.ids -}}
{{- $id := . -}}
{{- if reflect.IsMap . }}{{ $id = .id }}{{ end -}}
{{- if not (index $scope $id) }}{{ continue }}{{ end -}}
{{- $key := printf "%s|%s" $label $id -}}
{{- if index $seen $key }}{{ continue }}{{ end -}}
{{- $seen = merge $seen (dict $key true) -}}
- {{- $entry := dict "label" $label "title" $pg.Title "url" $pg.RelPermalink "year" (int (default 0 $pg.Params.year)) -}}
+ {{- /* ord is the position of the heading in the page. It orders
+ the headings of a page with no year, where there is no
+ date to sort by: the levels of organizers.md are listed
+ current board first, and the list has to read that way
+ rather than alphabetically, which put the 2018 board
+ above the current committee. */ -}}
+ {{- $entry := dict "label" $label "title" $pg.Title "url" $pg.RelPermalink "year" (int (default 0 $pg.Params.year)) "ord" $ord -}}
{{- $index = merge $index (dict $id (append $entry (default slice (index $index $id)))) -}}
{{- end -}}
{{- end -}}
diff --git a/themes/pybcn_theme/layouts/partials/person_appearances.html b/themes/pybcn_theme/layouts/partials/person_appearances.html
index c62757fb..a9b6da07 100644
--- a/themes/pybcn_theme/layouts/partials/person_appearances.html
+++ b/themes/pybcn_theme/layouts/partials/person_appearances.html
@@ -26,8 +26,13 @@
role the most recent page first. A page with no year is a role that
is held now, not an event: the organizers pages of PyBCN and of
PyLadies BCN. It sorts before every dated event, so the current board
- heads the list and the events follow, newest first. Ties fall back to
- the label and the title, so two builds give the same order.
+ heads the list and the events follow, newest first. Among those, the
+ order is the page and then the order the page itself lists its levels,
+ which is current board first: sorting them by label put Management
+ Board (2018 - 2025) above Permanent Committee, and the PyLadies page
+ above both. The page comes from its path, so the PyBCN organizers page
+ sorts before the PyLadies one. Ties fall back to the title and the
+ label, so two builds give the same order.
A person with no appearance gets nothing: no heading, no empty list.
Everyone on /organizers/ has at least that page, but the index covers
@@ -38,15 +43,15 @@
{{- $groups := dict -}}
{{- range index $index .Params.id -}}
{{- $rank := 0 -}}{{- if .year }}{{ $rank = sub 9999 .year }}{{ end -}}
- {{- $item := merge . (dict "key" (printf "%04d %s" $rank .title)) -}}
+ {{- $item := merge . (dict "key" (printf "%04d %s %04d %s" $rank .url .ord .title)) -}}
{{- $groups = merge $groups (dict .label (append $item (default slice (index $groups .label)))) -}}
{{- end -}}
{{- $list := slice -}}
{{- range $label, $items := $groups -}}
{{- $items = sort $items "key" -}}
- {{- $newest := (index $items 0).year -}}
- {{- $rank := 0 -}}{{- if $newest }}{{ $rank = sub 9999 $newest }}{{ end -}}
- {{- $list = $list | append (dict "label" $label "items" $items "key" (printf "%04d %s" $rank $label)) -}}
+ {{- $first := index $items 0 -}}
+ {{- $rank := 0 -}}{{- if $first.year }}{{ $rank = sub 9999 $first.year }}{{ end -}}
+ {{- $list = $list | append (dict "label" $label "items" $items "key" (printf "%04d %s %04d %s" $rank $first.url $first.ord $label)) -}}
{{- end -}}
{{- with $list -}}
From 90db6908d798d897a7b52443500ddc55e089c234 Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 10:51:47 +0200
Subject: [PATCH 22/39] Remove the trailing slash from every social URL, and
reject it
The four link fields (linkedin, github, twitter, site) in content/people
and content/sponsors mixed two styles: 110 of the 322 values ended with a
slash and 212 did not. A host carries no trailing slash of its own, as in
https://ber2.github.io, so a path under it gets none either. One rule, no
exceptions.
Only the final slash changes. Host, path, case, and the quoting of each
line stay as they were. canary.md, a test fixture, is not touched.
Per field, values with a slash before -> after:
people: linkedin 84/117, github 7/82, twitter 1/63, site 11/23 -> 0
sponsors: linkedin 5/6, twitter 2/31 -> 0
check_social() validated the host prefix and refused query parameters,
but said nothing about the final slash, which is how the values drifted.
The fix is mechanical and has one right answer, so it is now an error
and not a warning: it must never drift again. The rule covers the three
prefixed fields and site, and the message names the value to use. For
site, the http warning still fires on its own, so a slash does not hide
it.
---
bin/check-content | 16 ++++++++++++++--
content/people/adria-blanco.md | 2 +-
content/people/adrian-garcia-riber.md | 2 +-
content/people/albert-franzi.md | 2 +-
content/people/albert-pujol-torras.md | 2 +-
content/people/alberto.md | 2 +-
content/people/alicia-morales.md | 4 ++--
content/people/amir-azam.md | 2 +-
content/people/ana-eliza-barbosa.md | 2 +-
content/people/angel.md | 2 +-
content/people/ankit-mahato.md | 2 +-
content/people/antonio-molina.md | 2 +-
content/people/ariadna_fernandez_estevez.md | 2 +-
content/people/asia-noble.md | 2 +-
content/people/brian-power.md | 2 +-
content/people/camilo-chacon.md | 2 +-
content/people/carles_barrobes.md | 2 +-
content/people/carmen-iniesta-lopez.md | 2 +-
content/people/christian-adell.md | 4 ++--
content/people/cristina-cosma.md | 2 +-
content/people/daniel-sanchez-santolaya.md | 2 +-
content/people/dave-pitts.md | 2 +-
content/people/david-blazquez.md | 2 +-
content/people/david-de-la-iglesia-castro.md | 2 +-
content/people/david.md | 4 ++--
content/people/diego-quintana.md | 4 ++--
content/people/edgar-riba.md | 4 ++--
content/people/edgar-sarria-tenes.md | 2 +-
content/people/eduard_cespedes.md | 6 +++---
content/people/eloi.md | 2 +-
content/people/ely-farres.md | 2 +-
content/people/enric-domingo.md | 2 +-
content/people/eric-massip.md | 4 ++--
content/people/esperanza-buitrago.md | 2 +-
content/people/ester-jara.md | 2 +-
content/people/ferran-fabregas.md | 4 ++--
content/people/flavie-le-bars.md | 2 +-
content/people/francesco-faraone.md | 2 +-
content/people/gajendra-deshpande.md | 2 +-
content/people/gema-parreno.md | 2 +-
content/people/guille-abad.md | 2 +-
content/people/ifosch.md | 2 +-
content/people/javier-ramos-panduro.md | 2 +-
content/people/javier-sabariego.md | 2 +-
content/people/jimena-escobar.md | 2 +-
content/people/joan-fontanals-martinez.md | 2 +-
content/people/jose_haro.md | 2 +-
content/people/juan-bernardo-lince.md | 2 +-
content/people/juan-luis-cano.md | 4 ++--
content/people/julio-martinez.md | 4 ++--
content/people/kemalcan-bora.md | 2 +-
content/people/kevin-albes.md | 2 +-
content/people/kevin-sanchez.md | 2 +-
content/people/laysa-uchoa.md | 2 +-
content/people/lpmayos.md | 4 ++--
content/people/manuel-gijon.md | 2 +-
content/people/marc-pomar.md | 2 +-
content/people/marc-pous.md | 4 ++--
content/people/marc-ramirez.md | 2 +-
content/people/maria-teresa-grifa.md | 4 ++--
content/people/matteo-bruno.md | 2 +-
content/people/miquel-sarrias.md | 2 +-
content/people/mireia.md | 2 +-
content/people/miroslav_sedivy.md | 2 +-
content/people/natalia.md | 2 +-
content/people/nikita-polovinkin.md | 2 +-
content/people/noe-casas.md | 2 +-
content/people/nuria.md | 2 +-
content/people/oriol-abril-pla.md | 4 ++--
content/people/patricia-lamadrid.md | 4 ++--
content/people/paula-bassaganas.md | 2 +-
content/people/paula_szewach.md | 4 ++--
content/people/pavel-lonkin.md | 2 +-
content/people/pere-miquel-brull.md | 2 +-
content/people/rajdeep-pal.md | 2 +-
content/people/rberenguel.md | 2 +-
content/people/ricardo-ander-egg.md | 2 +-
content/people/ruben-afonso.md | 2 +-
content/people/sergi-baena-miret.md | 2 +-
content/people/thais-ruiz-de-alda.md | 2 +-
content/people/thomas-alisi.md | 2 +-
content/people/ubaldo-hervas.md | 2 +-
content/people/vincent-choubard.md | 2 +-
content/people/vyron-vasileiadis.md | 2 +-
content/people/xavi.md | 4 ++--
content/people/xiang-xu.md | 2 +-
content/sponsors/codurance.md | 2 +-
content/sponsors/coopdevs.md | 2 +-
content/sponsors/isdieducation.md | 2 +-
content/sponsors/okta.md | 2 +-
content/sponsors/protopixel.md | 2 +-
content/sponsors/typeform.md | 2 +-
content/sponsors/verse.md | 2 +-
93 files changed, 124 insertions(+), 112 deletions(-)
diff --git a/bin/check-content b/bin/check-content
index 0b33a67e..7c030bb4 100755
--- a/bin/check-content
+++ b/bin/check-content
@@ -234,6 +234,11 @@ def check_social(people, sponsors):
person's LinkedIn was `ttps://www.linkedin.com/...`, missing the h, which
a browser treats as a relative path. It had never worked and nobody had
noticed.
+
+ A trailing slash is an error, not a warning, because the fix is mechanical
+ and has one right answer. Left to taste, the values split about two to one
+ between the two styles across more than two hundred links. A host has no
+ trailing slash (https://ber2.github.io), so a profile path gets none either.
"""
for page_id, path in sorted({**people, **sponsors}.items()):
data = front_matter(path) or {}
@@ -249,6 +254,9 @@ def check_social(people, sponsors):
elif not value.startswith(prefix):
error(path, f"{field} is '{value}', which does not start with "
f"{prefix}")
+ elif value.endswith("/"):
+ error(path, f"{field} ends with a slash: '{value}'. "
+ f"Use '{value.rstrip('/')}'.")
site = data.get("site")
if site:
@@ -257,8 +265,12 @@ def check_social(people, sponsors):
error(path, f"site carries query parameters: '{site}'")
elif not site.startswith(("https://", "http://")):
error(path, f"site is '{site}', which is not an http or https URL")
- elif site.startswith("http://"):
- warn(path, f"site is served over http, not https: '{site}'")
+ else:
+ if site.endswith("/"):
+ error(path, f"site ends with a slash: '{site}'. "
+ f"Use '{site.rstrip('/')}'.")
+ if site.startswith("http://"):
+ warn(path, f"site is served over http, not https: '{site}'")
def check_logos(sponsors):
diff --git a/content/people/adria-blanco.md b/content/people/adria-blanco.md
index 8a8e43cb..d0ae078b 100644
--- a/content/people/adria-blanco.md
+++ b/content/people/adria-blanco.md
@@ -3,7 +3,7 @@ id: adria-blanco
name: "Adrià Blanco"
short_bio: "Quantum Engineer"
photo: "adria-blanco.jpg"
-linkedin: "https://www.linkedin.com/in/adriablancoculla/"
+linkedin: "https://www.linkedin.com/in/adriablancoculla"
---
Adrià is a last year BSc student in Physics at UB. Before joining Qilimanjaro’s QaaS team as a junior software engineer, he carried out two internships. First, he collaborated with Dr. Miquel Montero to develop teaching material for Master Students related to Quant Finance. Then, he worked as a Trainee Data Analyst for Schneider Electric, where he was introduced to AWS services. His professional interests span across Data Science, Quantitative Finance and Quantum Computing. In fact, in his BSc Final Thesis he is exploring how quantum annealing will help to solve very complex financial problems, such as portfolio optimization. He would define himself as proactive, intense and fast-learner. Always eager to learn and broaden his horizons.
\ No newline at end of file
diff --git a/content/people/adrian-garcia-riber.md b/content/people/adrian-garcia-riber.md
index 34daefa8..a2c683c5 100644
--- a/content/people/adrian-garcia-riber.md
+++ b/content/people/adrian-garcia-riber.md
@@ -2,7 +2,7 @@
id: adrian-garcia-riber
name: Adrián García Riber
photo: adrian-garcia-riber.jpg
-linkedin: https://www.linkedin.com/in/adriangriber/
+linkedin: https://www.linkedin.com/in/adriangriber
github: https://github.com/AdrianGRiber
---
diff --git a/content/people/albert-franzi.md b/content/people/albert-franzi.md
index 27425030..518711fc 100644
--- a/content/people/albert-franzi.md
+++ b/content/people/albert-franzi.md
@@ -6,5 +6,5 @@ photo: albert-franzi-cros.jpg
photo_anchor: Left
twitter: https://x.com/franzicros
-linkedin: https://www.linkedin.com/in/albertfranzi/
+linkedin: https://www.linkedin.com/in/albertfranzi
---
diff --git a/content/people/albert-pujol-torras.md b/content/people/albert-pujol-torras.md
index 7d4c43e5..bb27473e 100644
--- a/content/people/albert-pujol-torras.md
+++ b/content/people/albert-pujol-torras.md
@@ -2,7 +2,7 @@
id: albert-pujol-torras
name: Albert Pujol Torras
photo: albert-pujol-torras.jpg
-linkedin: https://www.linkedin.com/in/albert-pujol-torras-3a7367/
+linkedin: https://www.linkedin.com/in/albert-pujol-torras-3a7367
---
Albert Pujol Torras has a degree in Computer Science, and a Ph.D in computer vision. With 20+ years of experience in data and machine learning. He has contributed to 28 papers, and holds 6 patents. Albert has developed data science teams and platforms in aerospace, biotech, and digital marketing companies. Currently, he serves as the VP of Data Science at The Hotels Network.
\ No newline at end of file
diff --git a/content/people/alberto.md b/content/people/alberto.md
index af12f46f..7b09e881 100644
--- a/content/people/alberto.md
+++ b/content/people/alberto.md
@@ -6,7 +6,7 @@ short_bio: "Senior Data Scientist at Hybrid Theory"
photo: alberto-camara.jpg
pybcn_position: Organizer
twitter: "https://x.com/b3r2s"
-linkedin: "https://www.linkedin.com/in/alberto-camara/"
+linkedin: "https://www.linkedin.com/in/alberto-camara"
site: https://ber2.github.io
---
diff --git a/content/people/alicia-morales.md b/content/people/alicia-morales.md
index a663d04a..38262db2 100644
--- a/content/people/alicia-morales.md
+++ b/content/people/alicia-morales.md
@@ -10,8 +10,8 @@ pybcn_position: Organizer
twitter: https://x.com/amoralca16
github: https://github.com/amoralca16
-linkedin: https://www.linkedin.com/in/%F0%9F%91%A9%E2%80%8D%F0%9F%92%BB-alicia-morales-carrasco-81a3ba89/
-site: https://amoralca16.github.io/
+linkedin: https://www.linkedin.com/in/%F0%9F%91%A9%E2%80%8D%F0%9F%92%BB-alicia-morales-carrasco-81a3ba89
+site: https://amoralca16.github.io
---
Data Engineer deeply dedicated to crafting data pipelines, streamlining workflows using Spark, Scala, and Python, and remaining vigilant about emerging technologies. Currently managing data integration and ETL modernization efforts, contributing to data-driven decision-making.
\ No newline at end of file
diff --git a/content/people/amir-azam.md b/content/people/amir-azam.md
index eb4a8fd4..92796650 100644
--- a/content/people/amir-azam.md
+++ b/content/people/amir-azam.md
@@ -3,7 +3,7 @@ id: amir-azam
name: "Amir Azam"
short_bio: "Quantum Engineer"
photo: "amir-azam.jpg"
-linkedin: "https://www.linkedin.com/in/amir-az/"
+linkedin: "https://www.linkedin.com/in/amir-az"
github: "https://github.com/amirazzam2000"
---
diff --git a/content/people/ana-eliza-barbosa.md b/content/people/ana-eliza-barbosa.md
index e3527c7e..38717387 100644
--- a/content/people/ana-eliza-barbosa.md
+++ b/content/people/ana-eliza-barbosa.md
@@ -2,7 +2,7 @@
id: ana-eliza-barbosa
name: "Ana Eliza Barbosa"
photo: ana-eliza-barbosa.jpg
-linkedin: https://www.linkedin.com/in/anaelizabarbosa/
+linkedin: https://www.linkedin.com/in/anaelizabarbosa
---
Staff software engineer at Veriff. Has been coding professionally since 2005 and is currently building all sorts of cool platform software to support automated identity verification.
diff --git a/content/people/angel.md b/content/people/angel.md
index 811517ab..ffb01cdf 100644
--- a/content/people/angel.md
+++ b/content/people/angel.md
@@ -3,7 +3,7 @@ id: angel
name: Àngel Fernández Ibáñez
short_bio: "Software Engineer at Holaluz, with experience in web applications and data pipelines. Trying to leave the world better than I found it."
twitter: "https://x.com/anxodio"
-linkedin: "https://www.linkedin.com/in/anxodio/"
+linkedin: "https://www.linkedin.com/in/anxodio"
github: "https://github.com/anxodio"
photo: angel-fernandez-ibanez.jpg
photo_anchor: Right
diff --git a/content/people/ankit-mahato.md b/content/people/ankit-mahato.md
index efcfbfeb..17ee8f06 100644
--- a/content/people/ankit-mahato.md
+++ b/content/people/ankit-mahato.md
@@ -5,7 +5,7 @@ short_bio: Ankit is a die hard Pythonista & an open source contributor (titus2,
photo: ankit-mahato.png
twitter: https://x.com/ankitmahato
-linkedin: https://www.linkedin.com/in/ankitmahato/
+linkedin: https://www.linkedin.com/in/ankitmahato
github: https://github.com/animator
site: https://realworldpython.guide
---
diff --git a/content/people/antonio-molina.md b/content/people/antonio-molina.md
index 4f2c89b9..97b9d536 100644
--- a/content/people/antonio-molina.md
+++ b/content/people/antonio-molina.md
@@ -4,7 +4,7 @@ name: Antonio Molina
photo: antonio-molina.jpg
twitter: https://x.com/aydevosotros
-linkedin: https://www.linkedin.com/in/amolinag/
+linkedin: https://www.linkedin.com/in/amolinag
github: https://github.com/aydevosotros
---
diff --git a/content/people/ariadna_fernandez_estevez.md b/content/people/ariadna_fernandez_estevez.md
index e2c249ea..503e71af 100644
--- a/content/people/ariadna_fernandez_estevez.md
+++ b/content/people/ariadna_fernandez_estevez.md
@@ -4,7 +4,7 @@ name: Ariadna Fernández
photo: ariadna-fernandez.jpg
short_bio: "MLOps Engineer"
pybcn_position: PyLadiesBCN Organizer
-linkedin: "https://www.linkedin.com/in/ariadna-fernandez-estevez/"
+linkedin: "https://www.linkedin.com/in/ariadna-fernandez-estevez"
github: "https://github.com/afernaes"
---
Applied physicist converted into Machine Learning Engineer. Great interest into Cloud Computing
\ No newline at end of file
diff --git a/content/people/asia-noble.md b/content/people/asia-noble.md
index ef7cb80a..4f6d9909 100644
--- a/content/people/asia-noble.md
+++ b/content/people/asia-noble.md
@@ -4,6 +4,6 @@ name: Asia Noble
short_bio: "Data Science techstack: PowerBI, Python, Scikit Learn, Tensorflow. Background n the creative tech industry, management, consulting, and operations."
photo: asia-noble.jpg
-linkedin: https://www.linkedin.com/in/natasianoble/
+linkedin: https://www.linkedin.com/in/natasianoble
github: https://github.com/nnoble13
---
\ No newline at end of file
diff --git a/content/people/brian-power.md b/content/people/brian-power.md
index ad4ac245..bacfaa02 100644
--- a/content/people/brian-power.md
+++ b/content/people/brian-power.md
@@ -3,7 +3,7 @@ id: brian-power
name: Brian Power
photo: brian-power.jpg
short_bio: ""
-linkedin: "https://www.linkedin.com/in/brian-p-0070a834/"
+linkedin: "https://www.linkedin.com/in/brian-p-0070a834"
github: ""
---
diff --git a/content/people/camilo-chacon.md b/content/people/camilo-chacon.md
index f47c4f13..416862b1 100644
--- a/content/people/camilo-chacon.md
+++ b/content/people/camilo-chacon.md
@@ -3,7 +3,7 @@ id: camilo-chacon
name: Camilo Chacón Sartori
photo: camilo-chacon-sartori.jpg
twitter: https://x.com/camilo_chacon_s
-linkedin: https://www.linkedin.com/in/camilo-chacon-sartori/
+linkedin: https://www.linkedin.com/in/camilo-chacon-sartori
---
Camilo Chacón Sartori es doctorante en el Instituto de Investigación en Inteligencia Artificial (IIIA-CSIC) y en la Universidad Autónoma de Barcelona. Ha publicado tres libros: «Principios de programación», «Mentes geniales. La vida y obra de 12 grandes informáticos» y «Computación y programación funcional». Su principal proyecto, «Érase una vez un algoritmo», es un pódcast y un newsletter donde reflexiona sobre temas técnicos, científicos y filosóficos concernientes a la informática.
\ No newline at end of file
diff --git a/content/people/carles_barrobes.md b/content/people/carles_barrobes.md
index a5d68de9..a6e3a74c 100644
--- a/content/people/carles_barrobes.md
+++ b/content/people/carles_barrobes.md
@@ -6,7 +6,7 @@ short_bio: "Started coding at the age of 13, and it's still one of my most enjoy
I enjoy the world of Continuous Delivery, and often made myself a Developer Enabler: helping building the capabilities, platforms, tools and processes to make team members better and faster at delivering quality software-powered solutions to users."
photo: carles-barrobes.jpg
-linkedin: https://www.linkedin.com/in/carlesbarrobes/
+linkedin: https://www.linkedin.com/in/carlesbarrobes
github: https://github.com/txels
site: https://carles.barrobes.com/pro
---
diff --git a/content/people/carmen-iniesta-lopez.md b/content/people/carmen-iniesta-lopez.md
index be4daef6..6a91bd89 100644
--- a/content/people/carmen-iniesta-lopez.md
+++ b/content/people/carmen-iniesta-lopez.md
@@ -3,7 +3,7 @@ id: carmen-iniesta-lopez
name: Carmen Iniesta López
short_bio: NLP/ML engineer
photo: carmen-iniesta-lopez.jpg
-linkedin: https://www.linkedin.com/in/carmen-iniesta-lopez/
+linkedin: https://www.linkedin.com/in/carmen-iniesta-lopez
github: https://github.com/Ciniesta
twitter: https://x.com/Carmenisst
---
diff --git a/content/people/christian-adell.md b/content/people/christian-adell.md
index d46a4599..7897b6a4 100644
--- a/content/people/christian-adell.md
+++ b/content/people/christian-adell.md
@@ -4,9 +4,9 @@ name: Christian Adell
photo: christian-adell.jpg
twitter: https://x.com/chadell0
-linkedin: https://www.linkedin.com/in/christianadell/
+linkedin: https://www.linkedin.com/in/christianadell
github: https://github.com/chadell
-site: https://www.netbcn.cat/
+site: https://www.netbcn.cat
---
Christian Adell is a network software engineer who has played multiple roles related to networking and IT automation. Currently, as principal architect at Network to Code, he is focused on building network automation solutions for diverse use cases, with great emphasis on open source software. He is passionate about learning and helping others to be happier, but also has more hobbies than hours in the day, so working remotely from Barcelona gives him the time and the space to achieve his dreams. He is co-author of the book "Network Programmability and Automation, 2nd Edition" by O'Reilly. He can be found on Twitter as @chadell0.
\ No newline at end of file
diff --git a/content/people/cristina-cosma.md b/content/people/cristina-cosma.md
index 8fdf4469..6d04dfc1 100644
--- a/content/people/cristina-cosma.md
+++ b/content/people/cristina-cosma.md
@@ -3,5 +3,5 @@ id: cristina-cosma
name: "Cristina Cosma"
short_bio: ""
photo: "cristina-cosma.jpg"
-linkedin: "https://www.linkedin.com/in/cristina-cosma/"
+linkedin: "https://www.linkedin.com/in/cristina-cosma"
---
diff --git a/content/people/daniel-sanchez-santolaya.md b/content/people/daniel-sanchez-santolaya.md
index 934e56e6..fca41503 100644
--- a/content/people/daniel-sanchez-santolaya.md
+++ b/content/people/daniel-sanchez-santolaya.md
@@ -4,7 +4,7 @@ name: Daniel Sanchez Santolaya
short_bio: Data Scientist
photo: daniel-sanchez-santolaya.jpg
twitter: https://x.com/danisbd89
-linkedin: https://www.linkedin.com/in/daniel-sanchez-santolaya/
+linkedin: https://www.linkedin.com/in/daniel-sanchez-santolaya
github: https://github.com/DaniSanchezSantolaya
---
diff --git a/content/people/dave-pitts.md b/content/people/dave-pitts.md
index 2f701582..512c3501 100644
--- a/content/people/dave-pitts.md
+++ b/content/people/dave-pitts.md
@@ -3,7 +3,7 @@ id: dave-pitts
name: "Dave Pitts"
photo: "dave-pitts.png"
github: https://github.com/dgapitts
-linkedin: https://www.linkedin.com/in/dave-pitts-533a7b5/
+linkedin: https://www.linkedin.com/in/dave-pitts-533a7b5
---
I've worked on large, multinational projects for nearly 30 years, beginning as a developer (with COBOL, VB, and Java) and transitioning to Database Engineering over the last 20 years, where I started my DBA career with Oracle and SQL Server. In 2015, I shifted my focus primarily to PostgreSQL. From 2017 to 2021, I led a team responsible for migrating thousands of Oracle databases from a vast, global "private cloud" environment to PostgreSQL in the "public cloud," spanning multiple data centers in the US, EU, Singapore, Australia, and Korea.
In February 2021, I joined Adyen at their headquarters in Amsterdam, focusing on some exceptionally large PostgreSQL installations. In Sept 2022 I joined Gartner in Barcelona to lead multiple DBA teams based in US, Europe and India, this was a very exciting role and I loved living in Barcelona. However after a year, I had to move to Madrid for family/health reasons and so decided to return to Adyen who have a new Tech Hub in Madrid.
diff --git a/content/people/david-blazquez.md b/content/people/david-blazquez.md
index 06b54e61..06d53233 100644
--- a/content/people/david-blazquez.md
+++ b/content/people/david-blazquez.md
@@ -3,5 +3,5 @@ id: david-blazquez
name: "David Blázquez García"
short_bio: ""
photo: david-blazquez-garcia.jpg
-linkedin: "https://www.linkedin.com/in/dblazquezg/"
+linkedin: "https://www.linkedin.com/in/dblazquezg"
---
diff --git a/content/people/david-de-la-iglesia-castro.md b/content/people/david-de-la-iglesia-castro.md
index 01dcbda4..948a76a3 100644
--- a/content/people/david-de-la-iglesia-castro.md
+++ b/content/people/david-de-la-iglesia-castro.md
@@ -6,5 +6,5 @@ photo: david-de-la-iglesia-castro.jpg
twitter: https://x.com/daviddelachurch
github: https://github.com/daavoo
-linkedin: https://www.linkedin.com/in/david-de-la-iglesia-castro-b4b67b20a/
+linkedin: https://www.linkedin.com/in/david-de-la-iglesia-castro-b4b67b20a
---
diff --git a/content/people/david.md b/content/people/david.md
index 6b8ac132..3ac56a28 100644
--- a/content/people/david.md
+++ b/content/people/david.md
@@ -6,7 +6,7 @@ photo: david-arcos.jpg
pybcn_position: Organizer
twitter: https://x.com/DZPM
-linkedin: https://www.linkedin.com/in/davidarcos/
+linkedin: https://www.linkedin.com/in/davidarcos
github: https://github.com/DZPM
-site: https://davidarcos.net/
+site: https://davidarcos.net
---
diff --git a/content/people/diego-quintana.md b/content/people/diego-quintana.md
index 41cc6cdb..32233d11 100644
--- a/content/people/diego-quintana.md
+++ b/content/people/diego-quintana.md
@@ -2,8 +2,8 @@
id: diego-quintana
name: Diego Quintana
photo: diego-quintana.jpg
-linkedin: https://www.linkedin.com/in/diego-quintana-valenzuela/
-github: https://github.com/diegoquintanav/
+linkedin: https://www.linkedin.com/in/diego-quintana-valenzuela
+github: https://github.com/diegoquintanav
---
Python Developer and Electrical Engineer.
\ No newline at end of file
diff --git a/content/people/edgar-riba.md b/content/people/edgar-riba.md
index 807e5c2d..2872e75d 100644
--- a/content/people/edgar-riba.md
+++ b/content/people/edgar-riba.md
@@ -5,7 +5,7 @@ short_bio: Edgar Riba is a research scientist at Institut de Robòtica i Inform
photo: edgar-riba.jpg
twitter: https://x.com/edgarriba
-linkedin: https://www.linkedin.com/in/edgarriba/
+linkedin: https://www.linkedin.com/in/edgarriba
github: https://github.com/edgarriba
-site: https://kornia.github.io/
+site: https://kornia.github.io
---
diff --git a/content/people/edgar-sarria-tenes.md b/content/people/edgar-sarria-tenes.md
index 2d776592..7c2d9c6c 100644
--- a/content/people/edgar-sarria-tenes.md
+++ b/content/people/edgar-sarria-tenes.md
@@ -3,7 +3,7 @@ id: edgar-sarria-tenes
name: Edgar Sarria Tenes
short_bio: SDK developer at Shimoku.
photo: edgar-sarria-tenes.jpg
-linkedin: https://www.linkedin.com/in/edgar-sarria-tenes-7391a6176/
+linkedin: https://www.linkedin.com/in/edgar-sarria-tenes-7391a6176
github: https://github.com/shimoku-tech/shimoku-api-python
---
diff --git a/content/people/eduard_cespedes.md b/content/people/eduard_cespedes.md
index 152169ec..1ae515fe 100644
--- a/content/people/eduard_cespedes.md
+++ b/content/people/eduard_cespedes.md
@@ -4,7 +4,7 @@ name: Eduard Céspedes Borràs
short_bio: I'm a passionate Software Architect that loves to learn and that enjoys being out of the comfort zone, being faced with a great challenge and having to overcome it to achieve the goal! That's why I've been CTO in Belgium, I've created and streaming platform for an Australian company, I've worked as a senior frontend developer for a New Zealand company, I've done trainings for an Argentinian company and I've advised one of the biggest companies in Singapore. I'm good at what I do because I love what I do, and you can see it in how I work.
photo: eduard-cespedes-borras.jpg
twitter: https://x.com/haduart
-linkedin: https://www.linkedin.com/in/eduardcespedesborras/
-github: https://github.com/haduart/
-site: https://orkei.com/
+linkedin: https://www.linkedin.com/in/eduardcespedesborras
+github: https://github.com/haduart
+site: https://orkei.com
---
diff --git a/content/people/eloi.md b/content/people/eloi.md
index 226fa7e2..9fcb4b73 100644
--- a/content/people/eloi.md
+++ b/content/people/eloi.md
@@ -6,6 +6,6 @@ pybcn_position: "Organizer"
photo: eloi-puertas-prats.jpg
photo_anchor: Bottom
twitter: "https://x.com/eloipuertas"
-linkedin: "https://www.linkedin.com/in/eloipuertas/"
+linkedin: "https://www.linkedin.com/in/eloipuertas"
github: "https://github.com/eloipuertas"
---
diff --git a/content/people/ely-farres.md b/content/people/ely-farres.md
index f57e08a6..8ddd7f50 100644
--- a/content/people/ely-farres.md
+++ b/content/people/ely-farres.md
@@ -3,7 +3,7 @@ id: ely-farres
name: "Ely Farrés Palomeras"
short_bio: "Quantum Engineer"
photo: ely-farres-palomeras.jpg
-linkedin: "https://www.linkedin.com/in/ely-farr%C3%A9s-palomeras-4459882b7/"
+linkedin: "https://www.linkedin.com/in/ely-farr%C3%A9s-palomeras-4459882b7"
github: "https://github.com/elygoner"
---
diff --git a/content/people/enric-domingo.md b/content/people/enric-domingo.md
index 748f60c7..2ab6dd79 100644
--- a/content/people/enric-domingo.md
+++ b/content/people/enric-domingo.md
@@ -3,7 +3,7 @@ id: enric-domingo
name: "Enric Domingo"
short_bio: ""
photo: "enric-domingo.jpg"
-linkedin: "https://www.linkedin.com/in/e-domingo/"
+linkedin: "https://www.linkedin.com/in/e-domingo"
github: "https://github.com/enricd"
site: "https://www.enricdomingo.com"
---
\ No newline at end of file
diff --git a/content/people/eric-massip.md b/content/people/eric-massip.md
index 8a47c20e..3c6799ef 100644
--- a/content/people/eric-massip.md
+++ b/content/people/eric-massip.md
@@ -3,6 +3,6 @@ id: eric-massip
name: "Eric Massip"
short_bio: ""
photo: eric-massip.jpg
-linkedin: "https://www.linkedin.com/in/ericmassip/"
-github: "https://github.com/ericmassip/"
+linkedin: "https://www.linkedin.com/in/ericmassip"
+github: "https://github.com/ericmassip"
---
diff --git a/content/people/esperanza-buitrago.md b/content/people/esperanza-buitrago.md
index f1f8392b..3d1bb911 100644
--- a/content/people/esperanza-buitrago.md
+++ b/content/people/esperanza-buitrago.md
@@ -6,6 +6,6 @@ photo: esperanza-buitrago.jpg
photo_anchor: Top
twitter: https://x.com/ebuitragod
-linkedin: https://www.linkedin.com/in/ebuitragod/
+linkedin: https://www.linkedin.com/in/ebuitragod
github: https://github.com/ebuitragod
---
diff --git a/content/people/ester-jara.md b/content/people/ester-jara.md
index 3c8f7b60..b1d84485 100644
--- a/content/people/ester-jara.md
+++ b/content/people/ester-jara.md
@@ -3,5 +3,5 @@ id: ester-jara
name: "Ester Jara"
short_bio: "ML Engineer in HP"
photo: "ester-jara.jpg"
-linkedin: "https://www.linkedin.com/in/esterjara/"
+linkedin: "https://www.linkedin.com/in/esterjara"
---
\ No newline at end of file
diff --git a/content/people/ferran-fabregas.md b/content/people/ferran-fabregas.md
index 76c09116..6be3010e 100644
--- a/content/people/ferran-fabregas.md
+++ b/content/people/ferran-fabregas.md
@@ -4,9 +4,9 @@ name: "Ferran Fàbregas"
short_bio: Computer scientist and programmer by profession, I started in the "maker" world 7 years ago, in which I have developed a cross-disciplinary knowledge in different disciplines of digital manufacturing, electronics, robotics, micro-controller programming and education, trying to turn my passion into a full-time job.
photo: ferran-fabregas.png
twitter: https://x.com/ferrithemaker
-linkedin: https://www.linkedin.com/in/ferran-fabregas-94a68525/
+linkedin: https://www.linkedin.com/in/ferran-fabregas-94a68525
github: https://github.com/ferrithemaker
-site: https://ferranfabregas.me/
+site: https://ferranfabregas.me
---
Within this time I have published the book “How to use Raspberry Pi 4 through 100 practical exercises“ from Marcombo publisher and I’m working on another book about electronics for Makers. I have also been responsible for the technical correction of the Spanish translation of some tech-related books of the O’Reilly and Willey publishers.
diff --git a/content/people/flavie-le-bars.md b/content/people/flavie-le-bars.md
index 6a391c2d..43bd8854 100644
--- a/content/people/flavie-le-bars.md
+++ b/content/people/flavie-le-bars.md
@@ -2,7 +2,7 @@
id: flavie-le-bars
name: "Flavie Le Bars"
photo: "flavie-le-bars.jpg"
-linkedin: "https://www.linkedin.com/in/flavie-le-bars-0b97bb18a/"
+linkedin: "https://www.linkedin.com/in/flavie-le-bars-0b97bb18a"
github: "https://github.com/flavie-lebars"
---
diff --git a/content/people/francesco-faraone.md b/content/people/francesco-faraone.md
index 73c078a5..fa7976b8 100644
--- a/content/people/francesco-faraone.md
+++ b/content/people/francesco-faraone.md
@@ -6,7 +6,7 @@ photo: francesco-faraone.png
photo_anchor: Bottom
twitter: https://x.com/cicfaraone
-linkedin: https://www.linkedin.com/in/francesco-faraone-01568a8/
+linkedin: https://www.linkedin.com/in/francesco-faraone-01568a8
github: https://github.com/ffaraoneim
site: https://github.com/ffaraone
---
diff --git a/content/people/gajendra-deshpande.md b/content/people/gajendra-deshpande.md
index a269677d..975e5a30 100644
--- a/content/people/gajendra-deshpande.md
+++ b/content/people/gajendra-deshpande.md
@@ -7,5 +7,5 @@ photo: gajendra-deshpande.jpg
twitter: https://x.com/gcdeshpande
linkedin: https://www.linkedin.com/in/gajendradeshpande
github: https://github.com/gcdeshpande
-site: https://gcdeshpande.github.io/
+site: https://gcdeshpande.github.io
---
diff --git a/content/people/gema-parreno.md b/content/people/gema-parreno.md
index 1c65e4cf..30973016 100644
--- a/content/people/gema-parreno.md
+++ b/content/people/gema-parreno.md
@@ -2,7 +2,7 @@
id: gema-parreno
name: "Gema Parreño"
photo: gema-parreno.jpg
-linkedin: "https://www.linkedin.com/in/gemaparreno/"
+linkedin: "https://www.linkedin.com/in/gemaparreno"
github: "https://github.com/SoyGema"
twitter: "https://x.com/SoyGema"
---
diff --git a/content/people/guille-abad.md b/content/people/guille-abad.md
index 89048ebe..19796b37 100644
--- a/content/people/guille-abad.md
+++ b/content/people/guille-abad.md
@@ -3,7 +3,7 @@ id: guille-abad
name: "Guillermo Abad"
short_bio: "Quantum Engineer"
photo: guillermo-abad.jpg
-linkedin: "https://www.linkedin.com/in/guillermo-abad-l%C3%B3pez/"
+linkedin: "https://www.linkedin.com/in/guillermo-abad-l%C3%B3pez"
---
Guillermo studied Physics at the Autonomous University of Barcelona (UAB) where he did his Bachelor’s Thesis about Skyrmions in the superconducting group, where after graduating, he kept researching them and collaborating as an Associate Professor of Computer Modelling. Meanwhile, he also did an MSc in Theoretical Physics at the University of Barcelona (UB), where he did his Master’s Thesis about QED in 1+1dim. He then continued his career into the industry, working at Glovo for 7 months, where he made up his mind about entering the quantum computation world, joining Qilimanjaro’s Software Team, where he is using and growing his knowledge in quantum physics and computer science with the development of software to control our quantum hardware.
\ No newline at end of file
diff --git a/content/people/ifosch.md b/content/people/ifosch.md
index a5066dec..9994340d 100644
--- a/content/people/ifosch.md
+++ b/content/people/ifosch.md
@@ -6,7 +6,7 @@ photo: ignasi-fosch.jpg
pybcn_position: Organizer
twitter: https://x.com/ifosch
-linkedin: https://www.linkedin.com/in/ifosch/
+linkedin: https://www.linkedin.com/in/ifosch
github: https://github.com/ifosch
site: https://natx.cat
---
diff --git a/content/people/javier-ramos-panduro.md b/content/people/javier-ramos-panduro.md
index 2a567ea1..4bbdad72 100644
--- a/content/people/javier-ramos-panduro.md
+++ b/content/people/javier-ramos-panduro.md
@@ -3,6 +3,6 @@ id: javier-ramos-panduro
name: "Javier Ramos Panduro"
short_bio: "Solutions Architect"
photo: "javier-ramos-panduro.jpg"
-linkedin: "https://www.linkedin.com/in/javier-ramos-panduro-3ab4a316/"
+linkedin: "https://www.linkedin.com/in/javier-ramos-panduro-3ab4a316"
github: ""
---
\ No newline at end of file
diff --git a/content/people/javier-sabariego.md b/content/people/javier-sabariego.md
index 534a81ee..c17035a8 100644
--- a/content/people/javier-sabariego.md
+++ b/content/people/javier-sabariego.md
@@ -3,7 +3,7 @@ id: javier-sabariego
name: "Javier Sabariego"
short_bio: "Quantum Engineer"
photo: javier-sabariego.jpg
-linkedin: "https://www.linkedin.com/in/javiersabariegolopez/"
+linkedin: "https://www.linkedin.com/in/javiersabariegolopez"
---
Once he obtained his MSc in High Energy Physics (UAB, IFAE), he started his professional career working as a backend web developer for Air-Fi, a small communications company were he would contribute to the development of a wifi-based Indoor Positioning System (ISP). Eventually, he would become the Product Manager of the ISP. His professional and academic profiles would come together at Qilimanjaro, where he is currently a developer for the Quantum as a Service (QaaS) project.
\ No newline at end of file
diff --git a/content/people/jimena-escobar.md b/content/people/jimena-escobar.md
index 3b4765a5..0bd6e381 100644
--- a/content/people/jimena-escobar.md
+++ b/content/people/jimena-escobar.md
@@ -2,7 +2,7 @@
id: jimena-escobar
name: "Jimena Escobar Bermúdez"
photo: jimena-escobar-bermudez.jpg
-linkedin: "https://www.linkedin.com/in/jimena-eb/"
+linkedin: "https://www.linkedin.com/in/jimena-eb"
github: "https://github.com/JimenaEB"
twitter: "https://x.com/Jimena_y_yo"
---
diff --git a/content/people/joan-fontanals-martinez.md b/content/people/joan-fontanals-martinez.md
index 2c0a6cc9..154e99ae 100644
--- a/content/people/joan-fontanals-martinez.md
+++ b/content/people/joan-fontanals-martinez.md
@@ -7,6 +7,6 @@ For the last years, he has been focused on developing Search Systems and since J
photo: joan-fontanals-martinez.jpg
photo_anchor: Bottom
-linkedin: https://www.linkedin.com/in/joanfontanalsmartinez/
+linkedin: https://www.linkedin.com/in/joanfontanalsmartinez
github: https://github.com/JoanFM
---
diff --git a/content/people/jose_haro.md b/content/people/jose_haro.md
index 0351f963..82849795 100644
--- a/content/people/jose_haro.md
+++ b/content/people/jose_haro.md
@@ -6,6 +6,6 @@ photo: jose-haro-peralta.png
photo_anchor: Top
twitter: https://x.com/JoseHaroPeralta
-linkedin: https://www.linkedin.com/in/jose-haro-peralta/
+linkedin: https://www.linkedin.com/in/jose-haro-peralta
github: https://github.com/abunuwas
---
diff --git a/content/people/juan-bernardo-lince.md b/content/people/juan-bernardo-lince.md
index b12dc9fd..90811e41 100644
--- a/content/people/juan-bernardo-lince.md
+++ b/content/people/juan-bernardo-lince.md
@@ -4,7 +4,7 @@ name: Juan Bernardo Lince
short_bio: City Manager
photo: juan-bernardo-lince.jpg
twitter: https://x.com/LinceCabal
-linkedin: https://www.linkedin.com/in/juanblince/
+linkedin: https://www.linkedin.com/in/juanblince
github: https://github.com/jblince
---
diff --git a/content/people/juan-luis-cano.md b/content/people/juan-luis-cano.md
index 75976335..53468f96 100644
--- a/content/people/juan-luis-cano.md
+++ b/content/people/juan-luis-cano.md
@@ -3,8 +3,8 @@ id: juan-luis-cano
name: Juan Luis Cano Rodríguez
short_bio: Aerospace Engineer with a passion for STEM, programming, outreach, and sustainability
photo: juan-luis-cano-rodriguez.jpg
-linkedin: https://www.linkedin.com/in/juanluiscanor/
-github: https://github.com/astrojuanlu/
+linkedin: https://www.linkedin.com/in/juanluiscanor
+github: https://github.com/astrojuanlu
site: https://social.juanlu.space/@astrojuanlu
---
diff --git a/content/people/julio-martinez.md b/content/people/julio-martinez.md
index f20b3b79..c22b0c4f 100644
--- a/content/people/julio-martinez.md
+++ b/content/people/julio-martinez.md
@@ -5,7 +5,7 @@ short_bio: Julio is a senior developer, who has been working in the retail and a
photo: julio-martinez.jpg
twitter: https://x.com/liopic
-linkedin: https://www.linkedin.com/in/liopic/
+linkedin: https://www.linkedin.com/in/liopic
github: https://github.com/liopic
-site: https://liopic.me/
+site: https://liopic.me
---
diff --git a/content/people/kemalcan-bora.md b/content/people/kemalcan-bora.md
index aa9460e7..ab928f6b 100644
--- a/content/people/kemalcan-bora.md
+++ b/content/people/kemalcan-bora.md
@@ -2,7 +2,7 @@
id: kemalcan-bora
name: "Kemalcan Bora"
photo: "kemalcan-bora.jpg"
-linkedin: "https://www.linkedin.com/in/kemalcanbora/"
+linkedin: "https://www.linkedin.com/in/kemalcanbora"
github: "https://github.com/kemalcanbora"
twitter: "https://x.com/KemalcanBora"
---
diff --git a/content/people/kevin-albes.md b/content/people/kevin-albes.md
index a42873fd..92220528 100644
--- a/content/people/kevin-albes.md
+++ b/content/people/kevin-albes.md
@@ -3,6 +3,6 @@ id: kevin-albes
name: "Kevin Albes"
short_bio: ""
photo: "kevin-albes.jpg"
-linkedin: "https://www.linkedin.com/in/kalbes/"
+linkedin: "https://www.linkedin.com/in/kalbes"
github: ""
---
diff --git a/content/people/kevin-sanchez.md b/content/people/kevin-sanchez.md
index c8c1f2d1..94b85663 100644
--- a/content/people/kevin-sanchez.md
+++ b/content/people/kevin-sanchez.md
@@ -3,6 +3,6 @@ id: kevin-sanchez
name: "Kevin Sanchez Sancho"
short_bio: ""
photo: kevin-sanchez-sancho.jpg
-linkedin: "https://www.linkedin.com/in/kevin-sanchez-sancho-807b7268/"
+linkedin: "https://www.linkedin.com/in/kevin-sanchez-sancho-807b7268"
github: ""
---
\ No newline at end of file
diff --git a/content/people/laysa-uchoa.md b/content/people/laysa-uchoa.md
index d52e6650..f33db2e3 100644
--- a/content/people/laysa-uchoa.md
+++ b/content/people/laysa-uchoa.md
@@ -5,7 +5,7 @@ short_bio: "Python dev and Pyladies Munich organizer. I believe that technology
photo: laysa-uchoa.jpg
twitter: https://x.com/laysauchoa
-linkedin: https://www.linkedin.com/in/laysauchoa/
+linkedin: https://www.linkedin.com/in/laysauchoa
github: https://github.com/laysauchoa
---
diff --git a/content/people/lpmayos.md b/content/people/lpmayos.md
index d0407561..70a95fd8 100644
--- a/content/people/lpmayos.md
+++ b/content/people/lpmayos.md
@@ -3,11 +3,11 @@ id: lpmayos
name: "Laura Pérez Mayos"
short_bio: "Books, nature and NLP"
photo: laura-perez-mayos.jpg
-site: https://lpmayos.github.io/
+site: https://lpmayos.github.io
pybcn_position: "PyLadiesBCN Organizer"
-linkedin: "https://www.linkedin.com/in/lpmayos/"
+linkedin: "https://www.linkedin.com/in/lpmayos"
github: "https://github.com/lpmayos"
---
diff --git a/content/people/manuel-gijon.md b/content/people/manuel-gijon.md
index 3100b2f0..97fce487 100644
--- a/content/people/manuel-gijon.md
+++ b/content/people/manuel-gijon.md
@@ -3,7 +3,7 @@ id: manuel-gijon
name: Manuel Gijón Agudo
short_bio: "ML Engineer and Associate Professor teaching Data Mining at UPC"
photo: manuel-gijon-agudo.jpg
-linkedin: https://www.linkedin.com/in/manuel-gij%C3%B3n-agudo/
+linkedin: https://www.linkedin.com/in/manuel-gij%C3%B3n-agudo
github: https://github.com/MGijon
twitter: https://x.com/mgijon94
---
diff --git a/content/people/marc-pomar.md b/content/people/marc-pomar.md
index 28754eb8..561a4038 100644
--- a/content/people/marc-pomar.md
+++ b/content/people/marc-pomar.md
@@ -3,6 +3,6 @@ id: marc-pomar
name: "Marc Pomar"
short_bio: "t"
photo: "marc-pomar.jpg"
-linkedin: "https://www.linkedin.com/in/marcpomar/"
+linkedin: "https://www.linkedin.com/in/marcpomar"
github: ""
---
\ No newline at end of file
diff --git a/content/people/marc-pous.md b/content/people/marc-pous.md
index 4d350dfa..4d715474 100644
--- a/content/people/marc-pous.md
+++ b/content/people/marc-pous.md
@@ -5,7 +5,7 @@ short_bio: "Marc is currently the balena.io Developer Advocate. Former co-founde
photo: marc-pous.jpg
twitter: https://x.com/gy4nt
-linkedin: https://www.linkedin.com/in/marcpous/
+linkedin: https://www.linkedin.com/in/marcpous
github: https://github.com/mpous
-site: https://marcpous.com/
+site: https://marcpous.com
---
diff --git a/content/people/marc-ramirez.md b/content/people/marc-ramirez.md
index c902b54c..1bfdab9a 100644
--- a/content/people/marc-ramirez.md
+++ b/content/people/marc-ramirez.md
@@ -5,7 +5,7 @@ short_bio: ""
photo: marc-ramirez.jpg
photo_anchor: Top
-linkedin: https://www.linkedin.com/in/marcramirezinvernon/
+linkedin: https://www.linkedin.com/in/marcramirezinvernon
github: https://github.com/marcraminv
---
diff --git a/content/people/maria-teresa-grifa.md b/content/people/maria-teresa-grifa.md
index 833242a4..47a2c86a 100644
--- a/content/people/maria-teresa-grifa.md
+++ b/content/people/maria-teresa-grifa.md
@@ -8,6 +8,6 @@ I am an avid reader, techy a.e., and I am always hungry."
photo: maria-teresa-grifa.jpg
photo_anchor: Bottom
-linkedin: https://www.linkedin.com/in/maria-teresa-g-624967165/
-github: https://github.com/MT-G/
+linkedin: https://www.linkedin.com/in/maria-teresa-g-624967165
+github: https://github.com/MT-G
---
diff --git a/content/people/matteo-bruno.md b/content/people/matteo-bruno.md
index 4e98e2d2..8da93f1e 100644
--- a/content/people/matteo-bruno.md
+++ b/content/people/matteo-bruno.md
@@ -4,5 +4,5 @@ name: Matteo Bruno
short_bio: "Matteo Bruno is senior software engineering manager, pizza lover, traveller, runner, blockchain & crypto enthusiast... sometimes not in this order :)
He started programming @ 12y/o, and since then he aimed to develop software, fostering his ability to lead complex projects within a multicultural environment.
After 4 years in Milan, working for Viacom as Lead Software Engineer, in January 2019 he decided to move to Barcelona and face new challenges.
Currently he’s working at Onna as Engineering Manager."
xxxphoto: matteo-bruno.jpg
-linkedin: https://www.linkedin.com/in/brunomatteo/
+linkedin: https://www.linkedin.com/in/brunomatteo
---
diff --git a/content/people/miquel-sarrias.md b/content/people/miquel-sarrias.md
index 8af100e3..5a6fbd0e 100644
--- a/content/people/miquel-sarrias.md
+++ b/content/people/miquel-sarrias.md
@@ -5,7 +5,7 @@ short_bio: NLP/ML engineer
photo: miquel-sarrias.jpg
photo_anchor: Top
-linkedin: https://www.linkedin.com/in/miquel-s%C3%A0rrias-mont%C3%B3n-aa5067129/
+linkedin: https://www.linkedin.com/in/miquel-s%C3%A0rrias-mont%C3%B3n-aa5067129
twitter: https://x.com/MiquelSarrias
---
diff --git a/content/people/mireia.md b/content/people/mireia.md
index 19fae00e..84e0c543 100644
--- a/content/people/mireia.md
+++ b/content/people/mireia.md
@@ -4,6 +4,6 @@ name: Mireia Álvarez Domínguez
photo: mireia-alvarez-dominguez.jpg
pybcn_position: "Former Treasurer"
-linkedin: https://www.linkedin.com/in/mireialvarez/
+linkedin: https://www.linkedin.com/in/mireialvarez
---
diff --git a/content/people/miroslav_sedivy.md b/content/people/miroslav_sedivy.md
index e39c55e2..971cf7d5 100644
--- a/content/people/miroslav_sedivy.md
+++ b/content/people/miroslav_sedivy.md
@@ -4,7 +4,7 @@ name: "Miroslav Šedivý"
short_bio: "Greedy polyglot, data & open source rhymer, python3 charmer, sustainable urbanist, unicode collector, wandering openstreetmapper, and an hjkl juggler."
photo: miroslav-sedivy.jpg
twitter: "https://x.com/eumiro"
-linkedin: "https://www.linkedin.com/in/eumiro/"
+linkedin: "https://www.linkedin.com/in/eumiro"
github: "https://github.com/eumiro"
site: https://eumiro.github.io
diff --git a/content/people/natalia.md b/content/people/natalia.md
index 5b6db836..0056504b 100644
--- a/content/people/natalia.md
+++ b/content/people/natalia.md
@@ -6,7 +6,7 @@ photo: natalia-padilla.jpg
pybcn_position: "PyLadiesBCN Organizer"
twitter: "https://x.com/nataliasirera"
-linkedin: "https://www.linkedin.com/in/natàlia-padilla-sirera-8112305a/"
+linkedin: "https://www.linkedin.com/in/natàlia-padilla-sirera-8112305a"
github: "https://github.com/NataliaSirera"
---
diff --git a/content/people/nikita-polovinkin.md b/content/people/nikita-polovinkin.md
index e31ec207..672b570c 100644
--- a/content/people/nikita-polovinkin.md
+++ b/content/people/nikita-polovinkin.md
@@ -3,6 +3,6 @@ id: nikita-polovinkin
name: Nikita Polovinkin
short_bio: Data Scientist
photo: nikita-polovinkin.jpg
-linkedin: https://www.linkedin.com/in/npolovinkin/
+linkedin: https://www.linkedin.com/in/npolovinkin
---
diff --git a/content/people/noe-casas.md b/content/people/noe-casas.md
index 7d1bfba4..de28e006 100644
--- a/content/people/noe-casas.md
+++ b/content/people/noe-casas.md
@@ -2,7 +2,7 @@
id: noe-casas
name: " Noé Casas"
photo: noe-casas.png
-linkedin: "https://www.linkedin.com/in/noecasas/"
+linkedin: "https://www.linkedin.com/in/noecasas"
twitter: "https://x.com/noecasas"
---
diff --git a/content/people/nuria.md b/content/people/nuria.md
index d05a63b4..e1faa2ea 100644
--- a/content/people/nuria.md
+++ b/content/people/nuria.md
@@ -7,5 +7,5 @@ photo: nuria-pujol-vilanova.jpg
pybcn_position: "PyLadiesBCN Organizer"
twitter: "https://x.com/llevaneus"
-linkedin: "https://www.linkedin.com/in/n%C3%BAria-pujol-780a145/"
+linkedin: "https://www.linkedin.com/in/n%C3%BAria-pujol-780a145"
---
diff --git a/content/people/oriol-abril-pla.md b/content/people/oriol-abril-pla.md
index cad25cf5..a49b36de 100644
--- a/content/people/oriol-abril-pla.md
+++ b/content/people/oriol-abril-pla.md
@@ -3,8 +3,8 @@ id: oriol-abril-pla
name: Oriol Abril Pla
short_bio: Estadístic computacional
photo: oriol-abril-pla.png
-linkedin: https://www.linkedin.com/in/oriol-abril-pla-1b9123180/
-github: https://github.com/OriolAbril/
+linkedin: https://www.linkedin.com/in/oriol-abril-pla-1b9123180
+github: https://github.com/OriolAbril
---
Oriol discovered his passion for computational statistics and open source during his MSc in Astrophysics and has been working the topic since then. He started contributing to ArviZ and PyMC (two Python libraries related to Bayesian modeling) in 2019, joining their core teams not long after that. He started working in academia but he left after some years in order to be able to work more freely and collaboratively on open source, software and knowledge sharing. His main areas of interest are data visualization, model and inference diagnostics, model comparison, and prior elicitation. Within open source projects, he has also dedicated a large part of his work to documentation, governance and DEI. He currently works as a consultant with PyMC Labs, as an instructor on Intuitive Bayes and as open source maintainer for PyMC and ArviZ.
\ No newline at end of file
diff --git a/content/people/patricia-lamadrid.md b/content/people/patricia-lamadrid.md
index 664f88c1..0a15e952 100644
--- a/content/people/patricia-lamadrid.md
+++ b/content/people/patricia-lamadrid.md
@@ -6,8 +6,8 @@ short_bio: Data Engineer - Coding lover - Dressmaker
photo: patricia-lamadrid-robles.jpg
pybcn_position: Collaborator
-linkedin: https://www.linkedin.com/in/patricia-lamadrid/
-github: https://github.com/plamadridr/
+linkedin: https://www.linkedin.com/in/patricia-lamadrid
+github: https://github.com/plamadridr
---
I'm a data enthusiast who spends my days building and maintaining projects that process large volumes of data using mainly Python and Scala.
\ No newline at end of file
diff --git a/content/people/paula-bassaganas.md b/content/people/paula-bassaganas.md
index f7713d8b..62b063b0 100644
--- a/content/people/paula-bassaganas.md
+++ b/content/people/paula-bassaganas.md
@@ -4,7 +4,7 @@ name: Paula Bassagañas Òdena
short_bio: ""
photo: paula-bassaganas-odena.jpg
-linkedin: https://www.linkedin.com/in/paulabassaganas/
+linkedin: https://www.linkedin.com/in/paulabassaganas
github: https://github.com/bassagan
---
diff --git a/content/people/paula_szewach.md b/content/people/paula_szewach.md
index f9a8f001..2fb376a2 100644
--- a/content/people/paula_szewach.md
+++ b/content/people/paula_szewach.md
@@ -3,8 +3,8 @@ id: paula_szewach
name: "Paula Szewach"
short_bio: "Computational social scientist"
pybcn_position: PyLadiesBCN Organizer
-site: "https://www.paulaszewach.com/"
-linkedin: "https://www.linkedin.com/in/paulaszewach/"
+site: "https://www.paulaszewach.com"
+linkedin: "https://www.linkedin.com/in/paulaszewach"
github: "https://github.com/pszewach"
---
diff --git a/content/people/pavel-lonkin.md b/content/people/pavel-lonkin.md
index d22b8b9c..8a75b73b 100644
--- a/content/people/pavel-lonkin.md
+++ b/content/people/pavel-lonkin.md
@@ -2,7 +2,7 @@
id: pavel-lonkin
name: "Pavel Lonkin"
photo: "pavel-lonkin.jpg"
-linkedin: "https://www.linkedin.com/in/plonkin/"
+linkedin: "https://www.linkedin.com/in/plonkin"
github: "https://github.com/d3rky"
twitter: "https://x.com/pavel_lonkin"
---
diff --git a/content/people/pere-miquel-brull.md b/content/people/pere-miquel-brull.md
index 439c3303..fdaa613b 100644
--- a/content/people/pere-miquel-brull.md
+++ b/content/people/pere-miquel-brull.md
@@ -2,7 +2,7 @@
id: pere-miquel-brull
name: "Pere Miquel Brull"
photo: pere-miquel-brull.jpg
-linkedin: "https://www.linkedin.com/in/pmbrull/"
+linkedin: "https://www.linkedin.com/in/pmbrull"
github: "https://github.com/pmbrull"
twitter: "https://x.com/perembrull"
---
diff --git a/content/people/rajdeep-pal.md b/content/people/rajdeep-pal.md
index c6605d3a..9f46c93c 100644
--- a/content/people/rajdeep-pal.md
+++ b/content/people/rajdeep-pal.md
@@ -4,7 +4,7 @@ name: Rajdeep Pal
photo: rajdeep-pal.jpg
photo_anchor: Left
-linkedin: https://www.linkedin.com/in/rajdeeppal/
+linkedin: https://www.linkedin.com/in/rajdeeppal
---
Rajdeep is a data wizard who can turn raw data into valuable insights faster than you can say 'big data.' With a background in computer science and a Master's degree from Esade Business School, he has experience in retail and FMCG domains and a track record of designing and deploying large and scalable solutions. He's worked with startups and industry giants such as Rakuten and now bringing his expertise to a new level as a Data Science Engineer in the beautiful city of Barcelona. He is not only proficient in multiple cloud infrastructures but also has a track record of designing and deploying solutions that drive real results.
\ No newline at end of file
diff --git a/content/people/rberenguel.md b/content/people/rberenguel.md
index a696d66b..b6df1eed 100644
--- a/content/people/rberenguel.md
+++ b/content/people/rberenguel.md
@@ -6,7 +6,7 @@ photo: ruben-berenguel.png
pybcn_position: Organizer
twitter: "https://x.com/berenguel"
-linkedin: "https://www.linkedin.com/in/rberenguel/"
+linkedin: "https://www.linkedin.com/in/rberenguel"
github: https://github.com/rberenguel
site: https://mostlymaths.net
---
diff --git a/content/people/ricardo-ander-egg.md b/content/people/ricardo-ander-egg.md
index e465cf60..a3a30c39 100644
--- a/content/people/ricardo-ander-egg.md
+++ b/content/people/ricardo-ander-egg.md
@@ -5,7 +5,7 @@ photo: ricardo-ander-egg-aguilar.jpg
photo_anchor: Top
twitter: https://x.com/ricardoanderegg
-linkedin: https://www.linkedin.com/in/ricardoanderegg/
+linkedin: https://www.linkedin.com/in/ricardoanderegg
github: https://github.com/polyrand
---
diff --git a/content/people/ruben-afonso.md b/content/people/ruben-afonso.md
index 7259f83c..323be486 100644
--- a/content/people/ruben-afonso.md
+++ b/content/people/ruben-afonso.md
@@ -6,7 +6,7 @@ photo: ruben-afonso.png
photo_anchor: Bottom
twitter: https://x.com/rubenafo
-linkedin: https://www.linkedin.com/in/rubenafonso/
+linkedin: https://www.linkedin.com/in/rubenafonso
github: https://github.com/rubenafo
---
diff --git a/content/people/sergi-baena-miret.md b/content/people/sergi-baena-miret.md
index b5a9d19e..46e9aafa 100644
--- a/content/people/sergi-baena-miret.md
+++ b/content/people/sergi-baena-miret.md
@@ -2,7 +2,7 @@
id: sergi-baena-miret
name: Sergi Baena-Miret
photo: sergi-baena-miret.jpg
-linkedin: https://www.linkedin.com/in/sergibaena/
+linkedin: https://www.linkedin.com/in/sergibaena
---
Sergi Baena-Miret, Senior Project Manager and Researcher, is a PhD in Mathematics and Informatics (Universitat de Barcelona, Spain) and has a Master's in Bioinformatics and Biostatistics. Also, he has extensive experience as a software developer, mathematician, and university professor. His research interests and activities span Computer Science (machine learning, data analysis, etc.), Statistics (multivariate analysis, inference, etc.), Mathematics (artificial intelligence, mathematical algorithms, etc.) and Water Technologies (water data spaces, AI water models, etc.). Sergi Baena-Miret has actively participated in a series of projects (WATERVERSE, AI4Llobregat, Lab Digital Twins, PID2020-113048GB-I00, 2017SGR358, MTM2017-83499-P, MTM2016-75196-P) in the areas of Mathematics and Computer Science Research and Water Data Ecosystems, with an important position of responsibility (Project Manager) in three of them.
\ No newline at end of file
diff --git a/content/people/thais-ruiz-de-alda.md b/content/people/thais-ruiz-de-alda.md
index 1f842c37..4feea066 100644
--- a/content/people/thais-ruiz-de-alda.md
+++ b/content/people/thais-ruiz-de-alda.md
@@ -2,7 +2,7 @@
id: thais-ruiz-de-alda
name: Thais Ruiz de Alda
photo: thais-ruiz-de-alda.jpg
-linkedin: https://www.linkedin.com/in/thaisruizdealda/
+linkedin: https://www.linkedin.com/in/thaisruizdealda
---
Executive Director. Digital Innovation. Founder at Digital Fems. Entrepreneur. Social Digital Innovation Advisor
\ No newline at end of file
diff --git a/content/people/thomas-alisi.md b/content/people/thomas-alisi.md
index c2dc8d9e..fd672339 100644
--- a/content/people/thomas-alisi.md
+++ b/content/people/thomas-alisi.md
@@ -3,6 +3,6 @@ id: thomas-alisi
name: "Thomas Alisi"
short_bio: ""
photo: "thomas-alisi.jpg"
-linkedin: "https://www.linkedin.com/in/thomasalisi/"
+linkedin: "https://www.linkedin.com/in/thomasalisi"
github: ""
---
\ No newline at end of file
diff --git a/content/people/ubaldo-hervas.md b/content/people/ubaldo-hervas.md
index a02a8b0b..5b0bafc6 100644
--- a/content/people/ubaldo-hervas.md
+++ b/content/people/ubaldo-hervas.md
@@ -3,6 +3,6 @@ id: ubaldo-hervas
name: "Ubaldo Hervás"
short_bio: "Solutions Architect"
photo: "ubaldo-hervas.jpg"
-linkedin: "https://www.linkedin.com/in/ubaldo-hervas/"
+linkedin: "https://www.linkedin.com/in/ubaldo-hervas"
github: ""
---
\ No newline at end of file
diff --git a/content/people/vincent-choubard.md b/content/people/vincent-choubard.md
index ae2b222c..e22e3a22 100644
--- a/content/people/vincent-choubard.md
+++ b/content/people/vincent-choubard.md
@@ -3,6 +3,6 @@ id: vincent-choubard
name: Vincent Choubard
short_bio: "I have been working as a Software Engineer for 12 years. I have been working for a few different companies in Spain like Vocento, Tuenti but also in North America (Canada). During the last 7 years I have been at Rover, first as a Lead Engineer and since 2 years ago as an Engineering Manager. I am now Managing 2 teams at Rover, Supply acquisition, and Overnight & DayCare Service."
photo: vincent-choubard.jpg
-linkedin: https://www.linkedin.com/in/vincent-choubard-79a7045/
+linkedin: https://www.linkedin.com/in/vincent-choubard-79a7045
---
diff --git a/content/people/vyron-vasileiadis.md b/content/people/vyron-vasileiadis.md
index f970a99e..d57bd746 100644
--- a/content/people/vyron-vasileiadis.md
+++ b/content/people/vyron-vasileiadis.md
@@ -3,7 +3,7 @@ id: vyron-vasileiadis
name: Vyron Vasileiadis
short_bio: "Quantum Engineer"
photo: vyron-vasileiadis.jpg
-linkedin: https://www.linkedin.com/in/fedonman/
+linkedin: https://www.linkedin.com/in/fedonman
---
diff --git a/content/people/xavi.md b/content/people/xavi.md
index fd6270af..d5dc5462 100644
--- a/content/people/xavi.md
+++ b/content/people/xavi.md
@@ -5,7 +5,7 @@ short_bio: "[passion for passion in ('Python', 'Free Software', 'Privacy', 'Huma
photo: xavi-francisco-gilabert.jpg
pybcn_position: Organizer
-twitter: https://x.com/srxavi/
+twitter: https://x.com/srxavi
github: https://github.com/srxavi
-linkedin: https://www.linkedin.com/in/xavifrancisco/
+linkedin: https://www.linkedin.com/in/xavifrancisco
---
diff --git a/content/people/xiang-xu.md b/content/people/xiang-xu.md
index c2aab20f..56612754 100644
--- a/content/people/xiang-xu.md
+++ b/content/people/xiang-xu.md
@@ -5,7 +5,7 @@ short_bio: ""
photo: xiang-xu.jpg
photo_anchor: Right
-linkedin: https://www.linkedin.com/in/xiang-xu-68192b138/
+linkedin: https://www.linkedin.com/in/xiang-xu-68192b138
---
Xiang Xu holds a PhD in Computational Chemistry from the University of the Basque Country and has nearly 12 years of experience in computer programming, mathematical modeling, and scientific and engineering simulations. With a great passion for Python, high-performance computing, artificial intellgence algorithms, and data science, he currently works with cutting-edge technologies to integrate AI methods into the process simulation industry. He is passionate about learning new things and helping others in their learning journey.
\ No newline at end of file
diff --git a/content/sponsors/codurance.md b/content/sponsors/codurance.md
index fee83c17..61f0584c 100644
--- a/content/sponsors/codurance.md
+++ b/content/sponsors/codurance.md
@@ -4,6 +4,6 @@ name: Codurance
logo_image: codurance.png
web: https://www.codurance.com/es/
twitter: https://x.com/codurance_ES
-linkedin: https://www.linkedin.com/company/codurance/
+linkedin: https://www.linkedin.com/company/codurance
---
diff --git a/content/sponsors/coopdevs.md b/content/sponsors/coopdevs.md
index 671160e6..fa301d69 100644
--- a/content/sponsors/coopdevs.md
+++ b/content/sponsors/coopdevs.md
@@ -4,7 +4,7 @@ name: Coopdevs
logo_image: coopdevs.svg
web: https://coopdevs.org/
twitter: https://x.com/coopdevs
-linkedin: https://www.linkedin.com/company/coopdevs/
+linkedin: https://www.linkedin.com/company/coopdevs
mastodont: https://mastodon.economiasocial.org/@Coopdevs/
---
diff --git a/content/sponsors/isdieducation.md b/content/sponsors/isdieducation.md
index d49b6cdf..c5910a0d 100644
--- a/content/sponsors/isdieducation.md
+++ b/content/sponsors/isdieducation.md
@@ -3,7 +3,7 @@ id: isdieducation
name: ISDI Education
logo_image: isdi.png
web: https://www.isdi.education/es
-linkedin: https://www.linkedin.com/school/isdi/
+linkedin: https://www.linkedin.com/school/isdi
instagram: https://www.instagram.com/isdi_edu/
---
diff --git a/content/sponsors/okta.md b/content/sponsors/okta.md
index 0acbbe0b..7e855461 100644
--- a/content/sponsors/okta.md
+++ b/content/sponsors/okta.md
@@ -4,5 +4,5 @@ name: Okta
logo_image: okta.png
web: https://auth0.com/careers
twitter: https://x.com/auth0
-linkedin: https://www.linkedin.com/company/auth0/
+linkedin: https://www.linkedin.com/company/auth0
---
diff --git a/content/sponsors/protopixel.md b/content/sponsors/protopixel.md
index 86bc1887..09d4aef0 100644
--- a/content/sponsors/protopixel.md
+++ b/content/sponsors/protopixel.md
@@ -4,5 +4,5 @@ name: Protopixel
logo_image: protopixel.png
web: https://www.protopixel.io
twitter: https://x.com/protopixelbcn
-linkedin: https://www.linkedin.com/company/protopixel/
+linkedin: https://www.linkedin.com/company/protopixel
---
diff --git a/content/sponsors/typeform.md b/content/sponsors/typeform.md
index cd60e71b..d3d45d51 100644
--- a/content/sponsors/typeform.md
+++ b/content/sponsors/typeform.md
@@ -3,5 +3,5 @@ id: typeform
name: Typeform
logo_image: typeform.png
web: https://typeform.com
-twitter: https://x.com/typeform/
+twitter: https://x.com/typeform
---
diff --git a/content/sponsors/verse.md b/content/sponsors/verse.md
index 4a7391c6..b5f2b421 100644
--- a/content/sponsors/verse.md
+++ b/content/sponsors/verse.md
@@ -3,5 +3,5 @@ id: verse
name: Verse
logo_image: verse.jpg
web: https://verse.me
-twitter: https://x.com/joinverse/
+twitter: https://x.com/joinverse
---
From e9ec648e9c7102fb1558bc0e4fa3cecf567bcbbf Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 10:54:38 +0200
Subject: [PATCH 23/39] Balance what a reader sees above and below the role
The boxes had 5px above and below the role, and it still looked closer
to the icons than to the name. What a reader sees is the ink, not the
box. A line box reserves room under the baseline for descenders that the
text may not use, so the gap moves by about 4px with the letters alone:
Organizer fills that room and President does not, David Arcos does not
and Natalia Padilla nearly does.
Measured on the ink of all 22 cards of the organizers page, the gap was
7.9px above the role and 11.3px below. The name now has 3px under it and
the icon row 7px over it, which gives 9.6px above and 8.7px below. The
spread of 7 to 12 on each side is the letters, and no pair of numbers
removes it.
---
themes/pybcn_theme/assets/scss/people.scss | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/themes/pybcn_theme/assets/scss/people.scss b/themes/pybcn_theme/assets/scss/people.scss
index 98cc39e2..6b39a790 100644
--- a/themes/pybcn_theme/assets/scss/people.scss
+++ b/themes/pybcn_theme/assets/scss/people.scss
@@ -174,7 +174,16 @@
// neighbours and read as a different heading level
// rather than as the same name in less room.
font-size: 1.2em;
- margin-bottom: 5px;
+ // 3px here against 7px over the icons. What a reader
+ // sees is the ink, not the box, and a line box reserves
+ // room under the baseline for descenders that the text
+ // may not use: "Organizer" fills it and "President" does
+ // not, so the gap a reader sees moves by about 4px with
+ // the letters alone. These two numbers put the mean gap
+ // above and below the role at about 10px. With 5px on
+ // both the role sat 13px under the name and 5px over the
+ // icons, which is what it looked like.
+ margin-bottom: 3px;
// A name wider than the card is cut rather than wrapped.
// The whole name is in the title of the button and in the
@@ -213,10 +222,10 @@
// up the page, because this box has no positioned ancestor of
// its own, so the icons were only in the right place by luck.
margin-top: auto;
- // 5px over the icons, the same as the gap over the role, so
- // the role has equal space above and below it. It had 5px
- // above and none below, because margin-top: auto leaves no
- // gap of its own on a card whose content fills it.
+ // 7px over the icons against 3px under the name. The
+ // numbers differ because the boxes do: the name reserves
+ // descender room it often does not use, while the icon row
+ // starts at the top of its own box. See the h3 above.
//
// The side padding is 2px rather than 5px because the
// row has to survive the narrowest card on the site: an event
@@ -225,7 +234,7 @@
// the four icons need 170px. A little under the row, because
// the icons are the bottom of the card and the border would
// otherwise touch them.
- padding: 5px 2px 6px;
+ padding: 7px 2px 6px;
// Flex, not text-align: inline-block icons are separated by the
// whitespace between the tags, about 4 px each, which is enough
From 0723ec261e397599d0902f814c55e2daed6a1924 Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 11:04:24 +0200
Subject: [PATCH 24/39] Lay the person modal out as a header and labelled
sections
The modal was a stack of blocks with no label: the photo floated at
400px beside the name, a line of text, a bold word, the body text, the
page list and the links. A reader had to guess that the line of text
was a bio, that the bold word was a role, and that the body text was a
description, and a short modal wrapped its last links under the photo.
The page list itself was one list grouped by role, so "Organizer" with
four events sat on one row under "Permanent Committee" with one page,
and the rows were in no date order. A reader had to work out that one
row was a position and the other a history, and merge the rows to see
when the person was active. When the meetups arrive from the Archive
the list gets long, and a list that is not in date order cannot be
read.
Now the photo sits in a row with the name, the role in italics as on
the card, and the short bio behind a "Bio:" label. Below the row every
block is a section with a heading: Description for the body text,
Roles at PyBCN and Events from the appearance partial, and Links for
the social links. A section is left out with its heading when it is
empty, and the role line is left out when the person has no position,
which most speakers do not; it used to print an empty paragraph.
The pages with no year are the "Roles at PyBCN" list, grouped by label
in the order the page lists its levels, as before. The pages with a year
are the "Events" list, one line per event, newest first, with the role
in italics before the linked title. Within one year the tiebreak is the
title and then the URL. A person with two roles at one event gets one
line with both roles, sorted and joined with "and": two lines would read
as two events. The index comment says so: the modal lists a page once
with both roles, not once under each role.
The photo shows at 200px, the size of the card, and the 400px file
stays as the 2x image. On a phone it is 120px beside a smaller title,
and the roles stack under their labels because the label column left
80px for the page title.
The h3 rule for links in the title goes: the title has carried no link
since the links moved to the foot of the modal.
---
themes/pybcn_theme/assets/scss/people.scss | 141 ++++++++++++++++--
.../layouts/partials/appearances_index.html | 3 +-
.../layouts/partials/people_summary.html | 44 ++++--
.../layouts/partials/person_appearances.html | 96 ++++++++----
.../layouts/partials/person_links.html | 24 +--
5 files changed, 246 insertions(+), 62 deletions(-)
diff --git a/themes/pybcn_theme/assets/scss/people.scss b/themes/pybcn_theme/assets/scss/people.scss
index 6b39a790..78d6670e 100644
--- a/themes/pybcn_theme/assets/scss/people.scss
+++ b/themes/pybcn_theme/assets/scss/people.scss
@@ -308,30 +308,96 @@
.modal-dialog {
max-width: 70%;
- img {
- max-width: 400px;
- margin: 0 15px 15px 0;
+ // Who the person is: the photo on the left, the name,
+ // the role and the short bio beside it. A flex row and
+ // not a float: the photo used to float at 400px beside
+ // everything that followed, so a short modal wrapped
+ // its last links under the photo and a long one put
+ // the section headings against it, each at a different
+ // height. The row ends where the text ends, and the
+ // sections below run the full width.
+ .person_head {
+ display: flex;
+ align-items: flex-start;
+
+ // 200px, the size the card shows the same photo
+ // at. The 400px of before was a quarter of the
+ // modal and the only thing a reader saw at first.
+ // The 400px file stays as the 2x image.
+ img {
+ flex: 0 0 200px;
+ width: 200px;
+ height: 200px;
+ margin-right: 20px;
+ }
+
+ // min-width: 0 lets a long name wrap instead of
+ // pushing the row wider than the modal: a flex
+ // item is as wide as its longest word by default.
+ .person_identity {
+ min-width: 0;
+ }
+
+ .modal-title {
+ margin-bottom: 2px;
+ }
+
+ // Italic and plain, as on the card, so the pair
+ // under the photo reads the same in both places.
+ .person_role {
+ font-style: italic;
+ margin-bottom: 8px;
+ }
+
+ .person_bio {
+ margin-bottom: 0;
+ }
}
- h3 {
- a:first-child {
- margin-left: 10px;
+ // Every block of the modal below the name is a section
+ // with a heading: Description, Roles at PyBCN, Events,
+ // Links. The modal used to be a stack of blocks with no
+ // label, so a reader had to guess that a bold word was
+ // a role and a list of years was a history. A section
+ // is left out when it is empty, heading and all, so the
+ // rule sits on the section and not on the block inside.
+ .modal_section {
+ margin-top: 20px;
+
+ // Small and grey, so the heading labels the block
+ // without competing with the name above or the
+ // text below. A rule under it closes the gap to
+ // the previous block: without it the four sections
+ // read as one list.
+ h4 {
+ font-size: 0.8rem;
+ font-weight: bold;
+ text-transform: uppercase;
+ letter-spacing: 0.06em;
+ color: #51616e;
+ margin-bottom: 8px;
+ padding-bottom: 4px;
+ border-bottom: 1px solid #dee2e6;
}
- i {
- color: $blue-pybcn;
+
+ // The last block of a section sets no space of its
+ // own: the next section's margin-top is the gap,
+ // and the last section ends at the body padding.
+ > :last-child {
+ margin-bottom: 0;
}
}
- // The pages the person appears on, one row per role:
- // the role in the first column, the linked page titles
+ // The roles the person holds, one row per label: the
+ // label in the first column, the linked page titles
// in the second. A grid rather than a table, so the
- // role column is as wide as its longest word and no
+ // label column is as wide as its longest word and no
// wider. See person_appearances.html.
.appearances {
display: grid;
grid-template-columns: max-content 1fr;
gap: 4px 12px;
- margin: 15px 0 0;
+ margin: 0;
dt {
font-weight: bold;
@@ -341,6 +407,20 @@
}
}
+ // The events, one line per event, newest first, the
+ // role in italics before the linked title. A plain
+ // list: the bullet would say nothing the date order
+ // does not. See person_appearances.html.
+ .events {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+
+ li {
+ margin-bottom: 4px;
+ }
+ }
+
// The links of the card, listed with their text at the
// foot of the modal, so a reader can see the handle or
// the host without leaving the page. This is the only
@@ -350,7 +430,8 @@
.modal_links {
list-style: none;
padding: 0;
- margin: 15px 0 0;
+ // The section above sets the gap.
+ margin: 0;
li {
margin-bottom: 4px;
@@ -386,8 +467,38 @@
.modal {
.modal-dialog {
max-width: 100%;
- img {
- max-width: 100%;
+
+ // A 200px photo beside the name leaves 140px of a
+ // 390px screen for the title, which breaks a name
+ // one word to a line. At 120px the photo is still
+ // a face and the name has room. The title comes
+ // down with it: at Bootstrap's 28px a three-word
+ // name next to the photo took three lines.
+ .person_head {
+ img {
+ flex-basis: 120px;
+ width: 120px;
+ height: 120px;
+ margin-right: 12px;
+ }
+
+ .modal-title {
+ font-size: 1.4rem;
+ }
+ }
+
+ // The roles stack on a phone: the label column is
+ // as wide as "Management Board (2018 - 2025)", which
+ // left 80px of a 390px screen for the page title
+ // beside it, three lines for "PyLadies BCN
+ // Organizers". The page goes under its label,
+ // indented, as a definition list does by default.
+ .appearances {
+ display: block;
+
+ dd {
+ margin: 0 0 4px 1em;
+ }
}
}
}
diff --git a/themes/pybcn_theme/layouts/partials/appearances_index.html b/themes/pybcn_theme/layouts/partials/appearances_index.html
index bd23bdd1..ec707429 100644
--- a/themes/pybcn_theme/layouts/partials/appearances_index.html
+++ b/themes/pybcn_theme/layouts/partials/appearances_index.html
@@ -37,7 +37,8 @@
with no name that repeats the section title, and the modal would then
link that page twice under one label. Two different headings on one
page stay two appearances: Ferran Jovell is a Mentor and a Speaker of
- the Django page, and the modal lists that page once under each.
+ the Django page, and the modal lists that page once with both roles
+ (see person_appearances.html).
Drafts are skipped by name as well: site.RegularPages drops them in a
normal build, but a server run with -D would index content/canary.md.
diff --git a/themes/pybcn_theme/layouts/partials/people_summary.html b/themes/pybcn_theme/layouts/partials/people_summary.html
index dfb6a680..2af0fd2b 100644
--- a/themes/pybcn_theme/layouts/partials/people_summary.html
+++ b/themes/pybcn_theme/layouts/partials/people_summary.html
@@ -2,8 +2,8 @@
One person card, plus the modal that holds the long bio.
Photos come from assets/images/people/ and go through the Hugo image
- pipeline. The grid slot is 350 px wide at most and the modal caps the
- image at 400 px, so one 400 px WebP serves both, with an 800 px variant
+ pipeline. The grid slot is 350 px wide at most and the modal shows the
+ image at 200 px, so one 400 px WebP serves both, with an 800 px variant
for a 2x screen. A person with no photo falls back to anon_member.png.
Arguments:
@@ -78,15 +78,37 @@
- {{/* alt is empty here: the name is in the modal heading next to it. */}}
-
- {{/* The name only. The links used to sit next to it as
- bare icons, which repeated the list at the foot of the
- modal, where each one also says where it goes. */}}
-
{{ $.person.Params.name }}
- {{ $.person.Params.short_bio | markdownify }}
-
{{ $role }}
- {{ $.person.Content }}
+ {{/* Who the person is: the photo, the name, the role on
+ this page and the short bio, as one block. The rest
+ of the modal is a column of labelled sections:
+ Description, Roles at PyBCN, Events, Links. The
+ modal used to be a stack with no label and the
+ photo floated beside all of it, so the last lines
+ wrapped under the photo wherever the text ran out. */}}
+
+ {{/* alt is empty here: the name is in the modal heading next to it. */}}
+
+
+ {{/* The name only. The links used to sit next to it as
+ bare icons, which repeated the list at the foot of the
+ modal, where each one also says where it goes. */}}
+
{{ $.person.Params.name }}
+ {{/* Italic under the name, as on the card, so the pair
+ reads the same in both places. Most speakers have
+ no position, and the line used to print empty. */}}
+ {{ with $role }}
{{ . }}
{{ end }}
+ {{/* The label tells the short bio from the description
+ below: both are free text about the person, and
+ without it a reader could not say what either was. */}}
+ {{ with $.person.Params.short_bio }}
Bio: {{ . | markdownify }}
{{ end }}
+
+
+ {{ with $.person.Content }}
+
+
Description
+ {{ . }}
+
+ {{ end }}
{{ partial "person_appearances.html" $.person }}
{{ partial "person_links.html" $.person }}
diff --git a/themes/pybcn_theme/layouts/partials/person_appearances.html b/themes/pybcn_theme/layouts/partials/person_appearances.html
index a9b6da07..e6f95634 100644
--- a/themes/pybcn_theme/layouts/partials/person_appearances.html
+++ b/themes/pybcn_theme/layouts/partials/person_appearances.html
@@ -1,9 +1,15 @@
{{- /*
- The pages one person appears on, grouped by role, as links.
+ The pages one person appears on, as two labelled lists.
- Management Board (2026) Organizers
- Speaker PyDay BCN (2025)
- Organizer PyDay BCN (2024), PyDay BCN (2021), PyDay BCN (2020)
+ Roles at PyBCN
+ Permanent Committee Organizers
+ PyLadiesBCN Organizer PyLadies BCN Organizers
+
+ Events
+ Speaker at PyDay BCN (2025)
+ Organizer at PyDay BCN (2024)
+ Mentor and Speaker at Hands-on Django with PyLadiesBCN (2022)
+ Organizer at PyDay BCN (2021)
Argument: the person page.
@@ -22,17 +28,34 @@
on. That is the price of one list, and it stops being odd the day the
modal is a page.
- Order: the role with the most recent appearance first, and inside a
- role the most recent page first. A page with no year is a role that
- is held now, not an event: the organizers pages of PyBCN and of
- PyLadies BCN. It sorts before every dated event, so the current board
- heads the list and the events follow, newest first. Among those, the
- order is the page and then the order the page itself lists its levels,
- which is current board first: sorting them by label put Management
- Board (2018 - 2025) above Permanent Committee, and the PyLadies page
- above both. The page comes from its path, so the PyBCN organizers page
- sorts before the PyLadies one. Ties fall back to the title and the
- label, so two builds give the same order.
+ A page with no year is a role, not an event: the organizers pages of
+ PyBCN and of PyLadies BCN. A page with a year is an event. The two used
+ to share one list grouped by role, which put "Organizer" with four
+ events on one row under "Permanent Committee" with one page, and a
+ reader had to work out that the first was a position and the second a
+ history. They are now two lists under two headings, each one left out
+ when it is empty.
+
+ Roles: grouped by label, one row per label, the pages that give it as
+ links. The order is the page and then the order the page itself lists
+ its levels, which is current board first: sorting them by label put
+ Management Board (2018 - 2025) above Permanent Committee, and the
+ PyLadies page above both. The page comes from its path, so the PyBCN
+ organizers page sorts before the PyLadies one. Ties fall back to the
+ title and the label, so two builds give the same order.
+
+ Events: one line per event, newest first, the role on the line. The
+ old grouping by role listed the events of each role on one row, so a
+ reader had to merge four rows to see when the person was active, and
+ the rows themselves were in no date order. When the meetups arrive
+ from the Archive this list gets long, and a list that is not in date
+ order cannot be read. Within one year the tiebreak is the page title
+ and then its URL: the pages carry a year and no date, and the title is
+ what the reader sees, so the rule is visible. A person with two roles
+ at one event, Ferran Jovell as Mentor and Speaker of the Django day,
+ gets one line with both roles, sorted by name and joined with "and":
+ two lines for one event would read as two events, and the date order
+ is the point of the list.
A person with no appearance gets nothing: no heading, no empty list.
Everyone on /organizers/ has at least that page, but the index covers
@@ -41,23 +64,46 @@
*/ -}}
{{- $index := partialCached "appearances_index.html" site "appearances-index" -}}
{{- $groups := dict -}}
+{{- $events := dict -}}
{{- range index $index .Params.id -}}
- {{- $rank := 0 -}}{{- if .year }}{{ $rank = sub 9999 .year }}{{ end -}}
- {{- $item := merge . (dict "key" (printf "%04d %s %04d %s" $rank .url .ord .title)) -}}
- {{- $groups = merge $groups (dict .label (append $item (default slice (index $groups .label)))) -}}
+ {{- if .year -}}
+ {{- $ev := index $events .url | default (dict "title" .title "url" .url "year" .year "labels" slice) -}}
+ {{- $ev = merge $ev (dict "labels" ($ev.labels | append .label)) -}}
+ {{- $events = merge $events (dict .url $ev) -}}
+ {{- else -}}
+ {{- $item := merge . (dict "key" (printf "%s %04d %s" .url .ord .title)) -}}
+ {{- $groups = merge $groups (dict .label (append $item (default slice (index $groups .label)))) -}}
+ {{- end -}}
{{- end -}}
-{{- $list := slice -}}
+{{- $roles := slice -}}
{{- range $label, $items := $groups -}}
{{- $items = sort $items "key" -}}
{{- $first := index $items 0 -}}
- {{- $rank := 0 -}}{{- if $first.year }}{{ $rank = sub 9999 $first.year }}{{ end -}}
- {{- $list = $list | append (dict "label" $label "items" $items "key" (printf "%04d %s %04d %s" $rank $first.url $first.ord $label)) -}}
+ {{- $roles = $roles | append (dict "label" $label "items" $items "key" (printf "%s %04d %s" $first.url $first.ord $label)) -}}
+{{- end -}}
+{{- $list := slice -}}
+{{- range $url, $ev := $events -}}
+ {{- /* 9999 minus the year, so an ascending sort reads newest first. */ -}}
+ {{- $list = $list | append (merge $ev (dict "labels" (sort $ev.labels) "key" (printf "%04d %s %s" (sub 9999 $ev.year) $ev.title $url))) -}}
+{{- end -}}
+{{- with $roles -}}
+
+
Roles at PyBCN
+
+ {{- range sort . "key" }}
+
{{ .label }}
+
{{ range $i, $it := .items }}{{ if $i }}, {{ end }}{{ $it.title }}{{ end }}
+ {{- end }}
+
+
{{- end -}}
{{- with $list -}}
-
+
+
Events
+
{{- range sort . "key" }}
-
{{ .label }}
-
{{ range $i, $it := .items }}{{ if $i }}, {{ end }}{{ $it.title }}{{ end }}
+
{{ delimit .labels ", " " and " }} at {{ .title }}
{{- end }}
-
+
+
{{- end -}}
diff --git a/themes/pybcn_theme/layouts/partials/person_links.html b/themes/pybcn_theme/layouts/partials/person_links.html
index ad748fb5..cf26c2e1 100644
--- a/themes/pybcn_theme/layouts/partials/person_links.html
+++ b/themes/pybcn_theme/layouts/partials/person_links.html
@@ -5,10 +5,11 @@
Argument: the person page.
- The modal title shows the same links as a row of bare icons. That row
- says which networks the person is on and nothing more, so a reader
- had to follow a link to learn the handle. This list is in addition to
- that row, at the foot of the modal.
+ The modal title used to show the same links as a row of bare icons.
+ That row said which networks the person is on and nothing more, so a
+ reader had to follow a link to learn the handle. This list is now the
+ only one, the last section of the modal, under its own heading like
+ the sections above it (see people_summary.html).
The text comes from the stored URL, not from a separate field. The
person files carry one form per network, which bin/check-content
@@ -19,18 +20,21 @@
*/ -}}
{{- $p := .Params -}}
{{- if or $p.linkedin $p.github $p.twitter $p.site -}}
-
+
{{- end -}}
From bd2681b1ed2f9234b131db7c34fbe10d804fcdd9 Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 11:19:21 +0200
Subject: [PATCH 25/39] Call the sponsor home page site, as a person's, and
check it
A sponsor stored its home page in `web` and a person in `site`.
bin/check-content read `site` for both, so the 66 sponsor URLs were
never checked: 29 ended with a slash, which the social link rule
forbids, one is http and one carries a query string.
Rename the field in the 66 sponsor files and in sponsor_summary.html,
the only template that reads it, and remove the trailing slash from the
29 values. Nothing else about any URL changes: the sponsor links in the
built pages are the same as before apart from that slash. The old name
is an error now, so a sponsor file copied from an old commit does not
escape the check again. README.md documented the field as `url`, which
it never was.
The check now reports jobfluent.md, whose URL carries `?q=python`. The
value is left as it was, pending a decision on whether to drop the
query or keep that landing page.
---
README.md | 2 +-
bin/check-content | 9 +++++++++
content/sponsors/21buttons.md | 2 +-
content/sponsors/affectv.md | 2 +-
content/sponsors/aimsun.md | 2 +-
content/sponsors/apsl.md | 2 +-
content/sponsors/backmarket.md | 2 +-
content/sponsors/bitphy.md | 2 +-
content/sponsors/bling.md | 2 +-
content/sponsors/bmat.md | 2 +-
content/sponsors/business-insights.md | 2 +-
content/sponsors/canodrom.md | 2 +-
content/sponsors/capitole.md | 2 +-
content/sponsors/casadelmig.md | 2 +-
content/sponsors/cloudblue.md | 2 +-
content/sponsors/codelytv.md | 2 +-
content/sponsors/codeop.md | 2 +-
content/sponsors/codurance.md | 2 +-
content/sponsors/colorsensing.md | 2 +-
content/sponsors/coopdevs.md | 2 +-
content/sponsors/digitalfems.md | 2 +-
content/sponsors/edgetier.md | 2 +-
content/sponsors/europython_society.md | 2 +-
content/sponsors/flanks.md | 2 +-
content/sponsors/gluecharm.md | 2 +-
content/sponsors/holaluz.md | 2 +-
content/sponsors/hpc-now.md | 2 +-
content/sponsors/ikigai.md | 2 +-
content/sponsors/innoit.md | 2 +-
content/sponsors/innovamat.md | 2 +-
content/sponsors/iomed.md | 2 +-
content/sponsors/isdieducation.md | 2 +-
content/sponsors/izi.md | 2 +-
content/sponsors/jobfluent.md | 2 +-
content/sponsors/kiwi.md | 2 +-
content/sponsors/lambdaloopers.md | 2 +-
content/sponsors/letgo.md | 2 +-
content/sponsors/marfeel.md | 2 +-
content/sponsors/mundimoto.md | 2 +-
content/sponsors/nagarro.md | 2 +-
content/sponsors/nuclia.md | 2 +-
content/sponsors/okta.md | 2 +-
content/sponsors/onna.md | 2 +-
content/sponsors/orpheus.md | 2 +-
content/sponsors/preply.md | 2 +-
content/sponsors/protopixel.md | 2 +-
content/sponsors/psf.md | 2 +-
content/sponsors/pybcn.md | 2 +-
content/sponsors/pyladiesbcn.md | 2 +-
content/sponsors/pythones.md | 2 +-
content/sponsors/qida.md | 2 +-
content/sponsors/qilimanjaro.md | 2 +-
content/sponsors/quside.md | 2 +-
content/sponsors/qustodio.md | 2 +-
content/sponsors/rakuten.md | 2 +-
content/sponsors/rover.md | 2 +-
content/sponsors/satellogic.md | 2 +-
content/sponsors/shimoku.md | 2 +-
content/sponsors/skyscanner.md | 2 +-
content/sponsors/somenergia.md | 2 +-
content/sponsors/tecnologas.md | 2 +-
content/sponsors/travelperk.md | 2 +-
content/sponsors/typeform.md | 2 +-
content/sponsors/ub.md | 2 +-
content/sponsors/upf.md | 2 +-
content/sponsors/veriff.md | 2 +-
content/sponsors/verse.md | 2 +-
content/sponsors/xorq.md | 2 +-
themes/pybcn_theme/layouts/partials/sponsor_summary.html | 2 +-
69 files changed, 77 insertions(+), 68 deletions(-)
diff --git a/README.md b/README.md
index 24a88c78..1dff7738 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,7 @@ The MarkDown file for the sponsor will have a FrontMatter section with the follo
- `id`: Unique identifier of this sponsor. Should be a string without spaces, preferrably kebab-case.
- `name`: Sponsor's name to be shown in all renderings.
- `logo_image`: File name for the sponsor logo, which must be under `themes/pybcn_theme/assets/images/sponsors/`. An external URL is not accepted: copy the file into the repository. The template loads it with `resources.Get`, so a file under `static/` is not found, and `bin/check-content` reports it as an error.
-- `url`: URL for the sponsor web page.
+- `site`: URL of the sponsor home page, https and with no trailing slash. `bin/check-content` checks it, like the `site` of a person.
- `twitter`: URL for the sponsor's twitter account.
After this FrontMatter section, any valid MarkDown will be considered generic content to be shown in detail view.
diff --git a/bin/check-content b/bin/check-content
index 7c030bb4..9e00df06 100755
--- a/bin/check-content
+++ b/bin/check-content
@@ -239,6 +239,12 @@ def check_social(people, sponsors):
and has one right answer. Left to taste, the values split about two to one
between the two styles across more than two hundred links. A host has no
trailing slash (https://ber2.github.io), so a profile path gets none either.
+
+ A sponsor home page is in `site`, the same field as a person's. It was
+ `web` until October 2026, and this loop read `site` for both kinds of page,
+ so the 66 sponsor URLs were never checked: 29 ended with a slash, one was
+ http and one carried a query string. The old name is an error now, so a
+ sponsor file copied from an old commit cannot escape the check again.
"""
for page_id, path in sorted({**people, **sponsors}.items()):
data = front_matter(path) or {}
@@ -258,6 +264,9 @@ def check_social(people, sponsors):
error(path, f"{field} ends with a slash: '{value}'. "
f"Use '{value.rstrip('/')}'.")
+ if "web" in data:
+ error(path, "'web' is not a field: put the home page in 'site'")
+
site = data.get("site")
if site:
site = str(site).strip()
diff --git a/content/sponsors/21buttons.md b/content/sponsors/21buttons.md
index 2f39d531..353f3ab6 100644
--- a/content/sponsors/21buttons.md
+++ b/content/sponsors/21buttons.md
@@ -2,5 +2,5 @@
id: 21buttons
name: 21 Buttons
logo_image: 21buttons.png
-web: https://es.21buttons.com/
+site: https://es.21buttons.com
---
diff --git a/content/sponsors/affectv.md b/content/sponsors/affectv.md
index e74026d5..b38bff4c 100644
--- a/content/sponsors/affectv.md
+++ b/content/sponsors/affectv.md
@@ -2,7 +2,7 @@
id: affectv
name: affectv
logo_image: affectv.png
-web: https://www.affectv.com/
+site: https://www.affectv.com
twitter: https://x.com/affectv
---
diff --git a/content/sponsors/aimsun.md b/content/sponsors/aimsun.md
index cb026d81..1811b458 100644
--- a/content/sponsors/aimsun.md
+++ b/content/sponsors/aimsun.md
@@ -2,6 +2,6 @@
id: aimsun
name: Aimsun
logo_image: aimsun.jpg
-web: https://www.aimsun.com
+site: https://www.aimsun.com
twitter: https://x.com/aimsun
---
diff --git a/content/sponsors/apsl.md b/content/sponsors/apsl.md
index 1facbb5b..95a8641b 100644
--- a/content/sponsors/apsl.md
+++ b/content/sponsors/apsl.md
@@ -2,6 +2,6 @@
id: apsl
name: APSL
logo_image: apsl.svg
-web: https://apsl.tech
+site: https://apsl.tech
twitter: https://x.com/apsl_web
---
diff --git a/content/sponsors/backmarket.md b/content/sponsors/backmarket.md
index 76898f9e..f169392d 100644
--- a/content/sponsors/backmarket.md
+++ b/content/sponsors/backmarket.md
@@ -2,5 +2,5 @@
id: backmarket
name: BackMarket
logo_image: backmarket.png
-web: https://www.backmarket.com
+site: https://www.backmarket.com
---
diff --git a/content/sponsors/bitphy.md b/content/sponsors/bitphy.md
index 3b90fa5c..8f3d8fca 100644
--- a/content/sponsors/bitphy.md
+++ b/content/sponsors/bitphy.md
@@ -2,5 +2,5 @@
id: bitphy
name: BitPhy
logo_image: bitphy.png
-web: https://www.bitphy.com/
+site: https://www.bitphy.com
---
diff --git a/content/sponsors/bling.md b/content/sponsors/bling.md
index b037f57c..9302bd7b 100644
--- a/content/sponsors/bling.md
+++ b/content/sponsors/bling.md
@@ -2,5 +2,5 @@
id: bling
name: BLING
logo_image: bling.png
-web: https://www.bling.eu
+site: https://www.bling.eu
---
diff --git a/content/sponsors/bmat.md b/content/sponsors/bmat.md
index 7f57629c..2fcca302 100644
--- a/content/sponsors/bmat.md
+++ b/content/sponsors/bmat.md
@@ -2,5 +2,5 @@
id: bmat
name: BMAT
logo_image: bmat.jpeg
-web: https://www.bmat.com
+site: https://www.bmat.com
---
diff --git a/content/sponsors/business-insights.md b/content/sponsors/business-insights.md
index dfa20a82..e32e4021 100644
--- a/content/sponsors/business-insights.md
+++ b/content/sponsors/business-insights.md
@@ -2,5 +2,5 @@
id: business-insights
name: Business Insights
logo_image: business-insights.png
-web: https://www.businessinsights.es/
+site: https://www.businessinsights.es
---
diff --git a/content/sponsors/canodrom.md b/content/sponsors/canodrom.md
index c2fedc55..ffb65c5a 100644
--- a/content/sponsors/canodrom.md
+++ b/content/sponsors/canodrom.md
@@ -2,5 +2,5 @@
id: canodrom
name: Canòdrom - Ateneu d'innovació digital i democràtica
logo_image: canodrom.png
-web: https://canodrom.barcelona/
+site: https://canodrom.barcelona
---
diff --git a/content/sponsors/capitole.md b/content/sponsors/capitole.md
index cd3e3503..905ac3fd 100644
--- a/content/sponsors/capitole.md
+++ b/content/sponsors/capitole.md
@@ -2,5 +2,5 @@
id: capitole
name: Capitole Consulting
logo_image: capitole.jpg
-web: https://www.capitole-consulting.com/
+site: https://www.capitole-consulting.com
---
diff --git a/content/sponsors/casadelmig.md b/content/sponsors/casadelmig.md
index 7021fe12..5229f104 100644
--- a/content/sponsors/casadelmig.md
+++ b/content/sponsors/casadelmig.md
@@ -2,6 +2,6 @@
id: casadelmig
name: FAB Casa del Mig - Punt Multimèdia
logo_image: casadelmig.jpg
-web: https://www.puntmultimedia.org/
+site: https://www.puntmultimedia.org
twitter: https://x.com/Puntmultimedia
---
diff --git a/content/sponsors/cloudblue.md b/content/sponsors/cloudblue.md
index b15309af..4c04e3c1 100644
--- a/content/sponsors/cloudblue.md
+++ b/content/sponsors/cloudblue.md
@@ -2,5 +2,5 @@
id: cloudblue
name: CloudBlue
logo_image: cloudblue.png
-web: https://www.cloudblue.com/
+site: https://www.cloudblue.com
---
diff --git a/content/sponsors/codelytv.md b/content/sponsors/codelytv.md
index 9ebade35..5194b134 100644
--- a/content/sponsors/codelytv.md
+++ b/content/sponsors/codelytv.md
@@ -2,6 +2,6 @@
id: codelytv
name: Codely TV
logo_image: codely.png
-web: https://codely.tv/
+site: https://codely.tv
twitter: https://x.com/CodelyTV
---
diff --git a/content/sponsors/codeop.md b/content/sponsors/codeop.md
index 6a201b21..0daa2300 100644
--- a/content/sponsors/codeop.md
+++ b/content/sponsors/codeop.md
@@ -2,6 +2,6 @@
id: codeop
name: CodeOp
logo_image: codeop.png
-web: https://codeop.tech/
+site: https://codeop.tech
---
diff --git a/content/sponsors/codurance.md b/content/sponsors/codurance.md
index 61f0584c..bb15c184 100644
--- a/content/sponsors/codurance.md
+++ b/content/sponsors/codurance.md
@@ -2,7 +2,7 @@
id: codurance
name: Codurance
logo_image: codurance.png
-web: https://www.codurance.com/es/
+site: https://www.codurance.com/es
twitter: https://x.com/codurance_ES
linkedin: https://www.linkedin.com/company/codurance
---
diff --git a/content/sponsors/colorsensing.md b/content/sponsors/colorsensing.md
index 006c3875..b8be592f 100644
--- a/content/sponsors/colorsensing.md
+++ b/content/sponsors/colorsensing.md
@@ -2,6 +2,6 @@
id: colorsensing
name: ColorSensing
logo_image: colorsensing.svg
-web: https://www.color-sensing.com/en
+site: https://www.color-sensing.com/en
twitter: https://x.com/colorsensing
---
diff --git a/content/sponsors/coopdevs.md b/content/sponsors/coopdevs.md
index fa301d69..ea5ce45e 100644
--- a/content/sponsors/coopdevs.md
+++ b/content/sponsors/coopdevs.md
@@ -2,7 +2,7 @@
id: coopdevs
name: Coopdevs
logo_image: coopdevs.svg
-web: https://coopdevs.org/
+site: https://coopdevs.org
twitter: https://x.com/coopdevs
linkedin: https://www.linkedin.com/company/coopdevs
mastodont: https://mastodon.economiasocial.org/@Coopdevs/
diff --git a/content/sponsors/digitalfems.md b/content/sponsors/digitalfems.md
index 8b6845e3..710b6eb3 100644
--- a/content/sponsors/digitalfems.md
+++ b/content/sponsors/digitalfems.md
@@ -2,5 +2,5 @@
id: digitalfems
name: DigitalFems
logo_image: digitalfems.png
-web: https://www.digitalfems.org
+site: https://www.digitalfems.org
---
diff --git a/content/sponsors/edgetier.md b/content/sponsors/edgetier.md
index 46950ccc..9f514335 100644
--- a/content/sponsors/edgetier.md
+++ b/content/sponsors/edgetier.md
@@ -2,5 +2,5 @@
id: edgetier
name: EdgeTier
logo_image: edgetier.jpeg
-web: https://www.edgetier.com
+site: https://www.edgetier.com
---
diff --git a/content/sponsors/europython_society.md b/content/sponsors/europython_society.md
index 5cf2b9ab..97bf9632 100644
--- a/content/sponsors/europython_society.md
+++ b/content/sponsors/europython_society.md
@@ -2,5 +2,5 @@
id: europython_society
name: EuroPython Society
logo_image: europython_society.png
-web: https://www.europython-society.org
+site: https://www.europython-society.org
---
diff --git a/content/sponsors/flanks.md b/content/sponsors/flanks.md
index c5cba09b..1a57b8be 100644
--- a/content/sponsors/flanks.md
+++ b/content/sponsors/flanks.md
@@ -2,5 +2,5 @@
id: flanks
name: Flanks
logo_image: flanks.png
-web: https://flanks.io
+site: https://flanks.io
---
diff --git a/content/sponsors/gluecharm.md b/content/sponsors/gluecharm.md
index 8798f21a..d5a0f297 100644
--- a/content/sponsors/gluecharm.md
+++ b/content/sponsors/gluecharm.md
@@ -2,5 +2,5 @@
id: gluecharm
name: Gluecharm
logo_image: gluecharm.png
-web: https://gluecharm.com
+site: https://gluecharm.com
---
diff --git a/content/sponsors/holaluz.md b/content/sponsors/holaluz.md
index 19dbf563..c39cd9cd 100644
--- a/content/sponsors/holaluz.md
+++ b/content/sponsors/holaluz.md
@@ -2,7 +2,7 @@
id: holaluz
name: Holaluz
logo_image: holaluz.png
-web: https://www.holaluz.com/
+site: https://www.holaluz.com
twitter: https://x.com/holaluzcom
---
diff --git a/content/sponsors/hpc-now.md b/content/sponsors/hpc-now.md
index a8b9960f..9b520822 100644
--- a/content/sponsors/hpc-now.md
+++ b/content/sponsors/hpc-now.md
@@ -2,5 +2,5 @@
id: hpc-now
name: HPCNow!
logo_image: hpc-now.svg
-web: https://hpcnow.com/
+site: https://hpcnow.com
---
diff --git a/content/sponsors/ikigai.md b/content/sponsors/ikigai.md
index ee368289..4a1ea4a9 100644
--- a/content/sponsors/ikigai.md
+++ b/content/sponsors/ikigai.md
@@ -2,5 +2,5 @@
id: ikigai
name: IKIGAI
logo_image: ikigai.jpg
-web: https://ikigaitalentgroup.com/
+site: https://ikigaitalentgroup.com
---
diff --git a/content/sponsors/innoit.md b/content/sponsors/innoit.md
index 66781dbd..687b9f72 100644
--- a/content/sponsors/innoit.md
+++ b/content/sponsors/innoit.md
@@ -2,7 +2,7 @@
id: innoit
name: Innoit
logo_image: innoit.png
-web: https://www.inno-it.es/
+site: https://www.inno-it.es
twitter: https://x.com/InnoitES
linkedin: https://www.linkedin.com/company/innoit-consulting
---
diff --git a/content/sponsors/innovamat.md b/content/sponsors/innovamat.md
index e059e149..583389be 100644
--- a/content/sponsors/innovamat.md
+++ b/content/sponsors/innovamat.md
@@ -2,5 +2,5 @@
id: innovamat
name: Innovamat
logo_image: innovamat.gif
-web: https://www.innovamat.com
+site: https://www.innovamat.com
---
diff --git a/content/sponsors/iomed.md b/content/sponsors/iomed.md
index 99c751ad..7c991155 100644
--- a/content/sponsors/iomed.md
+++ b/content/sponsors/iomed.md
@@ -2,5 +2,5 @@
id: iomed
name: IOMED
logo_image: iomed.png
-web: https://iomed.health
+site: https://iomed.health
---
diff --git a/content/sponsors/isdieducation.md b/content/sponsors/isdieducation.md
index c5910a0d..06ec4091 100644
--- a/content/sponsors/isdieducation.md
+++ b/content/sponsors/isdieducation.md
@@ -2,7 +2,7 @@
id: isdieducation
name: ISDI Education
logo_image: isdi.png
-web: https://www.isdi.education/es
+site: https://www.isdi.education/es
linkedin: https://www.linkedin.com/school/isdi
instagram: https://www.instagram.com/isdi_edu/
---
diff --git a/content/sponsors/izi.md b/content/sponsors/izi.md
index fb165ab3..90677e48 100644
--- a/content/sponsors/izi.md
+++ b/content/sponsors/izi.md
@@ -2,6 +2,6 @@
id: izi
name: IZI Record
logo_image: izi.png
-web: https://izirecord.com
+site: https://izirecord.com
---
diff --git a/content/sponsors/jobfluent.md b/content/sponsors/jobfluent.md
index e47ef8bc..be100a97 100644
--- a/content/sponsors/jobfluent.md
+++ b/content/sponsors/jobfluent.md
@@ -2,5 +2,5 @@
id: jobfluent
name: Job Fluent
logo_image: jobfluent.png
-web: https://www.jobfluent.com/es/empleos-barcelona?q=python
+site: https://www.jobfluent.com/es/empleos-barcelona?q=python
---
diff --git a/content/sponsors/kiwi.md b/content/sponsors/kiwi.md
index b68de39a..e7b1f05c 100644
--- a/content/sponsors/kiwi.md
+++ b/content/sponsors/kiwi.md
@@ -2,6 +2,6 @@
id: kiwi
name: Kiwi.com
logo_image: kiwi.png
-web: https://www.kiwi.com/en/
+site: https://www.kiwi.com/en
twitter: https://x.com/kiwi
---
diff --git a/content/sponsors/lambdaloopers.md b/content/sponsors/lambdaloopers.md
index 63ff818d..cfbe0dc3 100644
--- a/content/sponsors/lambdaloopers.md
+++ b/content/sponsors/lambdaloopers.md
@@ -2,5 +2,5 @@
id: lambdaloopers
name: LambdaLoopers
logo_image: lambdaloopers.png
-web: https://lambdaloopers.com/
+site: https://lambdaloopers.com
---
diff --git a/content/sponsors/letgo.md b/content/sponsors/letgo.md
index fdf7b664..1e8c2eff 100644
--- a/content/sponsors/letgo.md
+++ b/content/sponsors/letgo.md
@@ -2,7 +2,7 @@
id: letgo
name: letgo
logo_image: letgo.png
-web: https://www.letgo.com/
+site: https://www.letgo.com
twitter: https://x.com/letgo
---
diff --git a/content/sponsors/marfeel.md b/content/sponsors/marfeel.md
index c1494a2f..dcbad68a 100644
--- a/content/sponsors/marfeel.md
+++ b/content/sponsors/marfeel.md
@@ -2,6 +2,6 @@
id: marfeel
name: Marfeel
logo_image: marfeel.png
-web: https://www.marfeel.com/
+site: https://www.marfeel.com
twitter: https://x.com/marfeel
---
diff --git a/content/sponsors/mundimoto.md b/content/sponsors/mundimoto.md
index c8f59901..21f7b69c 100644
--- a/content/sponsors/mundimoto.md
+++ b/content/sponsors/mundimoto.md
@@ -2,5 +2,5 @@
id: mundimoto
name: MundiMoto
logo_image: mundimoto.png
-web: https://mundimoto.com
+site: https://mundimoto.com
---
diff --git a/content/sponsors/nagarro.md b/content/sponsors/nagarro.md
index 2bc3e368..b60eb924 100644
--- a/content/sponsors/nagarro.md
+++ b/content/sponsors/nagarro.md
@@ -2,5 +2,5 @@
id: nagarro
name: Nagarro
logo_image: nagarro.svg
-web: https://www.nagarro.com
+site: https://www.nagarro.com
---
diff --git a/content/sponsors/nuclia.md b/content/sponsors/nuclia.md
index 3772c3d7..cec8a118 100644
--- a/content/sponsors/nuclia.md
+++ b/content/sponsors/nuclia.md
@@ -2,6 +2,6 @@
id: nuclia
name: Nuclia
logo_image: Nuclia.png
-web: https://nuclia.com/
+site: https://nuclia.com
twitter: https://x.com/nucliaAI
---
diff --git a/content/sponsors/okta.md b/content/sponsors/okta.md
index 7e855461..350118da 100644
--- a/content/sponsors/okta.md
+++ b/content/sponsors/okta.md
@@ -2,7 +2,7 @@
id: okta
name: Okta
logo_image: okta.png
-web: https://auth0.com/careers
+site: https://auth0.com/careers
twitter: https://x.com/auth0
linkedin: https://www.linkedin.com/company/auth0
---
diff --git a/content/sponsors/onna.md b/content/sponsors/onna.md
index b3381e11..17ddffed 100644
--- a/content/sponsors/onna.md
+++ b/content/sponsors/onna.md
@@ -2,5 +2,5 @@
id: onna
name: Onna
logo_image: onna.png
-web: https://onna.com
+site: https://onna.com
---
diff --git a/content/sponsors/orpheus.md b/content/sponsors/orpheus.md
index 80fda7ca..1982133f 100644
--- a/content/sponsors/orpheus.md
+++ b/content/sponsors/orpheus.md
@@ -2,5 +2,5 @@
id: orpheus
name: Orph.eus
logo_image: orpheus.png
-web: https://Orph.eus
+site: https://Orph.eus
---
diff --git a/content/sponsors/preply.md b/content/sponsors/preply.md
index a9824cb0..fdd0cea7 100644
--- a/content/sponsors/preply.md
+++ b/content/sponsors/preply.md
@@ -2,6 +2,6 @@
id: preply
name: Preply
logo_image: preply.png
-web: https://preply.com/
+site: https://preply.com
twitter: https://x.com/PreplyCom
---
diff --git a/content/sponsors/protopixel.md b/content/sponsors/protopixel.md
index 09d4aef0..ac13c1fd 100644
--- a/content/sponsors/protopixel.md
+++ b/content/sponsors/protopixel.md
@@ -2,7 +2,7 @@
id: protopixel
name: Protopixel
logo_image: protopixel.png
-web: https://www.protopixel.io
+site: https://www.protopixel.io
twitter: https://x.com/protopixelbcn
linkedin: https://www.linkedin.com/company/protopixel
---
diff --git a/content/sponsors/psf.md b/content/sponsors/psf.md
index df3abb7f..9c41ee57 100644
--- a/content/sponsors/psf.md
+++ b/content/sponsors/psf.md
@@ -2,6 +2,6 @@
id: psf
name: Python Software Foundation
logo_image: psf.png
-web: https://www.python.org/psf
+site: https://www.python.org/psf
twitter: https://x.com/psf
---
diff --git a/content/sponsors/pybcn.md b/content/sponsors/pybcn.md
index 8058b808..f3c81b49 100644
--- a/content/sponsors/pybcn.md
+++ b/content/sponsors/pybcn.md
@@ -2,6 +2,6 @@
id: pybcn
name: PyBCN
logo_image: pybcn.png
-web: https://pybcn.org
+site: https://pybcn.org
twitter: https://x.com/PyBCN
---
diff --git a/content/sponsors/pyladiesbcn.md b/content/sponsors/pyladiesbcn.md
index cf217fd7..a15698db 100644
--- a/content/sponsors/pyladiesbcn.md
+++ b/content/sponsors/pyladiesbcn.md
@@ -2,6 +2,6 @@
id: pyladiesbcn
name: PyLadiesBCN
logo_image: pyladiesbcn.jpeg
-web: https://pybcn.org/pyladies_bcn/
+site: https://pybcn.org/pyladies_bcn
twitter: https://x.com/PyLadiesBCN
---
diff --git a/content/sponsors/pythones.md b/content/sponsors/pythones.md
index 834c75a9..193f6855 100644
--- a/content/sponsors/pythones.md
+++ b/content/sponsors/pythones.md
@@ -2,6 +2,6 @@
id: pythones
name: Python España
logo_image: pythonES.png
-web: https://es.python.org
+site: https://es.python.org
twitter: https://x.com/python_es
---
diff --git a/content/sponsors/qida.md b/content/sponsors/qida.md
index c34b73db..0d34f47b 100644
--- a/content/sponsors/qida.md
+++ b/content/sponsors/qida.md
@@ -2,6 +2,6 @@
id: qida
name: Qida
logo_image: Qida.png
-web: https://qida.es/
+site: https://qida.es
twitter: https://x.com/qidacare
---
diff --git a/content/sponsors/qilimanjaro.md b/content/sponsors/qilimanjaro.md
index acf4a013..ed77ed87 100644
--- a/content/sponsors/qilimanjaro.md
+++ b/content/sponsors/qilimanjaro.md
@@ -2,5 +2,5 @@
id: qilimanjaro
name: Qilimanjaro
logo_image: qilimanjaro.png
-web: https://www.qilimanjaro.tech
+site: https://www.qilimanjaro.tech
---
diff --git a/content/sponsors/quside.md b/content/sponsors/quside.md
index ac47084b..186cf757 100644
--- a/content/sponsors/quside.md
+++ b/content/sponsors/quside.md
@@ -2,5 +2,5 @@
id: quside
name: Quside
logo_image: quside.png
-web: https://quside.com/
+site: https://quside.com
---
diff --git a/content/sponsors/qustodio.md b/content/sponsors/qustodio.md
index 9e08e48d..77a11153 100644
--- a/content/sponsors/qustodio.md
+++ b/content/sponsors/qustodio.md
@@ -2,5 +2,5 @@
id: qustodio
name: Qustodio
logo_image: qustodio.png
-web: https://www.qustodio.com
+site: https://www.qustodio.com
---
diff --git a/content/sponsors/rakuten.md b/content/sponsors/rakuten.md
index 15d2fdc6..83a20c45 100644
--- a/content/sponsors/rakuten.md
+++ b/content/sponsors/rakuten.md
@@ -2,6 +2,6 @@
id: rakuten
name: Rakuten
logo_image: RakutenTV.png
-web: https://www.rakuten.tv
+site: https://www.rakuten.tv
---
diff --git a/content/sponsors/rover.md b/content/sponsors/rover.md
index 014da3ef..dc0d6d0d 100644
--- a/content/sponsors/rover.md
+++ b/content/sponsors/rover.md
@@ -2,5 +2,5 @@
id: rover
name: Rover
logo_image: rover.png
-web: https://rover.com
+site: https://rover.com
---
diff --git a/content/sponsors/satellogic.md b/content/sponsors/satellogic.md
index 00a0d66d..a12cc183 100644
--- a/content/sponsors/satellogic.md
+++ b/content/sponsors/satellogic.md
@@ -2,6 +2,6 @@
id: satellogic
name: Satellogic
logo_image: satellogic.png
-web: https://satellogic.com/
+site: https://satellogic.com
twitter: https://x.com/satellogic
---
diff --git a/content/sponsors/shimoku.md b/content/sponsors/shimoku.md
index fab98899..b9fd1e5a 100644
--- a/content/sponsors/shimoku.md
+++ b/content/sponsors/shimoku.md
@@ -2,7 +2,7 @@
id: shimoku
name: Shimoku
logo_image: shimoku.png
-web: https://www.shimoku.com
+site: https://www.shimoku.com
twitter: https://x.com/AiShimoku
---
diff --git a/content/sponsors/skyscanner.md b/content/sponsors/skyscanner.md
index 16a02bd7..6b2610e9 100644
--- a/content/sponsors/skyscanner.md
+++ b/content/sponsors/skyscanner.md
@@ -2,5 +2,5 @@
id: skyscanner
name: SkyScanner
logo_image: skyscanner.png
-web: https://skyscanner.com
+site: https://skyscanner.com
---
diff --git a/content/sponsors/somenergia.md b/content/sponsors/somenergia.md
index f11e9b08..d3be2ea8 100644
--- a/content/sponsors/somenergia.md
+++ b/content/sponsors/somenergia.md
@@ -2,7 +2,7 @@
id: somenergia
name: Som Energia
logo_image: somenergia.jpg
-web: https://www.somenergia.coop
+site: https://www.somenergia.coop
twitter: https://x.com/SomEnergia
---
diff --git a/content/sponsors/tecnologas.md b/content/sponsors/tecnologas.md
index de17c7e7..09314b50 100644
--- a/content/sponsors/tecnologas.md
+++ b/content/sponsors/tecnologas.md
@@ -2,5 +2,5 @@
id: tecnologas
name: TECNOLOGAS.ORG
logo_image: tecnologas.png
-web: http://tecnologas.org/
+site: http://tecnologas.org
---
diff --git a/content/sponsors/travelperk.md b/content/sponsors/travelperk.md
index f013a3ff..0249dae6 100644
--- a/content/sponsors/travelperk.md
+++ b/content/sponsors/travelperk.md
@@ -2,7 +2,7 @@
id: travelperk
name: TravelPerk
logo_image: travelperk.png
-web: https://www.travelperk.com/
+site: https://www.travelperk.com
twitter: https://x.com/travelperk
---
diff --git a/content/sponsors/typeform.md b/content/sponsors/typeform.md
index d3d45d51..85ab670c 100644
--- a/content/sponsors/typeform.md
+++ b/content/sponsors/typeform.md
@@ -2,6 +2,6 @@
id: typeform
name: Typeform
logo_image: typeform.png
-web: https://typeform.com
+site: https://typeform.com
twitter: https://x.com/typeform
---
diff --git a/content/sponsors/ub.md b/content/sponsors/ub.md
index 9fa7d79a..be644a17 100644
--- a/content/sponsors/ub.md
+++ b/content/sponsors/ub.md
@@ -2,6 +2,6 @@
id: ub
name: Universitat de Barcelona
logo_image: ub.jpg
-web: https://www.ub.edu
+site: https://www.ub.edu
twitter: https://x.com/UniBarcelona
---
diff --git a/content/sponsors/upf.md b/content/sponsors/upf.md
index 09a82abb..cefbb248 100644
--- a/content/sponsors/upf.md
+++ b/content/sponsors/upf.md
@@ -2,6 +2,6 @@
id: upf
name: Universitat Pompeu Fabra
logo_image: upf.png
-web: https://upf.edu
+site: https://upf.edu
twitter: https://x.com/upfbarcelona
---
diff --git a/content/sponsors/veriff.md b/content/sponsors/veriff.md
index c6aec435..415a03ab 100644
--- a/content/sponsors/veriff.md
+++ b/content/sponsors/veriff.md
@@ -2,7 +2,7 @@
id: veriff
name: Veriff
logo_image: veriff.png
-web: https://veriff.com
+site: https://veriff.com
twitter: https://x.com/Veriff
---
diff --git a/content/sponsors/verse.md b/content/sponsors/verse.md
index b5f2b421..5ae5a764 100644
--- a/content/sponsors/verse.md
+++ b/content/sponsors/verse.md
@@ -2,6 +2,6 @@
id: verse
name: Verse
logo_image: verse.jpg
-web: https://verse.me
+site: https://verse.me
twitter: https://x.com/joinverse
---
diff --git a/content/sponsors/xorq.md b/content/sponsors/xorq.md
index d6c5a478..1c38d58e 100644
--- a/content/sponsors/xorq.md
+++ b/content/sponsors/xorq.md
@@ -2,5 +2,5 @@
id: xorq
name: Xorq Labs
logo_image: xorq.png
-web: https://www.xorq.dev/
+site: https://www.xorq.dev
---
\ No newline at end of file
diff --git a/themes/pybcn_theme/layouts/partials/sponsor_summary.html b/themes/pybcn_theme/layouts/partials/sponsor_summary.html
index 205b578d..0ca1cc0f 100644
--- a/themes/pybcn_theme/layouts/partials/sponsor_summary.html
+++ b/themes/pybcn_theme/layouts/partials/sponsor_summary.html
@@ -57,7 +57,7 @@
{{- end -}}
{{- end -}}
{{- $logo := dict "src" $src "srcset" $srcset "width" $width "height" $height "name" $name -}}
-{{- with $sponsor.Params.web -}}
+{{- with $sponsor.Params.site -}}
{{- template "pybcn_sponsor_logo" $logo -}}
{{- else -}}
{{- template "pybcn_sponsor_logo" $logo -}}
From 6189c210378669bc9b03903a8493b317ae073125 Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 11:21:35 +0200
Subject: [PATCH 26/39] Warn when a person photo is black and white
The person cards grey every photo with a CSS filter on a device that
can hover, so a photo that is already black and white looks like the
others there. On a phone and in the modal nothing greys them, and that
photo is the one grey face in a wall of colour. Ten of the 130 photos
are like that. Only the person can fix it, with another photo, so this
is a warning and never an error, and the exit code does not change.
The measure is the mean of max(r,g,b) - min(r,g,b) per pixel over a
64px thumbnail. The ten score 0.01 or less and the next photo 9.5, so
the threshold is 4. Two of the ten are stored as greyscale; the other
eight are RGB JPEGs with no colour in them, so a header check cannot do
this and the pixels are read, through Pillow. The 130 photos add about
0.7 s to the run.
Pillow is what bin/square-photos already needs. pr.yml installs it for
this check. A machine without it still runs every other check and gets
one note that the colour check did not run.
---
.github/workflows/pr.yml | 5 +++-
bin/check-content | 57 +++++++++++++++++++++++++++++++++++++++-
2 files changed, 60 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index 7e1e84ed..019cdbdd 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -53,7 +53,10 @@ jobs:
python-version: '3.12'
- name: Install dependencies
- run: pip install pyyaml
+ # pillow: bin/check-content reads every person photo to warn about
+ # one with no colour. Without it the check runs and says it skipped
+ # that.
+ run: pip install pyyaml pillow
- name: Check front matter and cross-references
run: bin/check-content
diff --git a/bin/check-content b/bin/check-content
index 9e00df06..059a1948 100755
--- a/bin/check-content
+++ b/bin/check-content
@@ -4,7 +4,7 @@
Catches the mistakes that a Hugo build does not: a person id that does not
match its filename, a duplicate id, a page that lists a person or sponsor id
with no page behind it, a declared photo with no file behind it, and a
-remote photo_url.
+remote photo_url. It warns about a person photo with no colour in it.
Exit code 1 if any error is found. Warnings do not fail the build.
@@ -20,6 +20,15 @@ import sys
import yaml
+# Pillow is the library bin/square-photos needs, and pr.yml installs it for
+# this check. A machine without it still runs every other check: the colour
+# check reports once that it did not run, so the gap is visible and not an
+# error.
+try:
+ from PIL import Image, ImageChops, ImageStat
+except ImportError:
+ Image = None
+
ROOT = pathlib.Path(__file__).resolve().parent.parent
CONTENT = ROOT / "content"
# Person photos moved from static/ to the theme assets so Hugo can process
@@ -197,13 +206,59 @@ def check_photos(people):
f"than 800. Run bin/square-photos.")
if min(width, height) < PHOTO_SIDE:
small.append((photo, (width, height)))
+
+ saturation = photo_saturation(found)
+ if saturation is not None and saturation < PHOTO_MIN_SATURATION:
+ warn(path, f"photo '{photo}' is black and white (colour "
+ f"{saturation:.1f}, under {PHOTO_MIN_SATURATION}). It "
+ f"looks like the others on a screen that greys them on "
+ f"hover, and grey on a phone and in the modal, where "
+ f"the others are in colour. Ask for a colour photo.")
report_small(small)
+ if Image is None and people:
+ note("Pillow is not installed, so the black and white photo check did "
+ "not run: pip install pillow")
PHOTO_SIDE = 400
PHOTO_MAX_SIDE = 1200
PHOTO_MAX_BYTES = 1_000_000
+# Mean of max(r,g,b) - min(r,g,b) per pixel, 0 to 255, over a 64px thumbnail.
+# Measured on the 130 photos of October 2026, ten score 0.01 or less and the
+# next one 9.5, so any value from 1 to 9 splits the two groups. 4 keeps the
+# grey group clear of JPEG chroma noise, which reached 0.01, and leaves the
+# muted colour photo nearest the line, at 9.5, more than twice that margin.
+PHOTO_MIN_SATURATION = 4
+
+
+def photo_saturation(path):
+ """Return the mean colour of a photo, or None when it cannot be measured.
+
+ The person cards grey every photo with a CSS filter on a device that can
+ hover, so a photo that is already black and white looks like the others
+ there. On a phone and in the modal nothing greys them, and that photo is
+ the one grey face in a wall of colour. Only the person can fix it, with
+ another photo, so this is a warning and never an error.
+
+ Two of the ten grey photos are stored as greyscale; the other eight are
+ RGB JPEGs with no colour in them, which no header can tell from a colour
+ photo. So the pixels are read, through a 64px thumbnail: Pillow decodes a
+ JPEG at a fraction of its size for that, and the 130 photos add about
+ 0.7 s to the run, 0.4 s to 1.1 s.
+ """
+ if Image is None:
+ return None
+ try:
+ with Image.open(path) as image:
+ image.thumbnail((64, 64))
+ red, green, blue = image.convert("RGB").split()
+ except (OSError, ValueError):
+ return None
+ high = ImageChops.lighter(ImageChops.lighter(red, green), blue)
+ low = ImageChops.darker(ImageChops.darker(red, green), blue)
+ return ImageStat.Stat(ImageChops.difference(high, low)).mean[0]
+
def report_small(small):
if not small:
From 97e461735c0acbd06acaa97fc8b87420b08ab6b0 Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 11:42:24 +0200
Subject: [PATCH 27/39] Warn, not fail, when a site URL carries a query
The rule was written for the three profile fields, where a query is
always what the browser added: one LinkedIn value carried a lipi
parameter that named the search session it was copied from. A site is
any address, and there the query can be the address. A sponsor links to
empleos-barcelona?q=python, and without it the link lands on every job
in Barcelona rather than the Python ones, which is not what the sponsor
is paying for.
An error on a profile field, a warning on a site, so tracking in a site
is still visible without failing the build.
---
bin/check-content | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/bin/check-content b/bin/check-content
index 059a1948..7edc9a61 100755
--- a/bin/check-content
+++ b/bin/check-content
@@ -326,7 +326,15 @@ def check_social(people, sponsors):
if site:
site = str(site).strip()
if "?" in site:
- error(path, f"site carries query parameters: '{site}'")
+ # A warning here, an error on the three profile fields. A
+ # profile URL never needs a query, so one is always the
+ # tracking the browser added. A site is any address, and the
+ # query can be the address: a sponsor links to
+ # empleos-barcelona?q=python, and without the query the link
+ # lands on every job in Barcelona rather than the Python ones.
+ warn(path, f"site carries query parameters: '{site}'. "
+ f"Keep them only if they are part of the "
+ f"address, not tracking the browser added.")
elif not site.startswith(("https://", "http://")):
error(path, f"site is '{site}', which is not an http or https URL")
else:
From de96d674c2b06c7f7a495cd5aa998b8fe37ac218 Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 11:49:27 +0200
Subject: [PATCH 28/39] Lay the modal out as a photo column and a text column,
capped at 900px
The photo was a flex item of the header only, beside the name, the role
and the bio, and the sections ran full width under it. The header is
three short lines, so the photo stood over a gap that the first section
had to clear. The body is now two columns: the photo on the left,
everything else on the right, top to bottom, and nothing runs under the
photo.
The photo is 300px, half again the 200px of before, and never larger
than the short side of its source: image_square.html enlarges a small
source to 400px for the grid, and 21 of the photos are under 300px, so
at 300px they would be soft next to the name. The column is as wide as
the photo, so a 200px photo leaves the room to the text.
The modal was 70% of the window: 1006px at 1440px, where a line of text
ran 650px and the foot of the modal was blank to the right of the
social links, and a percentage of a 2560px screen is wider still. The
cap is now 900px, from the content: the 300px photo column and its 20px
gap, a 548px text column and the body padding. The text column holds
the longest line the modal renders in one line, the 498px event line
behind its list indent, and is about 65 characters of the body font.
On a phone the columns stack and the photo is capped at 200px, so the
name stays on the first screen. The close button is positioned, because
a flex body ignores Bootstrap's float and would make it the first item
of the row, and its clearance sits on the title, the one line that
reaches that corner, so the lists get the whole column. A link text is
one unbroken string, and one LinkedIn path is 600px of percent-encoded
emoji: it breaks where it has to instead of running out of the modal.
The bio is a section with a heading, like the description and the lists
under it, and it is left out when the person has none, heading and all.
It was a line of the header with a bold "Bio:" label, the one block of
the modal with a label of its own kind. One "About" section for the
bio, the description and the links was the other option. It would mix
prose and a list under one heading, and 14 people have neither text, so
it would have to decide what to show over the links alone.
The links section is called Social Links: the modal links to event
pages and to the organizers pages as well, and "Links" alone did not
say which of them the last section held.
The event and social link lists are marked as lists. Both dropped the
marker and the padding, so five events were five loose lines with
nothing to say they were one list. One rule on the section lists gives
both a disc marker and the indent that goes with it, the width of the
marker and a space, so the two lists read the same.
On an event line, bold carries the roles and italic the words that join
them, "and" and "at". The role was italic and "at" plain, which read as
emphasis on the role and left "Mentor and Speaker" as one italic run
where the "and" looked like part of a role name. Now a reader can pick
the role out of the line.
---
themes/pybcn_theme/assets/scss/people.scss | 197 ++++++++++++------
.../layouts/partials/people_summary.html | 95 ++++++---
.../layouts/partials/person_appearances.html | 11 +-
.../layouts/partials/person_links.html | 6 +-
4 files changed, 205 insertions(+), 104 deletions(-)
diff --git a/themes/pybcn_theme/assets/scss/people.scss b/themes/pybcn_theme/assets/scss/people.scss
index 78d6670e..7ef5e864 100644
--- a/themes/pybcn_theme/assets/scss/people.scss
+++ b/themes/pybcn_theme/assets/scss/people.scss
@@ -306,58 +306,89 @@
.modal {
.modal-dialog {
- max-width: 70%;
-
- // Who the person is: the photo on the left, the name,
- // the role and the short bio beside it. A flex row and
- // not a float: the photo used to float at 400px beside
- // everything that followed, so a short modal wrapped
- // its last links under the photo and a long one put
- // the section headings against it, each at a different
- // height. The row ends where the text ends, and the
- // sections below run the full width.
- .person_head {
+ // 900px, from the content and not from the window: the
+ // 300px photo column and its 20px gap, a 548px text
+ // column, and the 16px of body padding each side. The
+ // text column holds the longest line the modal renders
+ // in one line, the 498px event line "Mentor and
+ // Organizer at Hands-on Django with PyLadiesBCN (2022)"
+ // behind its 20px list indent, and is about 65
+ // characters of the body font, a comfortable measure
+ // for a bio paragraph. The old cap was 70% of the
+ // window: 1006px at 1440px, where a line of text ran
+ // 650px and the foot of the modal was blank to the
+ // right of the social links, and a percentage of a
+ // 2560px screen is wider still. Under 900px the dialog
+ // fits the window, as a max-width does.
+ max-width: 900px;
+
+ // Two columns: the photo on the left, everything else
+ // on the right. The photo used to sit in the header
+ // only, beside the name, the role and the bio, with
+ // the sections running full width under it: three
+ // short lines beside a 200px photo left a gap under
+ // the photo that the first section had to clear. The
+ // right column now holds the sections too, so nothing
+ // runs under the photo whatever the length of the text.
+ .modal-body {
display: flex;
align-items: flex-start;
- // 200px, the size the card shows the same photo
- // at. The 400px of before was a quarter of the
- // modal and the only thing a reader saw at first.
- // The 400px file stays as the 2x image.
- img {
- flex: 0 0 200px;
- width: 200px;
- height: 200px;
- margin-right: 20px;
+ // Bootstrap floats the close button, and a flex
+ // container ignores floats: the button would become
+ // the first item of the row and push the photo
+ // right. It sits in the corner instead, where the
+ // float put it, at the body padding.
+ .close {
+ position: absolute;
+ top: 1rem;
+ right: 1rem;
}
+ }
- // min-width: 0 lets a long name wrap instead of
- // pushing the row wider than the modal: a flex
- // item is as wide as its longest word by default.
- .person_identity {
- min-width: 0;
- }
+ // The photo column is as wide as the photo and no
+ // wider: 300px, or the short side of a smaller source
+ // (see people_summary.html), so a 200px photo leaves
+ // the room to the text and not to a blank strip. 300px
+ // is a third of the dialog on a wide screen, half again
+ // the 200px of before, which was the card's size and
+ // small next to the text, and under the 400px that was
+ // a quarter of the modal and the only thing a reader
+ // saw at first. The 400px file serves it at 1x and the
+ // 800px file at 2x.
+ .person_photo {
+ flex: 0 0 auto;
+ margin-right: 20px;
+ }
- .modal-title {
- margin-bottom: 2px;
- }
+ // min-width: 0 lets a long name wrap instead of
+ // pushing the column wider than the modal: a flex
+ // item is as wide as its longest word by default.
+ .person_main {
+ flex: 1 1 auto;
+ min-width: 0;
+ }
- // Italic and plain, as on the card, so the pair
- // under the photo reads the same in both places.
- .person_role {
- font-style: italic;
- margin-bottom: 8px;
- }
+ // The right padding keeps the name clear of the close
+ // button, which no longer floats beside it. On the
+ // title only: the lists below do not reach that
+ // corner and get the whole column.
+ .modal-title {
+ margin-bottom: 2px;
+ padding-right: 24px;
+ }
- .person_bio {
- margin-bottom: 0;
- }
+ // Italic and plain, as on the card, so the pair
+ // under the photo reads the same in both places.
+ .person_role {
+ font-style: italic;
+ margin-bottom: 8px;
}
// Every block of the modal below the name is a section
- // with a heading: Description, Roles at PyBCN, Events,
- // Links. The modal used to be a stack of blocks with no
- // label, so a reader had to guess that a bold word was
+ // with a heading: Bio, Description, Roles at PyBCN,
+ // Events, Social Links. The modal used to be a stack of
+ // blocks with no label, so a reader had to guess that a bold word was
// a role and a list of years was a history. A section
// is left out when it is empty, heading and all, so the
// rule sits on the section and not on the block inside.
@@ -407,13 +438,19 @@
}
}
- // The events, one line per event, newest first, the
- // role in italics before the linked title. A plain
- // list: the bullet would say nothing the date order
- // does not. See person_appearances.html.
- .events {
- list-style: none;
- padding: 0;
+ // The two lists of the modal, the events and the
+ // social links, with one treatment: a disc marker and
+ // the indent that goes with it, so each reads as a
+ // list. Both used to drop the marker and the padding,
+ // and five events were five loose lines with nothing
+ // to say they were one list, under a heading styled
+ // like the one over a table. The indent is the width
+ // of the marker and a space, no more: the browser
+ // default of 40px pushed a list in from the headings.
+ .modal_section ul {
+ list-style: disc;
+ padding-left: 1.25em;
+ // The section above sets the gap.
margin: 0;
li {
@@ -421,6 +458,10 @@
}
}
+ // The events, one line per event, newest first, the
+ // role before the linked title. See
+ // person_appearances.html.
+
// The links of the card, listed with their text at the
// foot of the modal, so a reader can see the handle or
// the host without leaving the page. This is the only
@@ -428,13 +469,14 @@
// the name said the same thing with less. See
// person_links.html.
.modal_links {
- list-style: none;
- padding: 0;
- // The section above sets the gap.
- margin: 0;
-
- li {
- margin-bottom: 4px;
+ // A link text is one unbroken string, the path of
+ // a LinkedIn profile or a site address, and one of
+ // them is 600px of percent-encoded emoji. A string
+ // with no space does not wrap on its own, and at
+ // the 548px of the text column it ran out of the
+ // modal. It breaks where it has to instead.
+ a {
+ overflow-wrap: anywhere;
}
// One column for the icon whatever its width, so
@@ -468,23 +510,40 @@
.modal-dialog {
max-width: 100%;
- // A 200px photo beside the name leaves 140px of a
- // 390px screen for the title, which breaks a name
- // one word to a line. At 120px the photo is still
- // a face and the name has room. The title comes
- // down with it: at Bootstrap's 28px a three-word
- // name next to the photo took three lines.
- .person_head {
+ // The columns stack: the photo on top, the text
+ // under it. Side by side, a 300px photo left 50px
+ // of a 390px screen for the text, and the 120px
+ // photo the modal used beside the name left the
+ // name wrapping one word to a line. Stacked, the
+ // photo is capped at 200px so the name is still on
+ // the first screen: at 300px the first section
+ // started half way down it. The title comes down
+ // too: at Bootstrap's 28px a three-word name took
+ // three lines of a 374px dialog.
+ .modal-body {
+ flex-direction: column;
+ }
+
+ .person_photo {
+ margin: 0 0 12px;
+
img {
- flex-basis: 120px;
- width: 120px;
- height: 120px;
- margin-right: 12px;
+ max-width: 200px;
}
+ }
- .modal-title {
- font-size: 1.4rem;
- }
+ .person_main {
+ // The column is as wide as the dialog, not as
+ // wide as its content, so a list does not run
+ // past the edge.
+ width: 100%;
+ }
+
+ .modal-title {
+ font-size: 1.4rem;
+ // No close button beside the first line any
+ // more: it is above the photo.
+ padding-right: 0;
}
// The roles stack on a phone: the label column is
diff --git a/themes/pybcn_theme/layouts/partials/people_summary.html b/themes/pybcn_theme/layouts/partials/people_summary.html
index 2af0fd2b..5476a568 100644
--- a/themes/pybcn_theme/layouts/partials/people_summary.html
+++ b/themes/pybcn_theme/layouts/partials/people_summary.html
@@ -3,9 +3,17 @@
Photos come from assets/images/people/ and go through the Hugo image
pipeline. The grid slot is 350 px wide at most and the modal shows the
- image at 200 px, so one 400 px WebP serves both, with an 800 px variant
+ image at 300 px, so one 400 px WebP serves both, with an 800 px variant
for a 2x screen. A person with no photo falls back to anon_member.png.
+ The modal shows the photo no larger than the source. image_square.html
+ enlarges a small source to 400 px for the grid, where every slot has to
+ be one size, and bin/check-content warns about the 28 photos that are
+ under 400 px. At 300 px the modal would show 21 of them enlarged by half
+ again, soft, next to a name. The modal has no slot to fill, so a photo
+ with a short side under 300 px is shown at its own size instead: a
+ 200 px source is a 200 px photo, which is what the modal showed before.
+
Arguments:
person the person page
role optional, the role to show instead of pybcn_position, when
@@ -29,7 +37,11 @@
{{- $img = resources.Get "images/anon_member.png" -}}
{{- end -}}
{{- $small := "" -}}{{- $large := "" -}}{{- $srcset := "" -}}
+{{- /* The side the modal shows the photo at: 300 px, or the short side of
+ the source when that is smaller. See the note at the top. */ -}}
+{{- $shown := 300 -}}
{{- with $img -}}
+ {{- $shown = int (math.Min 300 (math.Min .Width .Height)) -}}
{{- $anchor := default "Smart" $.person.Params.photo_anchor -}}
{{- $small = partial "image_square.html" (dict "img" . "size" 400 "anchor" $anchor) -}}
{{- $large = partial "image_square.html" (dict "img" . "size" 800 "anchor" $anchor) -}}
@@ -78,39 +90,56 @@
- {{/* Who the person is: the photo, the name, the role on
- this page and the short bio, as one block. The rest
- of the modal is a column of labelled sections:
- Description, Roles at PyBCN, Events, Links. The
- modal used to be a stack with no label and the
- photo floated beside all of it, so the last lines
- wrapped under the photo wherever the text ran out. */}}
-
- {{/* alt is empty here: the name is in the modal heading next to it. */}}
-
-
- {{/* The name only. The links used to sit next to it as
- bare icons, which repeated the list at the foot of the
- modal, where each one also says where it goes. */}}
-
{{ $.person.Params.name }}
- {{/* Italic under the name, as on the card, so the pair
- reads the same in both places. Most speakers have
- no position, and the line used to print empty. */}}
- {{ with $role }}
{{ . }}
{{ end }}
- {{/* The label tells the short bio from the description
- below: both are free text about the person, and
- without it a reader could not say what either was. */}}
- {{ with $.person.Params.short_bio }}
Bio: {{ . | markdownify }}
{{ end }}
-
+ {{/* Two columns: the photo on the left, everything else
+ on the right, top to bottom. The photo used to be a
+ flex item of the header only, beside the name, the
+ role and the bio, and the sections ran full width
+ under it. A header is three short lines, so the
+ photo stood over an empty gap that the first section
+ then had to clear. Nothing goes under the photo now:
+ the sections are part of the right column. On a
+ phone the columns stack (see people.scss). */}}
+
+ {{/* alt is empty here: the name is in the modal heading next to it.
+ width and height are the shown size, not the file's, so
+ the browser lays out the right box before the image loads. */}}
+
+
+
+ {{/* The name only. The links used to sit next to it as
+ bare icons, which repeated the list at the foot of the
+ modal, where each one also says where it goes. */}}
+
{{ $.person.Params.name }}
+ {{/* Italic under the name, as on the card, so the pair
+ reads the same in both places. Most speakers have
+ no position, and the line used to print empty. */}}
+ {{ with $role }}
{{ . }}
{{ end }}
+ {{/* The bio and the description are two sections, one
+ heading each, like the sections under them. The bio
+ used to be a line of the header with a bold "Bio:"
+ label, the one block of the modal with a label of
+ its own kind. Both are free text about the person,
+ and a heading tells them apart as the label did. One
+ "About" section for both, with the links, was the
+ other option: it would mix prose and a list under
+ one heading, and 14 people have neither text, so it
+ would have to decide what to show over the links
+ alone. Each section is left out when it is empty. */}}
+ {{ with $.person.Params.short_bio }}
+
+
diff --git a/themes/pybcn_theme/layouts/partials/person_appearances.html b/themes/pybcn_theme/layouts/partials/person_appearances.html
index e6f95634..c542a254 100644
--- a/themes/pybcn_theme/layouts/partials/person_appearances.html
+++ b/themes/pybcn_theme/layouts/partials/person_appearances.html
@@ -11,6 +11,8 @@
Mentor and Speaker at Hands-on Django with PyLadiesBCN (2022)
Organizer at PyDay BCN (2021)
+ In the events the roles are bold and "at" and "and" italic.
+
Argument: the person page.
The index comes from appearances_index.html, built once per build.
@@ -102,7 +104,14 @@
Roles at PyBCN
Events
{{- range sort . "key" }}
-
{{ delimit .labels ", " " and " }} at {{ .title }}
+ {{- /* Bold carries the roles and italic the words that join them,
+ "and" and "at", so a reader can pick the role out of the line
+ and the joining words stay in the background. The role used to
+ be italic and "at" plain, which read as emphasis on the role
+ and left "Mentor and Speaker" as one italic run where the
+ "and" looked like part of a role name. */ -}}
+ {{- $labels := .labels }}
+
{{ range $i, $label := $labels }}{{ if $i }}{{ if eq $i (sub (len $labels) 1) }} and {{ else }}, {{ end }}{{ end }}{{ $label }}{{ end }} at{{ .title }}
{{- end }}
diff --git a/themes/pybcn_theme/layouts/partials/person_links.html b/themes/pybcn_theme/layouts/partials/person_links.html
index cf26c2e1..cb94f3d8 100644
--- a/themes/pybcn_theme/layouts/partials/person_links.html
+++ b/themes/pybcn_theme/layouts/partials/person_links.html
@@ -17,11 +17,15 @@
https://x.com/. Cutting the known prefix is therefore safe, and
it keeps a second copy of the handle out of the front matter, where
it would drift from the URL. A site is a free URL and is shown whole.
+
+ The heading says "Social Links", not "Links": the modal links to event
+ pages and to the organizers pages as well, and "Links" alone did not say
+ which of them this list held.
*/ -}}
{{- $p := .Params -}}
{{- if or $p.linkedin $p.github $p.twitter $p.site -}}
-
From a0d3756abc931ec1c6ffbf9ddf38ffcb6fa4fc38 Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 11:55:11 +0200
Subject: [PATCH 29/39] Refuse an http link, and move the last two to https
A link published over http invites a reader to follow it in the clear,
and the site it points at is not ours to make safe. The check now fails
on one rather than warning.
Two values moved. content/sponsors/tecnologas.md had the only http site
field, which nothing checked until the sponsor field was renamed from
web to site. content/people/ifosch.md had one inside a short bio, which
no field check sees: Hugo turns a bare URL in that text into a real
anchor, so the page carried an http link that no rule covered.
Neither domain resolves any more, over http or https: tecnologas.org and
entredevyops.es have no A record and no NS record at all. The links were
already broken, and David's standing decision is to leave a dead link
alone because we cannot know whether its owner will fix it. What changes
is that we no longer publish it insecurely.
---
bin/check-content | 10 +++++++++-
content/people/ifosch.md | 2 +-
content/sponsors/tecnologas.md | 2 +-
3 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/bin/check-content b/bin/check-content
index 7edc9a61..85870415 100755
--- a/bin/check-content
+++ b/bin/check-content
@@ -342,7 +342,15 @@ def check_social(people, sponsors):
error(path, f"site ends with a slash: '{site}'. "
f"Use '{site.rstrip('/')}'.")
if site.startswith("http://"):
- warn(path, f"site is served over http, not https: '{site}'")
+ # An error, not a warning. A link we publish over http is
+ # one we invite a reader to follow in the clear, and the
+ # site it points at is not ours to make safe. If https
+ # does not answer, that is for its owner to fix, and the
+ # link stays broken rather than insecure.
+ error(path, f"site is served over http, not https: "
+ f"'{site}'. Use https, and if the site does "
+ f"not answer over https, that is for its "
+ f"owner to fix.")
def check_logos(sponsors):
diff --git a/content/people/ifosch.md b/content/people/ifosch.md
index 9994340d..f6f28884 100644
--- a/content/people/ifosch.md
+++ b/content/people/ifosch.md
@@ -1,7 +1,7 @@
---
id: ifosch
name: Ignasi Fosch
-short_bio: UN*X Sysadmin and Infra automation with Ruby at Devex, Python and Go developer at home and blogger at http://entredevyops.es
+short_bio: UN*X Sysadmin and Infra automation with Ruby at Devex, Python and Go developer at home and blogger at https://entredevyops.es
photo: ignasi-fosch.jpg
pybcn_position: Organizer
diff --git a/content/sponsors/tecnologas.md b/content/sponsors/tecnologas.md
index 09314b50..0b59b681 100644
--- a/content/sponsors/tecnologas.md
+++ b/content/sponsors/tecnologas.md
@@ -2,5 +2,5 @@
id: tecnologas
name: TECNOLOGAS.ORG
logo_image: tecnologas.png
-site: http://tecnologas.org
+site: https://tecnologas.org
---
From d23451c789bddbe53a0c6dcfd1719155364d14c6 Mon Sep 17 00:00:00 2001
From: David Arcos
Date: Tue, 6 Oct 2026 12:05:45 +0200
Subject: [PATCH 30/39] Move the last six http links to https, and fail the
rendered check on any
bin/check-content refuses an http value in a site field, and it stops
there: a URL written inside prose or inside raw HTML in a content file
is not a field. One short_bio ended with a bare http URL, Hugo turned it
into a live anchor, and the page shipped an insecure link that no field
rule could see. The built site still carried six more: three on the
PyData 2017 page, the Pytorch guide on PyDay 2018, the Meetup
registration redirect on PyDay 2022 (written twice), and the PyLadies
parent site on the PyLadies about page.
Each host answers over TLS: 200 for the blog, pydata.org, slides.com and
pyladies.com, 403 for esade.edu (a bot block, not a TLS failure), and
404 for the bare clicks.meetup.com root, which shows the host serves
https even though the full tracking path was not requested. Only the
scheme changes: host, path, query and fragment are as they were.
The clicks.meetup.com URL is a newsletter tracking redirect with a
per-recipient token in its query. It keeps its scheme change here and
nothing else; whether to replace it with its destination is a separate
decision.
The built page is the one place where that class is visible whatever
printed it, so the rule now lives in bin/check-rendered. Every attribute
in URL_ATTRIBUTES counts the same, href and src alike, plus a meta
refresh and a url() in an inline style. What the browser does with each
differs (mixed content blocked, a reader sent out in the clear), the fix
does not, so one kind and one severity. The rule rides the attribute
walk and split_url that already exist, and costs about 0.02 s on the
108-page build.
A localhost or 127.0.0.1 address is reported under the same kind with a
note: https would not make it reachable, the fix is to remove the link.
An error with no allowlist entry. This site publishes no insecure link;
when a host does not answer over https its owner has to fix it, and the
message says so.
archives/ is exempt from this one rule, through INSECURE_EXEMPT. Those
56 pages are frozen copies of retired sites and their 132 http URLs are
part of the record. The rest of the check still reads them. An allowlist
entry would have printed two lines per URL on every run; the report
prints one line with the count instead.
---
bin/check-rendered | 80 ++++++++++++++++++-
.../other_events/pydata_2017_barcelona.md | 4 +-
content/events/pyday_bcn/pyday_bcn_2018.md | 2 +-
content/events/pyday_bcn/pyday_bcn_2022.md | 4 +-
content/pyladies_bcn/about.md | 2 +-
5 files changed, 83 insertions(+), 9 deletions(-)
diff --git a/bin/check-rendered b/bin/check-rendered
index 4713401e..ed66dfbd 100755
--- a/bin/check-rendered
+++ b/bin/check-rendered
@@ -22,6 +22,7 @@ reports:
from or navigates to (href, src, srcset, action, formaction, poster and
the rest of URL_ATTRIBUTES), in a meta refresh, and in a url() of an
inline style
+ - an http:// URL in any of those same places, see "Insecure URLs" below
- a