<?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>Forem: Malte Riechmann</title>
    <description>The latest articles on Forem by Malte Riechmann (@malteriechmann).</description>
    <link>https://forem.com/malteriechmann</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%2F566531%2Fd2c073cf-80e0-4476-ba78-067de2ebca91.jpeg</url>
      <title>Forem: Malte Riechmann</title>
      <link>https://forem.com/malteriechmann</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/malteriechmann"/>
    <language>en</language>
    <item>
      <title>New git guidelines: We have switched to Conventional Commits</title>
      <dc:creator>Malte Riechmann</dc:creator>
      <pubDate>Sat, 22 Oct 2022 08:28:39 +0000</pubDate>
      <link>https://forem.com/visuellverstehen/new-git-guidelines-we-have-switched-to-conventional-commits-1p0c</link>
      <guid>https://forem.com/visuellverstehen/new-git-guidelines-we-have-switched-to-conventional-commits-1p0c</guid>
      <description>&lt;p&gt;Giving teams as much autonomy as possible is a good idea, but having some company-wide guidelines can also help. Those guidelines will help you when people switch teams, work on multiple products, or train new colleagues.&lt;/p&gt;

&lt;h2&gt;
  
  
  Discuss, decide, repeat
&lt;/h2&gt;

&lt;p&gt;We recently discussed some technology-related topics with all software developers at &lt;a href="https://www.visuellverstehen.de"&gt;visuellverstehen&lt;/a&gt;. One of the outcomes of this discussion is new git guidelines. After a short debate, we have &lt;a href="https://twitter.com/malteriechmann/status/1582599067959320577"&gt;officially&lt;/a&gt; switched to &lt;a href="https://www.conventionalcommits.org"&gt;Conventional Commits&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is fun to see all the latest commits following a new syntax. I am curious about what we will say about this change in six or twelve months. For sure we will discuss and decide again – for the better.&lt;/p&gt;

&lt;h2&gt;
  
  
  New git guidelines
&lt;/h2&gt;

&lt;p&gt;Below you can find the November 2022 edition of our git guidelines.&lt;/p&gt;

&lt;h3&gt;
  
  
  Repositories
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Repositories should be named like this: &lt;code&gt;vvcode-name_of_project&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Branches
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The main branch should be named &lt;code&gt;main&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The people working on a product decide if they want to work with further branches&lt;/li&gt;
&lt;li&gt;If you need further branches, it is advisable, to add the number of the issue and a short title inside of a branch name, e. g.:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;100-validation-errors&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;101-basic-search&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;102-german-translation&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;103-live-deployment&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;104-url-formatting&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


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

&lt;h3&gt;
  
  
  Commits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;We use the syntax from Conventional Commits&lt;/li&gt;
&lt;li&gt;Commit messages include one of the following prefixes:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;fix:&lt;/code&gt; to fix bugs&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;feat:&lt;/code&gt; to introduce new features&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chore:&lt;/code&gt; to make general changes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ci:&lt;/code&gt; to work on continuous integration/continuous deployment&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;refactor:&lt;/code&gt; to improve existing source code&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Commit messages should be written in the present form&lt;/li&gt;
&lt;li&gt;Commit messages should be written in English&lt;/li&gt;
&lt;li&gt;Commit messages should start with a lowercase character&lt;/li&gt;
&lt;li&gt;It is advisable to add the issue number to a commit message&lt;/li&gt;
&lt;li&gt;Practical examples of commit messages:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;fix: display validation errors properly, refs #100&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;feat: implement basic search, refs #101&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chore: add correct german translation, refs #102&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ci: repair live deployment, refs #103&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;refactor: unify URL formatting, refs #104&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;If a commit is a work in progress, it should be marked as such:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;fix: display validation errors properly (WIP), refs #100&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;feat: implement basic search (WIP), refs #101&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chore: add correct german translation (WIP), refs #102&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ci: repair live deployment (WIP), refs #103&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;refactor: unify URL formatting (WIP), refs #104&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


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

</description>
      <category>git</category>
      <category>webdev</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Our tech stack in 2022</title>
      <dc:creator>Malte Riechmann</dc:creator>
      <pubDate>Fri, 25 Mar 2022 17:25:37 +0000</pubDate>
      <link>https://forem.com/visuellverstehen/our-tech-stack-in-2022-374o</link>
      <guid>https://forem.com/visuellverstehen/our-tech-stack-in-2022-374o</guid>
      <description>&lt;h2&gt;
  
  
  Preface
&lt;/h2&gt;

&lt;p&gt;Reading about our &lt;a href="https://happy-coding.visuellverstehen.de/posts/our-tech-stack-in-2021-2600"&gt;tech stack from one year ago&lt;/a&gt; gives me confidence for the future. Most of the languages and frameworks are still the same as twelve months ago. I think it is good we are not switching technology that often. It means we can maintain everything for a long time and get a lot of experience in our day-to-day tools.&lt;/p&gt;

&lt;p&gt;Of course, we also have to keep an eye on the new stuff in web development and make some innovation happen at visuellverstehen. Therefore we try out new things in real-life projects from time to time. For example, I am happy there is Meilisearch now in our tech stack of 2022.&lt;/p&gt;

&lt;p&gt;As always, I recommend not rushing into the last NewShinyFramework™. &lt;/p&gt;

