<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Laurent Senta</title>
    <description>The latest articles on DEV Community by Laurent Senta (@laurentsenta).</description>
    <link>https://dev.to/laurentsenta</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%2F221995%2Fd147da90-6d3e-4c5c-8c7c-4b5e85724f06.jpg</url>
      <title>DEV Community: Laurent Senta</title>
      <link>https://dev.to/laurentsenta</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/laurentsenta"/>
    <language>en</language>
    <item>
      <title>Using MerkleTree for Blockchainized
Document Certification</title>
      <dc:creator>Laurent Senta</dc:creator>
      <pubDate>Wed, 15 Sep 2021 09:42:08 +0000</pubDate>
      <link>https://dev.to/laurentsenta/using-merkletree-for-blockchainized-document-certification-4c1p</link>
      <guid>https://dev.to/laurentsenta/using-merkletree-for-blockchainized-document-certification-4c1p</guid>
      <description>&lt;p&gt;As a freelance I worked on document certification using blockchain. I received several similar requests, but one of them required the implementation of a new data structure: Merkle Trees. It is a data structure widely used in decentralization and for good reasons, thanks to Merkle Trees and Merkle Proofs we set up a certification system with unique properties.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use cases
&lt;/h2&gt;

&lt;p&gt;In a &lt;a href="https://laurentsenta.com/articles/blockchain-use-case-timestamping/"&gt;previous article&lt;/a&gt; I described a blockchain timestamping system that allowed one of my clients to certify contracts in an irrefutable and relatively affordable way. One important feature was the ability to prove that a contract was NOT generated &lt;em&gt;a posteriori&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I received a similar request a short time later, with additional constraints. Imagine a service that allows a company to certify the role and salary of its employees. Once this certification is issued, employees may prove, through my client's tool, the veracity of their résumé to a potential employer. It is a type of verification that comes with new constraints:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constraint 1, Scalability&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The quantity of document to be certified was much greater (hundreds of thousands per batch). This makes the "obvious" timestamp system prohibitive: it costs a few pennies to stamp a document. Multiplied by hundreds of thousands of documents, we reach tens of thousands of dollars per batch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constraint 2, Confidentiality and Right to Be Forgotten&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The document and its proof must remain in the hands of the user. Once the certification has been produced, we want to give the user full control of their data. We must therefore be very attentive to the information that is shared. You cannot timestamp a batch of documents as a single file, because you would then have to send ALL documents to all users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constraint 3, Durability&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Certification must persist for decades, even if the service provider disappears or abandons the product. This makes decentralized storage systems like IPFS hard to defend because they require "someone" to persist the data. Note that today a service like Filecoin might be suitable, but the solution we have put in place is always more cost effective.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Structure: The Merkle Trees
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://laurentsenta.com/articles/blockchain-use-case-timestamping/"&gt;the previous article&lt;/a&gt; we saw the hash functions that let you to calculate the fingerprint of a document. These functions are very useful, because if two people have a document they can quickly calculate their fingerprint and compare them without having to exchange the whole file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PihVw3gf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2r23iaf542pkliubfybr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PihVw3gf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2r23iaf542pkliubfybr.png" alt="Merkle Tree - Basic Hash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our case we will push the use of hashes even further with a data structure called the &lt;em&gt;Merkle Tree&lt;/em&gt;. It is a tree for which each node contains the hash of its children.&lt;/p&gt;

&lt;p&gt;The construction of the tree is simple, we calculate the fingerprint of each document, then we group these fingerprints two by two, and we calculate a new hash. The operation is repeated until a single fingerprint is obtained. This last hash is called the root of the tree.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mawmcjqF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rh46owgw93g5ww6n2g38.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mawmcjqF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rh46owgw93g5ww6n2g38.png" alt="Merkle Tree - Tree Hash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is a recursive operation that allows us to take any number of documents and produce a single fingerprint. This is very efficient for our service because we can time stamp this last imprint by following the method in the previous article.&lt;/p&gt;

&lt;p&gt;Using this approach, we can timestamp hundreds of thousands of documents very quickly. It takes a long time to compute the tree, but it's an off-chain operation run on a "regular" server. It doesn't cost much. We end up storing a single fingerprint on the blockchain. The cost on the blockchain is therefore the same, regardless of the number of documents to be certified.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This property allows us to pass Constraint 1 (Scalability)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We timestamp the root of our hash tree on the blockchain, and we send a proof to our users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Merkle Proof
&lt;/h2&gt;

&lt;p&gt;The Merkle Tree has another interesting property: it is possible to prove the existence of any document in the tree without knowing the other documents.&lt;/p&gt;

&lt;p&gt;If I send you a document and the intermediate hashes, you can recalculate the root fingerprint and therefore verify that my document has not been modified. For example, in the diagram below, with the two intermediate hashes (in blue) and the Contract B, it is possible to find the root.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3yDcXye8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v2zzd3thg140mxpvyoa4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3yDcXye8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v2zzd3thg140mxpvyoa4.png" alt="Merkle Tree - Proof"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that for 4 documents, the proof contains 2 intermediate hashes, For 1024 documents, the proof contains 10 hashes, For 500,000 documents, the proof contains 19 hashes. There is a logarithmic relationship between the input data and the size of the proof sent to users. Basically, the more documents you have, the more "profitable" the solution becomes.&lt;/p&gt;

&lt;h2&gt;
  
  
  In practice
&lt;/h2&gt;

&lt;p&gt;In practice, this means that a end user has to hold the document AND the proof (the intermediate hashes).&lt;/p&gt;

&lt;p&gt;This is an additional constraint but this compromise is useful in our case: only the end user receives the proof associated with their document, therefore they are the sole master of their data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This property allows us to pass Constraint 2 (Right to Be Forgotten)&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Demonstration
&lt;/h3&gt;

&lt;p&gt;We adopted the QR Code solution, here is an example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UTcbnf3E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fqjvvp3ozq902yt1grx5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UTcbnf3E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fqjvvp3ozq902yt1grx5.png" alt="Demo QR Code: Valid"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This QR Code contains Andrew O’Reilly’s identity, his role in the company, AND proof of merkle. If you read this QR code with your phone, you should come to a web application that will perform the verification described above.&lt;/p&gt;

