Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@
# instructions. These carry legal and financial statements.
/content/pybcn_association/ @pybcn/web

# The code of conduct itself. The page under content/pybcn_association/
# renders this file through the repo-markdown shortcode, so the legal text
# lives at the root and not in content/, and the rule above does not reach it.
/CODE_OF_CONDUCT.md @pybcn/web

# The custom domain of the GitHub Pages site. A change to this file points
# pybcn.org somewhere else.
/CNAME @pybcn/web
Expand Down
35 changes: 35 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Code of Conduct

PyBCN is dedicated to providing a respectful, harassment-free community for
everyone. We do not tolerate harassment or bullying of any community member in
any form. This does not only extend to members to local PyBCN communities,
but to anyone who chooses to become involved in the larger PyBCN community of
users, developers and integrators through events or interactions.

Harassment includes offensive verbal/electronic comments related to personal
characteristics or choices, sexual images or comments in public or online
spaces, deliberate intimidation, bullying, stalking, following, harassing
photography or recording, sustained disruption of talks, IRC chats, electronic
meetings, physical meetings or other events, inappropriate physical contact, or
unwelcome sexual attention. Participants asked to stop any harassing or
bullying behavior are expected to comply immediately.

If a participant engages in harassing behavior, representatives of the
community may take reasonable action they deem appropriate, including warning
the offender, expulsion from any PyBCN event, or expulsion from mailing
lists, IRC chats, discussion boards and other electronic communications
channels to resolve the issue. This may include expulsion from PyBCN Meetup
group membership.

If you are being harassed, notice that someone else is being harassed, or have
any other concerns, please act to intercede or ask for help from any member of
the PyBCN community, IRC chat admins, website admins, or
organizers/representatives of any physical events put on under the auspices of
PyBCN.