&lt;h2&gt;
  
  
  Clarification
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;This will not cover every technology in all of our projects, because individual projects do need individual solutions. But it will cover all the basics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Legacy projects might use outdated technologies and those will not be part of this. Of course, we always try to update legacy projects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is not easy to categorize every technology. Therefore the categorization might not always be 100 % correct.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Not every one of us is working with all of the technologies mentioned below. Our team is organized into smaller sub-teams, which then focus on different projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Our tech stack
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Core products
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Individual digital products using &lt;a href="https://laravel.com"&gt;Laravel&lt;/a&gt; and &lt;a href="https://vuejs.org"&gt;Vue.js&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Content management products using &lt;a href="https://statamic.com"&gt;Statamic&lt;/a&gt; and &lt;a href="https://typo3.org"&gt;TYPO3&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What people call »Backend«
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Extbase&lt;/li&gt;
&lt;li&gt;Laravel&lt;/li&gt;
&lt;li&gt;Laravel Nova&lt;/li&gt;
&lt;li&gt;Meilisearch&lt;/li&gt;
&lt;li&gt;MySQL&lt;/li&gt;
&lt;li&gt;PHP&lt;/li&gt;
&lt;li&gt;PHPUnit&lt;/li&gt;
&lt;li&gt;Statamic&lt;/li&gt;
&lt;li&gt;TYPO3&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What people call »Frontend«
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Alpine.js&lt;/li&gt;
&lt;li&gt;Antlers&lt;/li&gt;
&lt;li&gt;BEM&lt;/li&gt;
&lt;li&gt;Babel&lt;/li&gt;
&lt;li&gt;Blade&lt;/li&gt;
&lt;li&gt;CSS&lt;/li&gt;
&lt;li&gt;Fluid&lt;/li&gt;
&lt;li&gt;HTML&lt;/li&gt;
&lt;li&gt;JavaScript&lt;/li&gt;
&lt;li&gt;Laravel Livewire&lt;/li&gt;
&lt;li&gt;Sass&lt;/li&gt;
&lt;li&gt;Tailwind CSS&lt;/li&gt;
&lt;li&gt;Vue.js&lt;/li&gt;
&lt;li&gt;gulp.js&lt;/li&gt;
&lt;li&gt;npm&lt;/li&gt;
&lt;li&gt;webpack&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What people call »DevOps«
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Docker Compose&lt;/li&gt;
&lt;li&gt;Git&lt;/li&gt;
&lt;li&gt;GitHub&lt;/li&gt;
&lt;li&gt;GitHub Actions&lt;/li&gt;
&lt;li&gt;GitLab&lt;/li&gt;
&lt;li&gt;GitLab CI&lt;/li&gt;
&lt;li&gt;Hetzner Cloud&lt;/li&gt;
&lt;li&gt;Laravel Forge&lt;/li&gt;
&lt;li&gt;Mittwald&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Honorable mentions
&lt;/h3&gt;

&lt;p&gt;Three things are worth a special mention.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Although Shopware 6 is a well-crafted software, we decided against it. We want to focus on individual digital products using Laravel and Vue.js plus content management using Statamic and TYPO3. We will still maintain running client projects and support our &lt;a href="https://store.shopware.com/en/visuellverstehen-gmbh.html"&gt;Shopware plugins&lt;/a&gt; though.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One of our clients asked for &lt;a href="https://alpinejs.dev"&gt;Alpine.js&lt;/a&gt; in combination with Laravel Livewire. It turns out those work well together. Let us see if we want to use it more often in the future.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We are using Meilisearch for advanced search technologies more and more. It is a simple alternative to Solr and Elasticsearch written in Rust. It works smoothly with Laravel and Statamic. We also developed a &lt;a href="https://github.com/visuellverstehen/t3meilisearch"&gt;TYPO3 extension for Meilisearch&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Happy coding
&lt;/h2&gt;

&lt;p&gt;I am curious how this will change in the next twelve months. Well, we will find out. See you next year. Happy coding.&lt;/p&gt;

</description>
      <category>tooling</category>
      <category>devops</category>
      <category>technology</category>
      <category>stack</category>
    </item>
    <item>
      <title>Common mistakes when writing CSS with BEM</title>
      <dc:creator>Malte Riechmann</dc:creator>
      <pubDate>Fri, 22 Oct 2021 08:48:47 +0000</pubDate>
      <link>https://forem.com/visuellverstehen/common-mistakes-when-writing-css-with-bem-4921</link>
      <guid>https://forem.com/visuellverstehen/common-mistakes-when-writing-css-with-bem-4921</guid>
      <description>&lt;h2&gt;
  
  
  Software development is a team effort
&lt;/h2&gt;

&lt;p&gt;When doing software development it is essential to agree on guidelines, technology, and methodologies. Those agreements should be the result of discussions, proof of concepts, knowledge, and sometimes votes. The whole team should be invited to participate because software development is a team effort and everyone likes engaging team members.&lt;/p&gt;

&lt;p&gt;At visuellverstehen, we are divided into multiple teams. Some teams agreed on using &lt;a href="https://css-tricks.com/bem-101"&gt;Block-Element-Modifier (BEM)&lt;/a&gt; and other teams agreed on using &lt;a href="https://tailwindcss.com"&gt;Tailwind CSS&lt;/a&gt;. I think it is super important to agree on one way or the other, while both ways are totally fine for the success of our client projects.&lt;/p&gt;

&lt;p&gt;One thing is for sure. If you do not agree, it will become a mess. I have been there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn proper BEM
&lt;/h2&gt;

&lt;p&gt;Now and then new colleagues join our team. Some of them never have heard about BEM before. So they have to learn it and naturally some mistakes will happen. Mistakes are not a problem at all. They are part of the learning process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four most common mistakes
&lt;/h2&gt;

&lt;p&gt;To help you learn proper BEM, I wrote down some of the most common mistakes I see in my day-to-day work life.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Wrongly nested blocks and elements
&lt;/h3&gt;

&lt;p&gt;It is not allowed to nest blocks. If you start a new block, you are not allowed to proceed with elements from another block.&lt;/p&gt;

&lt;h4&gt;
  
  
  ❌ Wrong
&lt;/h4&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;article&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;header&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"header"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__headline"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  ✅ Correct
&lt;/h4&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;article&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;header&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__header"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__headline"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Great-grandchildren
&lt;/h3&gt;