&lt;p&gt;You can also test the application by opening &lt;a href="https://blockchain-proof.singulargarden.com/qrcode?code=eyJwcm9vZiI6WyJyMmdYSTBxaDNTOFJIREdGWGlnZUF2eHI4TmEzRVhQVVhZUHNMcVhrcXFjPSIsIkFBZHMvTTJpWXFLM0ZYVW14bG11dnNFS3lHcWdTL3k2UlMyc0ZrdEpCa2s9IiwiNUtUTTN5QnRteU9qRUJyMEh5alV2UjQvd2NyVTl3TUlYN0VndjcwWFVsQT0iLCJraDRnZ3A0UER5QnArRGJXTHdBOGNzcUFWbVhCc2J1TGlPUDY1c3hkTDJVPSIsImFhV280VG4zdmpSWlRMQUxiaVpHSk5hSG1QbHl4VFVNNWRwVHBoRVFqbjA9IiwiVnJLUHhRMkkvallLNDFic1FhQWpSMExLWjR2aURySXAwOHFZRkQxVEdQcz0iLCJqNW9YSmlpUCtvSUFSWVFwbHMrWHFTdVEzN2hYVUQxMXhDZzlSS3Npd29BPSIsIkl4Kzc3ZkV4NmRwWXl0bVg5RTJ0WHl1VDhLdS9ZbXdmdFlhZ0xWUFpRazQ9IiwiL09rSlVWTElCdGxBSUtNQ2Z2VTlkUlNpSEFRMnYzZ21BV29CSk1wK3pVRT0iLCJvQjlXQ0Roa2NuYWl2MnFJT3YwbGpzSGlsQ0tPbE5uNkVGcVZlcDhrd2ZjPSIsIkdwOWFBMGlhL1ZXYk92U1RibytSQy9KQW1jTG50bDd4ajRTVXlBMUdsSWM9IiwiM2xlcGdzaGc3MVp2NGlFeUQ1bCtLdmR1REltbWVUK3RGRnh4L0pwalkzND0iLCIySEYxb1owMDZJZy9yK1hJbGNSdDN4OE9nWmo1allPbmZEVng5NTJWZnNRPSIsIldNRjREbG43eS8vdmRQVGdFK3pzRWk4WUx1MmFPOHowUG12UE9KcWhaMTQ9IiwidlJtR1RFK2Fxd3BFb0NLRk1xQVFMNUNOdTFkZEgzQ3VxOGlEcEJvK3FEYz0iLCJENVV3UHhabVNUNXJsYUNWaXl4dFJQbnU4YnFnNGFLZlM0dGM3eU9jMXdVPSIsIlB6Y0NIVXo4TlpnWGdGZVlCOG9Bc1BjS0JJeXE2T3Q4QTRncEMwWE5Mc1k9IiwiT29jdUtnWGdvYTlvcER6VVdzV0NqK0FUeVp6dnRPMWNzTzgzQ1NFOGxrST0iLCJpMStGbWd6ZXUvekt3NkpVQU9KdndmWGZFLzBObnJtODVtdnYzeDFMVlJrPSJdLCJwYXlsb2FkIjp7ImkiOjMwOTIxMCwiaWQiOiIwMzA5MjEwIiwibmFtZSI6IkFuZHJldyBPJ1JlaWxseSIsInNsdWciOiJhbmRyZXctb3JlaWxseSIsIm9yZyI6IlNjaGlubmVyLCBHaXNsYXNvbiBhbmQgUmF1IiwiaGlyZWQiOiIyMDIxLTA5LTExVDAwOjUwOjI3LjAyMloiLCJ0aXRsZSI6IlByaW5jaXBhbCBHcm91cCBMaWFpc29uIn19"&gt;this page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a screenshot of the verification result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LQTbp5Im--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kcjo218j16hdk9udjivd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LQTbp5Im--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kcjo218j16hdk9udjivd.png" alt="Demo: Valid"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the next QR Code, I changed Andrew's role to pass him off as the CEO of the company:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Jvw-D7lw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1fhw3wqe915i37wq7yb7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Jvw-D7lw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1fhw3wqe915i37wq7yb7.png" alt="Demo QR Code: Invalid"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It will open the following link: &lt;a href="https://blockchain-proof.singulargarden.com/qrcode?code=eyJwcm9vZiI6WyJyMmdYSTBxaDNTOFJIREdGWGlnZUF2eHI4TmEzRVhQVVhZUHNMcVhrcXFjPSIsIkFBZHMvTTJpWXFLM0ZYVW14bG11dnNFS3lHcWdTL3k2UlMyc0ZrdEpCa2s9IiwiNUtUTTN5QnRteU9qRUJyMEh5alV2UjQvd2NyVTl3TUlYN0VndjcwWFVsQT0iLCJraDRnZ3A0UER5QnArRGJXTHdBOGNzcUFWbVhCc2J1TGlPUDY1c3hkTDJVPSIsImFhV280VG4zdmpSWlRMQUxiaVpHSk5hSG1QbHl4VFVNNWRwVHBoRVFqbjA9IiwiVnJLUHhRMkkvallLNDFic1FhQWpSMExLWjR2aURySXAwOHFZRkQxVEdQcz0iLCJqNW9YSmlpUCtvSUFSWVFwbHMrWHFTdVEzN2hYVUQxMXhDZzlSS3Npd29BPSIsIkl4Kzc3ZkV4NmRwWXl0bVg5RTJ0WHl1VDhLdS9ZbXdmdFlhZ0xWUFpRazQ9IiwiL09rSlVWTElCdGxBSUtNQ2Z2VTlkUlNpSEFRMnYzZ21BV29CSk1wK3pVRT0iLCJvQjlXQ0Roa2NuYWl2MnFJT3YwbGpzSGlsQ0tPbE5uNkVGcVZlcDhrd2ZjPSIsIkdwOWFBMGlhL1ZXYk92U1RibytSQy9KQW1jTG50bDd4ajRTVXlBMUdsSWM9IiwiM2xlcGdzaGc3MVp2NGlFeUQ1bCtLdmR1REltbWVUK3RGRnh4L0pwalkzND0iLCIySEYxb1owMDZJZy9yK1hJbGNSdDN4OE9nWmo1allPbmZEVng5NTJWZnNRPSIsIldNRjREbG43eS8vdmRQVGdFK3pzRWk4WUx1MmFPOHowUG12UE9KcWhaMTQ9IiwidlJtR1RFK2Fxd3BFb0NLRk1xQVFMNUNOdTFkZEgzQ3VxOGlEcEJvK3FEYz0iLCJENVV3UHhabVNUNXJsYUNWaXl4dFJQbnU4YnFnNGFLZlM0dGM3eU9jMXdVPSIsIlB6Y0NIVXo4TlpnWGdGZVlCOG9Bc1BjS0JJeXE2T3Q4QTRncEMwWE5Mc1k9IiwiT29jdUtnWGdvYTlvcER6VVdzV0NqK0FUeVp6dnRPMWNzTzgzQ1NFOGxrST0iLCJpMStGbWd6ZXUvekt3NkpVQU9KdndmWGZFLzBObnJtODVtdnYzeDFMVlJrPSJdLCJwYXlsb2FkIjp7ImkiOjMwOTIxMCwiaWQiOiIwMzA5MjEwIiwibmFtZSI6IkFuZHJldyBPJ1JlaWxseSIsInNsdWciOiJhbmRyZXctb3JlaWxseSIsIm9yZyI6IlNjaGlubmVyLCBHaXNsYXNvbiBhbmQgUmF1IiwiaGlyZWQiOiIyMDIxLTA5LTExVDAwOjUwOjI3LjAyMloiLCJ0aXRsZSI6IkNFTyJ9fQ=="&gt;Demo Page&lt;/a&gt; you will see that the evidence fails.&lt;/p&gt;

