About this website
Source of the website of the Canepa Research Lab, caneparesearch.org. The site is built with Jekyll and published through GitHub Pages from a separate and private repository. A HISTORY.md file in the source repository records the site’s milestones and the Cloudflare changes that git does not.
Build the site locally
The repository is private: ask Prof. Canepa for access, then clone it and install the dependencies (Ruby 3 and Bundler; the Jekyll version is pinned in the Gemfile):
git clone [email protected]:caneparesearch/source-care-website.git
cd source-care-website
bundle install
Build the site into _site/ with bundle exec jekyll build, or preview it with bundle exec jekyll serve and open http://127.0.0.1:4000/.
A local preview runs in Jekyll’s “development” environment, which leaves out the upgrade-insecure-requests Content-Security-Policy directive that the live site sends (update.sh builds with JEKYLL_ENV=production). This is expected: sent locally, it would make the browser retry every link over HTTPS against a plain-HTTP server.
Publish
publish.sh commits, pushes and publishes in one step:
./publish.sh "short description of the change" [new-file ...]
It commits the changes to tracked files (brand-new files only if you name them, never .jekyll-cache/), pushes, then runs update.sh with the same message. Add -n for a dry run or -y to skip the confirmation. It runs only on main, and stops before committing if the remote has commits you do not have. The live site is always built from a private snapshot (a temporary git worktree) of main, never from this folder’s files, so a checkout of another branch cannot end up on the live site (that happened once, on 8 October 2026, for about a minute).
update.sh publishes without committing anything. It needs caneparesearch.github.io checked out next to this repository, the aws CLI with access to the carepapers bucket, and jq:
./update.sh "short description of the change"
In turn it:
- pulls this repository (it never pushes it, so push your commits separately);
- regenerates
map.xml, the sitemap of the paper PDFs, in the bucket itself (update_aws_sitemap.sh), where the bucket’srobots.txtlists it, since Google ignores a sitemap of PDFs on another host; - builds the site and dates every address in
sitemap.xmlby its last real edit in git (_scripts/generate-sitemap.rb), ignoring commits that touch more than 30 files as repository-wide sweeps and following renamed files back to their old names; - makes
caneparesearch.github.iomatch_site/exactly (rsync --delete, keeping its.gitand.gitignore), then commits and pushes it.
So a page or image deleted or renamed here disappears from the live site on the next publish (a renamed page keeps working through redirect_from:, see below). It refuses to deploy from a missing or nearly empty _site/, so a failed build cannot wipe the site. After publishing, check that caneparesearch.github.io has a new commit; if it does not, run ./update.sh on its own.
Content
Every page is a Markdown file with a short YAML header. The date at the start of a post’s file name is its post date. Pictures go in images/, in a folder named after the section.
| Section | Location | Header fields |
|---|---|---|
| News | news/_posts/YYYY-MM-DD-short-topic.md |
layout: post, category: news, title, author (first name of a team member), optional image and image_fit: contain |
| Team | team/_posts/<date>-<name>.md |
layout: member, title, position, image, alumni: true for former members, and optional email, profile, profile_label, website, linkedin, github, scholar, orcid, twitter, cv, calendar, aliases, papers, alumni_group (see Team below) |
| Research | research/_posts/ |
layout: post, title, image, order, references, and optional description, image_fit, image_position, image_transparent, splash, short_title, listed and sitemap (see Research pages below) |
| Papers | papers/_posts/<date>-<first-author>-<journal>-<year>.md |
layout: paper, title, authors, journal, year, doi, image, and optional pdf and github |
| Videos | videos/_posts/YYYY-MM-DD-speaker-event.md |
layout: video, title, author, conference, youtubeId |
Addresses and renames
A page’s address is built from its file name, without the date, so a name must be unique and is best left unchanged once the page is out. Keep names lowercase, with words joined by hyphens:
- News: the date it was posted (two-digit month and day), then a few words saying what it is about, for example
2026-09-19-moving-to-purdue.md, at/news/moving-to-purdue/. - Papers:
<date>-<first-author>-<journal>-<year>, with the journal’s ISO 4 abbreviation in hyphens, for example2025-01-30-park-nat-mater-2025.md; addaandbafter the year for two papers by the same first author in the same journal and year. - Team:
<date>-<name>, matching the person’stitle, for example2020-10-25-aaron-tieu.md. - Videos: the talk’s date, the speaker’s surname and the event, for example
2021-04-20-canepa-mrs-seattle.md.
A post’s picture takes the same name as the post: for news, images/news/<name>.jpg for a photo or .png for a graphic or screenshot (a second picture in the text adds -figure); for papers, images/papers/<name>.png; for team members, images/team/<name>.jpg. Research pictures take the name of their page (its file name without the date) and an underscore: images/research/<page>_splash.jpg (or .png) for the page’s own picture, and images/research/<page>_<what-it-shows>.png for a figure in the text, in a few hyphenated words, for example batteries_nasicon-voltage-map.png.
To rename a page, list its old address in its header under redirect_from: (for example - /papers/old-name/), and _plugins/redirect-from.rb writes a redirect there. A rename that changes only letter case (such as /team/Piero-Canepa/ to /team/piero-canepa/) cannot have one: a Mac’s disk ignores case, so the redirect page would be written over the page itself. GitHub Pages tells the two apart, so the 404 page runs js/not-found-redirect.js, which sends a visitor to the lowercase address when that page exists. Every page except the 404 page names its own address in a <link rel="canonical"> (redirect pages name the new one), so search engines count variants such as /papers/?q=… as that page.
News
On the News page every picture is shown in the same 3:2 frame: photos fill it, cropped from the bottom, while logos (images/misc/logo_*, any .svg) and pictures more than twice as wide as tall are shown whole inside it. Add image_fit: contain to show a picture whole as well, for example a logo saved as a .jpg.
Papers
- The PDF is stored in the
carepapersS3 bucket as<year>/<name>.pdfand is public. Setpdf: <year>/<name>.pdf; the site builds the download link from it. - A preprint’s
doion arXiv (10.48550/arXiv.…) shows the arXiv icon and label, and one on ChemRxiv (10.26434/chemrxiv.…) a flask icon and the label “ChemRxiv”, instead of the DOI icon. - Write
authorssurname first,Surname I. I., comma-separated, with “and” before the last one (also after a comma when there are three or more) and your own name in<b>:Xie W., Deng Z., and <b>Canepa P.</b>. The site shows them initials first (“W. Xie, Z. Deng, and P. Canepa”, theinitials_firstfilter in_plugins/initials-first.rb), while the Google Scholar tags, BibTeX, the team pages’ Publications and the Papers search read the stored form. - Write
journalas<i>Journal</i> volume, pages (year), with the ISO 4 abbreviation (except Angewandte Chemie International Edition, writtenAngew. Chem.), no comma after the journal name, an en dash in page ranges and no issue number:<i>Chem. Mater.</i> 33, 5652–5667 (2021). Use<i>Journal</i> (year)while volume and pages are not known, and<i>arXiv</i> (year)or<i>ChemRxiv</i> (year)for a preprint. Keep anything else, such as a book’s ISBN, in a field of its own. - The line under a paper’s title is made from
authorsandjournal; when it would wrap,js/citation-fit.jsshortens the authors to the first ones that fit plus “et al.”, always keeping P. Canepa, with the full list in the tooltip. The short references on the home and Papers pages (A. First et al., <i>Journal</i>) come from the same fields (_includes/paper-ref.html), so the oldreffield is no longer used. - Every paper lists its topics in its header,
topics: [solid-state-batteries, interfaces], by the slugs in_data/topics.yml(Batteries, Lithium, Sodium, Solid-state batteries, Multivalent, Interfaces, Electrochemistry, Organic electroactive materials, Porous frameworks, Method development, Software and data, Optical materials, Other topics)._plugins/paper-topics.rbadds the topics those imply (a battery type adds Batteries, and Batteries adds Electrochemistry), and stops the build on an unknown slug or a paper with none. Software and data is not set by hand: every paper the Software page lists for a code (papersin_data/software.yml) gets it, and its page links to that code. The Papers page shows the topics as filter buttons, combined with the search and kept in the address (/papers/?topic=batteries); a paper’s page lists its topics, and a research page named as a topic’sresearchends with a link to all our papers on it. - The Collaborators page (
papers/collaborators/) draws everyone we have written with as a network, built at every build from the papers’authorsby_plugins/collaborators.rband drawn byjs/collaborators.jswith D3’s force layout, self-hosted injs/vendor/d3-force.min.jsbecause the Content-Security-Policy allows scripts only from this site. Team members are matched as on their team pages (by theirpaperslist, or as “Surname I”); an author written in more than one way (“Cheetham A.” and “Cheetham A. K.”) is merged by a line in_data/collaborator_names.yml. - The search box on the Papers page (
js/paper-filter.js) matches every word typed against each paper’s title, authors, journal (also by its full name, from_data/journals.yml: add a line there for a new journal), year, DOI and abstract. A full name such as “Jean-Noël Chotard” finds “Chotard J.-N.”, a team member is found by their name alone (“Tara”; a team page’saliases:adds other names), and words in double quotes must appear together. The query stays in the address (/papers/?q=sodium), so a filtered list can be shared. The abstracts come frompapers/search.json, built from every paper’s## Abstractsection and downloaded only once the box is used.
Team
- Write a bio in the first person. When a member leaves, set
alumni: true, open the bio with where they are now (“I am now a research scientist at …”), and put finished student or postdoc periods in the past tense; hobbies and current interests stay in the present. Current members are listed most recently added first. Alumni are grouped by the position they held (research fellows, PhD students, master’s students, undergraduate and summer students, then research staff), alphabetically within each group; the group comes fromposition, or fromalumni_group(research-fellows,phd-students,masters-students,undergraduatesorstaff) when the position names a later job, as for Zeyu Deng. - Sidebar links are shown alphabetically by label, whatever their order in the header.
profileis a university profile page, shown as “University profile” (setprofile_labelfor another heading, such as “Institutional profile”);websiteis a personal website;linkedinis the name inlinkedin.com/in/<name>;twitteris the X handle, linked to x.com;scholaris the Google Scholar profile ID (theuser=part of its address). - “Life in the group”, between the current members and the alumni, shows the photos listed in
_data/gallery.yml(its header says how to add one: the picture inimages/gallery/, its smaller copy, a date and a caption), in one horizontal strip, newest first, with the year over the first photo of each year: it is swiped on phones, scrolled sideways elsewhere, andjs/gallery-strip.jsadds arrow buttons wherever there is a mouse or trackpad, whatever the window’s width. Only add a photo everyone recognisable in it is happy to share. - Under Publications, a member’s page lists every paper whose
authorscontain their surname and first initial (“Wang J” for Juefan Wang). When that is shared with other authors, list their papers by address instead,papers: [wang-chem-mater-2021, wang-mater-futures-2023], as Juefan Wang, Yan Li and Yuheng Li have; Crossref (https://api.crossref.org/works/<doi>) gives each author’s full given name, to sort out whose paper is whose.
Research pages
ordersets a page’s place on the Research page (battery topics first), and in the row of research pictures on the home page, which shows the first four; there each title fits on one line, so a longer one needs a shorter form there, inshort_title.referenceslists the addresses of our papers the page cites (/papers/<name>/), in order of first citation;{% include research-refs.html refs=page.references %}lists them under “Relevant references” in the style of the papers’ pages, linked to them, and each citation in the text is a superscript number linked to the same page. A paper from another group, which has no page here, is given asauthors,journalanddoi.- Figures in the text are
<figure class="text-figure">blocks, placed before the paragraph they illustrate: floated right beside it, with their caption under them, and across the column on phones. Number them in order and cite each in the text (“see Figure 1”). Add the classtext-figure-mediumto give a figure 36% of the column instead of 45%, ortext-figure-smallfor 30% (a square or tall figure). Addtext-figure-leftto place a figure on the left of its paragraph instead. - On the Research page each picture fills a 3:2 frame, cropped from the bottom; a picture more than twice as wide as tall, or one whose page sets
image_fit: contain, is shown whole, andimage_position(for examplecenter 40%) moves the crop. A picture on a transparent background (saved as PNG, with a WebP copy that keeps the transparency) takesimage_transparent: true, so it sits straight on the page in dark mode instead of on the white card other pictures get. A page’simagealso shows at the top of the page itself; setsplash: falsewhen it is set in the text as a figure instead. listed: falsewithsitemap: falsekeeps a page at its address but leaves it off the Research page, its Index, the site search and the sitemap, as for Non-linear optics.
Conventions
- The navigation bar lists Research, Papers, Software, Team, News and Join, in that order (what the lab does, its output, its people, then news, and a way in for prospective members); its links are in
_layouts/default.html. The pages inmisc/_posts/are linked from the footer by theirtitle; give one anav_titlefor a shorter label (About) orfooter: falseto leave it out (Join, already in the navigation bar). - Titles and headings are in sentence case, with capitals only for the first word and for proper nouns (“Organic electroactive materials”, “Graduate study at Purdue”); paper titles keep their journal’s capitals, and people’s positions on the Team page (“PhD Student”) keep theirs.
- Dates are shown as “Sept. 19, 2026” everywhere (the
ap_datefilter in_plugins/last-update.rb). - News and research posts show an estimated reading time after their date, as do the About, Join, and Mission and values pages under their title: the words of the text, without its references, at 200 a minute, rounded up (
_includes/reading-time.html). To add it to another page, put<p class="news-author">{% include reading-time.html text=page.content %}</p>after its title block. - Every page gets a
<meta name="description">for search results: its owndescriptionfield, otherwise a paper’s abstract orTalk by <author> at <conference>: <title>for a video, otherwise a post’s first paragraph, otherwise the site tagline in_config.yml, cut to 160 characters. The home page sets its own inindex.html; add adescriptionto any other page whose first paragraph makes a poor summary. Character references in titles and descriptions (:,α) are decoded for link previews by thedecode_entitiesfilter (_plugins/decode-entities.rb).
E-mail addresses
Never write an e-mail address in a page. Use the include instead, which prints “name [at] example.org” and lets js/email-links.js build the mailto: link only while a visitor hovers, focuses or taps it, so the address is in neither the page source nor the loaded page. The member layout does this for a team page’s email field.
{% include email-link.html address="[email protected]" %}
Design
The site is a light layer over a trimmed Bootstrap 5 grid: text set in Inter, colors that follow the visitor’s light or dark setting and meet WCAG AA contrast in both, and every font, icon and script served from the site itself, apart from Google Analytics, the Altmetric and Dimensions badges, and the embedded videos and map. Pages are meant to load quickly on a phone, so pictures are served as WebP with their space reserved, and listing thumbnails load only as they scroll into view. The sections below give the details.
Styles and layout
- Styles are SCSS partials in
css/, compiled intocss/style.css; layouts are in_layouts/and shared snippets in_includes/. - Only the parts of Bootstrap 5 the site uses are compiled in: the
@imports at the top ofcss/style.scss(grid, containers, type, nav, navbar, collapse transitions, breadcrumb, helpers and utilities), which roughly halves the stylesheet. Cards, buttons, forms, dropdowns and modals are left out, so a page that uses one looks unstyled until its import is added there, in the same order asbootstrap.scss. Bootstrap’s JavaScript is not loaded either:js/nav-toggle.jsopens and closes the mobile menu with Bootstrap’scollapseclasses. - Long text fades out instead of stretching its row. Titles fade after two lines on the News page and four in its Index view, with the date and author below always in full (the
fade-linesmixin incss/_variables.scss, which leaves titles whole on phones). On the Papers pagejs/paper-titles.jsfades a title on the last line that keeps the card no taller than its picture (.is-cut), or after five lines without JavaScript. Preview text fades (thefade-boxmixin incss/style.scss) at a fixed height in the news list (.feedbox) and after five lines (six on phones) on the Research page (.feedboxblog). The home page’s Recent news and Recent papers show their two newest items in full. -
The card grids show one, two or three cards a row by window width, so text is not squeezed into narrow columns:
Page Cards a row, by window width Papers one below 992px, two at 992–1399px, three from 1400px; 64px apart Team one below 768px, two at 768–1199px, three from 1200px; 30px apart News, Index view one below 768px, two at 768–1199px, three from 1200px; 30px apart The Papers page switches later because each paper’s text sits beside a 120px picture, so the text is never narrower than about 245px; its wider gap (
.paper-row) keeps each title closer to its own picture than to the next card’s. - On the News, Research and Software pages each picture sits in its own column beside the text, in a 3:2 frame; on phones, Research and Software pictures keep their own proportions, at most 240px wide and 180px tall.
- A “back to top” button (
js/back-to-top.js,.back-to-top) fades in once a page is scrolled past 600px and scrolls smoothly to the top (instantly if the visitor prefers reduced motion); it is added once in_layouts/default.html, so every page has it. - The navbar’s magnifying glass opens a search overlay (
_includes/search-dialog.html,js/search-dialog.js,.search-dialog): one large field with the six best matches under it as you type and a “See all” link when there are more. Enter opens/search/?q=...with every result; Escape, the close button or a click outside closes it. The overlay and the search page share their matching (js/search-core.js), so they find the same pages in the same order, and both give the time the search took (“7 pages in 0.4 ms”); the overlay downloads the search index the first time it is opened. Without JavaScript the icon is a plain link to/search/. The X that Chrome, Edge and Safari show in a search field is restyled as the overlay’s thin close X. - The footer shows “Last update on Oct. 6, 2026 · Loaded in 0.42 s” at its right edge (below the copyright on phones). The date is that of the latest commit (
_plugins/last-update.rb), so it changes when the content does; the load time is the visitor’s own, from the browser’s Navigation Timing API (js/load-time.js), and is hidden when the browser does not report it. - Markdown tables on this page are styled under
.about-text, since Bootstrap’s table styles are not compiled in; on phones each row stacks into a block.
Colors and accessibility
- Colors are CSS variables in
css/_theme.scss. The site follows the visitor’s light or dark setting, and the moon/sun button in the navigation bar switches and remembers the choice. - All text meets WCAG AA contrast (4.5:1) in both themes; keep it that way when you change a color (the navigation bar’s hover and active text uses
$link-color-navlink-on-darkincss/_variables.scssfor this reason). Links in running text are not underlined, since their color sets them apart, except those drawn in the color of the surrounding text (the home page’s introduction, the author and DOI links in.smallnote, the footer credits), which get a faint underline so they are not told apart by color alone (WCAG 1.4.1). - Every page’s content sits in a
<main>element, and icon-only links carry anaria-label, witharia-hidden="true"on the icon.
Fonts
- Text is set in Inter, self-hosted in
css/fonts/inter/with its@font-facerules incss/_inter.scss: in the unicode-range subsets Google Fonts uses, so pages do not wait on two connections to Google before their text can render._layouts/default.htmlpreloadsnormal-latin.woff2, the one file every page needs. Until Inter has loaded, the text is set in “Inter fallback” (also incss/_inter.scss): Arial, or Liberation Sans on Linux, scaled to take the same room, so the page does not shift when Inter replaces it. Inter’s alternate lowercase l with a tail (cv05) and capital I with crossbars (cv08) are turned on incss/style.scss, so that I and l are told apart in formulas such as LiCl or Li₃InCl₆. Google Fonts’ copies of Inter drop these alternates, so the files are cut from the official release (rsms.me/inter) by_scripts/subset-inter-font.py, which explains how to rerun it. - Until October 2026 the site used IBM Plex Sans, kept on the
ibm-plex-sansbranch. Its files (css/fonts/ibm-plex-sans/,css/_plex-sans.scss) are still inmain, so switching back means changing the@importandfont-familyincss/style.scssand the preload in_layouts/default.html. Inter runs about 4% wider than Plex at the same size. - iOS Safari would link number runs such as a paper’s pages as phone numbers;
<meta name="format-detection" content="telephone=no">stops it, so a real phone number needs an explicittel:link.
Icons
- Icons are Font Awesome Free 6.7.2 (
fa-solid,fa-regularandfa-brands, for examplefa-brands fa-x-twitter) and Academicons 1.9.5 (ai ai-doi), both self-hosted: the SCSS incss/fontawesome/andcss/_academicons.scss, the fonts incss/webfonts/andcss/fonts/. The sun of the light/dark button is a hand-drawn inline SVG in_layouts/default.html, because Font Awesome’s looks like a cog. - Both icon fonts are trimmed to the icons the site uses (about 5 KB instead of 300 KB for Font Awesome, 3 KB instead of 128 KB for Academicons), and
css/_icons.scssemits only those icons’ classes. To use a new icon, add its name to$fa-used-iconsor$ai-used-iconsincss/_icons.scssand runpython3 _scripts/subset-icon-fonts.py(needspip install fonttools brotli); an unlisted icon shows as a blank square. The script also updates the fingerprints incss/_icons-version.scss; commit that file with the fonts. The full fonts are in_fontawesome-webfonts/and_academicons-webfonts/, which Jekyll does not publish. To upgrade Font Awesome, replacecss/fontawesome/with the new release’sscss/and_fontawesome-webfonts/with itswebfonts/(the.woff2files), then run the script. images/favicon/favicon.ico(and its copy at the repository root) holds 16, 32, 48 and 64px images; keep all four if you regenerate it, or it renders blurry on high-DPI displays.images/favicon/browserconfig.xml(Windows tiles) is published like any other file;_config.ymlmust not exclude*.xml, or it would be dropped.
Images
- Pictures rendered through
_includes/responsive-image.html(graphical abstracts, research and news pictures, team photos) are served as WebP, with the original PNG or JPEG as a<picture>fallback. Add a WebP copy beside every new picture (cwebp original.png -o original.webp) and never delete the original. A few large pictures also have smaller WebP copies, listed in_data/responsive_images.yml, which phones and the home page’s research row load instead: a news photo has a 640px copy,<name>-640w.webp, listed with the original’s width; a research picture lists the original’s width and then those of its copies, as[800, 640, 360]for<name>-640w.webpand<name>-360w.webp. A page passes the width a picture takes in its layout as the include’ssizes, so the browser picks the smallest copy that is sharp enough. _data/image_sizes.ymlrecords each picture’s width and height, so the include can reserve its space and the page does not shift while it loads; add an entry withsips -g pixelWidth -g pixelHeight path/to/image.- Thumbnails on the listing pages (news, research, papers, team) pass
loading="lazy"to the include, so they load only once they scroll into view.
Analytics
- Google Analytics is in
js/analytics.js(loaded by_includes/ga.html), not inline, because of the Content-Security-Policy (see Security). It queues the page view at once but downloads the ~150 KB gtag.js library only after the page has loaded, so it does not slow the first paint on phones; a visitor who leaves before then is not counted.
Browsers and standards
- Supported browsers are current Chrome, Edge, Firefox, Safari and Opera; Internet Explorer is not (the theme relies on CSS custom properties, and Bootstrap 5 dropped it).
- The site is checked by hand, from time to time, with the W3C Nu Html Checker and the W3C CSS Validator (most recently in September 2026, on one page per layout and the compiled stylesheet), and what they find is fixed; the CSS validator’s remaining messages are informational (vendor-prefixed selectors and custom properties, which it cannot evaluate).
- The scripts in
js/follow JavaScript Standard Style: no semicolons, two-space indentation,constandlet, and a space before a function’s parentheses. With Node.js installed,npx standard --env browser js/checks them and--fixcorrects most problems, without adding files to the repository; run it by hand when the scripts change. Write new JavaScript as a file injs/, never inline (see Security).
W3C Nu Html Checker
W3C CSS Validator
checked with npx standard
The HTML and CSS badges run the live site through the validator; the scripts are checked with npx standard, as described above, and the JavaScript badge leads to the style guide. HTML5 logo by the W3C (CC BY 3.0); CSS logo by the CSS-Next Community Group (CC0); JS logo by Christopher Williams and Manuel Strehl (MIT).
Security
- HTTPS everywhere. The custom domain (
CNAME,caneparesearch.org) is served over HTTPS by GitHub Pages, with Cloudflare in front as a CDN and cache. In production the page’s Content-Security-Policy sendsupgrade-insecure-requests, so a browser retries any plain-http://link over HTTPS (see Build the site locally for why a preview leaves it out). Paper PDFs in thecarepapersbucket are only linked overhttps://. Cloudflare’s SSL/TLS mode and GitHub Pages’ “Enforce HTTPS” are set in their dashboards, not in this repository, and are both on. - Fingerprinted addresses. The CSS, JS and search-index addresses end in
?v=and a fingerprint of the file (thefingerprintfilter in_plugins/fingerprint.rb), so a changed file gets a new address and is never held back by a stale cache, while an unchanged one stays cached. - Content-Security-Policy and Referrer-Policy, sent as
<meta>tags in_layouts/default.html:base-uri 'self'andform-action 'self'stop an injected script from changing the page’s base address or sending a form elsewhere;object-src 'none'blocks plugin content;strict-origin-when-cross-originsends other sites only the origin of a page, not its path. - Cloudflare settings are dashboard configuration, recorded below because no file holds them.
- E-mail addresses never appear in a page (see E-mail addresses above).
- No login of its own. The “Intranet” link in the footer leads to a separate Google Sites page that requires a Google sign-in; this codebase has no login, sessions or credentials.
- Search engines.
robots.txtallows every crawler and listssitemap.xml(written byjekyll-sitemapand dated byupdate.sh);map.xml, the sitemap of the paper PDFs, is listed by the bucket’s ownrobots.txt. Nothing on the site is meant to be hidden from search engines. Editrobots.txthere, not incaneparesearch.github.io, whose copy is overwritten on every publish.
Cloudflare settings
- Rules → Transform Rules, rule “CSP and permissions” (all requests) sets three response headers.
Content-Security-Policyis stricter than the<meta>one:default-src 'self', andscript-srcallows the site’s own files, a few named hosts (Google Tag Manager, Altmetric, Dimensions) and inline scripts only by their exact SHA-256 hash. The theme script in_includes/theme.htmlis the only inline script left, so keep its formatting: editing it, or adding another inline script, blocks it silently until its new hash is added to the rule. The rule still lists a second hash, for a jQuery call removed in September 2026, which can be deleted. A new third-party script, stylesheet, image or API host must be added to the matching directive.frame-srcallowshttps://www.youtube.comfor the talks andhttps://maps.google.com https://www.google.comfor the map on the Contact us page (the embed starts at the first and redirects to the second). The rule also setsPermissions-Policy(camera, microphone, geolocation, payment and USB off) andCross-Origin-Opener-Policy: same-origin. - SSL/TLS → Edge Certificates: HSTS on for 12 months with
includeSubDomains(every subdomain must serve HTTPS; today onlywww, which redirects to the main site), preload off;X-Content-Type-Options: nosniffon. - Caching → Cache Rules: “Versioned CSS and JS, 1 year” (
/css/style.cssand/js/*, safe because a changed file gets a new?v=), and “Fonts and images, 30 days” (/css/fonts/,/css/webfonts/,/images/: 31 days in browsers, while Cloudflare’s own copy follows the 10-minute origin setting). Pages keep GitHub Pages’ 10 minutes. An image keeps its address when it changes, so a returning visitor can see the old one for up to a month: give a replaced image a new file name. The icon fonts carry their own fingerprint (css/_icons-version.scss), so a changed icon set gets new addresses.
File conventions
.gitattributes and .editorconfig keep every text file in UTF-8 with LF line endings and a final newline, as POSIX defines a text file; let your editor honour them. The one exception is google736838dc293297e8.html, the Google Search Console verification file, which must stay exactly as Google issued it.
License
All source code in this repository, consisting of files with extensions .html, .css, .scss, .rb or .js, is freely available under an MIT license, unless otherwise noted within a file. You’re welcome to borrow or repurpose code to build your own site. The license’s text is in the LICENSE file of the source repository.
The MIT License (MIT)
Copyright (c) 2018-present Pieremanuele Canepa with the help of Bedford and CWD
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.