&lt;p&gt;There are no grandchildren nor great-grandchildren in BEM. Instead, »normal« elements of the block can be used.&lt;/p&gt;

&lt;h4&gt;
  
  
  ❌ Wrong
&lt;/h4&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;article&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;header&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__header"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__header__headline"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  ✅ Correct
&lt;/h4&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;article&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;header&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__header"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__headline"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Modifiers without a base class
&lt;/h3&gt;

&lt;p&gt;Modifiers cannot exist without a base block or element.&lt;/p&gt;

&lt;h4&gt;
  
  
  ❌ Wrong
&lt;/h4&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;article&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card--highlight"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;header&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__header"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  ✅ Correct
&lt;/h4&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;article&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card card--highlight"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;header&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__header"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  ❌ Wrong
&lt;/h4&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;article&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;header&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__header--important"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  ✅ Correct
&lt;/h4&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;article&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;header&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__header card__header--important"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Too big blocks
&lt;/h3&gt;

&lt;p&gt;It is not a good idea to create really big blocks. The idea of BEM is to create modular and reusable blocks.&lt;/p&gt;

&lt;h4&gt;
  
  
  ❌ Wrong
&lt;/h4&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;body&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"body"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;header&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"body__header"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;main&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"body__main"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;footer&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"body__footer"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/footer&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  ✅ Correct
&lt;/h4&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;body&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"body"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;header&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"header"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;main&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"main"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;footer&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"footer"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/footer&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Automate stuff
&lt;/h2&gt;

&lt;p&gt;Sometimes it is hard to find mistakes manually. Yesterday I learned there is a &lt;a href="https://github.com/postcss/postcss-bem-linter"&gt;BEM linter&lt;/a&gt;. I will look into it.&lt;/p&gt;

</description>
      <category>css</category>
      <category>programming</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>A little Slack app to ask our team social questions</title>
      <dc:creator>Malte Riechmann</dc:creator>
      <pubDate>Thu, 10 Jun 2021 09:10:46 +0000</pubDate>
      <link>https://forem.com/visuellverstehen/a-little-slack-app-to-ask-our-team-social-questions-4n83</link>
      <guid>https://forem.com/visuellverstehen/a-little-slack-app-to-ask-our-team-social-questions-4n83</guid>
      <description>&lt;h2&gt;
  
  
  Changes coming from the pandemic
&lt;/h2&gt;

&lt;p&gt;A lot has changed since the pandemic started and we all can learn a lot from the past 18 months. Because of COVID-19, we are now a remote workplace. Which is very nice, but also brings some challenges.&lt;/p&gt;

&lt;p&gt;For example, some people from our team have never met in person. While working remotely, you do not occasionally run into someone and have to talk to him*her. The social talk decreased a lot. While it is okay for some, others want it back. How can we counteract this?&lt;/p&gt;

&lt;h2&gt;
  
  
  A little idea
&lt;/h2&gt;

&lt;p&gt;We do not want to bring the office back and we do not want to add a lot of distraction. We just want to get to know each other a bit better. So we developed an app, which asks our team a social question every Monday at 1 pm. Those questions are posted to an off-topic channel, which is optional for everyone to read.&lt;/p&gt;

&lt;h2&gt;
  
  
  Questions to ask
&lt;/h2&gt;

&lt;p&gt;We gathered questions and put those into a JSON file. Sorry for using German here, but those are some real questions our team was asked in the last months.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;":palm_tree: An welchem Ort machst du am liebsten Urlaub? Vielleicht kannst du ja auch ein Foto teilen."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;":tv: Was ist deine Lieblingsserie? Und wo können die anderen diese Serie gucken?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;":green_salad: Welches Essen ist so gar nichts für dich?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;":musical_note: Welche Musik hörst du, wenn du einfach nur abschalten willst?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;":frame_with_picture: Wie hast du als Kind ausgesehen?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;":moneybag: Was meinst du? Wird Bitcoin die Währung der Zukunft?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;":children_crossing: Was ist deine schlimmste Jugendsünde?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;":movie_camera: Was ist dein Lieblingskinderfilm?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;":tropical_drink: Zitronen- oder Pfirsich-Eistee?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;":desert_island: Welche drei Dinge würdest du mit auf eine einsame Insel nehmen?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;":bread: Der, die oder das Nutella?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;":icecream: Was ist deine Lieblingseissorte und warum?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"[…]"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Source code
&lt;/h2&gt;

&lt;p&gt;The app is just a PHP script, which is run by a cronjob once a week. It works like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get a question from &lt;code&gt;questions.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Post the question using the &lt;a href="https://api.slack.com/methods/chat.postMessage"&gt;chat.postMessage&lt;/a&gt; API endpoint.&lt;/li&gt;
&lt;li&gt;Add the question to &lt;code&gt;questions-archive.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Remove the question from &lt;code&gt;questions.json&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;#!/usr/local/bin/php
&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="c1"&gt;// Abort, if not in CLI mode&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;php_sapi_name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s1"&gt;'cli'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Not in CLI mode'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;echo&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="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;die&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Prepare some variables&lt;/span&gt;
&lt;span class="nv"&gt;$archivedQuestionsFilename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'questions-archive.json'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$questionsFilename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'questions.json'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Read questions from file&lt;/span&gt;
&lt;span class="nv"&gt;$questions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;json_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file_get_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$questionsFilename&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// Abort, if no questions are left&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$questions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&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;echo&lt;/span&gt; &lt;span class="s1"&gt;'No questions left in '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$questionsFilename&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;echo&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="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;die&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Send question via cURL to Slack&lt;/span&gt;
&lt;span class="nv"&gt;$curlHandle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$sendQuestionUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'https://slack.com/api/chat.postMessage'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$sendQuestionParameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="s1"&gt;'channel'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'C03C9RPDF'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'text'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hallo Freund*innen der gepflegten Unterhaltung.