&lt;p&gt;And here is the capture of the failed verification:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qiZvuGyH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/puyhuhzik9mjp7o3x45c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qiZvuGyH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/puyhuhzik9mjp7o3x45c.png" alt="Demo - Invalid"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that these QR codes are quite large because they contain ALL of the data to be verified. Our certification system is therefore not based on an external service to store the data, which makes the service sustainable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This property allows us to pass Constraint 3 (Durability)&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Off-chain Part
&lt;/h2&gt;

&lt;p&gt;The off-chain part is similar to that mentioned in a previous article.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2wd5kWiA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pyut87hs0lizksvl83rq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2wd5kWiA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pyut87hs0lizksvl83rq.png" alt="Infochain Infra"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Blockchain's complexity is "absorbed" by the off-chain part and hidden from the rest of the application. Under these conditions, the blockchain becomes a service "like any other" which provides a very specific functionality in our infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some important details
&lt;/h2&gt;

&lt;p&gt;If you need to implement a similar service, consider:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Make sure that the hash creation and verification process is deterministic:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When checking the proof, we only have the hash to check and the hash of the current proof. However, &lt;code&gt;Hash (A + B)&lt;/code&gt; is different from &lt;code&gt;Hash (B + A)&lt;/code&gt;, so we have to define an ordering for the hashes. For the sake of simplicity I sort them alpha-numerically. Thus the process of calculating the proof is based solely on the information that we have during the proof.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add entropy on "simple" data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the case of identity verification, one must take into account the possibility that a malicious user tries to brute-force the fingerprints. With some initial information (name, first name, role), it would be possible to "guess" the other missing information. To avoid this, I add a random string of characters in the data. This makes the hash of the proof unpredictable, even with some or all of the initial data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ultimately
&lt;/h2&gt;

&lt;p&gt;The merkle tree is a structure widely used in decentralization. It has very useful properties, in our case it is used to timestamp hundreds of thousands of documents at minimum cost. The proof system lets us implement a timestamping system that also preserves the confidentiality and durability of user's data.&lt;/p&gt;

&lt;p&gt;A demonstration of the application is available: &lt;a href="https://blockchain-proof.singulargarden.com/"&gt;blockchain-proof.singulargarden.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can use the QR Code feature as shown above. There is also a more classic document verification on the home page. Here are two sample files and the proof.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://laurentsenta.com/static/medias/merkletree/wendy-blanda.json"&gt;Wendy Blanda&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://laurentsenta.com/static/medias/merkletree/tampered-wendy-blanda.json"&gt;Wendy Blanda  (Tampered)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://laurentsenta.com/static/medias/merkletree/wendy-blanda.proof.json"&gt;Wendy Blanda - Merkle Proof&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to know more or have any questions, please reach out on &lt;a href="https://www.linkedin.com/in/laurentsenta/"&gt;LinkedIn&lt;/a&gt; or &lt;a href="https://twitter.com/laurentsenta"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can find the latest version of the article, and subscribe to more on &lt;a href="https://laurentsenta.com/articles/blockchain-merkle-tree-algorithm/"&gt;my site&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>react</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>Ethereum Use Case: Document Certification</title>
      <dc:creator>Laurent Senta</dc:creator>
      <pubDate>Mon, 13 Sep 2021 11:52:08 +0000</pubDate>
      <link>https://dev.to/laurentsenta/ethereum-use-case-document-certification-31nf</link>
      <guid>https://dev.to/laurentsenta/ethereum-use-case-document-certification-31nf</guid>
      <description>&lt;p&gt;As a freelance, I worked on documents certification using the Blockchain. This is an interesting problem because it is a type of feature that we could not implement in a trustless way before. Thanks to this type of project, companies that have not yet "jumped" into decentralization are getting their first taste of the ecosystem and can implement completely new features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Public blockchains are great for timestamping.
&lt;/h2&gt;

&lt;p&gt;A public blockchain like Ethereum or Bitcoin is a database that the whole world verify at all time. No one can get around the rules of the Blockchain, not even its creators. As a result, the data stored there is exceptionally reliable.&lt;/p&gt;

&lt;p&gt;A use case of the Blockchain is therefore timestamping. The idea is to allow an entity, for example, a company, to certify a document by publishing the information "we, Acme Inc., certify the veracity of this document as of date X."&lt;/p&gt;

&lt;p&gt;It is very different from a centralized system: in a centralized system, an administrator, or a hacker with administrator rights, may modify the data or the program at any time. It would be possible to timestamp data &lt;em&gt;a posteriori&lt;/em&gt; for example.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Use-case&lt;/strong&gt;: Irrefutably prove the signing of a contract on a specific date.
&lt;/h2&gt;

