<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mathieu</title>
    <description>The latest articles on DEV Community by Mathieu (@mattioo).</description>
    <link>https://dev.to/mattioo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F298579%2Fd32e2827-891e-4921-9ba3-da3530bf9048.jpeg</url>
      <title>DEV Community: Mathieu</title>
      <link>https://dev.to/mattioo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mattioo"/>
    <language>en</language>
    <item>
      <title>Wisewand : L'outil de rédaction IA français pour optimiser votre SEO</title>
      <dc:creator>Mathieu</dc:creator>
      <pubDate>Fri, 28 Feb 2025 14:18:54 +0000</pubDate>
      <link>https://dev.to/mattioo/wisewand-loutil-de-redaction-ia-francais-pour-optimiser-votre-seo-dk1</link>
      <guid>https://dev.to/mattioo/wisewand-loutil-de-redaction-ia-francais-pour-optimiser-votre-seo-dk1</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Profitez de 10% de réduction avec le code promo : &lt;strong&gt;&lt;a href="https://link.la-minute-ia.fr/wisewand" rel="noopener noreferrer"&gt;MINUTE10&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Vous recherchez un outil de rédaction IA performant et rapide pour améliorer votre stratégie SEO ? &lt;a href="https://link.la-minute-ia.fr/wisewand" rel="noopener noreferrer"&gt;Wisewand&lt;/a&gt; pourrait répondre à vos attentes. Développé par une équipe d'experts SEO (Antho, Arthur et Franck de Les Wizards), cet outil se distingue par sa facilité d'utilisation et son efficacité.&lt;/p&gt;

&lt;p&gt;Surpassant les solutions de rédaction IA traditionnelles, ce logiciel 100% français propose de nombreuses fonctionnalités visant à créer du contenu fluide, optimisé et conforme aux exigences des moteurs de recherche.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://link.la-minute-ia.fr/wisewand" rel="noopener noreferrer"&gt;Wisewand&lt;/a&gt; offre plusieurs formules adaptées à tous les budgets avec un excellent rapport qualité/prix. Vous pouvez également bénéficier d'une réduction de 10% avec le code promo &lt;strong&gt;MINUTE10&lt;/strong&gt;, parfait pour commencer à moindre coût.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://link.la-minute-ia.fr/wisewand" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq81m54eh7uxez40v1ni2.png" alt="Image description" width="800" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Points forts et limites
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Decouvrez notre test complet sur &lt;a href="https://nugg.ad/fr/avis-wisewand/" rel="noopener noreferrer"&gt;https://nugg.ad/fr/avis-wisewand/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Avantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Interface intuitive et simple d'utilisation&lt;/li&gt;
&lt;li&gt;Contenu IA de haute qualité&lt;/li&gt;
&lt;li&gt;Optimisation SEO et maillage interne automatisés&lt;/li&gt;
&lt;li&gt;Intégration directe avec WordPress et Shopify&lt;/li&gt;
&lt;li&gt;Plusieurs modes de rédaction adaptés à différents besoins&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Inconvénients
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Absence de version gratuite&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Fonctionnalités principales
&lt;/h3&gt;

&lt;p&gt;Wisewand se démarque par ses fonctionnalités complètes, conçues pour simplifier la création de contenu optimisé pour le référencement, quel que soit votre profil : éditeur de site, blogueur, e-commerçant ou agence digitale.&lt;/p&gt;

&lt;h3&gt;
  
  
  Création de personas
&lt;/h3&gt;

&lt;p&gt;Wisewand permet de définir des personas en analysant le contexte et les besoins de votre audience cible. En renseignant quelques informations essentielles (âge, sexe, centres d'intérêt, comportement d'achat), l'outil adapte automatiquement le ton et le style rédactionnel, favorisant ainsi une meilleure conversion et un engagement accru des lecteurs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mode de rédaction autopilot
&lt;/h3&gt;

&lt;p&gt;Cette fonctionnalité gère automatiquement la structure et l'optimisation SEO du contenu. Il suffit d'entrer un mot-clé principal pour générer un article optimisé en quelques minutes. Chaque texte répond précisément à l'intention de recherche des internautes et intègre naturellement des liens internes et des mots-clés secondaires pertinents.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mode de rédaction avancé
&lt;/h3&gt;

&lt;p&gt;Destiné aux rédacteurs expérimentés, ce mode offre un contrôle plus précis sur le contenu :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Personnalisation de la longueur et de la structure des articles&lt;/li&gt;
&lt;li&gt;Définition précise des balises Hn (H1, H2, H3)&lt;/li&gt;
&lt;li&gt;Choix d'un ton spécifique adapté à l'intention de recherche&lt;/li&gt;
&lt;li&gt;Affinage de la mise en forme (listes, tableaux, citations)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Mode de rédaction affiliation
&lt;/h3&gt;

&lt;p&gt;Spécialement conçu pour les affiliés, ce mode se concentre sur l'intention commerciale et l'optimisation des conversions. Il intègre naturellement des éléments promotionnels et des appels à l'action adaptés aux intentions d'achat, idéal pour augmenter vos commissions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flux RSS
&lt;/h3&gt;

&lt;p&gt;Pour les sites d'actualités ou de niches spécifiques, Wisewand permet d'intégrer des flux RSS externes. Cette fonctionnalité s'appuie sur des sources d'information fiables pour créer régulièrement des articles optimisés, éliminant ainsi le besoin de mise à jour manuelle.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tarifs
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://link.la-minute-ia.fr/wisewand" rel="noopener noreferrer"&gt;Wisewand&lt;/a&gt; propose quatre formules basées sur un système de crédits (2 crédits = 1 article) :&lt;/p&gt;

&lt;p&gt;Explorer : 47€ (environ 23 articles)&lt;br&gt;
Creator : 197€ (environ 100 articles)&lt;br&gt;
Master : 497€ (environ 300 articles)&lt;br&gt;
Titan : 997€ (environ 650 articles)&lt;/p&gt;

&lt;p&gt;Selon la formule choisie, vous pouvez bénéficier de réductions allant de 5% à 33%. Toutes les fonctionnalités avancées sont incluses dans chaque offre.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pourquoi choisir &lt;a href="https://link.la-minute-ia.fr/wisewand" rel="noopener noreferrer"&gt;Wisewand&lt;/a&gt; ?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Humanisation du contenu
&lt;/h3&gt;

&lt;p&gt;Contrairement à d'autres outils qui produisent des textes impersonnels, Wisewand génère des articles naturels et engageants. L'algorithme intègre des nuances subtiles pour créer une rédaction fluide et parfaitement adaptée à l'expérience de lecture humaine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prix compétitifs
&lt;/h3&gt;

&lt;p&gt;Comparé à ses concurrents, Wisewand propose des fonctionnalités avancées à un prix accessible. Son système de crédits offre une grande flexibilité d'utilisation, s'adaptant aussi bien aux particuliers qu'aux grandes agences.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gestion automatisée du maillage interne
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://link.la-minute-ia.fr/wisewand" rel="noopener noreferrer"&gt;Wisewand&lt;/a&gt; insère automatiquement des liens internes pertinents dans chaque article, améliorant ainsi l'indexation et le référencement naturel du site. Cette fonctionnalité permet de gagner du temps tout en optimisant la cohérence entre les différentes pages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessibilité pour tous les créateurs de contenu
&lt;/h3&gt;

&lt;p&gt;Que vous soyez débutant ou expert, Wisewand s'adapte à tous les profils. L'outil ne nécessite aucune compétence en prompt engineering et son interface intuitive permet une prise en main rapide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternatives à &lt;a href="https://link.la-minute-ia.fr/wisewand" rel="noopener noreferrer"&gt;Wisewand&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Bien que Wisewand offre de nombreux avantages, d'autres outils existent sur le marché :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Skoatch : propose une rédaction automatisée abordable mais moins spécialisée en SEO&lt;/li&gt;
&lt;li&gt;TextBulker : idéal pour la production en grande quantité, mais parfois moins fluide&lt;/li&gt;
&lt;li&gt;ChatGPT : très polyvalent mais nécessite des ajustements manuels pour l'optimisation SEO&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wisewand se démarque par sa spécialisation SEO et son approche intégrée, offrant une solution complète pour les créateurs de contenu qui cherchent à allier qualité et simplicité d'utilisation.&lt;/p&gt;

</description>
      <category>wisewand</category>
      <category>codepromo</category>
      <category>aviswisewand</category>
      <category>codepromowisewand</category>
    </item>
    <item>
      <title>Structuring a Python application</title>
      <dc:creator>Mathieu</dc:creator>
      <pubDate>Sat, 26 Sep 2020 09:38:23 +0000</pubDate>
      <link>https://dev.to/mattioo/structuring-a-python-application-4a78</link>
      <guid>https://dev.to/mattioo/structuring-a-python-application-4a78</guid>
      <description>&lt;p&gt;&lt;em&gt;Original article : &lt;a href="https://brainsorting.dev/posts/structuring-a-python-application/"&gt;https://brainsorting.dev/posts/structuring-a-python-application/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this short article I will explain all the different ways of structuring a Python application, from a quick script to a more complex web application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Single python file containing all the code
&lt;/h2&gt;

&lt;p&gt;That's okay for code without dependencies or using a virtual environment. This is generally used for a quick script that doesn't need complexity in its file structure.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-single-file-project/
├── .gitignore
├── helloworld.py
├── test.py
├── pyproject.toml
├── LICENSE
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example of the &lt;code&gt;helloworld.py&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python
# helloworld.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"Hello, today is &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;datetime&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="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;do_hello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Installable Single Package
&lt;/h2&gt;

&lt;p&gt;When your app get more complex you generally wants to group your different files and helpers into a module.&lt;/p&gt;

&lt;p&gt;You also need to improve your tests so they cover all the files → test coverage. You can also add the use of a linter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-single-package-app/
├── helloworld/
│   ├── __init__.py
│   ├── helloworld.py
│   └── utils.py
├── tests/
│   ├── __init__.py
│   ├── test_helloworld.py
│   └── test_utils.py
├── runtest.sh
├── .gitignore
├── pyproject.toml
├── LICENSE
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we grouped the files from our app in two folders, the &lt;code&gt;helloworld&lt;/code&gt; app folder and the &lt;code&gt;tests&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;We match the &lt;code&gt;test_****.py&lt;/code&gt; files name with the files in the app module folder.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;__init__.py&lt;/code&gt; files are mandatory for python to know it is package and can be empty.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python
# helloworld.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;helloworld.utils&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;show_message&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;show_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"Hello, today is &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;datetime&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="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;do_hello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# pragma: no cover
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;runtests.sh&lt;/code&gt; file is a script to run all the test with the &lt;code&gt;coverage&lt;/code&gt; dependency that you can install with &lt;code&gt;poetry add coverage -D&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.pyc"&lt;/span&gt; &lt;span class="nt"&gt;-exec&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;
coverage run &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nt"&gt;--source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tests,helloworld &lt;span class="nt"&gt;-m&lt;/span&gt; unittest &lt;span class="c"&gt;# this is where you add the&lt;/span&gt;
                                                      &lt;span class="c"&gt;# folders you want to test&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"0"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;coverage combine
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;================================================"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Test Coverage"&lt;/span&gt;
    coverage report
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;run &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;coverage html&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; for full report"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="c"&gt;# pyflakes or its like should go here&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Application with internal packages
&lt;/h2&gt;

&lt;p&gt;In bigger apps you will probably have multiple modules, particularly if you do a GUI.&lt;/p&gt;

&lt;p&gt;Possible additions to your application are :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;bin directory, wrapper for your entry point.&lt;/li&gt;
&lt;li&gt;data directory, always separate your data from your code
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/
├── helloworld/
│   ├── __init__.py
│   ├── hello/
│   │   ├── __init__.py
│   │   ├── hello.py
│   │   └── utils.py
│   ├── world/
│   │   ├── __init__.py
│   │   └── world.py
├── tests/
│   ├── __init__.py
│   ├── hello/
│   │   ├── __init__.py
│   │   ├── test_hello.py
│   │   └── test_utils.py
│   ├── world/
│   │   ├── __init__.py
│   │   └── test_world.py
├── bin/
│   └── helloworld*
├── data/
│   └── translate.csv
├── docs/
│   ├── conf.py
│   ├── index.rst
│   ├── hello.rst
│   ├── world.rst
│   └── Makefile
├── runtest.sh
├── .gitignore
├── pyproject.toml
├── LICENSE
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  bin/
&lt;/h3&gt;

&lt;p&gt;This new folder holds any executable files the users will use. The script drop the &lt;code&gt;.py&lt;/code&gt; ending. It should have very little code logic, it's just a wrapper for the main module's entry point.&lt;/p&gt;

&lt;p&gt;You can configure &lt;code&gt;setup.py&lt;/code&gt; to package this if you build a wheel, the script will be put on the path.&lt;/p&gt;

&lt;h3&gt;
  
  
  data/
&lt;/h3&gt;

&lt;p&gt;If there are files that are not code that is usually where they should end up. It is also useful for test data.&lt;/p&gt;

&lt;h3&gt;
  
  
  docs/
&lt;/h3&gt;

&lt;p&gt;The documentation is very important if you want to share your app with users.&lt;/p&gt;

&lt;p&gt;A very useful library for that is &lt;code&gt;sphinx&lt;/code&gt;, it uses &lt;code&gt;pydoc&lt;/code&gt; comments to build the doc automatically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry add sphinx -D
poetry add sphinx-rtd-theme -D
cd docs
sphinx-quickstarts
make html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;.rst&lt;/code&gt; files are generated by &lt;code&gt;sphinx-quickstart&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Django web application
&lt;/h2&gt;