'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$questions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nv"&gt;$sendQuestionBearerToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'0123456789ABCDEF'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlHandle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_HTTPHEADER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$sendQuestionBearerToken&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlHandle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$sendQuestionUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlHandle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_POST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlHandle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_POSTFIELDS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$sendQuestionParameters&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlHandle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_RETURNTRANSFER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$sendQuestionResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlHandle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;curl_close&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlHandle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Read archived questions from file&lt;/span&gt;
&lt;span class="nv"&gt;$archivedQuestions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;json_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file_get_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$archivedQuestionsFilename&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// Add question to archived questions&lt;/span&gt;
&lt;span class="nv"&gt;$archivedQuestions&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$questions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Remove question from questions&lt;/span&gt;
&lt;span class="k"&gt;unset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$questions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="c1"&gt;// Persist archived questions&lt;/span&gt;
&lt;span class="nb"&gt;file_put_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$archivedQuestionsFilename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;array_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$archivedQuestions&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

&lt;span class="c1"&gt;// Persist questions&lt;/span&gt;
&lt;span class="nb"&gt;file_put_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$questionsFilename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;array_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$questions&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>showdev</category>
      <category>webdev</category>
      <category>php</category>
      <category>programming</category>
    </item>
    <item>
      <title>This article has 61 positive reactions and 24 comments</title>
      <dc:creator>Malte Riechmann</dc:creator>
      <pubDate>Fri, 04 Jun 2021 07:43:51 +0000</pubDate>
      <link>https://forem.com/visuellverstehen/this-article-has-positive-reactions-and-comments-ol3</link>
      <guid>https://forem.com/visuellverstehen/this-article-has-positive-reactions-and-comments-ol3</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Using the DEV API the title of this article gets automatically updated every 60 seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Addicted to numbers
&lt;/h2&gt;

&lt;p&gt;I started blogging on DEV only some months ago. You could say, I am quite new to all of this. After writing an article I find myself frequently checking the numbers of reactions and comments. It seems like I am a bit of an addict. And I bet some of you are too.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We share an addiction. We're approval junkies.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;— &lt;a href="https://www.youtube.com/watch?v=GkEE3gRX0kQ"&gt;Jake Green, Revolver&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is not why I started this and I am sure it is not healthy. So I will try to stop and instead make this a bit of fun. Let's play around with the numbers.&lt;/p&gt;

&lt;h2&gt;
  
  
  APIs are the future
&lt;/h2&gt;

&lt;p&gt;Back in 2010, I saw a &lt;a href="https://twitter.com/smashingmag/status/9646126079"&gt;tweet&lt;/a&gt; from Smashing Magazine asking about the future of the web. And I answered »&lt;a href="https://twitter.com/malteriechmann/status/9646229572"&gt;APIs&lt;/a&gt;«, which is the same answer I would give today — 11 years later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's have fun
&lt;/h2&gt;

&lt;p&gt;It is so much fun working with well-implemented APIs and I was happy to find the &lt;a href="https://docs.forem.com/api/"&gt;DEV API&lt;/a&gt; as one of those.&lt;/p&gt;