&lt;p&gt;A team contacted me to set up a document certification tool. They needed to generate and sign contracts with their users and have proof of each contract's existence on the date of signing. These contracts have many legal implications, and they are very binding for them and their clients: the proof must be irrefutable.&lt;/p&gt;

&lt;p&gt;The Blockchain was an ideal solution in this case. It allows proving that the contract was signed on a verified date and with a verified content. There is no need for a third party, so the evidence is as reliable as the crypto tools used by Ethereum.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basics of Crypto: Digital Fingerprint
&lt;/h2&gt;

&lt;p&gt;In areas related to Blockchain and networks, we are very attentive to data. Storing a few bytes of data on the Blockchain involves duplicating them millions of times on all the machines on the network. This is an expensive operation: we must transmit the data, verify it, and store it indefinitely. Therefore, we have to be smart when we ship and verify data.&lt;/p&gt;

&lt;p&gt;This is where hash functions come in. These functions allow you to calculate a file's fingerprint. This fingerprint is unique. No other file has the same fingerprint. So, just as a fingerprint identifies a human being, a file's cryptographic fingerprint uniquely identifies a file.&lt;/p&gt;

&lt;p&gt;Here is the hash of the first chapter of &lt;a href="https://gutenberg.net.au/ebooks03/0300771h.html#ppchap1"&gt;The Little Prince by Antoine de Saint-Exupéry&lt;/a&gt;: &lt;code&gt;d4b4e3e2b91edaed75b7791ced10afd53441e7f19e463a8b675619a081e3152d&lt;/code&gt;&lt;br&gt;
By changing the first letter, the hash is completely different: &lt;code&gt;009d8d2e8fd8e5a049c148bece24f1fdf401b87d5a0483ef910e367f273c891d&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;(I am using the SHA256 algorithm)&lt;/p&gt;

&lt;p&gt;If I want to prove to someone that I own a file, I can share the hash of that file with them.&lt;/p&gt;

&lt;p&gt;These are ideal for our use-case: We calculate the hash of every contract, and we publish it. We don't need to publish the entire file, which preserves confidentiality and drastically reduces our costs.&lt;/p&gt;
&lt;h2&gt;
  
  
  Smart Contract
&lt;/h2&gt;

&lt;p&gt;For this client, we set up a &lt;em&gt;"Smart Contract"&lt;/em&gt; on the Ethereum Blockchain. It's a piece of software that "exists" in Ethereum. It doesn't reside on a computer on the client's network; this program resides "in" Ethereum. As a result, it benefits from all the network's properties: impossible to falsify and cannot be modified without abiding by the rules of the network.&lt;/p&gt;

&lt;p&gt;We interact with this program by sending Ethereum transactions that contain data and instructions. That is very similar to an API but on the Blockchain.&lt;/p&gt;

&lt;p&gt;In this case, the timestamp contract we are using is straightforward: it has an owner and a "timestamp" function which outputs a timestamp signal.&lt;/p&gt;

&lt;p&gt;This is what our Smart Contract looks like:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;A few notes:&lt;/p&gt;

&lt;p&gt;We use OpenZeppelin, a common framework in the industry. It provides a reliable implementation for many classic features. Here we use &lt;code&gt;Ownable&lt;/code&gt;: the contract has an owner, and he is the only one who can call the timestamp function thanks to the &lt;code&gt;isOwner&lt;/code&gt; transformer.&lt;/p&gt;

&lt;p&gt;The timestamp function is highly optimized. We do not store data in the SmartContract's memory because it is an expensive operation. Instead, we emit a log to keep a trace of the timestamping process. Because of that, we won't be able to modify the data later, but this is a good trade-off for our use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  The timestamping process
&lt;/h2&gt;

&lt;p&gt;The process is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We compute the document's hash,&lt;/li&gt;
&lt;li&gt;Using our "administrator" account, we send a transaction that asks the SmartContract to process the hash. This hash is recorded on the Ethereum blockchain "definitively".&lt;/li&gt;
&lt;li&gt;We can now send the document a link to the transaction to the end-user. They will be able to prove irrefutably that the contract was certified at a given date.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can find the example of such a transaction on the Blockchain &lt;a href="https://ropsten.etherscan.io/tx/0xd02b342d9b0a8a71a55ebc622741c9fcd2303a3162ba21c078d04413305c2577"&gt;Here&lt;/a&gt;. According to today's price (September 2021), this operation would cost 15 cents.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Off-chain Part
&lt;/h2&gt;

&lt;p&gt;We have seen the relatively simple Blockchain part. However, in practice, for such a project, we must take care of other issues such as the security of the admin keys, error management, scalability, etc.&lt;/p&gt;

&lt;p&gt;In our case, we needed to sign a large number of contracts quickly. Unfortunately, transactions on Ethereum are relatively slow. You may have to wait several minutes for a confirmation. So we set up a service that lets the rest of the application interact with the Blockchain asynchronously.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tyoJsU1e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ibmehs1k79jodzy2xoyg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tyoJsU1e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ibmehs1k79jodzy2xoyg.png" alt="Timestamping Platform Diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Off-Chain Infrastructure
&lt;/h2&gt;

&lt;p&gt;The Blockchain's complexity is "absorbed" by the off-chain part and hidden from the rest of the application. Using this approach, the Blockchain becomes a service "like any other," which provides a particular feature to our infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  This is just the beginning.
&lt;/h2&gt;

&lt;p&gt;This system processes nearly ten thousand contracts daily. But of course, it's a sketch of the final product. We still lack details about keys management, parallel transaction management, errors, etc. I will be posting more articles on the subject, so you may want to subscribe on &lt;a href="https://laurentsenta.com"&gt;laurentsenta.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to know more or have any questions, please reach out on &lt;a href="https://www.linkedin.com/in/laurentsenta/"&gt;LinkedIn&lt;/a&gt; or &lt;a href="https://twitter.com/laurentsenta"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>blockchain</category>
      <category>smartcontract</category>
    </item>
    <item>
      <title>Where and how application
