<?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: Factorial GmbH</title>
    <description>The latest articles on Forem by Factorial GmbH (@factorial-io).</description>
    <link>https://forem.com/factorial-io</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%2Forganization%2Fprofile_image%2F3441%2Fac50bad2-1724-4ec3-8722-67e93238e00b.png</url>
      <title>Forem: Factorial GmbH</title>
      <link>https://forem.com/factorial-io</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/factorial-io"/>
    <language>en</language>
    <item>
      <title>What's new in phabalicious 3.8?</title>
      <dc:creator>Stephan Maximilian Huber</dc:creator>
      <pubDate>Mon, 22 Aug 2022 12:36:52 +0000</pubDate>
      <link>https://forem.com/factorial-io/whats-new-in-phabalicious-38-4g3h</link>
      <guid>https://forem.com/factorial-io/whats-new-in-phabalicious-38-4g3h</guid>
      <description>&lt;h2&gt;
  
  
  What has changed?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  PHP 7.3 required
&lt;/h3&gt;

&lt;p&gt;Phabalicious requires now PHP version 7.3. It should work with newer versions, including 8.1&lt;/p&gt;

&lt;h3&gt;
  
  
  Better integration with 1Password cli/ connect
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Support for version 2 of the cli&lt;/li&gt;
&lt;li&gt;added new script callback &lt;code&gt;get_file_from_1password&lt;/code&gt; which will retrieve an encrypted file from 1password,
decrypt it and store it somewhere, suitable when scaffolding.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Encryption and decryption
&lt;/h3&gt;

&lt;p&gt;Phab supports now encryption and decryption of files and strings. It uses &lt;a href="https://github.com/defuse/php-encryption"&gt;defuse/php-encryption&lt;/a&gt;,&lt;br&gt;
a widely used library for encryption  under the hood. You can encrypt files in a script with&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="na"&gt;secrets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name-of-secret&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;question&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;What is the password?&lt;/span&gt;