&lt;p&gt;My idea was simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get the properties of this article.&lt;/li&gt;
&lt;li&gt;Update the title using two of the properties (&lt;code&gt;positive_reactions_count&lt;/code&gt; and &lt;code&gt;comments_count&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The source
&lt;/h2&gt;

&lt;p&gt;I use PHP, which is one of my favorite programming languages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Get article properties
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getArticleProperties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$articleId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Prepare URL&lt;/span&gt;
    &lt;span class="nv"&gt;$url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'https://dev.to/api/articles/'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$articleId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Prepare headers&lt;/span&gt;
    &lt;span class="nv"&gt;$headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'api-key: 1234567890abcdef'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="c1"&gt;// Prepare method&lt;/span&gt;
    &lt;span class="nv"&gt;$method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Execute request&lt;/span&gt;
    &lt;span class="nv"&gt;$curlHandle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlHandle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlHandle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_HTTPHEADER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlHandle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_CUSTOMREQUEST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$method&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlHandle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_RETURNTRANSFER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$response&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlHandle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;curl_close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlHandle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;json_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&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;
  
  
  Update article title
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;updateArticleTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$articleId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$articleTitle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Prepare URL&lt;/span&gt;
    &lt;span class="nv"&gt;$url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'https://dev.to/api/articles/'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$articleId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Prepare payload&lt;/span&gt;
    &lt;span class="nv"&gt;$payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'article'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s1"&gt;'title'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$articleTitle&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="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Prepare headers&lt;/span&gt;
    &lt;span class="nv"&gt;$headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'Content-Length: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$payload&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="s1"&gt;'api-key: 1234567890abcdef'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="c1"&gt;// Prepare method&lt;/span&gt;
    &lt;span class="nv"&gt;$method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'PUT'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Execute request&lt;/span&gt;
    &lt;span class="nv"&gt;$curlHandle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlHandle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlHandle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_HTTPHEADER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlHandle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_CUSTOMREQUEST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$method&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlHandle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_POSTFIELDS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlHandle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_RETURNTRANSFER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$response&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlHandle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;curl_close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curlHandle&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;
  
  
  Putting it all together
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Prepare article ID&lt;/span&gt;
&lt;span class="nv"&gt;$articleId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;715066&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Get article properties using the API&lt;/span&gt;
&lt;span class="nv"&gt;$articleProperties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getArticleProperties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$articleId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Update article title using the API&lt;/span&gt;
&lt;span class="nf"&gt;updateArticleTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$articleId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'This article has '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$articleProperties&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'positive_reactions_count'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;' positive reactions and '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$articleProperties&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'comments_count'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;' comments'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A cronjob is executing this as a CLI script every 60 seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspiration
&lt;/h2&gt;

&lt;p&gt;This article is heavily inspired by &lt;a href="https://www.youtube.com/watch?v=BxV14h0kFs0"&gt;an awesome YouTube video&lt;/a&gt; I saw earlier this year.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>writing</category>
      <category>meta</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Use components without a frontend framework</title>
      <dc:creator>Malte Riechmann</dc:creator>
      <pubDate>Thu, 27 May 2021 11:49:25 +0000</pubDate>
      <link>https://forem.com/visuellverstehen/use-components-without-a-frontend-framework-4338</link>
      <guid>https://forem.com/visuellverstehen/use-components-without-a-frontend-framework-4338</guid>
      <description>&lt;h2&gt;
  
  
  Frontend frameworks
&lt;/h2&gt;

&lt;p&gt;Within this post, I will show you one, of many ways to use components without a frontend framework. Do not get me wrong, I like frameworks like Vue.js, React, or Angular. At our company, we write JavaScript with Vue.js on a daily basis.&lt;/p&gt;

&lt;p&gt;But sometimes those frameworks are too much. Especially when building simple websites instead of complex web applications. In these cases, we do not use a framework at all and just write HTML, CSS, and JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Components
&lt;/h2&gt;

&lt;p&gt;If your source code gets messy there is often an easy way to improve it. Move your source code into smaller chunks – &lt;a href="https://en.wikipedia.org/wiki/Divide-and-conquer_algorithm" rel="noopener noreferrer"&gt;divide and conquer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Splitting your source code into multiple components is a well-known way to structure your project. Things get isolated, readable, clear, reusable, extendable, and maintainable. In fact, that is what most of the frontend frameworks do themselves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Welcome to BEM
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://css-tricks.com/bem-101/" rel="noopener noreferrer"&gt;BEM (Block Element Modifier)&lt;/a&gt; is a methodology to organize your frontend. It is mostly known in the world of CSS, but I am going to show you how to use it for JavaScript, too. Please remember, BEM is a methodology and not a framework. It will come with zero dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  A card block
&lt;/h2&gt;

&lt;p&gt;In BEM the components are called blocks. It is just different terminology for the same thing.&lt;/p&gt;

&lt;p&gt;Now, imagine a card block (&lt;a href="https://jsfiddle.net/3stx2jqa/" rel="noopener noreferrer"&gt;source code&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F26ltrld7bskr6nd9sl4g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F26ltrld7bskr6nd9sl4g.png" alt="Example of a card block"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  HTML
&lt;/h3&gt;

&lt;p&gt;We use HTML for the structure and content of the card block. Of course, you can use programming languages, template engines, or other tools to improve the HTML part of the block.&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;article&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card card--highlight"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;figure&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__figure"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__image"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;figcaption&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__caption"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;#ffed00&lt;span class="nt"&gt;&amp;lt;/figcaption&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/figure&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__headline"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Corporate yellow&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__description"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;This yellow is defined as #ffed00. It is a very nice color. It is one of our corporate colors at visuellverstehen.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  CSS
&lt;/h3&gt;

&lt;p&gt;We use CSS for the presentation and style of the card block. Of course, you can use pre processors, post processors, or other tools to make CSS more comfortable to use.&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;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&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.5&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;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20rem&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="m"&gt;0.25rem&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#f6f6f6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.card.card--highlight&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffed00&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.card__figure&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="nc"&gt;.card__image&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="nb"&gt;block&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;100%&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;6rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.card__caption&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;padding-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.card__headline&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.5rem&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  JavaScript
&lt;/h3&gt;

&lt;p&gt;We use JavaScript for the functionality of the card block. Of course, you can use all kinds of tools to improve how you write JavaScript (Babel, TypeScript, ESLint, webpack, …).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;initializeCard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$card&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Do whatever this $card block should be doing.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DOMContentLoaded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;$cards&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.card&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$cards&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&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="nf"&gt;initializeCard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$cards&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&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="p"&gt;}());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes blocks have to communicate with each other. For that, there are at least two good options: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent" rel="noopener noreferrer"&gt;Custom events&lt;/a&gt; and &lt;a href="https://css-tricks.com/build-a-state-management-system-with-vanilla-javascript/" rel="noopener noreferrer"&gt;stage management&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn the basics
&lt;/h2&gt;

&lt;p&gt;It is remarkable how much can be done just using HTML, CSS, and JavaScript. That is one reason why I encourage everyone to &lt;a href="https://dev.to/visuellverstehen/but-first-learn-the-basics-1113"&gt;learn the basics&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>html</category>
      <category>css</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Avoid defective nouns when naming things</title>
      <dc:creator>Malte Riechmann</dc:creator>
      <pubDate>Fri, 30 Apr 2021 08:01:22 +0000</pubDate>
      <link>https://forem.com/visuellverstehen/avoid-defective-nouns-when-naming-things-47jm</link>
      <guid>https://forem.com/visuellverstehen/avoid-defective-nouns-when-naming-things-47jm</guid>
      <description>&lt;h2&gt;
  
  
  Naming things is hard
&lt;/h2&gt;

&lt;p&gt;You always have to keep in mind, software developers spend more time reading source code than actually writing it. A lot of other people will someday read the source code you are writing today. Better make sure to write it clear, consistent, and well structured. I can recommend reading &lt;a href="https://www.oreilly.com/library/view/clean-code-a/9780136083238/"&gt;Clean Code&lt;/a&gt; by &lt;a href="https://twitter.com/unclebobmartin"&gt;Robert C. Martin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Naming things is one part of writing clean code and often it is quite hard to find the right names. In the following, I just want to show you one easy step to improve your source code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid defective nouns
&lt;/h2&gt;