&lt;p&gt;After you've installed &lt;code&gt;Django&lt;/code&gt; you can use this included command to generate the architecture of the project as Django expects it :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;django-admin startproject django_world
django-admin startapp hello
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will end up with this basic folder tree where just a few things has been manually added :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;django_world/
├── docs/
├── static/
│   └── style.css
├── templates/
│   └── base.html
├── resetdb.sh
├── runserver.sh
├── hello/
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations/
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── django_world/
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;hello/&lt;/code&gt; folder is where all the logic, model, views and so on live.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;static&lt;/code&gt; folder contains all the static contents (css, js,...).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;templates&lt;/code&gt; folder has all the html templates.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;runserver.sh&lt;/code&gt; is a script that has only one line :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python manage.py runserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;resetdb.sh&lt;/code&gt; is a script for wiping all the database and start from scratch, it is just a helper tool :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.pyc"&lt;/span&gt; &lt;span class="nt"&gt;-exec&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;
&lt;span class="nb"&gt;rm &lt;/span&gt;db.sqlite3

python manage.py migrate

&lt;span class="c"&gt;# python manage.py create_test_data&lt;/span&gt;
&lt;span class="c"&gt;# comment that last line to use premade test data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Flask
&lt;/h2&gt;

&lt;p&gt;Flask is proud to show a working web app with 10 lines of code, but in practice you'll never do that. Here is a complete folder organization :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flaskr/
│
├── flaskr/
│   ├── ___init__.py
│   ├── db.py
│   ├── schema.sql
│   ├── auth.py
│   ├── blog.py
│   ├── templates/
│   │   ├── base.html
│   │   ├── auth/
│   │   │   ├── login.html
│   │   │   └── register.html
│   │   │
│   │   └── blog/
│   │       ├── create.html
│   │       ├── index.html
│   │       └── update.html
│   │
│   └── static/
│       └── style.css
│
├── tests/
│   ├── conftest.py
│   ├── data.sql
│   ├── test_factory.py
│   ├── test_db.py
│   ├── test_auth.py
│   └── test_blog.py
│
├── .gitignore
└── MANIFEST.in
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see that flask really uses python package way of working.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source : &lt;a href="https://realpython.com/python-application-layouts/"&gt;https://realpython.com/python-application-layouts/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Create a proxy with a Raspberry Pi 3 (or above)</title>
      <dc:creator>Mathieu</dc:creator>
      <pubDate>Thu, 27 Aug 2020 09:34:13 +0000</pubDate>
      <link>https://dev.to/mattioo/create-a-proxy-with-a-raspberry-pi-3-or-above-1gbc</link>
      <guid>https://dev.to/mattioo/create-a-proxy-with-a-raspberry-pi-3-or-above-1gbc</guid>
      <description>&lt;p&gt;&lt;em&gt;Original article : &lt;a href="https://brainsorting.dev/posts/create-a-proxy-with-a-raspberry-pi-3-or-above/"&gt;https://brainsorting.dev/posts/create-a-proxy-with-a-raspberry-pi-3-or-above/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you need to use a proxy that has the same IP address as your home, here is a tutorial on how to do it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install and configure your Raspberry Pi OS
&lt;/h3&gt;

&lt;p&gt;Install and configure a raspberry pi without a mouse nor a keyboard :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download the last version of raspbian lite &lt;a href="https://www.raspberrypi.org/downloads/raspberry-pi-os/"&gt;here&lt;/a&gt; and download &lt;a href="https://www.balena.io/etcher/"&gt;Etcher&lt;/a&gt; which we will use to flash the disk image on the SD card.&lt;/li&gt;
&lt;li&gt;Start Elena, select the Raspbian Lite imake disk, select the target which is the SD card you use for your raspberry pi and click on Flash!.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While the image disk is getting installed, we will create the file that contains the wifi information so the raspberry can connect to it automatically. Open a text note and paste this inside :&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ctrl_interface=/run/wpa_supplicant
update_config=1
country=FR

network={
    ssid="internet_box_name"
    scan_ssid=1
    psk="password"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;internet_box_name&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; by your home internet box settings and save that file under&lt;code&gt;wpa_supplicant.conf&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then we will create an empty file which name is simply &lt;code&gt;ssh&lt;/code&gt;. This file will tell the raspberry that you want to enable the SSH connection which is usually set off by default. With that settings on we will be able to connect to the raspberry pi through the network using another computer.&lt;/p&gt;

&lt;p&gt;Place both files that you just created in the BOOT folder of the SD card you just flashed.&lt;/p&gt;

&lt;p&gt;Congratulation ! Now you can eject the SD card and insert it in your raspberry pi.&lt;/p&gt;

&lt;p&gt;If everything worked out, when you switch on your Raspberry Pi you should see it in the list of the device connected to your home internet network by checking your router.&lt;/p&gt;

&lt;p&gt;Now the next step is to connect to your Raspberry Pi with SSH. Launch a terminal and if you are on mac type this command :&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ssh pi@local_ip_of_your_raspberry&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It will ask for a password, type  &lt;code&gt;raspberry&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To avoid that IP to change, we will set a static IP to your raspberry. You need to modify the file &lt;code&gt;dhcpd.conf&lt;/code&gt; located in the folder &lt;code&gt;/etc/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once you have opened the file, go to the last line and add this content&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;interface eth0
static &lt;span class="nv"&gt;ip_address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;192.168.1.100/24
static &lt;span class="nv"&gt;routers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;192.168.1.1
static &lt;span class="nv"&gt;domain_name_servers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;192.168.1.1

interface wlan0
static &lt;span class="nv"&gt;ip_address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;192.168.1.100/24
static &lt;span class="nv"&gt;routers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;192.168.1.1
static &lt;span class="nv"&gt;domain_name_servers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;192.168.1.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the &lt;code&gt;eth0&lt;/code&gt; correspond to a internet cable connection, and &lt;code&gt;wlan0&lt;/code&gt; to a internet wifi connection. Up to you to choose which one you will use.&lt;/p&gt;

&lt;p&gt;Static ip_address indicate the IP that your Raspberry Pi will have when it switch on. usually the IP is of the type &lt;code&gt;192.168.1.x&lt;/code&gt;, replace the x by an available slot on your network. If your box is on a different IP address then modify static router et static domain_name_servers accordingly.&lt;/p&gt;

&lt;p&gt;Save the file and exit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up the raspberry pi
&lt;/h3&gt;

&lt;p&gt;1) Update the raspberry pi&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get upgrade
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get dist-upgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2) Install terminal editor Joe&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;joe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3) Install the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;fail2ban software-properties-common
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;build-essential libevent-dev libssl-dev
&lt;span class="nb"&gt;cd&lt;/span&gt; /etc
&lt;span class="nb"&gt;sudo &lt;/span&gt;wget https://github.com/z3APA3A/3proxy/archive/0.8.12.tar.gz
&lt;span class="nb"&gt;sudo tar &lt;/span&gt;zxvf 0.8.12.tar.gz
&lt;span class="nb"&gt;sudo mv &lt;/span&gt;3proxy-0.8.12 3proxy
&lt;span class="nb"&gt;cd &lt;/span&gt;3proxy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4) Edit the file proxy.h&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;joe src/proxy.h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And add the line following line above the other lines starting with #DEFINE&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#define ANONYMOUS 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5) Compile and install the software&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;make &lt;span class="nt"&gt;-f&lt;/span&gt; Makefile.Linux
&lt;span class="nb"&gt;sudo &lt;/span&gt;make &lt;span class="nt"&gt;-f&lt;/span&gt; Makefile.Linux &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;6) Download 3proxy.cfg&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;wget https://gettraffic.pro/docs/3proxy.cfg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;7) Edit the 3proxy.cfg with Joe&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;joe 3proxy.cfg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;8) Change those lines&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;users &lt;/span&gt;root:CL:passwd
...
allow root
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To any username you prefer instead of &lt;code&gt;root&lt;/code&gt; and change the &lt;code&gt;passwd&lt;/code&gt; to a strong password. If you changed root to a different username don't forget to change &lt;code&gt;allow root&lt;/code&gt; to &lt;code&gt;allow&lt;/code&gt; and whatever username you decided. Save that file when you are finished&lt;/p&gt;

&lt;p&gt;9) Change file permission&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chmod &lt;/span&gt;700 3proxy.cfg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;10) Download the script file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /etc/3proxy/scripts/rc.d/
&lt;span class="nb"&gt;sudo mv &lt;/span&gt;proxy.sh saved-proxy.sh
&lt;span class="nb"&gt;sudo &lt;/span&gt;wget https://gettraffic.pro/docs/proxy.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;11) Start the proxy server&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;sh /etc/3proxy/scripts/rc.d/proxy.sh start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It should give the output “Starting 3Proxy”. If it doesn’t then there is a problem somewhere in your config files.&lt;/p&gt;

&lt;p&gt;12) Add it to the autorun so after reboot it will start again&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;joe /etc/rc.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And add line :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sh /etc/3proxy/scripts/rc.d/proxy.sh start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This line has to be added above the line &lt;code&gt;exit 0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The best way to check if everything is alright is by doing a full reboot of your Raspberry and checking if everything still works after the reboot :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;shutdown &lt;span class="nt"&gt;-r&lt;/span&gt; now
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Access your Raspberry Pi with SSH outside your home local network
&lt;/h3&gt;

&lt;p&gt;You will need to add the fixed IP you choose for your Raspberry Pi in your internet box router settings. Add this IP address in the DHCP settings (the aim of this tutorial is not to each how to do that so look ressources on google).&lt;/p&gt;

&lt;p&gt;Now edit your NAT/PAT settings to redirect the port 22 (SSH) and 3129 (your proxy) to the fixed IP address you just set up in the DHCP.&lt;/p&gt;

&lt;p&gt;Now to access your home internet network from outside, you need a way to now its public IP address which might change over time. We will use a very good services to achieve that is called no-ip.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Register on &lt;a href="https://www.noip.com/"&gt;https://www.noip.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Create a hostname like « myraspberrypiproxy.ddns.net »&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install the DUC on your raspberry pi which will automatically update the public IP no-ip will redirect the hostname to :&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /usr/local/src/
&lt;span class="nb"&gt;sudo &lt;/span&gt;wget http://www.no-ip.com/client/linux/noip-duc-linux.tar.gz
&lt;span class="nb"&gt;sudo tar &lt;/span&gt;xf noip-duc-linux.tar.gz
&lt;span class="nb"&gt;cd &lt;/span&gt;noip-2.1.9-1
&lt;span class="nb"&gt;sudo &lt;/span&gt;make &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Then a little bit of configuration&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo cp&lt;/span&gt; /usr/local/src/noip-2.1.9-1/debian.noip2.sh /etc/init.d/noip2.sh
&lt;span class="nb"&gt;sudo &lt;/span&gt;joe /etc/init.d/noip2.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;And add the following code abose this line &lt;code&gt;DAEMON=/usr/local/bin/noip2&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;### BEGIN INIT INFO&lt;/span&gt;
&lt;span class="c"&gt;# Provides:          noip2.sh&lt;/span&gt;
&lt;span class="c"&gt;# Required-Start:    $remote_fs $local_fs&lt;/span&gt;
&lt;span class="c"&gt;# Required-Stop:     $remote_fs $local_fs&lt;/span&gt;
&lt;span class="c"&gt;# Should-Start:&lt;/span&gt;
&lt;span class="c"&gt;# Should-Stop:&lt;/span&gt;
&lt;span class="c"&gt;# Default-Start:     2 3 4 5&lt;/span&gt;
&lt;span class="c"&gt;# Default-Stop:      0 1 6&lt;/span&gt;
&lt;span class="c"&gt;# Short-Description: Dynamic IP client updater&lt;/span&gt;
&lt;span class="c"&gt;# Description:&lt;/span&gt;
&lt;span class="c"&gt;### END INIT INFO&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Now the client can be started, stopped or restarted manually&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; /etc/init.d/noip2.sh &amp;lt;start|stop|restart&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Change files read write properties :&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chown &lt;/span&gt;root.root /etc/init.d/noip2.sh
&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; +x /etc/init.d/noip2.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Start the server&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; /etc/init.d/noip2.sh start
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To allow starting the service automatically at startup, run the following command:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;update-rc.d noip2.sh defaults
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Then try sudo reboot to see if service start by itself&lt;/p&gt;

&lt;p&gt;To check if there is a running instance use this command :&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;noip2 &lt;span class="nt"&gt;-S&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Finish ! Now you should be able to connect to your proxy with the hostname address you used in no-ip and the port 3129 like this 'myraspberrypiproxy.ddns.net:3129'. The authorized username and password to connect to the proxy are the one you decided previously in the step 8 of configuring the proxy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Useful Commands
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;If you need to reconfigure the DUC file from no-ip use that command :
&lt;code&gt;sudo /usr/local/bin/noip2 -C&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Connect to the raspberry pi by SSH with Terminal (Mac) :
&lt;code&gt;ssh pi@ip&lt;/code&gt;
Then yes, and type password&lt;/li&gt;
&lt;li&gt;Check if there is a no-ip instance running
&lt;code&gt;sudo noip2 -S&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Check if proxy is running
&lt;code&gt;ps -A&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>proxy</category>
      <category>raspberrypi</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to cancel a pending ethereum transaction with MetaMask</title>
      <dc:creator>Mathieu</dc:creator>
      <pubDate>Sat, 15 Aug 2020 10:31:20 +0000</pubDate>
      <link>https://dev.to/mattioo/how-to-cancel-a-pending-ethereum-transaction-with-metamask-4aah</link>
      <guid>https://dev.to/mattioo/how-to-cancel-a-pending-ethereum-transaction-with-metamask-4aah</guid>
      <description>&lt;p&gt;&lt;em&gt;Original article : &lt;a href="https://brainsorting.dev/posts/how-to-cancel-a-pending-ethereum-transaction-with-metamask/"&gt;https://brainsorting.dev/posts/how-to-cancel-a-pending-ethereum-transaction-with-metamask/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Having a &lt;strong&gt;pending transaction&lt;/strong&gt; can be quite annoying and usually happens when the network is heavy loaded and the fees are sky rocketing. Your transaction may have a &lt;strong&gt;too low gas fee&lt;/strong&gt; and miner are just ignoring it to prefer others transaction with higher fees.&lt;/p&gt;