&lt;span class="na"&gt;scripts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;encrypt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;encrypt_files(path/to/files/or/folders/to/encrypt/*.ext, path/to/folder/to/store/encrypted/files, name-of-secret)&lt;/span&gt;
  &lt;span class="na"&gt;decrypt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;decrypt_files(path/to/files/or/folders/to/decrypt/*.enc, path/to/folder/to/store/decrypted/files, name-of-secret)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The scaffolder has a new callback called &lt;code&gt;decrypt_assets&lt;/code&gt; which works the same as &lt;code&gt;copy_assets&lt;/code&gt; but with an additional&lt;br&gt;
decryption step&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="na"&gt;scaffold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;decrypt_assets(targetFolder, dataKey, secretName, twigExtension)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can also use &lt;code&gt;decrypt()&lt;/code&gt; and &lt;code&gt;encrypt()&lt;/code&gt; in your scaffold templates using the provided twig-functions:&lt;/p&gt;

&lt;p&gt;test.yml&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight twig"&gt;&lt;code&gt;data:
  my_secret_data: "&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;decrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;my_secret_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'name-of-secret'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;"
  encrypted: "&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello world"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'name-of-secret'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  New command &lt;code&gt;install:from-sql-file&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The command &lt;code&gt;install:from&lt;/code&gt; and the new command &lt;code&gt;install:from-sql-file&lt;/code&gt; get reworked to prevent double-work and to&lt;br&gt;
streamline the process. You can now install the app from an existing sql-file, which translates into an optimized&lt;br&gt;
flow of&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;phab &lt;span class="nt"&gt;-cmy-host-config&lt;/span&gt; &lt;span class="nb"&gt;install
&lt;/span&gt;phab &lt;span class="nt"&gt;-cmy-host-config&lt;/span&gt; restore:sql-from-file sql.gz
phab &lt;span class="nt"&gt;-cmy-host-config&lt;/span&gt; reset
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Instead run&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;phab &lt;span class="nt"&gt;-cmy-host-config&lt;/span&gt; &lt;span class="nb"&gt;install&lt;/span&gt;:from-sql-file sql.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Refactoring of data-handling
&lt;/h3&gt;

&lt;p&gt;Phab now handles data differently, by storing from which file or url a piece of data was loaded. This enables phab to&lt;br&gt;
use relative includes, even for remote configurations. Now you can do things like&lt;/p&gt;

&lt;p&gt;base.yml&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="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Hello world&lt;/span&gt;
    &lt;span class="na"&gt;bar&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Hello from base.yml&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;fabfile.yml:&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="na"&gt;inheritsFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./base.yml&lt;/span&gt;

&lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;

&lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Hello mars&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Running &lt;code&gt;output&lt;/code&gt; will show the resolved inheritances:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;❯ phab38 &lt;span class="nt"&gt;-ctest&lt;/span&gt; output &lt;span class="nt"&gt;--what&lt;/span&gt; host


Output of host-configuration &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="o"&gt;===================================&lt;/span&gt;

  &lt;span class="nb"&gt;test&lt;/span&gt;:
    foo: &lt;span class="s1"&gt;'Hello mars'&lt;/span&gt;
    bar: &lt;span class="s1"&gt;'Hello from base.yml'&lt;/span&gt;
    needs:
      - &lt;span class="nb"&gt;local&lt;/span&gt;
      - script
    &lt;span class="nb"&gt;type&lt;/span&gt;: dev
    &lt;span class="nb"&gt;.&lt;/span&gt;
    &lt;span class="nb"&gt;.&lt;/span&gt;
    &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This enhances also the introspection possibilities:&lt;/p&gt;
&lt;h3&gt;
  
  
  The about command got a &lt;code&gt;-v&lt;/code&gt; flag
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;about&lt;/code&gt; command has another trick up its sleeve now. When inheriting configurations from multiple files, it can now&lt;br&gt;
display the exact location from which a particular parameter is being picked. Thus, finding out if a value is coming from an inherited file from a remote server or some sensible defaults is at your fingertip.&lt;/p&gt;

&lt;p&gt;Let's have a look at an example to see this in action. The command displays not only the active value for a particular&lt;br&gt;
key but also the location from which it is picked up.&lt;/p&gt;

&lt;p&gt;In our case the ouput of &lt;code&gt;phab -ctest about&lt;/code&gt; will show the inheritance very in the second column:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ phab about -v -ctest

Configuration of test
=====================

+-----------------------------+-------------------------------------+---------------------------------------------------+
| Key                         | Value                               | Inherited from                                    |
+-----------------------------+-------------------------------------+---------------------------------------------------+
|   foo                       | Hello mars                          | /Users/stephan/Desktop/phab-38-blog/.fabfile.yaml |
|   bar                       | Hello from base.yml                 | /Users/stephan/Desktop/phab-38-blog/base.yml      |
|   needs                     |                                     | /Users/stephan/Desktop/phab-38-blog/.fabfile.yaml |
|     needs.0                 | local                               | /Users/stephan/Desktop/phab-38-blog/.fabfile.yaml |
|     needs.1                 | script                              | /Users/stephan/Desktop/phab-38-blog/.fabfile.yaml |
|   type                      | dev                                 | host defaults                                     |
.
.
.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  New command &lt;code&gt;find:property&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Phab 3.8 contains a new command named &lt;code&gt;find:property&lt;/code&gt; which provides a visual prompt where the user can start typing the&lt;br&gt;
name of a property they are interested in. Phab supports you by offering properties via autocomplete. As an alternative&lt;br&gt;
you can hit enter to get a list of suggestions. After you found the property you are interested in, hit return, and phab&lt;br&gt;
will display the actual value of that property, its ancestors and from where it got read.&lt;/p&gt;

&lt;p&gt;Here's a short walkthrough using the files and their config from above.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;a href="https://docs.phab.io/assets/img/phab-38-find-property.405edd1b.svg" rel="noopener noreferrer"&gt;
      docs.phab.io
    &lt;/a&gt;
&lt;/div&gt;



&lt;h3&gt;
  
  
  Enhancements to the database command
&lt;/h3&gt;

&lt;p&gt;There's a new subcommand available &lt;code&gt;db:query&lt;/code&gt; where you can run a query against the database of a given configuration&lt;br&gt;
without starting a database-shell and run the query manually.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;phab &lt;span class="nt"&gt;-cmy-host-config&lt;/span&gt; db:query &lt;span class="s2"&gt;"show tables"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will try to get the database credentials from the configuration and apply them. This command is only implemented for&lt;br&gt;
mysql/mariadb for now.&lt;/p&gt;
&lt;h3&gt;
  
  
  New command &lt;code&gt;restic&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Phab 3.7 got support for offsite backups via &lt;a href="https://github.com/restic/restic"&gt;restic&lt;/a&gt;. But it was still a bit cumbersome to interact with the restic&lt;br&gt;
repository for a given configuration using restic alone. That's why phab now has the restic command. It is applying the&lt;br&gt;
configuration and options from the fabfile and you can concentrate on the commands you want to pass to restic. Some&lt;br&gt;
examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;phab &lt;span class="nt"&gt;-cmy-host-config&lt;/span&gt; restic snapshots
phab &lt;span class="nt"&gt;-cmy-host-config&lt;/span&gt; restic &lt;span class="nt"&gt;--&lt;/span&gt; snapshots &lt;span class="nt"&gt;--host-name&lt;/span&gt; my-config
phab &lt;span class="nt"&gt;-cmy-host-config&lt;/span&gt; restic &lt;span class="nt"&gt;--&lt;/span&gt; forget &lt;span class="nt"&gt;--keep-daily&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;14 &lt;span class="nt"&gt;--keep-weekly&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4 &lt;span class="nt"&gt;--keep-monthly&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;6 &lt;span class="nt"&gt;--group-by&lt;/span&gt; host &lt;span class="nt"&gt;--prune&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Experimental integration with ddev
&lt;/h3&gt;

&lt;p&gt;ddev is a superb tool for managing local development environments and provides similar features as phabalicious. As it&lt;br&gt;
takes a lot of time to maintain a local development stack (like multibasebox) we thought it might make more sense to&lt;br&gt;
embrace existing open-source tools.&lt;/p&gt;

&lt;p&gt;As ddev is also using docker and docker-compose under the hood it was very unproblematic to integrate ddev with phabalicious.&lt;br&gt;
Phab will read the ddev configuration from &lt;code&gt;.ddev/config.yaml&lt;/code&gt; and provide it under the global property &lt;code&gt;ddev&lt;/code&gt;. So it's&lt;br&gt;
very easy to provide a phab configuration for your local ddev instance. Instead of copy-pasting the boilerplate into&lt;br&gt;
every project we store it on a central place and inherit from it in the fabfile:&lt;/p&gt;

&lt;p&gt;Store this file in a central place, e.g. in your user-folder or on a remote-server. For demonstration purposes we store&lt;br&gt;
this in the same folder as the fabfile&lt;/p&gt;

&lt;p&gt;the &lt;code&gt;ddev.yml&lt;/code&gt;-file:&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="na"&gt;requires&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3.8.0&lt;/span&gt;

&lt;span class="na"&gt;dockerHosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ddev&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;rootFolder&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;runLocally&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;


&lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ddev&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;additionalNeeds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ddev&lt;/span&gt;
    &lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Local ddev instance&lt;/span&gt;
      &lt;span class="na"&gt;publicUrls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://%settings.ddev.name%.ddev.site"&lt;/span&gt;
      &lt;span class="na"&gt;category&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;01-local&lt;/span&gt;
        &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Local development&lt;/span&gt;
    &lt;span class="na"&gt;executables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;drush&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/var/www/html/vendor/bin/drush&lt;/span&gt;

    &lt;span class="na"&gt;shellProvider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker-exec&lt;/span&gt;
    &lt;span class="na"&gt;composerRootFolder&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/var/www/html&lt;/span&gt;
    &lt;span class="na"&gt;gitRootFolder&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/var/www/html&lt;/span&gt;
    &lt;span class="na"&gt;rootFolder&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/var/www/html/web&lt;/span&gt;
    &lt;span class="na"&gt;backupFolder&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/var/www/backups&lt;/span&gt;
    &lt;span class="na"&gt;docker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;configuration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ddev&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ddev-%settings.ddev.name%-web&lt;/span&gt;
      &lt;span class="na"&gt;projectFolder&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the actual &lt;code&gt;.fabfile.yml&lt;/code&gt;:&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="na"&gt;inheritsFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./ddev.yml&lt;/span&gt;

&lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ddev&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# its a drupal installation, so add the drupal-specfic stuff&lt;/span&gt;
    &lt;span class="na"&gt;adminPass&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;admin&lt;/span&gt;
    &lt;span class="na"&gt;replaceSettingsFile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
    &lt;span class="na"&gt;alterSettingsFile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
    &lt;span class="na"&gt;executables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;drush&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/var/www/html/vendor/bin/drush&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;git&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;drush&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;files&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;running &lt;code&gt;phab list:hosts&lt;/code&gt; will show sth like this for your ddev-project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;❯ phab list:hosts &lt;span class="nt"&gt;-v&lt;/span&gt;

Available configurations &lt;span class="k"&gt;for &lt;/span&gt;your project
&lt;span class="o"&gt;=========================================&lt;/span&gt;

Local development
&lt;span class="nt"&gt;-----------------&lt;/span&gt;

 ‣ ddev
   Local ddev instance
   → https://my-ddev-site.ddev.site
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can run any command against the ddev site as usual. For controlling app lifetime please use ddev, e.g. &lt;code&gt;ddev start&lt;/code&gt;&lt;br&gt;
or &lt;code&gt;ddev stop&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  New run contexts for yarn, npm and others
&lt;/h3&gt;

&lt;p&gt;The configs for &lt;code&gt;yarn&lt;/code&gt;, &lt;code&gt;npm&lt;/code&gt;, &lt;code&gt;composer&lt;/code&gt; and &lt;code&gt;laravel&lt;/code&gt; changed. The composite property name like &lt;code&gt;yarnBuildCommand&lt;/code&gt; is&lt;br&gt;
deprecated, please move the config under a section named &lt;code&gt;yarn&lt;/code&gt;. This allows us to add more options for the respective&lt;br&gt;
commands by keeping a structure. Phab will support the old property-names until the next major release, for now you'll&lt;br&gt;
get a friendly reminder.&lt;/p&gt;

&lt;p&gt;One of the reasons for this change is the extension of the runContext, which got renamed into &lt;code&gt;context&lt;/code&gt; which will adapt&lt;br&gt;
the existing functionality of the script execution contexts. Build commands can now be multiline, but then please&lt;br&gt;
provide the executable-name by yourself:&lt;/p&gt;

&lt;p&gt;Old:&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="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;yarnBuildCommand&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build:production&lt;/span&gt;
    &lt;span class="na"&gt;yarnRunContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker-host&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;New:&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="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;yarn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;buildCommand&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;yarn build:production&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;yarn build:assets&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker-image&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node:16&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are two new contexts available which pigypack on the existing functionality of script execution contexts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;docker-image&lt;/code&gt; will execute the yarn build in a docker image (see script execution contexts for configuration options)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker-image-on-docker-host&lt;/code&gt; same as above, but it will be executed on the same instance where docker-commands are
executed, usually where your dockerConfig points to.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Smaller enhancements
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Passwords are now obfuscated in phabs output.&lt;/li&gt;
&lt;li&gt;Update-check is now using a maintained [php&lt;/li&gt;
&lt;li&gt;library](&lt;a href="https://github.com/consolidation/self-update"&gt;https://github.com/consolidation/self-update&lt;/a&gt;) and works more reliably. Please that the name of the option for getting a beta-version
changed too.&lt;/li&gt;
&lt;li&gt;When importing a sql-dump phab freezes the app, and unfreezes it afterwards. For drupal applications the site will be put in
maintenance mode and back.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Switch to conventional commits and semi-automated releases
&lt;/h3&gt;

&lt;p&gt;We switched to the conventional commits convention and introduced &lt;code&gt;standard-release&lt;/code&gt; to help us creating proper releases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to get it
&lt;/h2&gt;

&lt;p&gt;See the &lt;a href="https://docs.phab.io/installation.html"&gt;documentation&lt;/a&gt; for installation &lt;/p&gt;

</description>
      <category>phab</category>
      <category>phabalicious</category>
      <category>devops</category>
    </item>
    <item>
      <title>How to test a beta version of phabalicious in parallel</title>
      <dc:creator>Stephan Maximilian Huber</dc:creator>
      <pubDate>Sat, 13 Aug 2022 11:42:00 +0000</pubDate>
      <link>https://forem.com/factorial-io/how-to-test-a-beta-version-of-phabalicious-in-parallel-1kn0</link>
      <guid>https://forem.com/factorial-io/how-to-test-a-beta-version-of-phabalicious-in-parallel-1kn0</guid>
      <description>&lt;p&gt;Sometimes it would be neat to test if a new beta version of phabalicious works with my local projects, without breaking&lt;br&gt;
my productivity if I encounter problems. Fortunately it is rather safe to have two phab versions installed on your local&lt;br&gt;
computer.&lt;/p&gt;

&lt;p&gt;Usually you keep phabalicious up-to-date by running &lt;code&gt;phab self-update&lt;/code&gt;. The easiest way to install a beta-version side&lt;br&gt;
by side to the official version are the following commands:&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="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-L&lt;/span&gt;  https://github.com/factorial-io/phabalicious/releases/download/3.8.0-beta.16/phabalicious.phar &lt;span class="nt"&gt;--output&lt;/span&gt; /usr/local/bin/phab38
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x /usr/local/bin/phab38
&lt;span class="nv"&gt;$ &lt;/span&gt;phab38 &lt;span class="nt"&gt;--version&lt;/span&gt;
phabalicious 3.8.0-beta.16
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please adapt the version in the url to your likings. After a successfull installation you can update the beta version using&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;phab38 self-update &lt;span class="nt"&gt;--preview&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if you want to test if your project is still working with the new beta version, just substitute &lt;code&gt;phab&lt;/code&gt; with &lt;code&gt;phab38&lt;/code&gt;, e.g.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;phab38 &lt;span class="nt"&gt;-cmbb&lt;/span&gt; docker run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If you encounter any problems with a beta or a stable version please create an &lt;a href="https://github.com/factorial-io/phabalicious/issues"&gt;issue&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;To remove the beta-version just run &lt;code&gt;rm /usr/local/bin/phab38&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>phabalicious</category>
      <category>phab</category>
    </item>
    <item>
      <title>Backend Development at Factorial</title>
      <dc:creator>Niklas Franke</dc:creator>
      <pubDate>Mon, 28 Feb 2022 11:17:21 +0000</pubDate>
      <link>https://forem.com/factorial-io/backend-development-at-factorial-d72</link>
      <guid>https://forem.com/factorial-io/backend-development-at-factorial-d72</guid>
      <description>&lt;p&gt;What challenges do we face in backend development at Factorial? And what role does Drupal play in our work as an agency? In our latest video, Shibin, Senior Backend Developer at Factorial, gives an overview of our projects and how we develop digital solutions for our clients. &lt;/p&gt;

&lt;p&gt;He also mentions our technology stack we work with and the importance of open-source of us as a company.&lt;/p&gt;

&lt;p&gt;Find the clip here:&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=oRLrnhYAlSY&amp;amp;t=8s"&gt;See Video&lt;/a&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>drupal</category>
      <category>symfony</category>
      <category>laravel</category>
    </item>
    <item>
      <title>Contribution days at Factorial</title>
      <dc:creator>Niklas Franke</dc:creator>
      <pubDate>Mon, 27 Dec 2021 08:21:54 +0000</pubDate>
      <link>https://forem.com/factorial-io/contribution-days-at-factorial-33le</link>
      <guid>https://forem.com/factorial-io/contribution-days-at-factorial-33le</guid>
      <description>&lt;p&gt;We have an important announcement to make! By the start of 2022 we introduce the contribution days at Factorial. The contribution days will allow the team members to dedicate more time on their open source projects and will be available for every team member.&lt;/p&gt;

&lt;p&gt;Open source has always been shaping our corporate identity which is why we decided to take the leap and actively promote it in our team. Read in this article about our connection to open source and what led us to that decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why we encourage open source
&lt;/h2&gt;

&lt;p&gt;At Factorial, the words open source are strongly connected to our daily work. In our projects we most exclusively create our digital products with open source technology, building websites and web applications with Drupal, Laravel, Symfony, Node.js or Vue.js — only to name a few. This is why we are heavily relying on the awesome work, developers from all over the world are dedicating their valuable time to. It is their effort that keeps these technologies alive, updated and safe to use. &lt;/p&gt;

&lt;p&gt;Contributions therefore leave a great impact on the system and its community. In our projects we are trying to worship this approach as well by giving something back. This not only happens collaboratively as a team, also many of our team members have their individual projects where they are actively contributing to the open source community.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some open source projects from our team members
&lt;/h2&gt;

&lt;p&gt;We have a couple of team members that participate actively in the open source community. Our colleague Shibin for instance actively participates in the Decoupled Menu Initiative (&lt;a href="https://www.factorial.io/en/blog/drop-decoupled-menu-initiative"&gt;Read his article here&lt;/a&gt;) in order to improve the developer experience for Drupal acting as a headless CMS.&lt;/p&gt;

&lt;p&gt;Besides that there is Michi who created &lt;a href="https://www.miyagi.dev"&gt;Miyagi&lt;/a&gt;, a storybook alternative that allows you to have awesome and really well structured component libraries or living style guides. Its philosophy is to stick as close to the platform technologies as possible and doesn’t rely on many external libraries. It’s a great toolkit for component based frontend development. With clever naming conventions of your css custom properties, you get valuable design tokens such as font-variants, colors, spacings visualized out of the box.&lt;/p&gt;

&lt;p&gt;Another example for continuous contribution is our colleague Kristiaan. He picked up his work on his Drupal module Group already 8 years ago. The Group module enables users to create arbitrary collections of web content and handles the access control permissions on those collections. Currently almost 11.500 websites report using this module. In this year, a new release came to life (&lt;a href="https://www.factorial.io/en/blog/word-appreciation-groups-sponsors"&gt;Read his article here&lt;/a&gt;) that brought the additional feature of making Groups fully revisionable through code and the UI. Since the start of Group much has happened and Kristiaan received a wave of appreciation within the community for his work. But during years of development he also stumbled upon something that we think is giving the core idea of open source a negative connotation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Great power comes with great responsibility
&lt;/h2&gt;

&lt;p&gt;In the previous paragraph you have seen the amount of positive feedback that is passed on in the open source community. But in between all the acknowledgement there are the limitations a passionate developer is facing while dedicating his/her/their time to the numerous requests and bug fixes.&lt;/p&gt;

&lt;p&gt;The problem here is, that all of this open source contribution has to be made simultaneously to a full-time employment, because the open source work is mostly not being financially compensated. This means that the developer often squeezes extra work into his/her/their timetable in order to do equal justice to all. And this work doesn’t shrink on a long term perspective, because the more work that is put into the open source project, the louder the calls for requests get. Suddenly, the developer’s passionate project becomes an extra burden in order to keep up with the increased workload. If this goes on and on, it’s hard to maintain creativity and passion in such a high pressure environment.&lt;/p&gt;

&lt;p&gt;We think that tech companies that benefit from open source technologies have a responsibility to shape and also support that community. And they should try to enable their employees to participate in it as part of their jobs.&lt;/p&gt;

&lt;h2&gt;
  
  
  We want to give something back
&lt;/h2&gt;

&lt;p&gt;We at Factorial want to encourage our team members to focus on their contributional work without having to worry about the financial coverage that much. For this reason, from the beginning of 2022, we at Factorial announce the Contribution Days. We give 10 additional days every year to each of our team members to dedicate them to open source contributions. This is not only scoped to our team of developers. We want to encourage everyone, no matter what discipline, to contribute to open source. That could be fixing bugs in an existing open source project, designing a website for an open source project or even helping to organize a meetup or conference. Basically everything that helps the open source community is a great fit.&lt;/p&gt;

&lt;p&gt;With this approach we hope to get more of us engaged in open source projects and want to create a supportive environment for our team members in being more creative and passionate about their work. Also we want to highlight the very core of open source — to work together and spend your time on things you like.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>opensource</category>
      <category>codequality</category>
      <category>development</category>
    </item>
    <item>
      <title>Developing and Testing Web Components</title>
      <dc:creator>Andrew Beng</dc:creator>
      <pubDate>Thu, 14 Oct 2021 00:50:27 +0000</pubDate>
      <link>https://forem.com/factorial-io/developing-and-testing-web-components-224a</link>
      <guid>https://forem.com/factorial-io/developing-and-testing-web-components-224a</guid>
      <description>&lt;p&gt;This blog is a follow up from my previous article &lt;a href="https://www.factorial.io/en/blog/custom-elements-vue-reactivity"&gt;"Custom Elements with Vue Reactivity"&lt;/a&gt;. Here I will be sharing my thoughts on the challenges I faced setting up development and unit testing environments, while not forgetting about accessibility concerns for a Web Components project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thinking about Developer Experience
&lt;/h2&gt;

&lt;p&gt;As Vue.js developers, we are spoiled when it comes to &lt;a href="https://developerexperience.io/practices/good-developer-experience"&gt;developer experience&lt;/a&gt; (DX), or “the experience developers have while using or working on your product”. From first-class documentation, to browser extension based or standalone Vue developer tools, to opinionated packages for routing, state management and unit testing, Vue’s ecosystem has always been developer centric, and newcomer friendly. Good DX is therefore a key value software project maintainers should work towards for long-term sustainability of their projects or their developer community.&lt;/p&gt;

&lt;p&gt;When experimenting with Custom Elements in developing &lt;a href="https://github.com/andrewbeng89/vue-uhtml"&gt;vue-uhtml&lt;/a&gt;, the lack of (or at least the lack of documentation of) developer tooling with decent DX became quickly apparent. To date, there is now default or opinionated out-of-the-box solution for web developers to spin up a basic development server to serve vanilla HTML, CSS and JavaScript - the underlying web technologies Custom Elements builds upon. I chose to scope the developer experience considerations for the vue-uhtml project to three areas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How might developers use vue-uhtml to develop a UI library&lt;/li&gt;
&lt;li&gt;How might developers unit test components built with vue-uhtml&lt;/li&gt;
&lt;li&gt;How might developers be aware of accessibility issues when developing with vue-uhtml&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A dev environment for Custom Elements projects
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://storybook.js.org/"&gt;Storybook&lt;/a&gt; is a popular and easy-to-use open source tool for building UI components in isolation. Given my previous experience in using Storybook for Vue based projects, this was a natural option for UI development with vue-uhtml. Storybook’s Web Components flavour made this decision an even easier one since this is officially supported and well documented. One possible drawback when using &lt;a href="https://storybook.js.org/docs/web-components/get-started/introduction"&gt;Storybook for Web Components&lt;/a&gt; is the use of the lit-html templating utility to create “stories” for your components. The lit-html project is incidentally the library Evan You chose to implement his own Custom Elements project with. In the case of this project, having to implement components in a slightly different uhtml syntax and “stories” in the lit-html syntax is objectively a negative developer experience, and has to be considered further for a wider vue-uhtml developer community.&lt;/p&gt;

&lt;p&gt;A major hurdle to overcome when developing Custom Elements is an approach for implementing styles and CSS via the encapsulated Shadow DOM, especially when also using CSS pre and post processors. This issue is usually solved during the build process when tools like Webpack or Rollup orchestrate CSS transformations before bundling and injecting processed styles in the right place. Front-end framework CLI tools like vue-cli-service, Vite or create-react-app abstract much of the underlying processing and building for both development and production environments. For example, most Vue developers would not need to be concerned with how a Vue single file component gets compiled by Webpack or Vite and served on a local port when &lt;code&gt;yarn serve&lt;/code&gt; is run. This is great DX, but probably not something that would be easily achievable for vue-uhtml development in the short term.&lt;/p&gt;

&lt;p&gt;Putting the pieces together, these were the steps I took to set up a Storybook based development environment with decent DX to build UI components with vue-uhtml:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Configure a bare bones &lt;a href="https://github.com/andrewbeng89/vh-ui-components/blob/main/rollup.config.js"&gt;Rollup project&lt;/a&gt; to process vue-uhtml defined Custom Elements for both development and production&lt;/li&gt;
&lt;li&gt;Configure Rollup to &lt;a href="https://github.com/andrewbeng89/vh-ui-components/blob/main/rollup.config.js#L35"&gt;watch the &lt;code&gt;src&lt;/code&gt; directory&lt;/a&gt; to compile the components to a &lt;code&gt;dev&lt;/code&gt; directory&lt;/li&gt;
&lt;li&gt;Configure Storybook for Web Components and write &lt;a href="https://github.com/andrewbeng89/vh-ui-components/blob/main/src/components/UiCheckBox.stories.js"&gt;component stories&lt;/a&gt; using the rolled-up output component definitions in the &lt;code&gt;dev&lt;/code&gt; directory (rather than &lt;code&gt;src)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run Rollup and Storybook concurrently via a &lt;a href="https://github.com/andrewbeng89/vh-ui-components/blob/main/package.json#L51"&gt;&lt;code&gt;dev&lt;/code&gt; script&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// UiCheckBox.stories.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lit-html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineUiCheckBox&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../dev/index.esm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;defineUiCheckBox&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Components/UiCheckBox&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;ui-check-box&amp;gt;&amp;lt;/ui-check-box&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The trial and error in setting up these steps could in the future be the basis for vue-uhtml’s own CLI, or to extend or use Vite for a similar purpose.&lt;/p&gt;

&lt;h2&gt;
  
  
  Unit testing Custom Elements
&lt;/h2&gt;

&lt;p&gt;The next consideration I addressed was being able to easily write and run unit tests for vue-uhtml components. Having previously talked about a &lt;a href="https://www.factorial.io/en/blog/unit-testing-vuejs-theory-practice"&gt;unit testing approach for Vue.js components&lt;/a&gt;, I was keen to apply the principle of “writing tests that assert your component’s public interface”. Before I could even think about writing component tests, I had to pick the most appropriate and well supported tooling. Vue’s documentation on testing and own vue-test-utils package makes this choice a foregone conclusion with Jest as a comprehensive test framework, and using vue-test-util’s wrapper based API to mount components in an isolated jsdom environment. While jsdom has provided a &lt;a href="https://github.com/jsdom/jsdom/releases/tag/16.2.0"&gt;Custom Elements implementation since version 16&lt;/a&gt;, other Web Components APIs including Shadow DOM are not supported or reliable enough to be useful.&lt;/p&gt;

&lt;p&gt;Since Custom Elements is a browser based web technology, a common approach to work around jsdom’s limitations is to consider using Puppeteer to run tests on Custom Elements rendered in real browsers. However, in practice this usually isn’t the most practical solution as “boilerplate” code is required to navigate to the components on a served HTML page.&lt;/p&gt;

&lt;p&gt;To improve DX and streamline the unit testing approach for Custom Elements, the folks at Open Web Components have provided an opinionated testing package aptly called &lt;a href="https://open-wc.org/docs/testing/testing-package/"&gt;@open-wc/testing&lt;/a&gt; that “combines and configures testing libraries to minimize the amount of ceremony required when writing tests”. While not having a choice of test runner or assertion library (@open-wc/testing uses Mocha and Chai respectively with Puppeteer) may seem restrictive, the positive trade-off is clear documentation and concise examples to help get up and running writing component tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Potential gotcha: &lt;code&gt;shadowRoot.mode&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The encapsulation of Custom Element features is aided by the ability to set a component’s &lt;code&gt;shadowRoot&lt;/code&gt; mode to &lt;code&gt;”closed”&lt;/code&gt;, preventing the shadow root's internal features being accessible from JavaScript. This is a feature that is set to &lt;a href="https://github.com/andrewbeng89/vue-uhtml/blob/main/src/main.js#L27"&gt;&lt;code&gt;“closed”&lt;/code&gt; by default&lt;/a&gt; when building components with vue-uhtml. This has potential “gotcha” implication in preventing test scripts from asserting the components’ internal features. To prevent falling into this trap, components based on Custom Element should easily allow developers to be &lt;a href="https://github.com/andrewbeng89/vh-ui-components/blob/main/src/components/UiCheckBox.js#L63"&gt;defined with an &lt;code&gt;”open”&lt;/code&gt; shadow root mode&lt;/a&gt; when used in tests.&lt;/p&gt;

&lt;p&gt;The example below outlines tests for a custom checkbox component which:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Asserts that the initial &lt;code&gt;checked&lt;/code&gt; value is &lt;code&gt;false&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Asserts that the &lt;code&gt;checked&lt;/code&gt; value is &lt;code&gt;true&lt;/code&gt; if its attribute is passed&lt;/li&gt;
&lt;li&gt;Asserts that the &lt;code&gt;checked&lt;/code&gt; value is &lt;code&gt;true&lt;/code&gt; after the input is clicked
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fixture&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;elementUpdated&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@open-wc/testing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineUiCheckBox&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../dist/index.esm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;defineUiCheckBox&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;isTest&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="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;UiCheckBox&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;has a default checked value which is falsy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fixture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;` &amp;lt;ui-check-box&amp;gt;&amp;lt;/ui-check-box&amp;gt; `&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;has a checked of true when the 'checked' attribute is passed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fixture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;` &amp;lt;ui-check-box checked&amp;gt;&amp;lt;/ui-check-box&amp;gt; `&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&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;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;has checked value after click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fixture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;` &amp;lt;ui-check-box&amp;gt;Checkbox&amp;lt;/ui-check-box&amp;gt; `&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shadowRoot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;elementUpdated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&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;h2&gt;
  
  
  Developing with &lt;code&gt;a11y&lt;/code&gt; in mind
&lt;/h2&gt;

&lt;p&gt;Web accessibility (&lt;code&gt;a11y&lt;/code&gt;) has historically been an area overlooked by developers and designers alike, often seen as more of an art than precise science. While there is no single tool or methodology that solves all &lt;code&gt;a11y&lt;/code&gt; concerns for web development, significant progress in tooling has made it possible to integrate &lt;a href="https://www.w3.org/WAI/standards-guidelines/wcag/"&gt;Web Content Accessibility Guidelines&lt;/a&gt; (WCAGs) into development workflows. Although the use of such developer tools does not solve the actual task of authoring accessible websites and apps, they do help developers become more aware of the &lt;code&gt;a11y&lt;/code&gt; topic during development rather than after. One such tool at the forefront of this drive to assist developers in developing with &lt;code&gt;a11y&lt;/code&gt; is axe, which provides an open-source accessibility rule set for automated accessibility validation. The axe rule set can in turn be used in &lt;code&gt;a11y&lt;/code&gt; validation plugins in other developer tools. I was able to easily integrate an axe based &lt;a href="https://open-wc.org/docs/testing/chai-a11y-axe/"&gt;&lt;code&gt;a11y&lt;/code&gt; plugin for Chai with @open-wc/testing&lt;/a&gt; into my vue-uhtml components project.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.npmjs.com/package/chai-a11y-axe"&gt;axe plugin for Chai&lt;/a&gt; allows developers to automatically run &lt;code&gt;a11y&lt;/code&gt; validation as part of their TDD or BDD workflow.&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="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;accessible&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Take-aways
&lt;/h2&gt;

&lt;p&gt;Thinking about developer experience in the context of developing a Custom Elements based project has been a lot like thinking about user experience when developing front-end websites and applications. Instead of a visual user interface, a tool/library/framework’s API is the end user’s (in this case developer’s) medium for achieving their tasks. This small exercise in DX has made me appreciate the thoughtful contributions open source maintainers make in keeping their tools and documentation easy to use for the wider developer community.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.factorial.io/en/blog/custom-elements-vue-reactivity"&gt;Custom Elements with Vue Reactivity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.factorial.io/en/blog/unit-testing-vuejs-theory-practice"&gt;Unit Testing in Vue.js: From Theory into Practice&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/andrewbeng89/vh-ui-components"&gt;Demo project repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>vue</category>
      <category>webdev</category>
      <category>testing</category>
      <category>a11y</category>
    </item>
    <item>
      <title>Custom Elements with Vue Reactivity</title>
      <dc:creator>Andrew Beng</dc:creator>
      <pubDate>Thu, 08 Jul 2021 08:22:31 +0000</pubDate>
      <link>https://forem.com/factorial-io/custom-elements-with-vue-reactivity-25o1</link>
      <guid>https://forem.com/factorial-io/custom-elements-with-vue-reactivity-25o1</guid>
      <description>&lt;p&gt;The 13th Hamburg Vue.js Meetup was held last week, this time as an online live-stream due to the ongoing COVID-19 restrictions. I was pleased to represent Factorial to share a talk on some insights on a small experiment in building Custom Elements with Vue 3.x’s standalone Reactivity module. Having previously worked with Vue’s own &lt;a href="https://cli.vuejs.org/guide/build-targets.html#web-component"&gt;Custom Elements build option&lt;/a&gt;, I was keen to re-explore this topic with standalone Reactivity, also spurred on by Evan You’s &lt;a href="https://github.com/yyx990803/vue-lit#vuelit-"&gt;~70 lines-of-code experiment&lt;/a&gt;. My own question was, “could it really be that simple?”&lt;/p&gt;

&lt;h2&gt;
  
  
  Vue 3.x Reactivity
&lt;/h2&gt;

&lt;p&gt;Vue’s Reactive utility (previously known as Vue.observable) has been heavily overhauled since the release of Vue 3 late in 2020. Its dependency to ES6 Proxy makes observing state changes a breeze for developers, but also means that Vue 3 drops support for Internet Explorer 11.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Elements
&lt;/h2&gt;

&lt;p&gt;Custom Elements is a foundational Web Components which allows developers to create and extend HTML tags. The main goal of the Custom Elements API is in creating reusable components (an objective shared with front-end libraries and frameworks like Vue, React, or Angular), using web standards: HTML, CSS and JavaScript. In using web standards, the biggest advantage of using Custom Elements is their easy interoperability in other framework specific projects, e.g. sharing the same Custom Elements across Vue or React projects. &lt;/p&gt;

&lt;p&gt;In practice, creating vanilla Custom Elements often involves writing lots of boilerplate code, especially when setting up reactive properties and observed attributes. This is something which is solved in some of the &lt;a href="http://webcomponents.dev/new/"&gt;wide array of Custom Elements libraries and frameworks&lt;/a&gt; available. Addressing the issue of verbose boilerplate code is also an area where standalone Reactivity shines.&lt;/p&gt;

&lt;h2&gt;
  
  
  The “vue-micro” Experiment
&lt;/h2&gt;

&lt;p&gt;My experiment in creating a framework to build Custom Elements borrows from Vue creator Evan You’s own proof of concept called &lt;a href="https://github.com/yyx990803/vue-lit"&gt;vue-lit&lt;/a&gt;. The goals of my vue-uhtml (“vue-micro”) experiment were to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add props validation&lt;/li&gt;
&lt;li&gt;Add a &lt;code&gt;&amp;lt;slot&amp;gt;&lt;/code&gt; interface&lt;/li&gt;
&lt;li&gt;Implement some form of test coverage&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The pseudo code below provides an overview of how the Custom Elements API is used to emulate the rendering and reactive features seen in Vue components.&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;observedAttributes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Return a list of observed attribute names&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// 1. Scaffold reactive props&lt;/span&gt;
        &lt;span class="c1"&gt;// 2. Scaffold slots as reactive object&lt;/span&gt;
        &lt;span class="c1"&gt;// 3. Apply effect to render the template + run hooks&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nf"&gt;connectedCallback&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// 1. Run beforeMount hook&lt;/span&gt;
        &lt;span class="c1"&gt;// 2. Render template + invoke setup()&lt;/span&gt;
        &lt;span class="c1"&gt;// 3. Run mounted hook&lt;/span&gt;
        &lt;span class="c1"&gt;// 4. Bind template slots to reactive object&lt;/span&gt;
        &lt;span class="c1"&gt;// 5. Validate props&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nf"&gt;disconnectedCallback&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Run unmounted hook&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nf"&gt;attributeChangedCallback&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Parse, validate and update reactive props&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;[Pseudo code structure of vue-uhml - JavaScript]&lt;br&gt;
View the actual code &lt;a href="https://github.com/andrewbeng89/vue-uhtml/blob/main/src/main.js"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here’s an example of vue-uhtml in action combining reactive re-rendering on user input, props validation, and using a named &lt;code&gt;&amp;lt;slot&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/andrewbeng89/embed/RwVwMXJ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I spent some time researching how Custom Elements could be test-automated. The community driven Open Web Components initiative provides a set of defaults, recommendations and tools to help facilitate web components projects. The @open-wc/testing package combines and configures testing libraries to quickly get up to speed writing tests for Custom Elements. The vue-uhtml repository includes &lt;a href="https://github.com/andrewbeng89/vue-uhtml/tree/main/test"&gt;tests&lt;/a&gt; for a Custom Element built with vue-uhtml covering lifecycle hooks, user input and props interfaces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Take-aways and possible future
&lt;/h2&gt;

&lt;p&gt;To conclude the talk, I shared my top three take-aways from this experiment with the Vue.js Hamburg:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Standalone Vue Reactivity is pretty awesome&lt;/li&gt;
&lt;li&gt;Custom Elements are not scary&lt;/li&gt;
&lt;li&gt;More developers should also get out there and experiment&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My learning experience through this process of experimenting with community driven open source software far outweighed the extent of checking off the original goals I had set out. I was encouraged on this point that the second talk of the evening by Thomas Jacob from sum.cumo (“VueGround: Ein Design-Tool und Playground für Vuetify, in Vuetify”) was also in the spirit of experimentation.&lt;/p&gt;

&lt;p&gt;Writing user centric documentation and more comprehensive test coverage for vue-uhtml are two areas to focus on before vue-uhtml to be “production ready”. Whether vue-uhtml will be added to the wide selection of Custom Elements frameworks already available remains a question for the wider developer community to engage with.&lt;/p&gt;

&lt;p&gt;Many thanks to Vue.js Hamburg and Joe Ray Gregory for organising this online Meetup, and to sum.cumo for the smooth hosting of the live-stream on YouTube. We are indeed looking forward to the day when in-person Vue.js Hamburg meetups will be possible again.&lt;/p&gt;

&lt;h3&gt;
  
  
  Links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://slides.com/andrewbeng89/vue-reactivity-custom-elements"&gt;Talk slide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/andrewbeng89/vue-uhtml"&gt;vue-uhtml repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>vue</category>
      <category>webdev</category>
    </item>
    <item>
      <title>From design to code</title>
      <dc:creator>Michael Großklaus</dc:creator>
      <pubDate>Tue, 13 Apr 2021 07:49:40 +0000</pubDate>
      <link>https://forem.com/factorial-io/from-design-to-code-4f72</link>
      <guid>https://forem.com/factorial-io/from-design-to-code-4f72</guid>
      <description>&lt;p&gt;Since 2020, we at &lt;a href="https://www.factorial.io/"&gt;Factorial&lt;/a&gt; do not only offer web development, but also conception and design for all kinds of web projects. And while in the past designing and developing websites has usually been a quite separate process, there are nowadays powerful tools for cooperation between designers and developers. At Factorial we try to make use of these tools as much as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Designing in Figma
&lt;/h2&gt;

&lt;p&gt;Our designers work with &lt;em&gt;&lt;a href="https://www.figma.com/"&gt;Figma&lt;/a&gt;&lt;/em&gt;, a web-based design tool developed for easy collaboration with developers. We will show later how we actually make use of that, but for now let us have a look at how we structure the projects.&lt;/p&gt;

&lt;p&gt;Usually we create five so called “Pages” in &lt;em&gt;Figma&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Design Tokens&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Elements&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Patterns&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Template components&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Templates&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Design Tokens
&lt;/h3&gt;

&lt;p&gt;Design tokens are a set of styles — colors, typography, size and effect variables that are used across the product — to create a consistent and simple design language.&lt;/p&gt;

&lt;p&gt;On the &lt;em&gt;Design Tokens&lt;/em&gt; page, we create four different art boards: &lt;em&gt;Colors&lt;/em&gt;, &lt;em&gt;Typography&lt;/em&gt;, &lt;em&gt;Spacings&lt;/em&gt;, &lt;em&gt;Other&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7fvexllfmbl71mpyisg4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7fvexllfmbl71mpyisg4.png" alt="Screenshot of design tokens in Figma" width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Colors&lt;/em&gt; can contain colors for typography but also decorational colors. It is important for us to separate these two to make sure that certain colors should only be used for certain things. E.g. a light grey might be good for background or an outline, but not good for typography as the contrast ratio could fail, especially for visually impaired users.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Spacings&lt;/em&gt; contain a list of pixel based spacing values (which will later be converted to rem in CSS), usually starting at 4 and containing not more than 8-10 values.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Typography&lt;/em&gt; lists all different types of text styles: headlines, copy, highlighted text, links and so on.&lt;/p&gt;

&lt;p&gt;On &lt;em&gt;Other&lt;/em&gt; we define values for elevation, borders, radiuses or certain effect styles needed for i.e. hover effects or overlays.&lt;/p&gt;

&lt;h3&gt;
  
  
  Elements, Patterns, Template Components and Templates
&lt;/h3&gt;

&lt;p&gt;The pages &lt;em&gt;Elements&lt;/em&gt;, &lt;em&gt;Patterns&lt;/em&gt;, &lt;em&gt;Template Components&lt;/em&gt; and &lt;em&gt;Templates&lt;/em&gt; are where the actual designs are located.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffx5edbn53u5p5oqi1cel.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffx5edbn53u5p5oqi1cel.png" alt="Screenshot of an elements page in Figma" width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On &lt;em&gt;Elements&lt;/em&gt; we have small components which can be reused everywhere. These are usually components like buttons, icons, form elements, images, etc..&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Patterns&lt;/em&gt; are combinations of &lt;em&gt;elements&lt;/em&gt;, but not only. They are rather complex components like an image gallery, rich text, a slide show and so on. These components can later be picked by the editors of a CMS to compose the content of a website, e.g. using Drupal’s Layout Builder.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Template components&lt;/em&gt; are the single parts of a template: header, footer, navigation, search results, sidebar etc.. These elements can not be picked by editors, but are instead a fixed part of &lt;em&gt;templates&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Templates&lt;/em&gt; bring everything together: They connect &lt;em&gt;template components&lt;/em&gt; and &lt;em&gt;patterns&lt;/em&gt; and represent completes pages like a homepage, product page, search results, etc..&lt;/p&gt;

&lt;h2&gt;
  
  
  Importing design tokens via Figma API
&lt;/h2&gt;

&lt;p&gt;When naming pages, art boards and tokens in &lt;em&gt;Figma&lt;/em&gt;, it is very important that we follow a certain structure and naming convention. Not only does that make communication and reusability easier, it also allows us to use the Figma API to import our design tokens and components directly into our projects.&lt;/p&gt;

&lt;p&gt;Our frontend stack, which is part of every new project, contains a small script, which lets us do exactly that. When executing it, it will use the Figma API to connect to our Figma file, receive a JSON response containing all the necessary information about the designs and then create&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;em&gt;tokens.css&lt;/em&gt; file, which contains CSS custom properties based on the &lt;em&gt;Design Tokens&lt;/em&gt; page in our figma file,&lt;/li&gt;
&lt;li&gt;empty components based on the other four pages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The custom properties are named accordingly to the design tokens in the Figma file. This makes sure that designers and developers talk about the same things and it simply makes it easier to remember how things are named. Since this file is auto-generated, it should never be changed manually. As soon as we run the import again, this file would be overwritten.&lt;/p&gt;

&lt;p&gt;For elements, patterns, template components and templates, the script creates empty components in the same hierarchy. If the Figma file e.g. contains a button component on the &lt;em&gt;Elements&lt;/em&gt; artboard, it would create&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;elements
└── button
    ├── button.css
    ├── button.twig
    ├── mocks.yaml
    └── schema.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It would only do that if this component does not exist yet to avoid overwriting components, which have already been implemented.&lt;/p&gt;

&lt;p&gt;While the button.css and button.twig (twig is template language of our choice) are part of the actual component, the mocks.yaml and schema.yaml are important for collaboration with backend developers and for our component library.&lt;/p&gt;

&lt;h2&gt;
  
  
  Developing in miyagi
&lt;/h2&gt;

&lt;p&gt;After having used &lt;em&gt;Pattern Lab&lt;/em&gt; for many years, it met our requirements as a component library less and less. It is a proven, well-working tool, but it started feeling too heavy and too slow for us. We also had increasing needs, which our component library should fulfil and Pattern Lab was simply not able to do that. After evaluating lots of different tools and not being able to find just one tool which would be able to deliver everything we need, I ended up creating a tool myself to serve that purpose. It is called &lt;em&gt;&lt;a href="https://www.miyagi.dev/"&gt;miyagi&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqlznwbyz7oy6h7m7vca.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqlznwbyz7oy6h7m7vca.png" alt="Screenshot of our Frontend Starter Kit in miyagi" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;miyagi&lt;/em&gt; is a node module, using an express server and can basically fit to any project structure you have. You can name your folders and components any way you want, nest them as deep as you want, use (almost) any kind of JavaScript templating language and all it needs in your project is one configuration file (it actually even works without a configuration file by trying to guess your template language, but you need to follow a certain naming convention for your folders and components then). This allows us to use it in different kinds of projects while keeping the project structure completely independent from our component library. If we ever want to use a different one, all we need to do is remove the configuration file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Design tokens
&lt;/h3&gt;

&lt;p&gt;When you open the start page of a &lt;em&gt;miyagi&lt;/em&gt; instance, you will get a representation of our design tokens: &lt;em&gt;miyagi&lt;/em&gt; is able to parse our CSS files, look for custom properties with a certain naming (which we get out of the box thanks to our token importer) and create a nice overview of all design tokens we have in a project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Customer theme
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;miyagi&lt;/em&gt; can also be styled in the CI of our customers: fonts, colors, a logo and basically any CSS can be added to give the customer the feeling that it is &lt;em&gt;their&lt;/em&gt; component library.&lt;/p&gt;

&lt;h3&gt;
  
  
  The schema files
&lt;/h3&gt;

&lt;p&gt;The schema files are &lt;a href="https://json-schema.org/"&gt;JSON schema&lt;/a&gt; files. We use them to agree on a certain data structure for a component, to make sure that the provided data by a backend service actually fits to that component. But they also allow our designers to come up with certain restrictions, e.g. a given text should only be 200 characters long etc..&lt;/p&gt;

&lt;p&gt;While these schema files are independent from a component library, they are still used by &lt;em&gt;miyagi&lt;/em&gt; to validate the mock data: If the given mock data for a component does not fit to the given JSON schema, it will render an error.&lt;/p&gt;

&lt;h3&gt;
  
  
  The mock files
&lt;/h3&gt;

&lt;p&gt;One aspect of component libraries is usually that they allow encapsulated and indepenent development of components. This means that frontend developers can build a component without having to wait for a backend service, which provides them data or an environment to render this component.&lt;br&gt;
To do that in &lt;em&gt;miyagi&lt;/em&gt;, we can create mock files to provide dummy data for our components. This can be static using yaml or json, but you can also use JavaScript files, which asynchronously export data coming from some API, for example. That way we can have many different variants of a component to make sure that the components always work, no matter how the data which is passed to the component looks like.&lt;/p&gt;

&lt;p&gt;Based on these mock files, &lt;em&gt;miyagi&lt;/em&gt; creates a separate view for every variant. We use these views also for our visual regression tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing for visual regressions using our component library
&lt;/h2&gt;

&lt;p&gt;To make sure that we do not accidentally create visual regressions, we use &lt;a href="https://garris.github.io/BackstopJS/"&gt;BackstopJS&lt;/a&gt; to test our components (including all elements, patterns, template components and templates) for exactly that.&lt;/p&gt;

&lt;p&gt;The way this works is that when creating a pull request in our git repository, we first create a static build of our component library (which will later be deployed to a dedicated instance, so everyone can have access to that: designers, developers, project managers, the client, …) and then use these static build files to compare them with the previous ones (which are checked in to the git repository).&lt;br&gt;
That means we have a direct coupling between our component library and our visual regression tests and are not depending on some third party services: there won’t be any downtime and nothing leaves our servers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting projects with the Frontend Starter Kit
&lt;/h2&gt;

&lt;p&gt;Last but not least, we tried to make things even easier, even more consistent and therefore even better and stable.&lt;/p&gt;

&lt;p&gt;Since websites do quite often consist out of the same (or at least very similar) components, we came up with the Frontend Starter Kit, which is basically made of all of the above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a Figma file which contains accessible colors, typography, components like form elements and so on&lt;/li&gt;
&lt;li&gt;web components for form elements and other recurring components, which are published as node modules&lt;/li&gt;
&lt;li&gt;a Drupal theme providing form elements and other types of components&lt;/li&gt;
&lt;li&gt;all developed and tested for visual regressions using miyagi&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This Frontend Starter Kit works for many different types of projects and since we publish the components as node modules, we can even use them in Vue projects.&lt;/p&gt;

&lt;p&gt;Overall this allows us to have a standardized, well-proven and consistent base for all our projects, avoiding the “stupid” work which every project contains and letting us concentrate on the rest.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F147cmd69xyu6lcu3fcs0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F147cmd69xyu6lcu3fcs0.png" alt="Screenshot of our Frontend Starter Kit in Figma" width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>design</category>
      <category>frontend</category>
      <category>workflow</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Frontend Development at Factorial</title>
      <dc:creator>Niklas Franke</dc:creator>
      <pubDate>Thu, 28 Jan 2021 14:47:16 +0000</pubDate>
      <link>https://forem.com/factorial-io/frontend-development-at-factorial-34m8</link>
      <guid>https://forem.com/factorial-io/frontend-development-at-factorial-34m8</guid>
      <description>&lt;p&gt;What does a frontend developer do at Factorial? Our colleague Julian shares some insights about the Frontend Developer role in our team. &lt;br&gt;
See the full video: &lt;a href="https://bit.ly/3aaCGcZ"&gt;https://bit.ly/3aaCGcZ&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>firstpost</category>
      <category>frontend</category>
      <category>hiring</category>
    </item>
    <item>
      <title>About the importance of including DevOps in your team</title>
      <dc:creator>Stephan Maximilian Huber</dc:creator>
      <pubDate>Thu, 17 Dec 2020 16:17:42 +0000</pubDate>
      <link>https://forem.com/factorial-io/about-the-importance-of-including-devops-in-your-team-2k2c</link>
      <guid>https://forem.com/factorial-io/about-the-importance-of-including-devops-in-your-team-2k2c</guid>
      <description>

&lt;p&gt;Developers working on client projects are taking care of numerous tasks. When you think the list gets shorter, new things are added at the bottom. What you can do is provide an infrastructure that lets them tackle their issues. But this doesn’t include only the administrative side but also the technical requirements for the developers to work properly. What’s missing is someone who is familiar with the IT area of the developers and has the capacity to assist in operative processes aside from the usual management. This is where the DevOps enter the field.&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%2Fbo.factorial.io%2Fsites%2Fdefault%2Ffiles%2F2020-12%2FFAC_Blogartikel_DevOps_v1.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%2Fbo.factorial.io%2Fsites%2Fdefault%2Ffiles%2F2020-12%2FFAC_Blogartikel_DevOps_v1.png" alt="Devops illustration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The DevOps work to hold the development team’s back. They appear as the merge between operations and development, supporting the team by managing the software and applications, deployment of tools in order to simplify procedures and smoothen the development process. With his work the DevOps face delays and other performance interferences by reducing downtimes and system failures. The use of DevOps in your team not only assures quality and an optimized workflow, you also stick to the latest development trends and keep yourself and your team up to date.&lt;/p&gt;

&lt;h2&gt;
  
  
  What skill set do the DevOps need?
&lt;/h2&gt;

&lt;p&gt;Let’s start with the most obvious one: The development skills. The differentiation element of the DevOps in comparison to an administrative manager are their skills regarding programming and scripting. This includes various programming languages, open source technologies and tools as well as knowledge in server systems and security concepts. The DevOps prove their expertise for the position through their understanding of source control systems, infrastructure automation tools, cloud services and testing skills. Aside from the technological competences required in this area, the DevOps need to combine this with a set of soft skills that they can come up with. &lt;/p&gt;

&lt;p&gt;As they stand for the binding component between different teams an excellent communication is indispensable. Bearing in mind the amount of possible issues the DevOps need to solve, which is a challenge for itself, and to keep a cool head and show empathy and integrity is not easy. Last but not least the job requires more than any other the willingness to educate yourself. The digital environment is in a continuous change and so are the skills the DevOps have to maintain in order to stay an expert in their area. Being well-informed about new technologies, systems and procedures will prepare the DevOps for the never ending wave of issues and errors they need to solve to support their team.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do we implement the DevOps role at Factorial?
&lt;/h2&gt;

&lt;p&gt;We at Factorial divide the tasks of the development operations on various shoulders. In this case we not only have specific members of the team dealing with specific tasks, we also use administrative development programs in order to automate workflows. We established a way to centralise logging and monitoring and also administer our zoo of hosted applications like Jira, Confluence and Mattermost to constantly improve our corporate infrastructure. With this we work on new ways of streamlining our processes and think about new features like rapid rollouts of dev instances.&lt;/p&gt;

&lt;p&gt;In addition to that we enhance and develop our local dev stack based on &lt;a href="https://github.com/factorial-io/multibasebox" rel="noopener noreferrer"&gt;MultiBaseBox&lt;/a&gt;. Our devs are using docker for spinning up the needed dependencies for their projects. We are using MultiBaseBox and &lt;a href="https://docs.phab.io/" rel="noopener noreferrer"&gt;phabalicious&lt;/a&gt; for local development. The underlying haproxy container with automatic configuration is also used as an easy way to spin up remote dev instances, so clients can test new features. Our team is constantly enhancing and extending these tools. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://docs.phab.io/" rel="noopener noreferrer"&gt;phabalicious&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By using phabalicious our devs are equipped with all necessary and project related information within one single configuration file. With this program our devs can connect to the actual app installation, be it locally installed, behind a ssh-jump-host or part of a kubernetes cluster and can execute common, every-day tasks as getting a database dump, deploying a new version of the application or just get a shell on that particular instance. Recently our engineers added support for kubernetes. It’s actively maintained by our team, and adapted to the ever changing needs of our developers and clients, while trying to be as open as possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  kubernetes
&lt;/h3&gt;

&lt;p&gt;Our devs can rely on kubernetes as a valuable tool to administer and create definition files for our clusters and the clients’ clusters. They can bring Drupal-, Laravel- or Node-based websites and applications into a kubernetes based cluster and monitor the applications over time.&lt;/p&gt;

&lt;h3&gt;
  
  
  GitLab &amp;amp; docker
&lt;/h3&gt;

&lt;p&gt;As passionate developers we work with GitLab as our main code repository and make full use of its strong integration capabilities provided by Pipelines. In addition to that we use docker to provide the best working environment for our developers all across the globe.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;The DevOps appear as the perfect match to your development team. In fact, as we at Factorial see it, the development team isn’t complete without someone uniting the understanding of development processes and programs with the administrative knowledge that ties all together. The true value this role can bring to your business, is not only from an economical standpoint but also in terms of stress reduction and process optimization. If you haven’t thought working with this role yet, you might be surprised about the value it can contribute to your company. &lt;/p&gt;

</description>
      <category>devops</category>
    </item>
  </channel>
</rss>