&lt;p&gt;Defective nouns are nouns without singulars, nouns without plurals, or nouns that have the same singular and plural (e. g. information, music, or news). See &lt;a href="https://en.wikipedia.org/wiki/English_plurals#Defective_nouns"&gt;Wikipedia&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;Usually, in software development, you will need a noun that differs in singular and plural. So you are well-advised not to use defective nouns.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;Think about the list of posts on &lt;a href="https://dev.to"&gt;DEV&lt;/a&gt;. How would you name those? There are multiple options, but you should definitely avoid a defective noun.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Wrong: newss/news
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;newss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;news&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;news&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doSomething&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;
  
  
  ❌ Wrong: newsList/news
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;newsList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;news&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;news&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doSomething&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;
  
  
  ❌ Wrong: news/singleNews
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;news&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;singleNews&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;currentNews&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doSomething&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;
  
  
  ✅ Correct: posts/post
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doSomething&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;
  
  
  Bonus: Irregular plural nouns
&lt;/h2&gt;

&lt;p&gt;I will tell you a little secret. This might be a bit fussy, but I try to avoid irregular plural nouns, too. I do not like medium and media, child and children, or radius and radii. I just like good ol' regular plural nouns like post and posts, user and users, list and lists.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>But first, learn the basics</title>
      <dc:creator>Malte Riechmann</dc:creator>
      <pubDate>Thu, 22 Apr 2021 07:42:50 +0000</pubDate>
      <link>https://forem.com/visuellverstehen/but-first-learn-the-basics-1113</link>
      <guid>https://forem.com/visuellverstehen/but-first-learn-the-basics-1113</guid>
      <description>&lt;h1&gt;
  
  
  There is too much to learn
&lt;/h1&gt;

&lt;p&gt;The World Wide Web has always been a messy place. A lot of people from all over the world are simultaneously contributing to it. That is, why it gets messier every day. It is, in its entirety, kind of the biggest software project on the planet. And we all know, how easy it is to mess up big software projects.&lt;/p&gt;

&lt;p&gt;Over the last 30 years, a lot of technologies have been created. There are so many programming languages, tools, frameworks, and libraries out there, it is hard to keep track of them all. And the variety gets bigger day by day.&lt;/p&gt;

&lt;p&gt;Every now and then a new shiny thing™ arises. People will talk about it and will recommend it to you. If you are a beginner in web development, please do not listen to them. You should not invest time in the new shiny thing™. Instead, you should learn the basics. Because the basics will outlive the new shiny thing™.&lt;/p&gt;

&lt;h1&gt;
  
  
  What not to learn first
&lt;/h1&gt;

&lt;p&gt;Gatsby, Hugo, or Jekyll will someday help you build static websites, but first, learn the basics.&lt;/p&gt;

&lt;p&gt;Block-Element-Modifier (BEM), Sass, or Tailwind CSS will someday help you organize your CSS, but first, learn the basics.&lt;/p&gt;

&lt;p&gt;React, Vue.js, or Angular will someday help you build awesome user interfaces, but first, learn the basics.&lt;/p&gt;

&lt;p&gt;MySQL, PostgreSQL, or MongoDB will someday help you store data in a database, but first, learn the basics.&lt;/p&gt;

&lt;p&gt;Ruby on Rails, Laravel, Django, or another Model-View-Controller (MVC) framework will someday help you build feature-rich backends, but first, learn the basics.&lt;/p&gt;

&lt;p&gt;Docker, Docker Compose, or Kubernetes will someday help you build and host websites, but first, learn the basics.&lt;/p&gt;

&lt;h1&gt;
  
  
  What to learn first
&lt;/h1&gt;

&lt;p&gt;As I said before: Start with the basics. I recommend building a ton of websites just using basic technologies. Maybe ten websites are enough to learn the basics, maybe you will need 50. It does not really matter, you just have to get started and keep going.&lt;/p&gt;

&lt;p&gt;There will be a day, where you understand enough about &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP"&gt;HTTP&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/URL"&gt;URL&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML"&gt;HTML&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS"&gt;CSS&lt;/a&gt;, and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript"&gt;JavaScript&lt;/a&gt;. Then and only then you can carefully start adding more technologies to the stack.&lt;/p&gt;

&lt;p&gt;If you want to learn the basics, I can recommend following the developer roadmaps at &lt;a href="https://roadmap.sh/roadmaps"&gt;roadmaps.sh&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>webdev</category>
      <category>career</category>
    </item>
    <item>
      <title>Docker, Docker Compose and permissions</title>
      <dc:creator>Malte Riechmann</dc:creator>
      <pubDate>Fri, 09 Apr 2021 08:29:39 +0000</pubDate>
      <link>https://forem.com/visuellverstehen/docker-docker-compose-and-permissions-2fih</link>
      <guid>https://forem.com/visuellverstehen/docker-docker-compose-and-permissions-2fih</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Docker and Docker Compose are awesome. Just yesterday I had to install a software to create a user interface on top of the software's API. It took me only minutes to download the Dockerfile, add some configuration using Docker Compose, build the image and run the container. I am super happy Docker and Docker Compose exist, but I would like to see some &lt;a href="https://github.com/docker/for-mac/issues/1592"&gt;improvements on macOS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The concept of users, groups and file permissions is awesome, too. If you are new to this, I would recommend &lt;a href="https://www.linux.com/training-tutorials/understanding-linux-file-permissions/"&gt;this article&lt;/a&gt;, that covers all the basics.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Last year &lt;a href="https://twitter.com/malteriechmann/status/1258352758069121025"&gt;I switched from macOS to Linux&lt;/a&gt; because of some performance issues. The switch definitely improved speed and stability of Docker volumes, but I kept running into a problem which did not occur on macOS: Broken file permissions.&lt;/p&gt;

&lt;p&gt;When using Docker on macOS the file permissions do not get synchronized between your local machine and docker containers. On Linux file permissions get synchronized, which in my opinion is actually the way it should be for all operating systems.&lt;/p&gt;

&lt;p&gt;This was a huge problem.&lt;/p&gt;