&lt;p&gt;This result in you being stuck because until that transaction is resolved you cannot send any other transaction. Annoying right ?&lt;/p&gt;

&lt;p&gt;Let's dive right in on how to fix this !&lt;/p&gt;

&lt;h2&gt;
  
  
  Gather all the informations we need
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisite
&lt;/h3&gt;

&lt;p&gt;This tutorial is about using &lt;strong&gt;MetaMask&lt;/strong&gt; to cancel the pending transactions so you need to have it.&lt;/p&gt;

&lt;p&gt;If you don't have MetaMask installed on chrome, &lt;a href="https://metamask.io/"&gt;here&lt;/a&gt; is the official address to do so.&lt;/p&gt;

&lt;h3&gt;
  
  
  Etherscan
&lt;/h3&gt;

&lt;p&gt;The first step is to go on &lt;strong&gt;etherscan&lt;/strong&gt; and paste the tx hash of your pending transaction. You can also paste your ethereum address and will be able to find all your pending transactions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Oi5cnXmQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brainsorting.dev/images/How%2520to%2520cancel%2520a%2520pending%2520ethereum%2520transaction%2520with%2520%2520cad19359c1ff45df83833f5ee11b6e58/Untitled.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Oi5cnXmQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brainsorting.dev/images/How%2520to%2520cancel%2520a%2520pending%2520ethereum%2520transaction%2520with%2520%2520cad19359c1ff45df83833f5ee11b6e58/Untitled.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Find the oldest pending transaction, click on it and then click on &lt;strong&gt;Click to see More ↓&lt;/strong&gt; to get the &lt;strong&gt;Nonce&lt;/strong&gt; number of that transaction.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H3j4nUbP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brainsorting.dev/images/How%2520to%2520cancel%2520a%2520pending%2520ethereum%2520transaction%2520with%2520%2520cad19359c1ff45df83833f5ee11b6e58/Capture_decran_2020-08-15_a_10.54.48.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H3j4nUbP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brainsorting.dev/images/How%2520to%2520cancel%2520a%2520pending%2520ethereum%2520transaction%2520with%2520%2520cad19359c1ff45df83833f5ee11b6e58/Capture_decran_2020-08-15_a_10.54.48.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All the transactions of an ethereum address have a nonce number that increment after each transaction.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3zwd1iMQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brainsorting.dev/images/How%2520to%2520cancel%2520a%2520pending%2520ethereum%2520transaction%2520with%2520%2520cad19359c1ff45df83833f5ee11b6e58/Untitled%25201.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3zwd1iMQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brainsorting.dev/images/How%2520to%2520cancel%2520a%2520pending%2520ethereum%2520transaction%2520with%2520%2520cad19359c1ff45df83833f5ee11b6e58/Untitled%25201.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now the concept behind cancelling a pending transaction is to actually send a new transaction with the same &lt;strong&gt;Nonce&lt;/strong&gt; but with a higher fees that the miner will verify and confirm. When this will be done, the previous pending transaction with the same nonce will simply be cancelled and forget by the network because only unique nonce transaction per ETH address can exists.&lt;/p&gt;

&lt;p&gt;You should have those informations for going to the next phase :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your Ethereum address&lt;/li&gt;
&lt;li&gt;The Nonce of your blocked pending transaction&lt;/li&gt;
&lt;li&gt;MetaMask installed and running with your Ethereum address&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How can I send my own custom transaction
&lt;/h2&gt;

&lt;p&gt;The basic configuration of MetaMask doesn't allow us to use custom Nonce, but you can enable that option in the configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enabling the custom gas settings and custom nonce
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Click on this button&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5n0b8HQP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brainsorting.dev/images/How%2520to%2520cancel%2520a%2520pending%2520ethereum%2520transaction%2520with%2520%2520cad19359c1ff45df83833f5ee11b6e58/Capture_decran_2020-08-15_a_11.03.58.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5n0b8HQP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brainsorting.dev/images/How%2520to%2520cancel%2520a%2520pending%2520ethereum%2520transaction%2520with%2520%2520cad19359c1ff45df83833f5ee11b6e58/Capture_decran_2020-08-15_a_11.03.58.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The go into the settings&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1vM4yOII--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brainsorting.dev/images/How%2520to%2520cancel%2520a%2520pending%2520ethereum%2520transaction%2520with%2520%2520cad19359c1ff45df83833f5ee11b6e58/Capture_decran_2020-08-15_a_11.05.19.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1vM4yOII--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brainsorting.dev/images/How%2520to%2520cancel%2520a%2520pending%2520ethereum%2520transaction%2520with%2520%2520cad19359c1ff45df83833f5ee11b6e58/Capture_decran_2020-08-15_a_11.05.19.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now click on &lt;strong&gt;Advanced&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I suggest to enable both &lt;strong&gt;Advanced gas controls&lt;/strong&gt; and &lt;strong&gt;Customize Transaction nonce&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Sending a custom transaction to fix the pending tx
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Once that's done, quit the configuration and now click on the SEND button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6A-6tbcv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brainsorting.dev/images/How%2520to%2520cancel%2520a%2520pending%2520ethereum%2520transaction%2520with%2520%2520cad19359c1ff45df83833f5ee11b6e58/Capture_decran_2020-08-15_a_11.08.22.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6A-6tbcv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brainsorting.dev/images/How%2520to%2520cancel%2520a%2520pending%2520ethereum%2520transaction%2520with%2520%2520cad19359c1ff45df83833f5ee11b6e58/Capture_decran_2020-08-15_a_11.08.22.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Paste your ETH address, and then add 10 GWEI to the transaction fee gas price to be sure you are above the network average Gas Price so this transaction won't be stuck pending as well. Always verify on &lt;a href="https://ethgasstation.info/"&gt;Eth Gas Station&lt;/a&gt; and use a Gas Price above the FAST recommendation. Leave Gas Limit as it is (21000).&lt;/p&gt;

&lt;p&gt;Click on Next when you are done.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b1WhrScN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brainsorting.dev/images/How%2520to%2520cancel%2520a%2520pending%2520ethereum%2520transaction%2520with%2520%2520cad19359c1ff45df83833f5ee11b6e58/Capture_decran_2020-08-15_a_11.15.32.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b1WhrScN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brainsorting.dev/images/How%2520to%2520cancel%2520a%2520pending%2520ethereum%2520transaction%2520with%2520%2520cad19359c1ff45df83833f5ee11b6e58/Capture_decran_2020-08-15_a_11.15.32.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In this screen you should be able to set your own custom Nonce if you enable it properly in MetaMask config as explained in the beginning of that article. Write down the Nonce of your blocked pending transaction and click on Confirm.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UnTauVsE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brainsorting.dev/images/How%2520to%2520cancel%2520a%2520pending%2520ethereum%2520transaction%2520with%2520%2520cad19359c1ff45df83833f5ee11b6e58/Capture_decran_2020-08-15_a_11.17.25.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UnTauVsE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brainsorting.dev/images/How%2520to%2520cancel%2520a%2520pending%2520ethereum%2520transaction%2520with%2520%2520cad19359c1ff45df83833f5ee11b6e58/Capture_decran_2020-08-15_a_11.17.25.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MetaMask will ask you to sign your transaction and how will depend on if you are using a Ledger or something else. Once you did sign it, the transaction will be sent and if you were above the FAST Gas Price recommendation from Eth Gas Station website it should be confirmed in less than a minute and your blocked pending transaction should now be cancelled.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you had other pending transaction after that one that are still blocked after this, you will need to repeat the process for each one of them, from the oldest to the newest until you eventually cleared your whole pile of pending transactions.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  How can I prevent that from happening again
&lt;/h3&gt;

&lt;p&gt;Regularly keep an eye on the Eth Gas Station website to know the current average Gas Price, and don't always trust pre configured gas price from MetaMask. If you are doing a transaction that is very important, you can always Edit the Gas Price MetaMask is choosing for you and set it to fast, or even a custom one that you decide.&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>blockchain</category>
      <category>metamask</category>
    </item>
    <item>
      <title>The no hello policy</title>
      <dc:creator>Mathieu</dc:creator>
      <pubDate>Thu, 30 Jul 2020 07:25:02 +0000</pubDate>
      <link>https://dev.to/mattioo/the-no-hello-policy-13hn</link>
      <guid>https://dev.to/mattioo/the-no-hello-policy-13hn</guid>
      <description>&lt;p&gt;&lt;em&gt;Original article : &lt;a href="https://brainsorting.dev/posts/the-no-hello-policy/"&gt;https://brainsorting.dev/posts/the-no-hello-policy/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Please Don't Say Just Hello In Chat
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2010-07-19 12:32:12 you: Hi
2010-07-19 12:32:15 co-worker: Hello.
# CO-WORKER WAITS WHILE YOU PHRASE YOUR QUESTION
2010-07-19 12:34:01 you: I'm working on [something] and I'm trying to do [etc...]
2010-07-19 12:35:21 co-worker: Oh, that's [answer...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's as if you called someone on the phone and said "Hi!" and then put them on&lt;br&gt;
hold!&lt;/p&gt;

&lt;p&gt;Please do this instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2010-07-19 12:32:12 you: Hi -- I'm working on [something] and I'm trying to do [etc...]
2010-07-19 12:33:32 co-worker: [answers question]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that you get help minutes sooner, and you don't make them wait. Instead,&lt;br&gt;
the co-worker can start thinking about your question right away!&lt;/p&gt;

&lt;p&gt;You're trying to be polite by not jumping right into the request, like you&lt;br&gt;
would do in person or on the phone. But Chat is neither of those things. Typing&lt;br&gt;
is much slower than talking. Instead of being polite, you are just making the&lt;br&gt;
other person wait for you to phrase your question, which is lost productivity.&lt;/p&gt;

&lt;p&gt;The same goes for "Hello -- Are you there?", "Hi Bob -- quick question.", "Do&lt;br&gt;
you have a sec ?", "yt?" and "ping". Just ask the question!&lt;/p&gt;

&lt;p&gt;If you feel it's brusque to simply say "Hi" and ask the question, you can do&lt;br&gt;
something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2010-07-19 12:32:12 you: Hi -- if you're not busy I was wondering if I could ask a question. I'm working on [something] and I'm trying to do [etc...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, asking your question before getting a reply allows asynchronous&lt;br&gt;
communication. If the other party is away, and you leave before they come back,&lt;br&gt;
they can still answer your question, instead of just staring at a "Hello" and&lt;br&gt;
wondering what they missed.&lt;/p&gt;

&lt;p&gt;Some people like to probe with an initial "hello" to verify whether the presence&lt;br&gt;
status shown is true, hoping they can determine whether the recipient is near a device,&lt;br&gt;
then will immediately follow up with a call. Don't do that either.&lt;br&gt;
If someone is able and willing to answer a chat message, it does not mean that they are also available for&lt;br&gt;
a voice or video call.&lt;/p&gt;