data is stored in Ethereum?
</title>
      <dc:creator>Laurent Senta</dc:creator>
      <pubDate>Wed, 12 May 2021 10:24:23 +0000</pubDate>
      <link>https://dev.to/laurentsenta/where-and-how-application-data-is-stored-in-ethereum-28e8</link>
      <guid>https://dev.to/laurentsenta/where-and-how-application-data-is-stored-in-ethereum-28e8</guid>
      <description>&lt;p&gt;This article was &lt;a href="https://laurentsenta.com/articles/storage-and-dapps-on-ethereum-blockchain/"&gt;published in 2017&lt;/a&gt;, updated in February 2021.&lt;/p&gt;

&lt;p&gt;Ethereum is used to build decentralized applications, a.k.a. DAPPs. These applications exist &lt;em&gt;through&lt;/em&gt; small programs that live on the Blockchain, called &lt;em&gt;smart contracts&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Before jumping into the platform and writing a smart contract, it’s really important to understand where your application data is stored. Code execution, servers and programming language are rarely critical to the design of an application. But data --its structure and its security-- will constrain our design the most.&lt;/p&gt;

&lt;p&gt;Let's imagine we are porting apps to Ethereum:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For a &lt;em&gt;Facebook-like&lt;/em&gt;, where are the publications and comments data?&lt;/li&gt;
&lt;li&gt;For a &lt;em&gt;Dropbox-like&lt;/em&gt;, where are my private files?&lt;/li&gt;
&lt;li&gt;For a &lt;em&gt;Slack-like&lt;/em&gt; chat app, where do we store discussion channels? And what about private messages?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Account Machine
&lt;/h2&gt;

&lt;p&gt;Let’s skip the explanation of blockchain for a minute (you can read my post on why Blockchain can be best understood as a &lt;a href="https://laurentsenta.com/articles/the-point-of-the-blockchain/"&gt;machine that generates Consensus here&lt;/a&gt;). Let’s look at Ethereum from a higher level of abstraction -- the &lt;em&gt;software&lt;/em&gt; that powers it, which is basically a big, slow, reliable computer.&lt;/p&gt;

&lt;p&gt;Ethereum holds a set of accounts. Every account has an owner and a balance (a quantity of Ether).&lt;/p&gt;

&lt;p&gt;If I prove my identity, I can transfer Ether from my account to another. The money will flow from one account to the other. It's an atomic operation called a “transaction”.&lt;/p&gt;

&lt;p&gt;In other words, the &lt;em&gt;Ethereum Software&lt;/em&gt; is a transaction processing system that works as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The system is in a certain state, i.e. every account has a certain balance. &lt;/li&gt;
&lt;li&gt;We carry out one or more transactions&lt;/li&gt;
&lt;li&gt;We get a new state: an updated set of accounts and their balances.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It’s as simple as that!&lt;/p&gt;

&lt;p&gt;With that out of the way, we can turn our attention to how to execute code and programs within a transaction. And that's where &lt;em&gt;Smart Contracts&lt;/em&gt; come into play.&lt;/p&gt;

&lt;h2&gt;
  
  
  Robot Accounts
&lt;/h2&gt;

&lt;p&gt;Every account has an owner and a balance. But some of these accounts are special: they own themselves. At creation time, we give them a piece of code and memory. That's a &lt;em&gt;Smart Contract&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A smart contract is really a smart bank account. The term "contract" is unclear—I prefer to think of them as Robot Accounts.&lt;/p&gt;

&lt;p&gt;A smart contract is basically a robot that executes some code when it receives transactions. This transaction happens within the blockchain. It is public, replicated and validated by the network. That means a smart contract won't fail because of a power outage in a Datacenter.&lt;/p&gt;

&lt;p&gt;A smart contract has a balance, some code, and some storage. This storage is &lt;a href="https://en.wikipedia.org/wiki/Persistence_(computer_science)"&gt;persistent&lt;/a&gt;, and that’s where we’ll find DAPP data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Storage of Robot Accounts
&lt;/h2&gt;