This Code of Conduct has been adapted from the
[PyLadies](https://www.pyladies.com/CodeOfConduct/) one, which is licensed
under a
[Creative Commons Attribution-Share Alike 3.0 Unported license](https://creativecommons.org/licenses/by-sa/3.0/),
and is licensed under a
[Creative Commons Attribution-ShareAlike 4.0 International license](https://creativecommons.org/licenses/by-sa/4.0/).
127 changes: 127 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# Contributing to the PyBCN site

This repository holds the source of [pybcn.org](https://pybcn.org/), the site
of the Python Barcelona association, built with [Hugo](https://gohugo.io). A
change goes through a pull request against the `edition` branch, and this
guide says how. The [README](README.md) documents the site itself: the content
fields, the layouts, and what each check looks for.

## Code of conduct

The PyBCN [Code of Conduct](CODE_OF_CONDUCT.md) applies to every contribution:
a pull request, an issue, a review, and the discussion around them. It is the
same text the site publishes at
[pybcn.org/pybcn_association/coc/](https://pybcn.org/pybcn_association/coc/),
which renders that file.

## Licence

The code of the site is under the [MIT License](LICENSE) and the content is
under [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/).
[LICENSING.md](LICENSING.md) says which paths each one covers, and which paths
are not licensed at all: the photographs of people, the person pages, the
sponsor logos, the association's own logos, the third-party libraries, and the
archived sites.

A pull request is a contribution under those terms. A change to a template, a
script, or a stylesheet is offered under the MIT License, and a change to the
text of a page is offered under CC BY-SA 4.0. Your own page under
`content/people/` and your photo are different: you keep every right in them,
and you give PyBCN permission to publish them on this site, which you can
withdraw.

## Which branch

Open the pull request against `edition`. It is the default branch and it holds
the source. `master` holds the built site: the `github-pages` workflow writes
it on every merge to `edition` and replaces its history each time, so nothing
is edited there, and a change made on `master` is lost on the next deploy.

## Add content without writing code

Most changes to this site are content: a person, a sponsor, an event. Each one
is a Markdown file with a front matter, and the README documents the fields.
Edit the file on GitHub, or clone the repository and follow the steps below.

- **A person** (an organizer, a speaker, a mentor): copy a file under
`content/people/` and edit it. The front matter carries `id`, which has to
match the file name, `name`, `photo`, the role at PyBCN, and the links to
the person's own profiles. The bio goes in the body. Leave out any field the
person does not have. The photo goes under
`themes/pybcn_theme/assets/images/people/` and has to be square, see
[Person photos](README.md#person-photos).
- **A sponsor**: run `bin/hugo new sponsors/my-sponsor.md` and fill the four
fields listed in [How to add a new sponsor](README.md#how-to-add-a-new-sponsor).
The logo goes under `themes/pybcn_theme/assets/images/sponsors/`. Then list
the sponsor on the sponsors page, or on the event, that shows it.
- **An event**: copy the previous edition under `content/events/`, for example
`content/events/pyday_bcn/pyday_bcn_2025.md`, and edit it. The sections, the
agenda and the people grids are described in
[Event page](README.md#event-page). An event lists its people and sponsors by
their `id`, so add those files first.

`bin/check-content` reads every person, sponsor and event file. The pull
request fails when a field is empty, an `id` does not match the file name, a
declared photo is missing, or an event names a person or a sponsor that does
not exist. Run it locally, step 5 below, to see what it would say.

To report a problem with the site, open an issue and give the URL of the page.

## Make the change

Nothing is pushed to `edition` directly.

1. Clone the repository. `git clone --single-branch --branch edition` is enough
and skips the built site, which lives on its own branch.
2. Run `bin/install`. It downloads the pinned Hugo binary into `bin/hugo` and
verifies its checksum. You do not need Python, Go, or npm for this step.
3. Run `bin/serve` to see the site at `http://localhost:1313` while you work.
4. Make the change.
5. Run the three checks locally, so you find what the pull request would find:

```
pip install pyyaml pillow
bin/check-content
bin/check-html-safety
bin/hugo --minify -D -d public && bin/check-rendered
```

Pillow is only needed for the black and white photo check. Without it the

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should this be updated after the merge of #206? After all, Pillow is needed for the fit-sources script

rest still runs and the check says it was skipped, so a missing Pillow
never fails a build for the wrong reason.

6. Open the pull request against `edition`.

## What the pull request goes through

The `pr-checks` workflow runs the same checks on your branch, plus a build and
a link check. **All of them have to pass**, and one approving review is needed
before the pull request can be merged.

What each check is for:

| Check | Fails when |
|---|---|
| Build the site | Hugo cannot build, or emits a warning |
| `bin/check-content` | Front matter does not parse, a person `id` does not match its filename, an id is duplicated, a declared photo is missing, an event references a person or sponsor that does not exist, a social URL has the wrong shape, or a field is empty. It warns, without failing, about a photo that is too small or has no colour |
| `bin/check-html-safety` | Content carries raw HTML that turns a content change into script execution, a redirect, a credential prompt, or a page overlay. See [Content safety check](README.md#content-safety-check) |
| `bin/check-rendered` | The built pages carry that same markup, which catches a template that produces it even when no content file does, or they link to anything over `http`. See [Rendered page check](README.md#rendered-page-check) |
| Check the links | Reported, never blocking, because external sites rate-limit |

A merge to `edition` deploys the site. The `github-pages` workflow builds it and
publishes the result, so a change is live within a few minutes of the merge.

## Review by the web team

`.github/CODEOWNERS` lists the paths where a change reaches every page of the
site, or reaches money, or reaches the deploy: `.github/`, `bin/`,
`config.toml`, `layouts/`, `static/`, `themes/`, `CNAME`, the association
pages under `content/pybcn_association/`, `CODE_OF_CONDUCT.md`, and the
sponsor and event files under `content/sponsors/` and `content/events/`.

A pull request that touches one of those paths requests a review from
`@pybcn/web` automatically, and the branch protection on `edition` requires
it, so the pull request waits until a member of that team approves it. A
person's file under `content/people/` is not on the list on purpose: a speaker
edits their own page and needs no organizer for that, only the one approving
review every pull request needs.
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2013-2026 Associació Python Barcelona (PyBCN) and contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
171 changes: 171 additions & 0 deletions LICENSING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
# Licensing

This repository holds the source of [pybcn.org](https://pybcn.org/), the site
of the Associació Python Barcelona (PyBCN). It holds three kinds of thing, and
one licence does not fit all of them: the code of the site, the text of the
site, and material that the association publishes but does not own. This file
says which licence covers which path, and which paths no licence covers at all.

GitHub reads the licence of a repository from the `LICENSE` file alone, and a
second licence in that file stops the detection. So `LICENSE` holds the MIT
License text and nothing else, and everything else about licensing is here.

## Code: MIT License

The MIT License in [`LICENSE`](LICENSE) covers the code that builds and runs
the site:

- `layouts/`: the Hugo templates and shortcodes of the site.
- `themes/pybcn_theme/`: the theme. Its templates and partials (`layouts/`),
its stylesheets (`assets/scss/`), the scripts written for this site
(`assets/js/`, except `cookieconsent.min.js`, which is a third-party
library, see below), its `archetypes/`, `theme.toml`, and `README.md`. The
images and the vendored libraries under the theme are listed under
[Not licensed](#not-licensed).
- `bin/`: the build, check, and maintenance scripts.
- `.github/`: the workflows, the code owners, and the Dependabot configuration.
- `config.toml`, `archetypes/`, and the other configuration files at the root
(`.gitignore`, `.hugo-version`, `CNAME`).

The copyright line in `LICENSE` names the association and the contributors,
and runs from 2013, the year of the first commit. The theme began as a copy of
the `hugo-theme-bootstrap4-blog` theme, which is also under the MIT License;
its notice stays in `themes/pybcn_theme/LICENSE.txt` and covers what remains
of it.

## Content: CC BY-SA 4.0

The text of the site is licensed under the Creative Commons
Attribution-ShareAlike 4.0 International licence (CC BY-SA 4.0):

- `content/`, except `content/people/`, see [Person pages](#person-pages).
- `README.md` and `CONTRIBUTING.md`.
- `static/humans.txt`.
- `CODE_OF_CONDUCT.md`, an adaptation of the PyLadies code of conduct, see
[Code of conduct](#code-of-conduct) below.

Deed: <https://creativecommons.org/licenses/by-sa/4.0/>

Legal code: <https://creativecommons.org/licenses/by-sa/4.0/legalcode>

Attribute the text to "Python Barcelona (PyBCN), https://pybcn.org/". The
licence requires attribution, a link to the licence, a note of any change, and
the same licence on any adaptation.

The full legal code is not copied here. Creative Commons keeps the canonical
text at the URL above and says a link to it is enough, and a copy in this
repository would be a second licence text at the root, which is what confuses
the detection described above.

### Code of conduct

`CODE_OF_CONDUCT.md` was adapted from the
[PyLadies code of conduct](https://www.pyladies.com/CodeOfConduct/), which is
licensed under
[CC BY-SA 3.0 Unported](https://creativecommons.org/licenses/by-sa/3.0/). The
adaptation is licensed under CC BY-SA 4.0, like the rest of the content, so
the whole repository is on one version of the licence family.

The licence of the original permits that. Section 4(b) of the
[CC BY-SA 3.0 legal code](https://creativecommons.org/licenses/by-sa/3.0/legalcode)
says that an Adaptation may be distributed under "(ii) a later version of
this License with the same License Elements as this License", and section 1
names those elements: "Attribution, ShareAlike". CC BY-SA 4.0 is a later
version of that licence, and its License Elements are Attribution and
ShareAlike. The same section 4(b) requires the notices that refer to the
licence of the original to stay intact, so the file keeps its attribution to
PyLadies and the mention of CC BY-SA 3.0, and adds the link to CC BY-SA 4.0.

ShareAlike is also why the file cannot go under the MIT License: an
adaptation has to stay in the CC BY-SA family, at the same version or a later
one.

## Not licensed

The paths below are published on the site but are not covered by either
licence, because the rights in them are not the association's to give. A
licence that promised more than that would tell people they may do things they
may not.

### Photographs of people

`themes/pybcn_theme/assets/images/people/` holds one photograph per person on
the site, and `themes/pybcn_theme/assets/images/photos/` holds photographs
taken at PyBCN events.

The people on this site sent their own photograph for publication on it.
Anyone who did not want one did not send one, and the site shows a silhouette
instead. The association publishes those photographs with the permission of
the people in them, given for that purpose. That permission is not a licence
for anyone else to reuse a photograph, for two reasons:

- The copyright in a photograph belongs to whoever took it. Giving PyBCN a
copy to publish does not transfer that copyright, so PyBCN has nothing to
sub-license.
- Consent to appear on this site is narrower than a CC BY-SA grant, which
would let a stranger reuse and adapt the image, commercially, for ever.
Under Spanish law (Ley Orgánica 1/1982) the right to one's own image is a
personality right and the consent is revocable, so it cannot become a
perpetual and irrevocable licence, which is what CC BY-SA is.

So the photographs are not licensed. They are published with the permission
of the people in them, and that permission can be withdrawn. The event
photographs are the same case: the photographer keeps the copyright, and the
people in them keep their image rights.

### Person pages

`content/people/` holds one page per person. Each person wrote their own text
and sent it for publication here, so the same reasoning applies: the
association publishes the text, it does not own it, and it cannot license it.

There is a second reason, specific to these pages. A person can ask the
association to erase their page, and the GDPR (Article 17.2) then obliges the
association to take reasonable steps to tell anyone else holding a copy that
erasure was requested. A licence that invites lawful copies of a person's
entry multiplies the copies the association would have to chase, and works
against the erasure it has to be able to deliver.

### Sponsor logos

`themes/pybcn_theme/assets/images/sponsors/` holds the logos of the sponsors.
Each logo is the trade mark of its owner, shown here to acknowledge its
support of PyBCN, with that owner's permission. A trade mark is not the
association's to license, and CC BY-SA 4.0 does not license trade marks in any
case (section 2(b)(2) of the legal code).

### The association's own marks

The PyBCN logo and its variants (`themes/pybcn_theme/assets/images/logo.png`,
`themes/pybcn_theme/assets/images/favicon.png`, `static/favicon.ico`,
`static/favicon.png`, and the files under `static/images/backgrounds/`)
identify the association. They are not covered by the content licence: use
them to refer to PyBCN, not to suggest that PyBCN endorses something it has
not seen. The PyLadies name and logo in that same folder are not the
association's.

### Third-party libraries

Each of these keeps its own licence, and the notice inside each file stays
with it:

- `themes/pybcn_theme/assets/vendor/`: jQuery 3.3.1 (MIT), jQuery Easing
1.4.1 (BSD), Bootstrap 4.0.0 (MIT), and Font Awesome Free 5.8.2 (icons
CC BY 4.0, fonts SIL OFL 1.1, code MIT).
- `themes/pybcn_theme/static/vendor/font-awesome/webfonts/`: the Font Awesome
fonts (SIL OFL 1.1).
- `themes/pybcn_theme/assets/css/bootstrap.min.css`: Bootstrap 4.0.0 (MIT).
- `themes/pybcn_theme/assets/css/cookieconsent.min.css` and
`themes/pybcn_theme/assets/js/cookieconsent.min.js`: the Cookie Consent
library by Osano (MIT).
- `themes/pybcn_theme/assets/images/anon_member.png`: the Font Awesome `user`
icon as a PNG (CC BY 4.0).

### Archived sites

`static/archives/` holds copies of two sites as they were published, made
with `bin/archive`: `pybcn.org/`, the previous site of the association, and
`hacktoberfestbarcelona.com/`, the site of Hacktoberfest BCN 2018. They are
kept as a record and are not maintained. Each carries its own photographs,
logos, fonts, and libraries, so nothing under `static/archives/` is licensed by
this repository.
Loading