&lt;p&gt;If I changed files locally, the file permissions would get changed inside of the container with user and group which did not even exist inside of the container.&lt;/p&gt;

&lt;p&gt;If I changed files inside of the container using the only existing root user, the file permissions would also get changed on my local machine to &lt;code&gt;root:root&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At the time a configuration looked roughly like the following:&lt;/p&gt;

&lt;p&gt;
  Click to open Dockerfile
  &lt;br&gt;

&lt;pre&gt;&lt;code&gt;# Define base image
FROM php:8.0-cli-buster
&lt;/code&gt;&lt;/pre&gt;




&lt;/p&gt;

&lt;p&gt;
  Click to open docker-compose.yml
  &lt;br&gt;

&lt;pre&gt;&lt;code&gt;version: '3.3'

networks:
  web:
    external: true

services:
  application:
    container_name: application
    build:
      context: .
      dockerfile: ./Dockerfile
    networks:
      - web
    volumes:
      - ./:/var/www/html/
    restart: always
&lt;/code&gt;&lt;/pre&gt;




&lt;/p&gt;

&lt;p&gt;We used to run commands 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;docker-compose exec application bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;Create a user and a group inside of the Docker container with the same IDs you are using locally. When this is done file permissions can be synchronized, because the same user and group is used.&lt;/p&gt;