&lt;p&gt;When a smart contract is created or when a transaction awakens it, the contract’s code can read and write to its storage space.&lt;br&gt;
Here’s a breakdown of its Storage Specifications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's a big dictionary (key-value store) that maps keys to values.&lt;/li&gt;
&lt;li&gt;Keys are strings of 32 bytes. We can have 2&lt;sup&gt;32 x 8 bits&lt;/sup&gt; = 2&lt;sup&gt;256&lt;/sup&gt; different keys. Same for values.&lt;/li&gt;
&lt;li&gt;It's like Redis, RocksDB or LevelDB storage.&lt;/li&gt;
&lt;li&gt;DAPP and Smart Contracts function in a similar way to a hard-drive storage in a regular program.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's an example of a Smart Contract structure. It uses the Solidity Programming Language:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'' Solidity Code (solidity.readthedocs.io)
struct Voter {
 uint weight;
 bool voted;
 uint8 vote;
 address delegate;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2&lt;sup&gt;256&lt;/sup&gt; keys x 32 bytes (values) is around 10&lt;sup&gt;63&lt;/sup&gt; PETABYTES. You would need several billions of times the age of the universe to go through this amount of data with an SSD.&lt;/p&gt;

&lt;p&gt;Basically, we can safely assume that there’s no storage limit for a DAPP.&lt;/p&gt;

&lt;p&gt;But there &lt;strong&gt;is&lt;/strong&gt; a cost:&lt;/p&gt;

&lt;h2&gt;
  
  
  DAPPs Fuel
&lt;/h2&gt;

&lt;p&gt;For every transaction, we add some Ether, the fuel needed to power it. The emitter of the transaction pays this tax to motivate the miners to process the transaction. Miners ensure the network is reliable and we reward them with some Ether. &lt;br&gt;
So we send transactions and some fuel to this big machine. When the transaction targets a Smart Contract, the Ethereum machine starts the Account’s Robot. Each action of this robot will burn some more gas.&lt;br&gt;
The actions taken by this robot are translated into instructions in the &lt;em&gt;Ethereum Virtual Machine&lt;/em&gt; (EVM). There are instructions to read in storage, instructions to write, and so on. Each of these transactions has a cost in fuel, and that cost will constrain how much storage we can use.&lt;/p&gt;
&lt;h2&gt;
  
  
  Storage Cost
&lt;/h2&gt;

&lt;p&gt;The cost of each instruction in a Smart Contract will limit the amount of storage it uses. In theory, Ethereum enables infinite storage space. But, in return, you have to provide gas for every read/write operation.&lt;br&gt;
This cost changes all the time, depending on the network, the market and the way Ethereum specs develop. To get a general idea of the pricing, I simulated a few Smart Contracts:&lt;/p&gt;

&lt;p&gt;I tried three operations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Writing a &lt;code&gt;uint8&lt;/code&gt; (one byte) in storage&lt;/li&gt;
&lt;li&gt;Incrementing a &lt;code&gt;uint8&lt;/code&gt; in the storage (read then write)&lt;/li&gt;
&lt;li&gt;A simple voting function, which checks whether the emitter of the transaction has the right to vote and then updates the vote result. You can vote only once; the second attempt is short-circuited.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Code and tools are in the Appendix below. Here are the numbers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YUB90RuC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t2iqm2xb4b0esvrffo9h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YUB90RuC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t2iqm2xb4b0esvrffo9h.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(note from 2021: numbers here are outdated, but the currency is so volatile these days, use this as a rough order of magnitude).&lt;/p&gt;

&lt;p&gt;Based on this table, this article would cost around 50 Euros to store with a Smart Contract, excluding pictures.&lt;/p&gt;

&lt;p&gt;Posting a tweet costs a few euros, and ordering on Amazon a few cents.&lt;/p&gt;

&lt;p&gt;Of course, these are estimations with different orders of magnitude. The exact cost will depend on the exact instructions you use, as well as on the network load, the current price of gas, etc. New algorithms might also bring down the price of Ethereum (Proof Of Stake).&lt;/p&gt;
&lt;h2&gt;
  
  
  Finally, where should I store my data?
&lt;/h2&gt;

&lt;p&gt;Well, maybe not on the Ethereum Blockchain. The data stored there, with Smart Contracts, is safe and easy to access. But the cost and the structure of the store is especially suited for metadata-related uses.&lt;br&gt;
Taking the examples from the introduction: User Posts, Files and Message Boxes will probably be on another platform like IPFS. In the Ethereum Blockchain, we would store critical data, like encryption keys, roots to storage trees &amp;amp; authorizations.&lt;/p&gt;

&lt;p&gt;Find all my previous articles on &lt;a href="https://laurentsenta.com/articles/storage-and-dapps-on-ethereum-blockchain/"&gt;laurentsenta.com&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Appendix
&lt;/h2&gt;

&lt;p&gt;Piece of code used for the table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pragma solidity ^0.4.0;

contract Test {
    mapping(uint =\&amp;gt; uint) tests;

    function Test() {
    }

    function one_set() {
        tests[0] = 0;
    }

    function two_increment() {
        tests[0] = tests[0] + 1;
    }
}

/// Give a single vote to proposal $(proposal).
function vote(uint8 proposal) {
    Voter storage sender = voters[msg.sender];
    if (sender.voted || proposal &amp;gt;= proposals.length) return;
        sender.voted = true;
        sender.vote = proposal;
        proposals[proposal].voteCount += sender.weight;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tools used to run the code and evaluate the costs:&lt;br&gt;
Ethereum Gas Station to follow gas cost&lt;br&gt;
Remix Solidity IDE to write and run Smart Contracts&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://ethgasstation.info/"&gt;Ethereum Gas Station&lt;/a&gt; to follow gas cost&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://remix.ethereum.org/"&gt;Remix Solidity IDE&lt;/a&gt; to write and run Smart Contracts&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>blockchain</category>
      <category>database</category>
      <category>decentralization</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>How to stop falling for the Shiny New Toy Syndrome</title>
      <dc:creator>Laurent Senta</dc:creator>
      <pubDate>Fri, 22 Jan 2021 14:09:30 +0000</pubDate>
      <link>https://dev.to/laurentsenta/how-to-stop-falling-for-the-shiny-new-toy-syndrome-5hnd</link>
      <guid>https://dev.to/laurentsenta/how-to-stop-falling-for-the-shiny-new-toy-syndrome-5hnd</guid>
      <description>&lt;p&gt;For those creators that are spending too much of their time catching up: that’s ok. Here is a fix.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt; This article is for creators feeling the Shiny New Toy Syndrome. I believe this is expected, and I describe why. Then we go on with a few methods that might get us out of it.&lt;/p&gt;

&lt;p&gt;Are you spending a lot of time reading about new technologies? How often do you wonder if you should try this new tool, this new language, this new framework? How often do you use a technology that you just started using?&lt;/p&gt;

&lt;h2&gt;
  
  
  The JavaScript Fatigue, Decision Fatigue, or any other fatigue is lurking
&lt;/h2&gt;

&lt;p&gt;You spend a lot of time thinking about which tools are the most efficient to do your job, and you spend a lot of time trying new things.&lt;/p&gt;

&lt;p&gt;Here is a secret you might know already: you spend a lot of time learning things that you don’t need, and you don’t build as much as you should.&lt;/p&gt;

&lt;p&gt;That’s you? Then nice to meet you! 👋 We’re both addict to the shiny new tool syndrome.&lt;/p&gt;

&lt;h2&gt;
  
  
  That’s perfectly natural
&lt;/h2&gt;

&lt;p&gt;Creators are eager to create new things. That’s obvious.&lt;/p&gt;

&lt;p&gt;And as a creator, we are very sensitive to new things around us. Maybe they make you uncomfortable “someone is having success with another great idea I wanted to build.” Or perhaps they intrigue you “that looks so much better than what we had before; I need to try this.”&lt;/p&gt;

&lt;p&gt;We’re always on the lookout for things changing around us. That’s perfectly reasonable and even expected, below a certain point.&lt;/p&gt;

&lt;p&gt;I believe it becomes a problem when we spend more time learning about new things than using them. Or when we spend most of our time working with tools, we don’t really know.&lt;/p&gt;

&lt;h2&gt;
  
  
  For years, I’ve read bazillions articles about new technologies
&lt;/h2&gt;

&lt;p&gt;Always on the lookout for the latest HackerNews articles, following hundreds of RSS feeds. That felt amazing, every time a discussion about a new tech arise, I knew about it, and I already had an opinion. I tried so many of them.&lt;/p&gt;

&lt;p&gt;I forgot most of these techs, and most of these are dead. Have you ever heard of famo.us? The future of web apps, with their 3D rendering engine that was shaking the world? They build Shopify stores now, and Facebook is still in 2D.&lt;/p&gt;

&lt;p&gt;I’ve fallen for this trap multiple times. I’ve seen teams and clients fall for this trap too, and I’ve found a few ways to mitigate this.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's about learning!
&lt;/h2&gt;

&lt;p&gt;I believe this is why we do this: we love learning new things. Every time we learn, we get a small release of dopamine. Success your brain tells you, I like when that clicks, do it again.&lt;/p&gt;

&lt;p&gt;But the more we know a tool, the less learning we get per unit of time using it. The less dopamine we get from actually using that thing.&lt;/p&gt;

&lt;p&gt;When I try a new Software, give me 25 minutes with it, I learn 5 things about it. But after years, I might discover one novel idea every month.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WKARArSj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/72bmzyy44fat6diur8q3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WKARArSj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/72bmzyy44fat6diur8q3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The more we know a tech, the less rewarding it is to use it. Especially if you care too much about learning. I recognize this as the “Sugar” of my Knowledge Worker role. Learning rocks, especially at the beginning of a career, but it isn’t sustainable by itself. That applies to businesses and individuals alike.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_mt_2HNr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/446q742qc805l3axa96o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_mt_2HNr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/446q742qc805l3axa96o.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So learning is my thing, is it yours?&lt;/p&gt;

&lt;p&gt;I wouldn’t be surprised that’s the same thing for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  The way we share information and organize ourselves promotes the Shiny New Tools Syndrome
&lt;/h2&gt;

&lt;p&gt;Say I release a new JavaScript framework tomorrow. I’m going to talk about it and make sure the information spreads. I’ll get a bunch of curious people to learn about it.&lt;/p&gt;

&lt;p&gt;What’s the rational thing to do once you spent time learning? You write about it. And that is the first rule of content marketing: If you publish about something, you become an expert. And if you’re an expert, you get more views, and you get more money and more jobs.&lt;/p&gt;

&lt;p&gt;It’s easier to become the top 1% expert for software with twenty users than it is to become the leading expert for some old school beast that has seen generations of users.&lt;/p&gt;

&lt;p&gt;So following trends is incentivized, and it’s rewarding.&lt;/p&gt;

&lt;p&gt;Up to a certain point.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to come back from the shiny toy syndrome?
&lt;/h2&gt;

&lt;p&gt;A few ideas, I’m still learning on this,&lt;/p&gt;

&lt;h3&gt;
  
  
  Define who you are
&lt;/h3&gt;

&lt;p&gt;Define what your competitive advantage is and where you should be on top. Then forget about everything else.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gugYTsfT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/op1igb7v400lg9wehdro.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gugYTsfT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/op1igb7v400lg9wehdro.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are a few decisions I took recently:&lt;/p&gt;

&lt;p&gt;I am not a Javascript Runtime Expert, and I’m not building infrastructures that rely on these runtimes. I use these infrastructures. So I haven’t looked for a minute at Deno. I might use it in a few years.&lt;/p&gt;

&lt;p&gt;I am not a Frontend Expert, and I am not a Frontend Architect. I know enough about data management and how to separate concerns to ignore state management libraries in the frontend. I’ll use whichever is by default in my library.&lt;/p&gt;

&lt;p&gt;My clients don’t hire me for my UI designer skills, and I don’t care about scaling UI to large teams. I know enough CSS and HTML to use a “ready to use” toolkit. I won’t use TailWindCSS or anything more recent than SASS and Bulma.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choose mature tools and forget about them
&lt;/h3&gt;

&lt;p&gt;First, keep in mind that tech hardly becomes obsolete. Once it reached mainstream status, a piece of tech will stay around for a LONG time.&lt;/p&gt;

&lt;p&gt;If you’ve heard about a 50 years old book, you can bet this is a good book, and it’ll be around for 50 more years. A trendy book released last year might not stand the test of time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Are you going to use this a hundred times?
&lt;/h3&gt;

&lt;p&gt;Because we hear a lot of success stories about new gadgets, we think we should use them. I think that’s ill-advised. We should ask if the gadget we are going to use is going to pay itself.&lt;/p&gt;

&lt;p&gt;When you learn a new tool or a new skill, ask yourself: am I going to be more productive on the first project? Nope, On the third project? Maybe, On the fifth project? You might have wandered to another tool anyway.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Knowledge is only a rumor until it is in the muscle."&lt;br&gt;
~ Various and contradictory sources&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And you know what happens to a rumor after a few weeks? You forget about it.&lt;/p&gt;

&lt;p&gt;Because the high of learning is so quick and rewarding, we have to use the rest of our brain to think about the long term. Stay away from things you won’t use a hundred times. Don’t even think about it. They’ll come back later, and you can catch up because you’ll have matured on fundamental skills.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep it fun
&lt;/h3&gt;

&lt;p&gt;This one is the hard part. How can we keep working with our mature and old tools rewarding?&lt;/p&gt;

&lt;p&gt;I have a few strategies:&lt;/p&gt;

&lt;p&gt;first of all, I work using the Pomodoro Method. Completing a Pomodoro is a reward in itself. Using old tools means I can complete tasks faster and this is rewarding.&lt;/p&gt;

&lt;p&gt;Second, I redefined the metrics I focus on, like releasing new code, having more users, etc. This is where makers have an edge against creators working within a company. They can define and align their incentives however they want.&lt;/p&gt;

&lt;p&gt;Third, I stay on top of a couple of very tiny circles of interest. This is where I get all my “Software Engineer High”.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;Now, can you write down the tools you are going to use for your next hundred projects? Or at least your next five projects?&lt;/p&gt;

&lt;p&gt;If this content resonates with you and you want more of it, please like and let me know! That's the only way I can tell if I should keep going.&lt;/p&gt;

&lt;p&gt;Also, I’m working on a new article called The One Year Stack, so I’d love to know more about your process. Leave a comment and let me know how you deal with that SNT Syndrome :)&lt;/p&gt;

</description>
    </item>
    <item>
      <title>orbital-list 🪐 - My first React Library</title>
      <dc:creator>Laurent Senta</dc:creator>
      <pubDate>Fri, 08 Jan 2021 10:49:10 +0000</pubDate>
      <link>https://dev.to/laurentsenta/orbital-list-my-first-react-library-3j64</link>
      <guid>https://dev.to/laurentsenta/orbital-list-my-first-react-library-3j64</guid>
      <description>&lt;p&gt;A while ago I wrote a web application that lets you see your team and coworkers on a circular clock.&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%2Fi%2F061jciqjtsthnvqtp3lq.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%2Fi%2F061jciqjtsthnvqtp3lq.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This circular interface is the core feature of &lt;a href="https://whena.re" rel="noopener noreferrer"&gt;whena.re&lt;/a&gt; to me. Time, especially the time of day, goes round and round. It's more natural and more intuitive to represent it on a circle.&lt;/p&gt;

&lt;p&gt;This design took me hours and hours to implement. I skipped the data visualization libraries because most of them rely on an abstraction that is data-oriented. It wasn't ideal here.&lt;/p&gt;

&lt;p&gt;For example, if I have a list of users, in React you'd go with something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Tom (GMT, 12:02)&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Martine (UTC-2, 14:02)&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// which you write:&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; (&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timezone&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; - &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whereas in libraries such as &lt;code&gt;d3&lt;/code&gt;, you have to convert your data into "pie chart data" and setup some sort of rendering engine. Like in &lt;a href="https://www.d3-graph-gallery.com/graph/pie_basic.html" rel="noopener noreferrer"&gt;this example&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the end, I wrote a library of components that would let me represent circular interfaces. It generates a "circular context" and position components inside this context.&lt;/p&gt;

&lt;p&gt;It looks like having HTML lists displayed as orbits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;OrbitalList&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Dial&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'#1f2041'&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Orbit&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'rgba(244, 205, 205, 1)'&lt;/span&gt; &lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mf"&gt;0.15&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Slice&lt;/span&gt;
        &lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;angleStart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;angleEnd&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mf"&gt;202.5&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'blue'&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Place&lt;/span&gt;
        &lt;span class="na"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#ed254e&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.2rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fontWeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bold&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Place&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;OrbitalList&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Today I release this as an open-source library. It's small, the code is embarrassing, but you know what they say...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"If you're not embarrassed, you've launched too late."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I'd be happy to hear from you, if the approach makes sense and if you find the demo and library pleasant to use.&lt;/p&gt;

&lt;p&gt;The demo is here:&lt;br&gt;
&lt;a href="https://orbital-list.laurentsenta.com/" rel="noopener noreferrer"&gt;https://orbital-list.laurentsenta.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The GitHub repository is here:&lt;br&gt;
&lt;a href="https://github.com/laurentsenta/orbital-list" rel="noopener noreferrer"&gt;https://github.com/laurentsenta/orbital-list&lt;/a&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>react</category>
      <category>tsdx</category>
      <category>design</category>
    </item>
    <item>
      <title>The Pomodoro Method hacks how you define your tasks</title>
      <dc:creator>Laurent Senta</dc:creator>
      <pubDate>Tue, 08 Dec 2020 16:55:41 +0000</pubDate>
      <link>https://dev.to/laurentsenta/the-pomodoro-method-hacks-how-you-define-your-tasks-36lo</link>
      <guid>https://dev.to/laurentsenta/the-pomodoro-method-hacks-how-you-define-your-tasks-36lo</guid>
      <description>&lt;p&gt;Do you know the Pomodoro Method? Here's a quick slice of the benefits hidden behind its rituals.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's hard to define tasks in the right way.
&lt;/h2&gt;

&lt;p&gt;You'll find this advice everywhere:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Only define goals and tasks you have control over.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tasks that you don't have control over are productivity killers.&lt;/p&gt;

&lt;p&gt;For example: "get a positive answer to proposal X," "get thousands of followers," "finish project in time."&lt;/p&gt;

&lt;p&gt;These goals mess with your definition of done.&lt;/p&gt;

&lt;p&gt;The world is moving around you, and it's hard to achieve something and get a feeling of progress if it depends more on the rest of the world than on your actions.&lt;/p&gt;

&lt;p&gt;That's why I like the Pomodoro Method: When you start using it, it'll force you to add a subtle layer of Pomodoro on top of each task.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pomodoro Method redefines how you measure success
&lt;/h2&gt;

&lt;p&gt;Your task list for today might resemble something like that:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z54o_Ijs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zkza3hrzcfe8bcerrfq9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z54o_Ijs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zkza3hrzcfe8bcerrfq9.png" alt="tricky task list"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How many of these depend on something external?&lt;/p&gt;

&lt;p&gt;What happens when the requirements for Project A change and you have to start over? Do you need to wait for another document before replying to Arthur? Or what if the complexity of the issue you were working on explodes and you need to make three more decisions before finishing your job?&lt;/p&gt;

&lt;p&gt;On some days, I might end up with &lt;strong&gt;zero&lt;/strong&gt; tasks completed. Even after seven, eight, or ten hours in front of a computer. This is exhausting.&lt;/p&gt;

&lt;p&gt;At the end of the day, I might have completed ZERO tasks. But when I apply the Pomodoro Method, I still have feedback of the time I spent pushing things forward anyway:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--le5ybMkT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kw6e9wckbd79an2y7kwf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--le5ybMkT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kw6e9wckbd79an2y7kwf.png" alt="task list redefined"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That would be a fantastic day. These Xs mean that I completed fourteen sessions of 30 minutes of deep focus. That's 7 hours of work. And these two C mean that I slid out of focus only twice during the day.&lt;/p&gt;

&lt;h2&gt;
  
  
  I can tell how much progress I made with the Pomodoro Method, even if I couldn't complete any task.
&lt;/h2&gt;

&lt;p&gt;That's where the Pomodoro Method is ingenious. It adds a subtle layer where "a deep focus session" is a success in itself.&lt;/p&gt;

&lt;p&gt;The one thing you have control over, your focus, becomes the real subject of most tasks. And with the Pomodoro "layer", you have a metric of success that tells you if you've been focused and lets you ask, "should I change something in my workflow?."&lt;/p&gt;

&lt;p&gt;This method is crucial to me; I'm trying to have more people use it "the right way." That's why I published an &lt;a href="https://tickingfocus.com/pomodoro-technique/pomodoro-method-guide/"&gt;interactive step-by-step guide&lt;/a&gt; on my website. I'd love to know if this helped you in the comments. &lt;/p&gt;

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