&lt;p&gt;Instead of sending a call probe, or asking "hey, do you have time for a call?"&lt;br&gt;
(which is better but not great), you can try something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2020-07-08 12:32:12 you: Hi - do you have X min for a quick call to talk about XYZ? [etc...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This does three things: it time bounds the request, it gives the recipient some context, and&lt;br&gt;
it helps you remember what you wanted to talk about if the recipient can't or doesn't respond&lt;br&gt;
until later.&lt;/p&gt;

&lt;p&gt;This version was inspired by the original website &lt;a href="http://www.nohello.com/"&gt;nohello.com&lt;/a&gt;.&lt;br&gt;
Acknowledgements go to the original anonymous author.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Create a blog with Pelican, hosted on Github/Netlify</title>
      <dc:creator>Mathieu</dc:creator>
      <pubDate>Sat, 18 Jul 2020 16:52:30 +0000</pubDate>
      <link>https://dev.to/mattioo/create-a-blog-with-pelican-hosted-on-github-netlify-498p</link>
      <guid>https://dev.to/mattioo/create-a-blog-with-pelican-hosted-on-github-netlify-498p</guid>
      <description>&lt;p&gt;&lt;em&gt;Original article : &lt;a href="https://brainsorting.dev/posts/create-a-blog-with-pelican/"&gt;https://brainsorting.dev/posts/create-a-blog-with-pelican/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I hope this article / tutorial will give you the essential knowledge and steps to create and deploy your Pelican static blog on Netlify for free !&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Goals&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install Pelican&lt;/li&gt;
&lt;li&gt;Create a website running on Pelican&lt;/li&gt;
&lt;li&gt;Deploy a Pelican based site to &lt;a href="http://netlify.com/"&gt;Netlify.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic knowledge about git and python&lt;/li&gt;
&lt;li&gt;Python 3 and git installed on your workstation&lt;/li&gt;
&lt;li&gt;VSCode or other IDE&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Install Pelican
&lt;/h2&gt;

&lt;p&gt;The first step is to create a python virtual environment on your machine and then install Pelican and other necessary dependencies.&lt;/p&gt;

&lt;p&gt;I personally use &lt;a href="https://python-poetry.org/"&gt;poetry&lt;/a&gt; and the command in your terminal would go this way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /path-to-your-blog-folder
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; poetry init

This &lt;span class="nb"&gt;command &lt;/span&gt;will guide you through creating your pyproject.toml config.

Package name &lt;span class="o"&gt;[&lt;/span&gt;blog]:
Version &lt;span class="o"&gt;[&lt;/span&gt;0.1.0]:
Description &lt;span class="o"&gt;[]&lt;/span&gt;:  My personal blog
Author &lt;span class="o"&gt;[&lt;/span&gt;MattiooFR &amp;lt;&lt;span class="k"&gt;*****&lt;/span&gt;@&lt;span class="k"&gt;*****&lt;/span&gt;.com&amp;gt;, n to skip]:
License &lt;span class="o"&gt;[]&lt;/span&gt;:
Compatible Python versions &lt;span class="o"&gt;[&lt;/span&gt;^3.8]:

Would you like to define your main dependencies interactively? &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt;/no&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; no
Would you like to define your development dependencies interactively? &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt;/no&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; no
Generated file

&lt;span class="c"&gt;# a few more lines telling your about the generated config file..&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; poetry shell
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; poetry add pelican Markdown typogrify invoke livereload
&lt;span class="c"&gt;# install happening...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; pelican-quickstart

Welcome to pelican-quickstart v4.2.0.

This script will &lt;span class="nb"&gt;help &lt;/span&gt;you create a new Pelican-based website.

Please answer the following questions so this script can generate the files
needed by Pelican.

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Where &lt;span class="k"&gt;do &lt;/span&gt;you want to create your new web site? &lt;span class="o"&gt;[&lt;/span&gt;.]
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; What will be the title of this web site? Your blog title
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Who will be the author of this web site? Your name
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; What will be the default language of this web site? &lt;span class="o"&gt;[&lt;/span&gt;fr] en
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Do you want to specify a URL prefix? e.g., https://example.com   &lt;span class="o"&gt;(&lt;/span&gt;Y/n&lt;span class="o"&gt;)&lt;/span&gt; n
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Do you want to &lt;span class="nb"&gt;enable &lt;/span&gt;article pagination? &lt;span class="o"&gt;(&lt;/span&gt;Y/n&lt;span class="o"&gt;)&lt;/span&gt; y
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; How many articles per page &lt;span class="k"&gt;do &lt;/span&gt;you want? &lt;span class="o"&gt;[&lt;/span&gt;10]
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; What is your &lt;span class="nb"&gt;time &lt;/span&gt;zone? &lt;span class="o"&gt;[&lt;/span&gt;Europe/Paris]
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Do you want to generate a tasks.py/Makefile to automate generation and publishing? &lt;span class="o"&gt;(&lt;/span&gt;Y/n&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Do you want to upload your website using FTP? &lt;span class="o"&gt;(&lt;/span&gt;y/N&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Do you want to upload your website using SSH? &lt;span class="o"&gt;(&lt;/span&gt;y/N&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Do you want to upload your website using Dropbox? &lt;span class="o"&gt;(&lt;/span&gt;y/N&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Do you want to upload your website using S3? &lt;span class="o"&gt;(&lt;/span&gt;y/N&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Do you want to upload your website using Rackspace Cloud Files? &lt;span class="o"&gt;(&lt;/span&gt;y/N&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Do you want to upload your website using GitHub Pages? &lt;span class="o"&gt;(&lt;/span&gt;y/N&lt;span class="o"&gt;)&lt;/span&gt;
Done. Your new project is available at &lt;span class="k"&gt;***&lt;/span&gt;/&lt;span class="k"&gt;***&lt;/span&gt;/Blog

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; pelican
&lt;span class="c"&gt;# says nothing to generate but it will still generate your empty blog files, congratulation !&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, now that we have the skeleton of our blog done we can move on to the next part.&lt;/p&gt;

&lt;p&gt;You should see an arborescence that looks like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
├── content            &lt;span class="c"&gt;# this is where your articles written in markdown for eg will be placed&lt;/span&gt;
├── output             &lt;span class="c"&gt;# your website will be generated in this folder&lt;/span&gt;
├── Makefile           &lt;span class="c"&gt;# file for automating generating and publishing tasks&lt;/span&gt;
├── pelicanconf.py     &lt;span class="c"&gt;# config file for the generation of the output&lt;/span&gt;
├── publishconf.py     &lt;span class="c"&gt;# also a config file for publishing&lt;/span&gt;
└── tasks.py           &lt;span class="c"&gt;# file also for the automation part&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now go in your content folder and create a file, for the purpose if this tutorial, here is a markdown file article.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Title: Prime number finder in python
Date: 2020-03-21 16:00
Tags: maths, python
Category: maths
Slug: primes-list
Authors: Mathieu
Summary: Find all the prime numbers in a composite number with python.

&lt;span class="gu"&gt;## Extract all the prime number from a composite number with python&lt;/span&gt;

This is a quick article to show you how to create an algorithm to extract all the prime numbers from a composite number in Python.

&lt;span class="gu"&gt;### Algorithm&lt;/span&gt;&lt;span class="sb"&gt;

    def primes_list(N):
        """
        Extract all the prime numbers
        from a composite number

        Keyword arguments:
        N -- an integer
        Return: a list of prime numbers
        """
        for i in range(N-1, 0, -1):
            if i == 1:
                return [N]
            elif N % i == 0:
                return [int(N/i)] + primes_list(int(i))

&lt;/span&gt;&lt;span class="gu"&gt;### Usage&lt;/span&gt;&lt;span class="sb"&gt;

    print(primes_lists(12))
    &amp;gt; [2,2,3]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first 7 lines will be more detailed in the next article but they are essential for pelican to generate properly your article and are called the metadata.&lt;/p&gt;

&lt;p&gt;On your terminal do the command &lt;code&gt;pelican&lt;/code&gt; or &lt;code&gt;invoke build&lt;/code&gt; (if you installed the invoke package) to generate the files for your new article, and if you now have a look in your blog folder you should see new folders and files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lets have a break with a quick explanation on the &lt;code&gt;invoke build&lt;/code&gt; command&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While following tutorial to learn myself how to use pelican to create a blog, I faced a few issues and I want to prevent you facing the same, while still understanding &lt;strong&gt;why.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The integrated &lt;code&gt;make ***&lt;/code&gt; commands produces errors when your blog folder is located in a path that includes spaces so this was the first pain point.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;make build&lt;/code&gt; doesn't output anything, the first time I thought there was a problem with my terminal but it was actually working. I don't like when things are unclear so this was a second pain point for me.&lt;/li&gt;
&lt;li&gt;The last and ultimate pain point was that the &lt;code&gt;make devserver&lt;/code&gt; is just not working. This command is supposed to automatically detect changes in your file and regenerate your blog.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After looking on the revered google, I discovered that a second command can be used. This is &lt;code&gt;invoke&lt;/code&gt; but you need to install a separate package, which is why I made you install it at the beginning. With this new package you could do &lt;code&gt;invoke build&lt;/code&gt; to build your blog without the path pain point.&lt;/p&gt;

&lt;p&gt;If you want to regenerate your blog when a changes in a file is detected, &lt;code&gt;invoke regenerate&lt;/code&gt; or &lt;code&gt;pelican --autoreload&lt;/code&gt; is your command.&lt;/p&gt;

&lt;p&gt;Alright, that was quite a long break but I think it was necessary !&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's see how your blog looks like no ?
&lt;/h2&gt;

&lt;p&gt;For that you need to use the command &lt;code&gt;invoke serve&lt;/code&gt; or  &lt;code&gt;pelican --listen&lt;/code&gt; in your terminal, if your terminal looks frozen don't worry, it actually works. If you now open your web navigator and go here &lt;a href="http://127.0.0.1:8000/"&gt;http://127.0.0.1:8000&lt;/a&gt; your blog should now appear !&lt;/p&gt;

&lt;p&gt;Now I will tell you a magical command that require one more package to be installed, it is &lt;code&gt;invoke livereload&lt;/code&gt;. If you followed the tutorial, you should already have installed the &lt;code&gt;livereload&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;If you do &lt;code&gt;invoke livereload&lt;/code&gt; your blog will be regenerated when a changes is made, AND your browser will be automatically reloaded as well ! Look at that ! Removing the need for you to do cmd + R !&lt;/p&gt;

&lt;p&gt;With one terminal windows running your blog will be served, auto regenerated, and your browser will be automatically reloaded each time you save a change in your blog. This is really really useful when you are developing your blog before deploying it to everybody.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hosting your blog files
&lt;/h2&gt;

&lt;p&gt;Create an account in &lt;a href="https://github.com/join?source=header-home"&gt;GitHub&lt;/a&gt; if you don't have one yet.&lt;/p&gt;

&lt;p&gt;Next, create a repository called "blog_source". This is where you will push all your blog files. Once the repository is made do the following command in your terminal at your blog folder location.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; git init
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; git add &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Initial commit"&lt;/span&gt;

&lt;span class="c"&gt;# change &amp;lt;your_github_name&amp;gt; in the command down below&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; git remote add origin https://github.com/&amp;lt;your_github_name&amp;gt;/blog_source.git
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Publishing your static blog
&lt;/h2&gt;

&lt;p&gt;Now that you have a beautiful basic blog locally, the next step is to make it available to everybody right ?&lt;/p&gt;

&lt;p&gt;Netlify offer the free service of hosting and deploying a free static page blog, and this what pelican is making 💪🏼, a free static page blog. The procedure is quite straightforward.&lt;/p&gt;

&lt;p&gt;Register in &lt;a href="https://app.netlify.com/signup"&gt;Netlify&lt;/a&gt;, you can signup with your GitHub account. After you signed up, click on create a new site and select Github as a source. You can accept to give only your blog_source repository to Netlify. In the last step you need to provide the command to build your website in the input labeled &lt;code&gt;build command&lt;/code&gt; which is &lt;code&gt;invoke build&lt;/code&gt;. The published directory is &lt;code&gt;output&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Netlify require a requirements.txt file to properly build your blog. Enter this command in your terminal to export your poetry dependencies to this required file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;poetry export -f requirements.txt &amp;gt; requirements.txt&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now your blog is almost ready, simply commit and push a new change in your blog, like adding a new article, and Netlify will automatically detect a change in your git repository. It will then build your files and deploy your static blog. In the settings you can specify the name of your blog. I personally decided to buy a domain name so I can have my own url like &lt;a href="http://www.brainsorting.dev"&gt;www.brainsorting.dev&lt;/a&gt; instead of &lt;a href="http://www.brainsorting.netlify.com"&gt;www.brainsorting.netlify.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The procedure is to directly buy the domain with Netlify, or buy it through &lt;a href="https://domains.google/"&gt;https://domains.google/&lt;/a&gt; and then follow the instruction in Netlify to use that domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing articles
&lt;/h2&gt;

&lt;p&gt;The power of Pelican is that you can write in markdown, reStructuredText or directly HTML and then it will be generated in the same output format, HTML. For writing in Markdown you need to have the parser package installed, which is done with a quick &lt;code&gt;pip install Markdown&lt;/code&gt;or &lt;code&gt;poetry add Markdown&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It is really helpful to add images, and to do so when writing in Markdown you need to follow those instructions.&lt;/p&gt;

&lt;p&gt;Create a new folder &lt;code&gt;images&lt;/code&gt; in your &lt;code&gt;content&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;pelicanconf.py&lt;/code&gt; file and add this line &lt;code&gt;STATIC_PATHS = ['images']&lt;/code&gt;. This is telling Pelican to include the folder images in the output when building your blog.&lt;/p&gt;

&lt;p&gt;Now you can write &lt;code&gt;![your_image](/images/your-images.png)&lt;/code&gt; in Markdown and get your image displayed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing a theme
&lt;/h2&gt;

&lt;p&gt;You can choose a pelican theme &lt;a href="http://pelicanthemes.com"&gt;here&lt;/a&gt;. Then store the theme somewhere in your blog folder, create a &lt;code&gt;THEME&lt;/code&gt; variable in your &lt;code&gt;pelicanconf.py&lt;/code&gt; file and set it to the location where you downloaded your theme in your blog folder.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing the Jupyter Plugin
&lt;/h2&gt;

&lt;p&gt;This &lt;a href="https://github.com/danielfrg/pelican-ipynb"&gt;plugin&lt;/a&gt; enables the support for .ipynb file. Create the &lt;code&gt;plugins&lt;/code&gt; folder. Run the &lt;code&gt;git submodule add git://github.com/danielfrg/pelican-ipynb.git plugins/ipynb&lt;/code&gt; command to add the plugin as git submodule in this folder.&lt;/p&gt;

&lt;p&gt;Be sure to have these lines in your &lt;code&gt;pelicanconf.py&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;MARKUP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'md'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'ipynb'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;PLUGIN_PATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'./plugins'&lt;/span&gt;
&lt;span class="n"&gt;PLUGINS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'ipynb.markup'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the notebook file into the &lt;code&gt;content&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;Create a file that has the same name as your notebook, but with the extension &lt;code&gt;.ipynb-meta&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add the following content to the &lt;code&gt;ipynb-meta&lt;/code&gt; file, but change the fields to match your own post:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Jupyter&lt;/span&gt; &lt;span class="n"&gt;notebook&lt;/span&gt;
&lt;span class="n"&gt;Slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;jupyter&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;
&lt;span class="n"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;07&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;
&lt;span class="n"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;posts&lt;/span&gt;
&lt;span class="n"&gt;Tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;pelican&lt;/span&gt;
&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;mathieu&lt;/span&gt; &lt;span class="n"&gt;dugue&lt;/span&gt;
&lt;span class="n"&gt;Summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Test&lt;/span&gt; &lt;span class="n"&gt;jupyter&lt;/span&gt; &lt;span class="n"&gt;notebook&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each time you want to add a new notebook you need to repeat those steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Useful Modules
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/cqql/pelican-katex"&gt;Katex in Pelican&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/getpelican/pelican-plugins"&gt;Pelican plugins&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.getpelican.com/en/3.3.0/"&gt;Official website of pelican&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/getpelican"&gt;Github of the pelican project with templates and plugins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet"&gt;A great Markdown Cheat Sheet for helping writing your articles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pelican.readthedocs.io/en/latest/settings.html"&gt;Pelican documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.dataquest.io/blog/how-to-setup-a-data-science-blog/"&gt;Dataquest tutorial to create a data science blog with Pelican&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Using environment variables in a Flask + Heroku project</title>
      <dc:creator>Mathieu</dc:creator>
      <pubDate>Tue, 05 May 2020 16:36:07 +0000</pubDate>
      <link>https://dev.to/mattioo/using-environment-variables-in-a-flask-heroku-project-1bn</link>
      <guid>https://dev.to/mattioo/using-environment-variables-in-a-flask-heroku-project-1bn</guid>
      <description>&lt;p&gt;&lt;em&gt;You can also read that article on my &lt;a href="https://www.brainsorting.dev/posts/environment-variable-flask-heroku/"&gt;blog&lt;/a&gt; or on &lt;a href="https://medium.com/@mattioo/using-environement-variables-in-a-flask-heroku-project-34a61b2ea15"&gt;medium&lt;/a&gt; !&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Using environment variables is fundamental in a project. This is how you tell your app if you are running in &lt;code&gt;production&lt;/code&gt; or &lt;code&gt;locally&lt;/code&gt; for example. This is where you also store more sensible information like &lt;code&gt;SECRET_KEY&lt;/code&gt; or API credentials. Storing those directly in your web app code can be easy at first, but it is not safe when you will push your code in production, so taking good habits from the beginning is a good idea.&lt;/p&gt;

&lt;p&gt;Before jumping in the topic of configuring environment variables, I will first make you set up and deploy a basic app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flask
&lt;/h2&gt;

&lt;p&gt;In this project I use Flask. Create a folder for your app and a new virtual environment (check out &lt;a href="https://github.com/python-poetry/poetry"&gt;poetry&lt;/a&gt; if you don't know what it is). Once your virtual environment is running, we need to install a few dependencies first :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# if you use poetry as virtual environment manager&lt;/span&gt;
&lt;span class="c"&gt;# use the command 'poetry add' instead of 'pip install'&lt;/span&gt;

pip &lt;span class="nb"&gt;install &lt;/span&gt;flask gunicorn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Flask is the web server running with python, and Gunicorn is what will basically run our web server on Heroku when we will deploy our app.&lt;/p&gt;

&lt;p&gt;Lets first set up a basic app and create a file &lt;code&gt;app.py&lt;/code&gt; in your folder :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;render_template&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/'&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;index&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hello"&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;excited&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'EXCITED'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"!!!!!"&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"index.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;greeting&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you see we will render an &lt;code&gt;index.html&lt;/code&gt; so create that file too inside a &lt;code&gt;templates&lt;/code&gt; folder and paste this code inside :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;My App&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        {{ greeting }}
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before running the web app locally we need to set two variable in your terminal so Flask knows what to do exactly :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;FLASK_ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;development
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;FLASK_APP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;app.py
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;EXCITED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lets run our app locally with &lt;code&gt;flask run&lt;/code&gt; . As you can see we are greeted like expected, with all the '!!!!', but I had to export the variable in my terminal. Every time you close your terminal you need to do that again. Not very efficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  Heroku
&lt;/h2&gt;

&lt;p&gt;Now if we want to deploy our app on Heroku we need to do a few things.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a &lt;code&gt;Procfile&lt;/code&gt; at the root of your folder. Paste this code inside :&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;web: gunicorn app:app
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We need to export all the python dependencies in a &lt;code&gt;requirements.txt&lt;/code&gt; file :&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip freeze &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# if you use poetry you can do as following&lt;/span&gt;
poetry &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; requirements.txt &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install Heroku CLI on your machine and then login on your Heroku account (&lt;a href="https://signup.heroku.com/"&gt;here to register&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# if you are on mac and use homebrew&lt;/span&gt;
brew tap heroku/brew &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; brew &lt;span class="nb"&gt;install &lt;/span&gt;heroku

&lt;span class="c"&gt;# you can also use npm&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; heroku
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Once Heroku is available on your terminal, we can create your Heroku App :&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;heroku create &amp;lt;name_of_your_app&amp;gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Now if you check your Heroku Dashboard in the browser, you'll see an application with that name. But it doesn't have our code or anything yet - it's completely empty. Let's get our code up there.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The next step is initializing git in your repository, and add the Heroku remote in your git repository :&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init
heroku git:remote &lt;span class="nt"&gt;-a&lt;/span&gt; &amp;lt;name_of_your_app&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now before pushing our app on Heroku, we need to set that &lt;code&gt;EXCITED&lt;/code&gt; variable to true. You can do that on the web interface of Heroku, or using the CLI with :&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;heroku config:set &lt;span class="nv"&gt;EXCITED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;True
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To push our web app to Heroku we can simply do :&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt;&lt;span class="s2"&gt;"deploying app on heroku"&lt;/span&gt;
git push heroku master
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now if you look at &lt;a href="https://name_of_your_app.heroku.com"&gt;https://name_of_your_app.heroku.com&lt;/a&gt; you should have a nice excited greeting message : &lt;code&gt;Hello !!!!&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Environment Variable
&lt;/h2&gt;

&lt;p&gt;Alright, thank you Mathieu, but how is that suppose to teach us how to manage environment variable ?&lt;/p&gt;

&lt;p&gt;Well, now that you are set up properly, let me introduce the &lt;code&gt;.env&lt;/code&gt;  and &lt;code&gt;.flaskenv&lt;/code&gt; files. By convention, the &lt;code&gt;.flaskenv&lt;/code&gt; is where you store your variables related to your flask configuration, such as the type of environment, or the files that contains your flask app. For this example we will write those lines inside this file :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#.flaskenv file

FLASK_APP=app.py
FLASK_ENV=development
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the &lt;code&gt;.env&lt;/code&gt; file contains the sensible variable information that your app needs to run. This file stay locally and you must include it in your &lt;code&gt;.gitignore&lt;/code&gt; to avoid sharing sensible informations. For the purpose of this tutorial we will just include one variable :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#.env file

EXCITED=True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your folder structure should look something like this :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── templates
    └── index.html
├── .env
├── .flaskenv
├── .gitignore
├── Procfile
├── app.py
└── requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have two different use case possible. If you want to use flask to run your app locally you need to install one more dependencies&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;python-dotenv

&lt;span class="c"&gt;# with poetry use&lt;/span&gt;
poetry add python-dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You don't need to do anything else, thanks to this new package, flask will automatically detect your two new files and will load their variables in the app context.&lt;/p&gt;

&lt;p&gt;If instead of using flask to run your app locally you prefer to use &lt;code&gt;heroku local web&lt;/code&gt; then you don't need to install &lt;code&gt;python-dotenv&lt;/code&gt;, Heroku will detect the &lt;code&gt;.env&lt;/code&gt; file by itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We saw how to implement a behavior that allows us to protect our sensible information by putting them in external files that wont be pushed to a public git repository. In the same time our app will work seamlessly when deployed on Heroku, if you set up the same variables in your &lt;code&gt;.env&lt;/code&gt; files on the config of your Heroku app (with the web interface or the CLI).&lt;/p&gt;

&lt;p&gt;You can find all the code of this tutorial &lt;a href="https://github.com/MattiooFR/Tutorials/tree/master/FlaskHerokuEnv"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>flask</category>
      <category>heroku</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Publish a package on PyPi using Poetry</title>
      <dc:creator>Mathieu</dc:creator>
      <pubDate>Tue, 05 May 2020 16:36:05 +0000</pubDate>
      <link>https://dev.to/mattioo/publish-a-package-on-pypi-using-poetry-5e5</link>
      <guid>https://dev.to/mattioo/publish-a-package-on-pypi-using-poetry-5e5</guid>
      <description>&lt;p&gt;&lt;em&gt;You can also read that article on my &lt;a href="https://www.brainsorting.dev/posts/publish-a-package-on-pypi-using-poetry/"&gt;blog&lt;/a&gt; or on &lt;a href="https://medium.com/@mattioo/publish-a-package-on-pypi-using-poetry-f55c169fd43e"&gt;medium&lt;/a&gt; !&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;First thing first, you need Poetry if you don't have it already.&lt;/p&gt;

&lt;p&gt;Poetry is the new standard for creating and managing virtual environment for your Python project. It is also a Python dependency management tool that is working differently as pip. It uses the new standard &lt;code&gt;pyproject.toml&lt;/code&gt; decided by the Python Packaging Authority with PEP-518. This file merges all the previous config files that were necessary before, &lt;code&gt;setup.py&lt;/code&gt;, &lt;code&gt;requirements.txt&lt;/code&gt;, &lt;code&gt;setup.cfg&lt;/code&gt;, &lt;code&gt;MANIFEST.in&lt;/code&gt; et &lt;code&gt;Pipfile&lt;/code&gt;, in one unique file to rule them all ! Ok, enough of Lord of the Ring.&lt;/p&gt;

&lt;p&gt;I advise you to follow along with the &lt;a href="https://python-poetry.org/docs/cli/"&gt;documentation&lt;/a&gt; of poetry open.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Poetry
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sSL&lt;/span&gt; https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py | python
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feel free to look &lt;a href="https://python-poetry.org/docs/"&gt;here&lt;/a&gt; for more instructions. Updating Poetry is very easy by the way &lt;code&gt;poetry update&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create the package you want to publish on PyPi
&lt;/h2&gt;

&lt;p&gt;Poetry has a nice command that can create your project tree at once &lt;code&gt;poetry new &amp;lt;package_name&amp;gt;&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/&amp;lt;package_name&amp;gt;
├── README.rst &lt;span class="c"&gt;# I personnaly change it to .md as I prefer writing in Markdown&lt;/span&gt;
├── &amp;lt;package_name&amp;gt;
│   └── __init__.py
├── pyproject.toml
└── tests
    ├── __init__.py
    └── test_package_name.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will need to add things to the generated &lt;code&gt;pyproject.toml&lt;/code&gt; file, feel free to check the &lt;a href="https://poetry.eustace.io/docs/pyproject/"&gt;poetry documentation&lt;/a&gt; to see all the options.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;tool.poetry&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="s"&gt;name = "vspoetry"&lt;/span&gt;
&lt;span class="s"&gt;version = "0.1.0"&lt;/span&gt;
&lt;span class="s"&gt;description = "Description of your package"&lt;/span&gt;
&lt;span class="s"&gt;authors = ["MattiooFR &amp;lt;dugue.mathieu@gmail.com&amp;gt;"]&lt;/span&gt;
&lt;span class="s"&gt;keywords = ["keyword", "another_keyword"]&lt;/span&gt;
&lt;span class="s"&gt;readme = "README.md"&lt;/span&gt;
&lt;span class="s"&gt;license = "MIT"&lt;/span&gt;
&lt;span class="s"&gt;homepage = "https://github.com/MattiooFR/package_name"&lt;/span&gt;
&lt;span class="s"&gt;repository = "https://github.com/MattiooFR/package_name"&lt;/span&gt;
&lt;span class="s"&gt;include = [&lt;/span&gt;
    &lt;span class="s"&gt;"LICENSE",&lt;/span&gt;
&lt;span class="err"&gt;]&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;tool.poetry.dependencies&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="s"&gt;python = "^3.5"&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;tool.poetry.dev-dependencies&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;tool.poetry.scripts&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="s"&gt;cli_command_name = 'package_name:function'&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;build-system&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="s"&gt;requires = ["poetry&amp;gt;=0.12"]&lt;/span&gt;
&lt;span class="s"&gt;build-backend = "poetry.masonry.api"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The beginning of the file is pretty straightforward. Lets focus on those three part :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;[tool.poetry.dependencies]&lt;/strong&gt;: This is where you can list all the dependencies that your package needs to work. It's like the old &lt;code&gt;requirements.txt&lt;/code&gt; file.
You can do it by hand and then call the command &lt;code&gt;poetry install&lt;/code&gt; to install them all for your package development and working purposes. If you use &lt;code&gt;poetry add &amp;lt;dependency_name&amp;gt;&lt;/code&gt; (equivalent to the &lt;code&gt;pip install &amp;lt;dependency_name&amp;gt;&lt;/code&gt;), poetry will add it there for you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;[tool.poetry.dev-dependencies]&lt;/strong&gt;: If you need development dependencies, that's where they go. Again, you can also install them with &lt;code&gt;poetry add &amp;lt;dependency_name&amp;gt; --dev (or -D)&lt;/code&gt; and poetry will also put that in the right place in your &lt;code&gt;pyproject.toml&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;[tool.poetry.scripts]&lt;/strong&gt;: This last block is very important if you want your package to have script callable from the terminal.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;script_name = '{package_name}:{function_name}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the way, if you still need to have a &lt;code&gt;requirements.txt&lt;/code&gt; with all the dependencies (if you use Heroku for example), you can easily have it with this command :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; requirements.txt &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Build your package
&lt;/h2&gt;

&lt;p&gt;When your package is ready, simply do &lt;code&gt;poetry build&lt;/code&gt; to create the package files&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;❯ poetry build
Building package_name &lt;span class="o"&gt;(&lt;/span&gt;0.1.0&lt;span class="o"&gt;)&lt;/span&gt;
 - Building sdist
 - Built package_name-0.1.0.tar.gz

 - Building wheel
 - Built package_name-0.1.0-py3-none-any.whl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can test your package by doing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &amp;lt;path_to_package_name-0.1.0-py3-none-any.whl&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything works, congrats ! Now lets publish it to PyPi so others can use your great package too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Publish your package
&lt;/h2&gt;

&lt;p&gt;Before publishing you should first create an account on &lt;a href="https://pypi.org/account/register/"&gt;PyPi&lt;/a&gt;. You can also register an account on &lt;a href="https://test.pypi.org/account/register/"&gt;TestPyPi&lt;/a&gt; if you want publishing on a test repository before trying on the official one.&lt;/p&gt;

&lt;p&gt;Your package need to be built, so first run &lt;code&gt;poetry build&lt;/code&gt; if you haven't done it already.&lt;/p&gt;

&lt;p&gt;Then simply run &lt;code&gt;poetry publish&lt;/code&gt; and your package will be publish on PyPi :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;❯ poetry publish

Publishing vspoetry &lt;span class="o"&gt;(&lt;/span&gt;0.1.0&lt;span class="o"&gt;)&lt;/span&gt; to PyPI
Username: Mattioo
Password:
 - Uploading vspoetry-0.1.0-py3-none-any.whl 100%
 - Uploading vspoetry-0.1.0.tar.gz 100%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you need to update your package, simply increment the version in the &lt;code&gt;pyproject.toml&lt;/code&gt; file and use &lt;code&gt;poetry publish&lt;/code&gt; (after you build the new package with &lt;code&gt;poetry build&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Once you have done that you can then install your package :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &amp;lt;your_package&amp;gt;

poetry add &amp;lt;your_package&amp;gt; &lt;span class="c"&gt;# but lets be honest now you use Poetry so you would do this !&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congrats on publishing your package on PyPi and experiencing the simplicity of using a tool like Poetry.&lt;/p&gt;

&lt;p&gt;Happy coding !&lt;/p&gt;

&lt;h2&gt;
  
  
  End notes
&lt;/h2&gt;

&lt;p&gt;I actually just published my first package, &lt;a href="https://pypi.org/project/vspoetry/"&gt;vspoetry&lt;/a&gt;, while writing this tutorial. It is a package that add the &lt;code&gt;vspoetry&lt;/code&gt; script command to my terminal and this simply add the path of the current poetry virtual environment of the project to VScode &lt;code&gt;settings.json&lt;/code&gt;. This tells to VScode where to grab the project python venv because VScode does not do that automatically yet.&lt;/p&gt;

</description>
      <category>pypi</category>
      <category>poetry</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Create a blog using Nikola static website generator</title>
      <dc:creator>Mathieu</dc:creator>
      <pubDate>Tue, 05 May 2020 16:36:03 +0000</pubDate>
      <link>https://dev.to/mattioo/create-a-blog-using-nikola-static-website-generator-l71</link>
      <guid>https://dev.to/mattioo/create-a-blog-using-nikola-static-website-generator-l71</guid>
      <description>&lt;p&gt;&lt;em&gt;You can also read that article on my &lt;a href="https://www.brainsorting.dev/posts/create-a-blog-with-nikola/"&gt;blog&lt;/a&gt; or on &lt;a href="https://medium.com/@mattioo/create-a-blog-using-nikola-static-website-generator-ecb30f73d9fb"&gt;medium&lt;/a&gt; !&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you don't know what is Nikola, it is a static website/blog generator (like gatsby and other tools). It's written in Python and it is working out of the box for rendering markdown, rst, latex math formula and jupyter notebook files.&lt;/p&gt;

&lt;p&gt;I like to understand what I am using, and pushing it to some limits to really get what I want from it, and making a blog with Nikola was no exception. Here I tried to summarize all the informations I found, and all the experimentation I did. I hope you'll enjoy ! 🙏🏼&lt;/p&gt;

&lt;h2&gt;
  
  
  1) Installation
&lt;/h2&gt;

&lt;p&gt;The first step is to have Python 3 installed on your computer, I recommend using virtual environment management.&lt;/p&gt;

&lt;p&gt;Once you have create your virtual environment :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; pip setuptools wheel
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; &lt;span class="s2"&gt;"Nikola[extras]"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2) Create the blog
&lt;/h2&gt;

&lt;p&gt;After installing Nikola, creating your site will be very easy, just use the command &lt;code&gt;nikola init &amp;lt;directory_name&amp;gt;&lt;/code&gt;. You can add the &lt;code&gt;--demo&lt;/code&gt; argument if you want a website built with demo content.&lt;/p&gt;

&lt;p&gt;All the configurations are done in a single &lt;code&gt;conf.py&lt;/code&gt; file, at the root of your blog folder.&lt;/p&gt;

&lt;p&gt;You can now build your site and see how it looks like. Use the command &lt;code&gt;nikola auto&lt;/code&gt; to use a server with automatic rebuilds when changes is detected in your files. Visit &lt;a href="http://128.0.0.1:8000"&gt;http://128.0.0.1:8000&lt;/a&gt; to see your site.&lt;/p&gt;

&lt;h2&gt;
  
  
  3) Add a Post
&lt;/h2&gt;

&lt;p&gt;Now if you want to add a post in your blog you should use the command &lt;code&gt;nikola new_post&lt;/code&gt;(the default use reStructuredText format, add &lt;code&gt;-f markdown&lt;/code&gt; if like me you prefer to write in markdown). The CLI will ask for the title of your blog post and then create the file in the folder &lt;code&gt;posts/*.md&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  4) Enable Jupyter Notebook file format
&lt;/h2&gt;

&lt;p&gt;Just add &lt;code&gt;*.ipynb&lt;/code&gt; as recognizable formats:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;POSTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"posts/*.rst"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"blog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"post.tmpl"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"posts/*.md"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"blog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"post.tmpl"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"posts/*.txt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"blog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"post.tmpl"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"posts/*.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"blog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"post.tmpl"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"posts/*.ipynb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"blog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"post.tmpl"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;# new line
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;PAGES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pages/*.rst"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"page.tmpl"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pages/*.md"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"page.tmpl"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pages/*.txt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"page.tmpl"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pages/*.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"page.tmpl"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pages/*.ipynb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"page.tmpl"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;# new line
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can create a blog post with &lt;code&gt;nikola new_post -f ipynb&lt;/code&gt; or add your jupyter notebook in your &lt;code&gt;posts&lt;/code&gt; folder. Don't forget to add and configure these line in the metadata of your jupyter notebook file if you don't let nikola create the file for yourself :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="s"&gt;"nikola"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="s"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s"&gt;"date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"2020-03-28 16:27:51 UTC+01:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s"&gt;"link"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s"&gt;"slug"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"jupyter-notebook-test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Jupyter Notebook Test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"text"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5) Using Markdown for your post
&lt;/h2&gt;

&lt;p&gt;Nikola handle markdown files by default. The meta are auto generated when you use &lt;code&gt;nikola new_post&lt;/code&gt; but I prefer to do it differently. Add the &lt;code&gt;markdown.extensions.meta&lt;/code&gt; to your &lt;code&gt;conf.py&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;MARKDOWN_EXTENSIONS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
 &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'markdown.extensions.fenced_code'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'markdown.extensions.codehilite'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'markdown.extensions.extra'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'markdown.extensions.meta'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can simply add these line on top of your markdown files, in a pelican style, to indicate Nikola all the information it needs to build your post :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Title: Test post in markdown
Date: 2020-04-01
Slug: test-post
Tags: markdown, test
Categories: Tutorial
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my situation I decided to use &lt;code&gt;pandoc&lt;/code&gt; instead of the default markdown compiler. I did this because I often have code blocks nested in numbered or bullet list and the default markdown compiler does not render those properly. It also looses the numbered list sometimes whereas &lt;code&gt;pandoc&lt;/code&gt; is doing an absolute great job. Thanks to this &lt;a href="https://mrinalpurohit.in/blog/moving-from-markdown-to-pandoc-in-nikola/"&gt;great blog post&lt;/a&gt; that was explaining how to do it !&lt;/p&gt;

&lt;p&gt;To use &lt;code&gt;pandoc&lt;/code&gt; instead of the default markdown you need to first install it. You can use &lt;code&gt;brew install pandoc&lt;/code&gt; if you have a mac, or look &lt;a href="https://pandoc.org/installing.html"&gt;here&lt;/a&gt; for more instructions. Then you can change those lines in the &lt;code&gt;conf.py&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;COMPILERS &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"rest"&lt;/span&gt;: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.rst'&lt;/span&gt;, &lt;span class="s1"&gt;'.txt'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;,
    &lt;span class="c"&gt;# "markdown": ('.md', '.mdown', '.markdown'),&lt;/span&gt;
    &lt;span class="s2"&gt;"textile"&lt;/span&gt;: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.textile'&lt;/span&gt;,&lt;span class="o"&gt;)&lt;/span&gt;,
    &lt;span class="s2"&gt;"txt2tags"&lt;/span&gt;: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.t2t'&lt;/span&gt;,&lt;span class="o"&gt;)&lt;/span&gt;,
    &lt;span class="s2"&gt;"bbcode"&lt;/span&gt;: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.bb'&lt;/span&gt;,&lt;span class="o"&gt;)&lt;/span&gt;,
    &lt;span class="s2"&gt;"wiki"&lt;/span&gt;: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.wiki'&lt;/span&gt;,&lt;span class="o"&gt;)&lt;/span&gt;,
    &lt;span class="s2"&gt;"ipynb"&lt;/span&gt;: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.ipynb'&lt;/span&gt;,&lt;span class="o"&gt;)&lt;/span&gt;,
    &lt;span class="s2"&gt;"html"&lt;/span&gt;: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.html'&lt;/span&gt;, &lt;span class="s1"&gt;'.htm'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;,
    &lt;span class="c"&gt;# PHP files are rendered the usual way (i.e. with the full templates).&lt;/span&gt;
    &lt;span class="c"&gt;# The resulting files have .php extensions, making it possible to run&lt;/span&gt;
    &lt;span class="c"&gt;# them without reconfiguring your server to recognize them.&lt;/span&gt;
    &lt;span class="s2"&gt;"php"&lt;/span&gt;: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.php'&lt;/span&gt;,&lt;span class="o"&gt;)&lt;/span&gt;,
    &lt;span class="c"&gt;# Pandoc detects the input from the source filename&lt;/span&gt;
    &lt;span class="c"&gt;# but is disabled by default as it would conflict&lt;/span&gt;
    &lt;span class="c"&gt;# with many of the others.&lt;/span&gt;
    &lt;span class="s2"&gt;"pandoc"&lt;/span&gt;: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.md'&lt;/span&gt;, &lt;span class="s1"&gt;'txt'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;,
&lt;span class="o"&gt;}&lt;/span&gt;
...
PANDOC_OPTIONS &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'-f'&lt;/span&gt;, &lt;span class="s1"&gt;'gfm'&lt;/span&gt;, &lt;span class="s1"&gt;'--toc'&lt;/span&gt;, &lt;span class="s1"&gt;'-s'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See how I commented the markdown compiler and uncommented &lt;code&gt;pandoc&lt;/code&gt; for &lt;code&gt;.md&lt;/code&gt; files. The last two &lt;code&gt;PANDOC_OPTIONS&lt;/code&gt; (--toc and -s) are used for automatically generating a Table of Content on the HTML generated output.&lt;/p&gt;

&lt;p&gt;Once you use pandoc for compiling your markdown file, for creating a new blog post in markdown you need yo use this command &lt;code&gt;nikola new _post -f pandoc&lt;/code&gt; and not markdown anymore.&lt;/p&gt;

&lt;p&gt;Adding solely the pandoc as markdown compiler is unfortunately not enough because we lose the ability to use the &lt;code&gt;CODE_COLOR_SCHEME = monokai&lt;/code&gt; option in conf.py. One solution is to use &lt;code&gt;pandoc&lt;/code&gt; generated css for one of its code highlight theme (kate in my case).&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;custom.css&lt;/code&gt; file in &lt;code&gt;files/assets/css/&lt;/code&gt; as explained here and add this css code :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;white-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pre-wrap&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.smallcaps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;font-variant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;small-caps&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.underline&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;underline&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nc"&gt;.column&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;vertical-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;top&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;

&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nc"&gt;.sourceLine&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.25&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nc"&gt;.sourceLine&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;pointer-events&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inherit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inherit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nc"&gt;.sourceLine&lt;/span&gt;&lt;span class="nd"&gt;:empty&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.2em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.sourceCode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt;&lt;span class="nc"&gt;.sourceCode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;white-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pre&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nc"&gt;.sourceCode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1em&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;pre&lt;/span&gt;&lt;span class="nc"&gt;.sourceCode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nc"&gt;.sourceCode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&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;@media&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt;&lt;span class="nc"&gt;.sourceCode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;white-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pre-wrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nc"&gt;.sourceLine&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;text-indent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-1em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;padding-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1em&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="nt"&gt;pre&lt;/span&gt;&lt;span class="nc"&gt;.numberSource&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nc"&gt;.sourceLine&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;pre&lt;/span&gt;&lt;span class="nc"&gt;.numberSource&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nc"&gt;.sourceLine&lt;/span&gt;&lt;span class="nd"&gt;:empty&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;pre&lt;/span&gt;&lt;span class="nc"&gt;.numberSource&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nc"&gt;.sourceLine&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data-line-number&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-5em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;right&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;vertical-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;baseline&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;pointer-events&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-webkit-touch-callout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;-webkit-user-select&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-khtml-user-select&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;-moz-user-select&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-ms-user-select&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="py"&gt;user-select&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#a0a0a0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;pre&lt;/span&gt;&lt;span class="nc"&gt;.numberSource&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;border-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#a0a0a0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="nl"&gt;padding-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nc"&gt;.sourceCode&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#1f1c1b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nc"&gt;.sourceLine&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;underline&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="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#1f1c1b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Normal */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.al&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#bf0303&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#f7e6e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Alert */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.an&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ca60ca&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Annotation */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.at&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0057ae&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Attribute */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.bn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#b08000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* BaseN */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.bu&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#644a9b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* BuiltIn */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.cf&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#1f1c1b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* ControlFlow */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.ch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#924c9d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Char */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.cn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#aa5500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Constant */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.co&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#898887&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Comment */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.cv&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0095ff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* CommentVar */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#607880&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Documentation */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.dt&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0057ae&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* DataType */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.dv&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#b08000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* DecVal */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.er&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#bf0303&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;underline&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Error */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.ex&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0095ff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Extension */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.fl&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#b08000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Float */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.fu&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#644a9b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Function */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.im&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ff5500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Import */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#b08000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Information */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.kw&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#1f1c1b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Keyword */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.op&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#1f1c1b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Operator */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.ot&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#006e28&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Other */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.pp&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#006e28&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Preprocessor */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.re&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0057ae&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#e0e9f8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* RegionMarker */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.sc&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#3daee9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* SpecialChar */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.ss&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ff5500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* SpecialString */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.st&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#bf0303&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* String */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.va&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0057ae&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Variable */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.vs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#bf0303&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* VerbatimString */&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.wa&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#bf0303&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Warning */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your code blocks should be highlighted. It's up to you to custom it further to change the color background or stuff like this.&lt;/p&gt;

&lt;p&gt;I also wanted to style the table of content :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.p-summary.entry-summary&lt;/span&gt; &lt;span class="nf"&gt;#TOC&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;None&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* disable showing the TOC in my blog home page teasers */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;#TOC&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#e9f8f8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;18px&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6) Pages vs Posts
&lt;/h2&gt;

&lt;p&gt;Nikola has two type for entries on your website, POSTS and PAGES.&lt;/p&gt;

&lt;h3&gt;
  
  
  POSTS
&lt;/h3&gt;

&lt;p&gt;These are your blog posts. POSTS are added to feeds, indexes, tag lists and archives.&lt;/p&gt;

&lt;h3&gt;
  
  
  PAGES
&lt;/h3&gt;

&lt;p&gt;These are generally static pages that may be built when you design your website. Once your design will be done you should not been making many new pages.&lt;/p&gt;

&lt;p&gt;For example in PAGES, I have the following pages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resume (html)&lt;/li&gt;
&lt;li&gt;Cheatsheet (html)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7) Customizing the navigation bar
&lt;/h2&gt;

&lt;p&gt;Customization of the navigation top bar is done, again, in the &lt;code&gt;conf.py&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;NAVIGATION_LINKS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;DEFAULT_LANG&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="s"&gt;"/resume/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Resume"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/cheatsheet/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Cheatsheet"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/archive/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Archive"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an example of how I've done mine.&lt;/p&gt;

&lt;h2&gt;
  
  
  8) Indexes as a list of links or list of posts
&lt;/h2&gt;

&lt;p&gt;Nikola allows you to categorize posts in a number of ways such as category, tags, archives, and authors. For each means of categorizing, an associated index page is generated so that viewers can see all available posts (&lt;em&gt;_PAGES_ARE_INDEXES = True&lt;/em&gt;) or links associated to that category (&lt;em&gt;_PAGES_ARE_INDEXES = False&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;You can choose for these indexes to produce a list of the full posts (or showing teasers instead of the full post) or a list of links to each post. Depending on your needs, you can change any of the following index settings in &lt;code&gt;conf.py&lt;/code&gt; to True.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;CATEGORY_PAGES_ARE_INDEXES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;span class="n"&gt;TAG_PAGES_ARE_INDEXES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;span class="n"&gt;ARCHIVES_ARE_INDEXES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;span class="n"&gt;AUTHOR_PAGES_ARE_INDEXES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what makes Nikola so customizable. For example, since there are less Categories, and you may have more posts under each category, you might want them as a list of links. Alternatively, with Tags there are usually more of them, so less posts under each Tag so you want a list of posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  9) Enable a comment system
&lt;/h2&gt;

&lt;p&gt;Because static sites do not have databases, you need to use a third-party comment system as documented on the official doc.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sign up for an account on &lt;a href="https://disqus.com/"&gt;https://disqus.com/&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;On Disqus, select "Create a new site" (or visit &lt;a href="https://disqus.com/admin/create/"&gt;https://disqus.com/admin/create/&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;During configuration, take note on the "Shortname" you use. Other configs are not very important.&lt;/li&gt;
&lt;li&gt;At "Select a plan", choosing the basic free plan is enough.&lt;/li&gt;
&lt;li&gt;At "Select Platform", just skip the instructions. No need to insert the "Universal Code" manually, as it is built into Nikola. Keep all default and finish the configuration.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In &lt;code&gt;conf.py&lt;/code&gt;, add your Disqus shortname:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;COMMENT_SYSTEM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"disqus"&lt;/span&gt;
&lt;span class="n"&gt;COMMENT_SYSTEM_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"[disqus-shortname]"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deploy to GitHub and now the comment system should be enabled.&lt;/p&gt;

&lt;h2&gt;
  
  
  10) Deploying your website
&lt;/h2&gt;

&lt;p&gt;My workflow is separated in two parts :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Github Pages&lt;/li&gt;
&lt;li&gt;Netlify&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Github Pages
&lt;/h3&gt;

&lt;p&gt;I decided to host my blog files on GitHub and use their free service, GitHub Pages, for deploying my blog on this address &lt;a href="https://mattioo.github.io"&gt;https://mattioo.github.io&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For doing that you will need to have a &lt;a href="https://github.com/"&gt;GitHub&lt;/a&gt; account, and enable &lt;a href="https://pages.github.com/"&gt;GitHub Pages&lt;/a&gt;. Once you created your repository as explained for GitHub Pages, initialize GitHub in your source directory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init &lt;span class="nb"&gt;.&lt;/span&gt;
git remote add origin https://github.com/&amp;lt;USER_NAME&amp;gt;/&amp;lt;USER_NAME&amp;gt;.github.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;conf.py&lt;/code&gt; should have the following settings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;GITHUB_SOURCE_BRANCH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'src'&lt;/span&gt;
&lt;span class="n"&gt;GITHUB_DEPLOY_BRANCH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'master'&lt;/span&gt;
&lt;span class="n"&gt;GITHUB_REMOTE_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'origin'&lt;/span&gt;
&lt;span class="n"&gt;GITHUB_COMMIT_SOURCE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;.gitignore&lt;/code&gt; file with the following entries as a minimum. You may use &lt;a href="https://www.gitignore.io/"&gt;gitignore.io&lt;/a&gt; to generate a suitable set of &lt;code&gt;.gitignore&lt;/code&gt; entries for your platform by typing in the relevant tags (e.g., mac,&lt;code&gt;nikola&lt;/code&gt;,jupyternotebooks).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cache
.doit.db
__pycache__
output
ipynb_checkpoints
*/.ipynb_checkpoints/*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By using the &lt;code&gt;nikola github_deploy&lt;/code&gt; command, it will create a &lt;code&gt;src&lt;/code&gt; branch that will contain your contents (i.e., &lt;code&gt;*.ipynb&lt;/code&gt;, &lt;code&gt;*.md&lt;/code&gt;, and a &lt;code&gt;master&lt;/code&gt; branch that will only contain your html output pages that are viewed by the browser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nikola github_deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Netlify extra steps
&lt;/h3&gt;

&lt;p&gt;Because of &lt;a href="https://dev.to/eroberts/why-you-should-use-netlify-instead-of-github-pages-3on1"&gt;all these reasons&lt;/a&gt; I wanted to use Netlify for deploying my blog with a custom domains, &lt;a href="http://www.brainsorting.dev"&gt;www.brainsorting.dev&lt;/a&gt;. I simply configured a trigger on Netlify to start building my blog when it detects any new push on my GitHub blog repository. It is as simple as said, everything kind of works out of the box and the service provided by Netlify has been very stable and giving me very good SEO statistics.&lt;/p&gt;

&lt;h2&gt;
  
  
  11) Archives
&lt;/h2&gt;

&lt;p&gt;Nikola has many options for how you would display your archive of posts. I've kept it pretty simple on my end.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Create per-month archives instead of per-year
&lt;/span&gt;&lt;span class="n"&gt;CREATE_MONTHLY_ARCHIVE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;span class="c1"&gt;# Create one large archive instead of per-year
&lt;/span&gt;&lt;span class="n"&gt;CREATE_SINGLE_ARCHIVE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;span class="c1"&gt;# Create year, month, and day archives each with a (long) list of posts
# (overrides both CREATE_MONTHLY_ARCHIVE and CREATE_SINGLE_ARCHIVE)
&lt;/span&gt;&lt;span class="n"&gt;CREATE_FULL_ARCHIVES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;span class="c1"&gt;# If monthly archives or full archives are created, adds also one archive per day
&lt;/span&gt;&lt;span class="n"&gt;CREATE_DAILY_ARCHIVE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;span class="c1"&gt;# Create previous, up, next navigation links for archives
&lt;/span&gt;&lt;span class="n"&gt;CREATE_ARCHIVE_NAVIGATION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;span class="n"&gt;ARCHIVE_PATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"archive"&lt;/span&gt;
&lt;span class="n"&gt;ARCHIVE_FILENAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"archive.html"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  12) Content Footer
&lt;/h2&gt;

&lt;p&gt;I use the recommended license :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;LICENSE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"""
&amp;lt;a rel="license" href="https://creativecommons.org/licenses/by-nc-sa/4.0/"&amp;gt;
&amp;lt;img alt="Creative Commons License BY-NC-SA"
style="border-width:0; margin-bottom:12px;"
src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png"&amp;gt;&amp;lt;/a&amp;gt;"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might want to have a specific message (i.e., license, copyright, contact e-mail address) at the footer of every page and this is where to do it. In this case I've added a &lt;a href="https://mailchimp.com/"&gt;Mailchimp&lt;/a&gt; link so that readers can subscribe to my page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;CONTENT_FOOTER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'''
&amp;lt;center&amp;gt;
'''&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;MAILCHIMP_SIGNUP&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;'''
&amp;lt;br&amp;gt;
Contents &amp;amp;copy; {date} &amp;lt;a href="mailto:{email}"&amp;gt;{author}&amp;lt;/a&amp;gt; &amp;lt;a href="https://dev.to/mattioo"&amp;gt;&amp;lt;i class="fab fa-dev" title="mattioo's DEV Profile"&amp;gt;&amp;lt;/i&amp;gt; &amp;lt;/a&amp;gt; - Powered by &amp;lt;a href="https://getnikola.com" rel="nofollow"&amp;gt;Nikola&amp;lt;/a&amp;gt; {license} - favicon &amp;lt;a href="https://www.flaticon.com/"&amp;gt;FlatIcon&amp;lt;/a&amp;gt;
&amp;lt;/center&amp;gt;
&amp;lt;br&amp;gt;
'''&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  13) Rendering math equations
&lt;/h2&gt;

&lt;p&gt;I have enabled KaTeX because its prettier with the &lt;code&gt;$...$&lt;/code&gt; syntax as thats more similar to LaTeX.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;USE_KATEX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="n"&gt;KATEX_AUTO_RENDER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"""
delimiters: [
    {left: "$$", right: "$$", display: true},
    {left: "&lt;/span&gt;&lt;span class="se"&gt;\\\\&lt;/span&gt;&lt;span class="s"&gt;[", right: "&lt;/span&gt;&lt;span class="se"&gt;\\\\&lt;/span&gt;&lt;span class="s"&gt;]", display: true},
    {left: "&lt;/span&gt;&lt;span class="se"&gt;\\\\&lt;/span&gt;&lt;span class="s"&gt;begin{equation*}", right: "&lt;/span&gt;&lt;span class="se"&gt;\\\\&lt;/span&gt;&lt;span class="s"&gt;end{equation*}", display: true},
    {left: "$", right: "$", display: false},
    {left: "&lt;/span&gt;&lt;span class="se"&gt;\\\\&lt;/span&gt;&lt;span class="s"&gt;(", right: "&lt;/span&gt;&lt;span class="se"&gt;\\\\&lt;/span&gt;&lt;span class="s"&gt;)", display: false}
]
"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  14) Implementing Google tools
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Google search
&lt;/h3&gt;

&lt;p&gt;I've enabled Google search form to search in my site.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;SEARCH_FORM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"""
 &amp;lt;form method="get" action="https://www.google.com/search" class="form-inline my-2 my-lg-0" role="search"&amp;gt;
 &amp;lt;div class="form-group"&amp;gt;
 &amp;lt;input type="text" name="q" class="form-control mr-sm-2" placeholder="Search"&amp;gt;
 &amp;lt;/div&amp;gt;
 &amp;lt;button type="submit" class="btn btn-secondary my-2 my-sm-0"&amp;gt;
    &amp;lt;i class="fas fa-search"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/button&amp;gt;
 &amp;lt;/button&amp;gt;
 &amp;lt;input type="hidden" name="sitesearch" value="%s"&amp;gt;
 &amp;lt;/form&amp;gt;
"""&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;SITE_URL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Google Analytics
&lt;/h3&gt;

&lt;p&gt;Google Analytics can be added to the bottom of &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; to function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;BODY_END&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"""
&amp;lt;!-- Global Site Tag (gtag.js) - Google Analytics --&amp;gt;
&amp;lt;script async src="https://www.googletagmanager.com/gtag/js?id=GA_TRACKING_ID"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script&amp;gt;
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', '&amp;lt;YOUR GOOGLE ANALYTICS IDENTIFIER&amp;gt;');
&amp;lt;/script&amp;gt;
"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  15) Customizing your blog
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Theme &amp;amp; Template customization
&lt;/h3&gt;

&lt;p&gt;To create a new theme, we can use the following command which will create a new folder in themes called &lt;code&gt;brainsorting&lt;/code&gt;. It is using the mako templating engine and the parent theme is &lt;code&gt;bootstrap4&lt;/code&gt;. We don't necessarily want to create a theme from scratch, so we base it off the bootstrap4 theme (or whatever theme you want) and make the adjustments that we want.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nikola theme &lt;span class="nt"&gt;--new&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;brainsorting &lt;span class="nt"&gt;--engine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mako &lt;span class="nt"&gt;--parent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bootstrap4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also copy over any templates from the parent theme where we want to make modifications by using the following command :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nikola theme &lt;span class="nt"&gt;--copy-template&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;base.tmpl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to examine all the components of the parent theme (i.e., bootstrap4 in my case), the following command will give you the path to the parent theme for you to explore.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nikola theme &lt;span class="nt"&gt;-g&lt;/span&gt; bootstrap4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full list of templates is shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── authors.tmpl
├── base_helper.tmpl
├── base.tmpl
├── gallery.tmpl
├── index_helper.tmpl
├── listing.tmpl
├── pagination_helper.tmpl
├── post.tmpl
├── tags.tmpl
└── ui_helper.tmpl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example if you want to make the nav bar sticky at the top, so that when readers scroll downwards, they can still access the menu bar, you need to update the &lt;code&gt;base.tmpl&lt;/code&gt; file as shown below with the command sticky-top. To get the &lt;code&gt;base.tmpl&lt;/code&gt; file in your template folder use &lt;code&gt;nikola theme --copy-template=base.tmpl&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;nav&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navbar navbar-expand-md sticky-top mb-4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setting your favicon
&lt;/h3&gt;

&lt;p&gt;Pick an icon and store it in the folder '/file/', then edit the conf.py as follows :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;FAVICONS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/brain.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"128x128"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tweaking the CSS
&lt;/h3&gt;

&lt;p&gt;This is quite easy and can be done by dropping a custom.css document here &lt;code&gt;files/assets/css/custom.css&lt;/code&gt;. This will be loaded from the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; block of the site when built.&lt;/p&gt;

&lt;p&gt;If you really want to change the pages radically, you will want to do a &lt;a href="https://getnikola.com/theming.html"&gt;custom theme&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Files and Listings
&lt;/h3&gt;

&lt;p&gt;This two folders are used to transfer any file or code file to the output folder (your generated website). By default, putting anything in the &lt;code&gt;files&lt;/code&gt; folder will be available in the root of your website. Anything in &lt;code&gt;listings&lt;/code&gt; or subfolder will be available in &lt;code&gt;output/listings&lt;/code&gt;. This last folder allows user to view and download any code file you put in this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Date formatting
&lt;/h3&gt;

&lt;p&gt;You can customize how the timestamp are displayed on your blog posts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;DATE_FORMAT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'yyyy-MMM-dd'&lt;/span&gt;
&lt;span class="n"&gt;DATE_FANCINESS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I like to set it like this to have a more human friendly reading with dates displayed like "3 months ago". Hovering the date with the mouse display the exact date.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using mailchimp for user to subscribe
&lt;/h3&gt;

&lt;p&gt;Mailchimp allows you to run e-mail campaigns and contact subscribers when you have new content on your site. See &lt;a href="https://mailchimp.com/help/getting-started-with-mailchimp/"&gt;Getting Started with Mailchimp&lt;/a&gt; for more detailed instructions.&lt;/p&gt;

&lt;p&gt;After you created your account you can create your signup form and get a code that looks like this one. Create a &lt;code&gt;MAILCHIMP_SIGNUP&lt;/code&gt; variable in &lt;code&gt;conf.py&lt;/code&gt; and paste this code :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;MAILCHIMP_SIGNUP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"""
&amp;lt;!-- Begin Mailchimp Signup Form --&amp;gt;
&amp;lt;div id="mc_embed_signup"&amp;gt;
&amp;lt;form action="&amp;lt;YOUR MAILCHIMP IDENTIFIER&amp;gt;" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate&amp;gt;
    &amp;lt;div id="mc_embed_signup_scroll"&amp;gt;
    &amp;lt;label for="mce-EMAIL"&amp;gt;Subscribe&amp;lt;/label&amp;gt;
    &amp;lt;input type="email" value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="email" required&amp;gt;
    &amp;lt;!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups--&amp;gt;
    &amp;lt;div style="position: absolute; left: -5000px;" aria-hidden="true"&amp;gt;&amp;lt;input type="text" name="b_3ffb6593478debd1efe5bf3e7_e432d28210" tabindex="-1" value=""&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;div class="clear"&amp;gt;&amp;lt;input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button"&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/form&amp;gt;
&amp;lt;/div&amp;gt;

&amp;lt;!--End mc_embed_signup--&amp;gt;
"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Loading bar
&lt;/h3&gt;

&lt;p&gt;To make use of the &lt;a href="https://github.hubspot.com/pace/docs/welcome/"&gt;pace.js&lt;/a&gt; loading library I added this code in the &lt;code&gt;base_helper.tmpl&lt;/code&gt; file :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;# below the &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt; in the base_helper.tmpl file

{% if use_pace %}
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/assets/js/pace.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/assets/css/pace.css"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
{% endif %}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I then activate it with in the &lt;code&gt;conf.py&lt;/code&gt; settings :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;GLOBAL_CONTEXT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"use_pace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Remove .html suffix from archive.html
&lt;/h3&gt;

&lt;p&gt;This is just a small annoyance, but by default, the archive is located in &lt;code&gt;/archive.html&lt;/code&gt;. If you want it to be in &lt;code&gt;/archive/&lt;/code&gt;, add the following lines to your &lt;code&gt;conf.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ARCHIVE_PATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"archive"&lt;/span&gt;
&lt;span class="n"&gt;ARCHIVE_FILENAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"index.html"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember to also fix the navigation links:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;NAVIGATION_LINKS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;DEFAULT_LANG&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="s"&gt;"/pages/resume/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"My Resume"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/pages/cheatsheet/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Cheat Sheet"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/archive/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Archive"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Short blog post teaser in index page
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;index.tmpl&lt;/code&gt; will generate a list of posts associated to the tag/category/year/author. This index can either be the entire post or post with just a teaser. To just show a teaser of the post, set &lt;code&gt;conf.py&lt;/code&gt; as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;INDEX_TEASERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't forget to write in your post file where is the end of the teaser, in Markdown or html or ipynb do like this :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- TEASER_END --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In reStructuredText, select the end of your teasers with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.. TEASER_END
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are using teasers, the default is a Read more... link to access the full post. To make it more informative, you can have statements such as XX minute read... in &lt;code&gt;conf.py&lt;/code&gt; as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;INDEX_READ_MORE_LINK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;p class="more"&amp;gt;&amp;lt;a href="{link}"&amp;gt;{reading_time} minute read…&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;'&lt;/span&gt;
&lt;span class="n"&gt;FEED_READ_MORE_LINK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;p&amp;gt;&amp;lt;a href="{link}"&amp;gt;{read_more}…&amp;lt;/a&amp;gt; ({min_remaining_read})&amp;lt;/p&amp;gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  16) Optimizing your blog
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Filters
&lt;/h3&gt;

&lt;p&gt;I want to be sure that all the files on my blog are optimized (such as .html, .js, .jpeg, .png, .css) so I am making use of the filters functionality.&lt;/p&gt;

&lt;p&gt;In my &lt;code&gt;conf.py&lt;/code&gt; I have the following settings for FILTERS :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;FILTERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="s"&gt;".html"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"filters.typogrify"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
   &lt;span class="s"&gt;".css"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"filters.yui_compressor"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
   &lt;span class="s"&gt;".jpg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"jpegoptim --strip-all -m75 -v %s"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
   &lt;span class="s"&gt;".png"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"filters.optipng"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For them to work I need to have &lt;code&gt;typogify&lt;/code&gt;, &lt;code&gt;yui_compressor&lt;/code&gt;, &lt;code&gt;jpegoptim&lt;/code&gt;, and &lt;code&gt;optipng&lt;/code&gt; installed on my machine. Those instructions are for mac using &lt;code&gt;homebrew&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;yuicompressor
brew &lt;span class="nb"&gt;install &lt;/span&gt;optipng
brew &lt;span class="nb"&gt;install &lt;/span&gt;jpegoptim
poetry add typogrify &lt;span class="c"&gt;# or "pip install typogrify" if you don't use poetry&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Posting automatically on Medium
&lt;/h3&gt;

&lt;p&gt;To publish your Nikola posts on Medium there is this &lt;a href="https://plugins.getnikola.com/v8/medium/"&gt;plugin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You just need to install it with this command :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nikola plugin &lt;span class="nt"&gt;-i&lt;/span&gt; medium
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add a &lt;code&gt;medium.json&lt;/code&gt; file in your blog folder with a generated access token that you can get &lt;a href="https://medium.com/me/settings"&gt;here&lt;/a&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"TOKEN"&lt;/span&gt;: &lt;span class="s2"&gt;"your_token_here"&lt;/span&gt;,
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then simply add the metadata &lt;code&gt;markdown : yes&lt;/code&gt; in the blog post you want to publish on medium and run the command :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nikola medium
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Posting automatically on Dev.to
&lt;/h3&gt;

&lt;p&gt;To publish your Nikola posts on Dev there is this &lt;a href="https://plugins.getnikola.com/v8/devto/"&gt;plugin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You just need to install it with this command :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nikola plugin &lt;span class="nt"&gt;-i&lt;/span&gt; devto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add a &lt;code&gt;devto.json&lt;/code&gt; file in your blog folder with a generated access token that you can get &lt;a href="https://docs.dev.to/api/"&gt;here&lt;/a&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"TOKEN"&lt;/span&gt;: &lt;span class="s2"&gt;"your_token_here"&lt;/span&gt;,
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then simply add the metadata &lt;code&gt;devto : yes&lt;/code&gt; in the blog post you want to publish on medium and run the command :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nikola devto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Other plugin I didn't try
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/getnikola/plugins/tree/master/v7/similarity"&gt;similarity&lt;/a&gt; :&lt;/strong&gt; Find posts that are similar to the one being read. Requires install of Natural Language Processing packages such as &lt;code&gt;gensim&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;That's it for the big tutorial. I hope I was precise enough for giving you all the tools to make a blog very much like you want it. Some part of that article were very inspire (if not copy/pasted for some stuff) from resources down below that helped me a LOT to understand everything I need to understand to reach a result that I like with my blog. My next step will be to automate as much things as possible, you'll know it in a new article when I will have achieve it 😄&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Google group to discuss about Nikola : &lt;a href="https://groups.google.com/forum/#!forum/nikola-discuss"&gt;https://groups.google.com/forum/#!forum/nikola-discuss&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://getnikola.com/handbook.html"&gt;https://getnikola.com/handbook.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://getnikola.com/getting-started.html"&gt;https://getnikola.com/getting-started.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nikola.readthedocs.io/en/latest/manual"&gt;https://nikola.readthedocs.io/en/latest/manual&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://jiaweizhuang.github.io/blog/nikola-guide/"&gt;https://jiaweizhuang.github.io/blog/nikola-guide&lt;/a&gt;/&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.jaakkoluttinen.fi/blog/how-to-blog-with-jupyter-ipython-notebook-and-nikola/"&gt;http://www.jaakkoluttinen.fi/blog/how-to-blog-with-jupyter-ipython-notebook-and-nikola/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://randlow.github.io/posts/python/create-nikola-coding-blog/#theme-template-customization"&gt;https://randlow.github.io/posts/python/create-nikola-coding-blog&lt;/a&gt;/&lt;/p&gt;

&lt;h3&gt;
  
  
  Themes
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://themes.getnikola.com/v7/mdl/"&gt;https://themes.getnikola.com/v7/mdl/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hackerthemes.com/bootstrap-themes/"&gt;https://hackerthemes.com/bootstrap-themes/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bootswatch.com/"&gt;https://bootswatch.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>blogging</category>
      <category>tutorial</category>
      <category>python</category>
      <category>nikola</category>
    </item>
  </channel>
</rss>