&lt;p&gt;At first you have to export your user and group ID in your shell configuration (e. g. &lt;code&gt;~/.zshrc&lt;/code&gt; or &lt;code&gt;~/.bashrc&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Export variables for Docker and Docker Compose
export USER_ID=$(id -u)
export GROUP_ID=$(id -g)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our configuration looks roughly like this:&lt;/p&gt;

&lt;p&gt;
  Click to open Dockerfile
  &lt;br&gt;

&lt;pre&gt;&lt;code&gt;# Define base image
FROM php:8.0-cli-buster

# Define build arguments
ARG USER_ID
ARG GROUP_ID

# Define environment variables
ENV USER_ID=$USER_ID
ENV GROUP_ID=$GROUP_ID
ENV USER_ID=${USER_ID:-1001}
ENV GROUP_ID=${GROUP_ID:-1001}

# Add group and user based on build arguments
RUN addgroup --gid ${GROUP_ID} alice
RUN adduser --disabled-password --gecos '' --uid ${USER_ID} --gid ${GROUP_ID} alice

# Set user and group of working directory
RUN chown -R alice:alice /var/www/html
&lt;/code&gt;&lt;/pre&gt;




&lt;/p&gt;

&lt;p&gt;
  Click to open docker-compose.yml
  &lt;br&gt;

&lt;pre&gt;&lt;code&gt;version: '3.3'

networks:
  web:
    external: true

services:
  application:
    container_name: application
    build:
      context: .
      dockerfile: ./Dockerfile
      args:
        USER_ID: $USER_ID
        GROUP_ID: $GROUP_ID
    networks:
      - web
    volumes:
      - ./:/var/www/html/
    restart: always
&lt;/code&gt;&lt;/pre&gt;




&lt;/p&gt;

&lt;p&gt;From now on you have to execute commands inside of the container using the newly generated user. We now run commands 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;docker-compose exec --user alice application bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;p&gt;If you want to read more about our local development environment using Docker and Docker Compose, have a look at &lt;a href="https://dev.to/flemssound/development-enviroment-with-docker-and-traefik-1lg6"&gt;an article&lt;/a&gt; a colleague of mine wrote a while ago.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>linux</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Our tech stack in 2021</title>
      <dc:creator>Malte Riechmann</dc:creator>
      <pubDate>Thu, 01 Apr 2021 15:44:12 +0000</pubDate>
      <link>https://forem.com/visuellverstehen/our-tech-stack-in-2021-2600</link>
      <guid>https://forem.com/visuellverstehen/our-tech-stack-in-2021-2600</guid>
      <description>&lt;h2&gt;
  
  
  Preface
&lt;/h2&gt;

&lt;p&gt;Nine years ago I co-founded an agency called &lt;a href="https://www.visuellverstehen.de"&gt;visuellverstehen&lt;/a&gt; here in Germany. We have steadily grown and are now 25 people strong. Looking back I would really like to get an overview how our tech stack has changed over time. Unfortunately we do not have any data about that.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The best time to plant a tree is twenty years ago. The second best time is now. &lt;em&gt;— &lt;a href="https://www.quora.com/What-is-the-origin-of-the-quotation-The-best-time-to-plant-a-tree-is-twenty-years-ago-The-second-best-time-is-now"&gt;Origin unknown&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is why we are starting this series about our tech stack now – and plan to publish it yearly.&lt;/p&gt;

&lt;p&gt;Big firms use technology radars. I first stumbled upon this on &lt;a href="https://www.thoughtworks.com/radar"&gt;ThoughtWorks&lt;/a&gt; and really liked the idea. We are too small to create such a comprehensive resource, but we are able to list the technologies we use. And that is what we are going to do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clarification
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;This will not cover every technology in all of our projects, because individual projects do need individual solutions. But it will cover all the basics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Legacy projects might use outdated technologies and those will not be part of this. Of course, we always try to update legacy projects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is not easy to categorize every technology. Therefore the categorization might not always be 100 % correct.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Not every one of us is working with all of the technologies mentioned below. Our team is organized into smaller sub-teams, which then focus on different projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Our tech stack
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Core products
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Individual digital products using &lt;a href="https://laravel.com"&gt;Laravel&lt;/a&gt; and &lt;a href="https://vuejs.org"&gt;Vue.js&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Content management products using &lt;a href="https://statamic.com"&gt;Statamic&lt;/a&gt; and &lt;a href="https://typo3.org"&gt;TYPO3&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;E-commerce products using &lt;a href="https://www.shopware.com"&gt;Shopware&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What people call »Backend«
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Extbase&lt;/li&gt;
&lt;li&gt;Laravel&lt;/li&gt;
&lt;li&gt;Laravel Nova&lt;/li&gt;
&lt;li&gt;MySQL&lt;/li&gt;
&lt;li&gt;PHP&lt;/li&gt;
&lt;li&gt;PHPUnit&lt;/li&gt;
&lt;li&gt;Shopware&lt;/li&gt;
&lt;li&gt;Statamic&lt;/li&gt;
&lt;li&gt;TYPO3&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What people call »Frontend«
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Antlers&lt;/li&gt;
&lt;li&gt;BEM&lt;/li&gt;
&lt;li&gt;Babel&lt;/li&gt;
&lt;li&gt;Blade&lt;/li&gt;
&lt;li&gt;CSS&lt;/li&gt;
&lt;li&gt;Cypress&lt;/li&gt;
&lt;li&gt;Fluid&lt;/li&gt;
&lt;li&gt;HTML&lt;/li&gt;
&lt;li&gt;JavaScript&lt;/li&gt;
&lt;li&gt;Laravel Livewire&lt;/li&gt;
&lt;li&gt;Sass&lt;/li&gt;
&lt;li&gt;Tailwind CSS&lt;/li&gt;
&lt;li&gt;Twig&lt;/li&gt;
&lt;li&gt;Vue.js&lt;/li&gt;
&lt;li&gt;gulp.js&lt;/li&gt;
&lt;li&gt;npm&lt;/li&gt;
&lt;li&gt;webpack&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What people call »DevOps«
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Docker Compose&lt;/li&gt;
&lt;li&gt;Git&lt;/li&gt;
&lt;li&gt;GitHub&lt;/li&gt;
&lt;li&gt;GitHub Actions&lt;/li&gt;
&lt;li&gt;GitLab&lt;/li&gt;
&lt;li&gt;GitLab CI&lt;/li&gt;
&lt;li&gt;Hetzner Cloud&lt;/li&gt;
&lt;li&gt;Laravel Forge&lt;/li&gt;
&lt;li&gt;Mittwald&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Honorable mentions
&lt;/h3&gt;

&lt;p&gt;Three things are worth a special mention.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;We are moving all of our websites and web applications from shared hosting to Laravel Forge and Hetzner Cloud. Kubernetes was on our minds, but we decided against it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We are moving from gulp.js to only webpack, because we want to make things as simple as possible. If we can get rid of gulp.js, web developers must only learn about one and not two technologies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Our tech stack is more diverse than ever. We know that using less software is definitely the way to go. Nevertheless we added some major new technology (e. g. Statamic, Tailwind CSS and Laravel Livewire) to our portfolio last year. This has open interesting doors.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  So let me ask you this:
&lt;/h2&gt;

&lt;p&gt;What does your tech stack look like? Do you focus on too many technologies? How do you handle legacy projects? How do you keep technology simple?&lt;/p&gt;

&lt;p&gt;I am curious how this will change in the next twelve months. Well, we will find out. See you next year. Happy coding.&lt;/p&gt;

</description>
      <category>tooling</category>
      <category>devops</category>
      <category>technology</category>
      <category>stack</category>
    </item>
    <item>
      <title>Your website does not need cookies</title>
      <dc:creator>Malte Riechmann</dc:creator>
      <pubDate>Tue, 23 Mar 2021 08:23:05 +0000</pubDate>
      <link>https://forem.com/visuellverstehen/your-website-does-not-need-cookies-23k7</link>
      <guid>https://forem.com/visuellverstehen/your-website-does-not-need-cookies-23k7</guid>
      <description>&lt;h2&gt;
  
  
  GDPR and respect
&lt;/h2&gt;

&lt;p&gt;The regulation in EU law on data protection and privacy called »General Data Protection Regulation &lt;a href="https://en.wikipedia.org/wiki/General_Data_Protection_Regulation"&gt;GDPR&lt;/a&gt;« is generally a good thing, but unfortunately it makes browsing the web way worse.&lt;/p&gt;

&lt;p&gt;Instead of respecting the users privacy I see a lot of websites and web applications which display annoying cookie overlays, force the user accept incomprehensible privacy disclaimers, slow everything down by loading a ton of unneeded JavaScript and still integrate third party tracking software.&lt;/p&gt;

&lt;p&gt;Let's face it: we failed. Thanks to GDPR the user is disrespected even more by most of the websites out there.&lt;/p&gt;

&lt;h2&gt;
  
  
  The obvious solution
&lt;/h2&gt;

&lt;p&gt;Of course there is another way. Your website does not need cookies. Recently we removed all of the cookies on &lt;a href="https://www.visuellverstehen.de"&gt;our website&lt;/a&gt; and you can do it too. It is not so difficult.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remove all third party tracking software.&lt;/li&gt;
&lt;li&gt;If you need website analytics, use a privacy friendly alternative (e. g. &lt;a href="https://plausible.io"&gt;Plausible&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Do not blindly  install fancy marketing plugins from a marketplace. Instead understand how a website works and build things yourself.&lt;/li&gt;
&lt;li&gt;Do not use similar techniques as an alternative. By cookies I mean all kind of stored client data. Using local storage instead of cookies will not help you.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I do not really see a good reason to use cookies except for storing user sessions to enable authentication. If you need this functionality, please explain it to the user in your login and register forms.&lt;/p&gt;

&lt;p&gt;By the way, I am neither the first nor the only one talking about this (e. g. &lt;a href="https://github.blog/2020-12-17-no-cookie-for-you/"&gt;GitHub&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Not convinced yet?
&lt;/h2&gt;

&lt;p&gt;There is a nice &lt;a href="https://cookieconsentspeed.run"&gt;little game&lt;/a&gt; out there which will help you understand.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ux</category>
      <category>analytics</category>
    </item>
  </channel>
</rss>
