<?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: Can Burak Sofyalioglu</title>
    <description>The latest articles on DEV Community by Can Burak Sofyalioglu (@canburaks).</description>
    <link>https://dev.to/canburaks</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F161632%2F1c88f1c5-3232-4b0e-b7ce-e23af550261d.jpg</url>
      <title>DEV Community: Can Burak Sofyalioglu</title>
      <link>https://dev.to/canburaks</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/canburaks"/>
    <language>en</language>
    <item>
      <title>Road to State Machines Part III - But How Do We Represent the Entire Lifecycle as One Behavioral Contract?</title>
      <dc:creator>Can Burak Sofyalioglu</dc:creator>
      <pubDate>Thu, 01 Oct 2026 09:03:58 +0000</pubDate>
      <link>https://dev.to/canburaks/road-to-state-machines-part-iii-but-how-do-we-represent-the-entire-lifecycle-as-one-behavioral-1mp0</link>
      <guid>https://dev.to/canburaks/road-to-state-machines-part-iii-but-how-do-we-represent-the-entire-lifecycle-as-one-behavioral-1mp0</guid>
      <description>&lt;p&gt;Our operations now reject invalid changes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;capture_payment()&lt;/code&gt; requires a valid &lt;code&gt;created&lt;/code&gt; order and a payment record. &lt;code&gt;ship_order()&lt;/code&gt; requires a valid &lt;code&gt;paid&lt;/code&gt; order. Both inspect the existing record before changing it.&lt;/p&gt;

&lt;p&gt;But suppose we ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What operations are available to a paid order?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We still have to inspect the functions.&lt;/p&gt;

&lt;p&gt;One function says that payment capture requires &lt;code&gt;created&lt;/code&gt;. Another says that shipping requires &lt;code&gt;paid&lt;/code&gt;. Their assignments tell us where the order goes afterward.&lt;/p&gt;

&lt;p&gt;The lifecycle exists, but we must reconstruct it from the implementation.&lt;/p&gt;

&lt;p&gt;How do we make that lifecycle explicit and make the operations use it?&lt;/p&gt;

&lt;h3&gt;
  
  
  Start by writing down the rules we already have
&lt;/h3&gt;

&lt;p&gt;We do not need more states yet. Our model still has three:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;created → paid → shipped
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It also has two operations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;capture_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;ship_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a valid order, the status-based rules are:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Current status&lt;/th&gt;
&lt;th&gt;Capture payment&lt;/th&gt;
&lt;th&gt;Ship order&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;created&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Move to &lt;code&gt;paid&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Reject&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;paid&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Reject&lt;/td&gt;
&lt;td&gt;Move to &lt;code&gt;shipped&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;shipped&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Reject&lt;/td&gt;
&lt;td&gt;Reject&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This table contains six combinations. Only two permit a change.&lt;/p&gt;

&lt;p&gt;The payment argument still needs validation. The table does not claim that &lt;em&gt;every&lt;/em&gt; call to &lt;code&gt;capture_payment()&lt;/code&gt; from &lt;code&gt;created&lt;/code&gt; is valid, regardless of its arguments. It describes which operations are eligible from each lifecycle state.&lt;/p&gt;

&lt;p&gt;That distinction preserves the separation we established in Part II:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The current record must be consistent. The requested movement must also be permitted.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Until now, this table was a summary we produced by reading the code. Let’s reverse that relationship.&lt;/p&gt;

&lt;p&gt;The table should define the lifecycle. The operations should consult it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Give the vocabulary explicit names
&lt;/h3&gt;

&lt;p&gt;First, let’s replace the unrestricted status vocabulary with named values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;enum&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Enum&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;CREATED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;created&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;PAID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;SHIPPED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shipped&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An enumeration defines a set of named members. Each member here retains the lowercase string we already use to represent the status.[1]&lt;/p&gt;

&lt;p&gt;We can distinguish the member from its external representation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAID&lt;/span&gt;
&lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAID&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;  &lt;span class="c1"&gt;# "paid"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also need names for the inputs that request a change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;CAPTURE_PAYMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;capture_payment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;SHIP_ORDER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ship_order&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will call these &lt;strong&gt;commands&lt;/strong&gt; because they request operations. They do not announce that the operations have already succeeded.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SHIP_ORDER&lt;/code&gt; means “attempt the shipping operation.” It does not mean that a carrier has confirmed shipment.&lt;/p&gt;

&lt;p&gt;Likewise, &lt;code&gt;CAPTURE_PAYMENT&lt;/code&gt; identifies our existing simulated operation, which records a supplied &lt;code&gt;Payment&lt;/code&gt;. We have not added a payment-provider call.&lt;/p&gt;

&lt;p&gt;These names give the lifecycle two distinct vocabularies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;States:
    Where is the order?

Commands:
    What operation is being requested?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Update the model without changing its supporting data
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Payment&lt;/code&gt; class remains unchanged. In &lt;code&gt;Order&lt;/code&gt;, only the status representation changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;decimal&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;payment_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;captured_amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;customer_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;delivery_address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;OrderState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CREATED&lt;/span&gt;
    &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A newly constructed order now starts with &lt;code&gt;OrderState.CREATED&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When loading a status from an external representation, we can convert it explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAID&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unknown spellings are rejected by the enum lookup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nc"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shiped&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Raises ValueError.
&lt;/span&gt;&lt;span class="nc"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PAID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;# Raises ValueError.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have not introduced case normalization or guessed what an unknown value means.[1]&lt;/p&gt;

&lt;p&gt;However, changing the annotation does not make arbitrary assignment impossible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;something_else&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A normal dataclass does not enforce field annotations at runtime.[2] The operation boundary must still validate incoming records.&lt;/p&gt;

&lt;p&gt;The enum gives us a defined vocabulary. Validation determines whether a particular record uses it correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Turn the transition table into executable data
&lt;/h3&gt;

&lt;p&gt;Each permitted transition needs three pieces of information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;current state
requested command
next state
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can represent the first two as a dictionary key and the third as its value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MappingProxyType&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Mapping&lt;/span&gt;


&lt;span class="n"&gt;TRANSITIONS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Mapping&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OrderCommand&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MappingProxyType&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CREATED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;OrderCommand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAPTURE_PAYMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;OrderCommand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SHIP_ORDER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SHIPPED&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;&lt;code&gt;MappingProxyType&lt;/code&gt; provides a read-only view of the mapping. Ordinary callers cannot insert another transition through &lt;code&gt;TRANSITIONS&lt;/code&gt;.[3]&lt;/p&gt;

&lt;p&gt;We have stored only the permitted changes. The rejected combinations remain absent.&lt;/p&gt;

&lt;p&gt;Now we need a function that interprets the table. We keep the exception types from Part II:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvalidOrderOperation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvalidOrderState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;next_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;OrderCommand&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="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;InvalidOrderState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status must be an OrderState member.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OrderCommand&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;command must be an OrderCommand member.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;TRANSITIONS&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;KeyError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;InvalidOrderOperation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cannot &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;while the order is &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function answers one question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Given this lifecycle state and this command, which next state is permitted?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;next_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CREATED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;OrderCommand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAPTURE_PAYMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAID&lt;/span&gt;

&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;next_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;OrderCommand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SHIP_ORDER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SHIPPED&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this is rejected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;next_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CREATED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;OrderCommand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SHIP_ORDER&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;The missing entry is not an implementation omission. It expresses the business rule that an unpaid order must not be shipped.&lt;/p&gt;

&lt;p&gt;Notice what &lt;code&gt;next_state()&lt;/code&gt; does &lt;strong&gt;not&lt;/strong&gt; do.&lt;/p&gt;

&lt;p&gt;It does not modify an order. It does not store payment information. It does not call a provider or create a shipment.&lt;/p&gt;

&lt;p&gt;It selects a permitted destination or rejects the request.&lt;/p&gt;

&lt;h3&gt;
  
  
  We now have an explicit finite state machine
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;finite state machine&lt;/strong&gt; describes a finite set of states, an initial state, inputs, and rules that determine the next state from the current state and input.[4]&lt;/p&gt;

&lt;p&gt;Our example has each of those elements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;States:
    CREATED, PAID, SHIPPED

Initial state:
    CREATED

Inputs:
    CAPTURE_PAYMENT, SHIP_ORDER

Permitted transitions:
    CREATED + CAPTURE_PAYMENT → PAID
    PAID + SHIP_ORDER → SHIPPED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same relationship can be written as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;next_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or, using conventional mathematical notation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;δ(current_state, command) = next_state
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The symbol &lt;code&gt;δ&lt;/code&gt; names the transition function. It does not introduce another mechanism.&lt;/p&gt;

&lt;p&gt;Our transition model is &lt;strong&gt;deterministic&lt;/strong&gt;: for a particular state and command, there is one declared destination or a defined rejection.&lt;/p&gt;

&lt;p&gt;Mathematical treatments sometimes define a transition for every state–input pair. Our application uses a partial transition table: an absent pair means “reject without changing the order.” We do not silently treat rejection as success, nor move the order into a newly invented failure state.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SHIPPED&lt;/code&gt; is terminal &lt;strong&gt;within this model&lt;/strong&gt;, because no supported command leaves it. That does not mean the real order can never be delivered or returned. Those processes are outside the lifecycle we have implemented.&lt;/p&gt;

&lt;p&gt;“Finite” describes this control model. It does not mean that every possible customer name, delivery address, or payment record has been enumerated.&lt;/p&gt;

&lt;h3&gt;
  
  
  But the table does not replace the invariants
&lt;/h3&gt;

&lt;p&gt;Consider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order-66&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;customer_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;delivery_address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Istanbul&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&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;The transition table contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PAID + SHIP_ORDER → SHIPPED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this particular order is inconsistent. Its payment record is missing.&lt;/p&gt;

&lt;p&gt;The table cannot detect that because it receives only the lifecycle state and command.&lt;/p&gt;

&lt;p&gt;Let’s update the validator to use our enum while preserving both payment rules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;InvalidOrderState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status must be an OrderState member.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CREATED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;InvalidOrderState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A created order cannot contain a captured payment.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SHIPPED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;InvalidOrderState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;An order marked &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;must contain a Payment record.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;created&lt;/code&gt; order must still have no payment record. A &lt;code&gt;paid&lt;/code&gt; or &lt;code&gt;shipped&lt;/code&gt; order must still retain one.&lt;/p&gt;

&lt;p&gt;We are not adding validation of payment amounts, currencies, or provider-side capture. The scope remains the same as in Part II.&lt;/p&gt;

&lt;p&gt;We now have two deliberately separate functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;validate_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;Is&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;existing&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt; &lt;span class="n"&gt;consistent&lt;/span&gt;&lt;span class="err"&gt;?&lt;/span&gt;

&lt;span class="nf"&gt;next_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;Is&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;lifecycle&lt;/span&gt; &lt;span class="n"&gt;movement&lt;/span&gt; &lt;span class="n"&gt;permitted&lt;/span&gt;&lt;span class="err"&gt;?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both are necessary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Make the operations consult the table
&lt;/h3&gt;

&lt;p&gt;We can now replace their status-specific conditions with calls to &lt;code&gt;next_state()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;capture_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;validate_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;OrderCommand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAPTURE_PAYMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;payment must be a Payment record.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;
    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ship_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;validate_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;OrderCommand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SHIP_ORDER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compare the new shipping operation with the previous version.&lt;/p&gt;

&lt;p&gt;It no longer contains its own declaration that shipping requires &lt;code&gt;paid&lt;/code&gt;, followed by an independent assignment to &lt;code&gt;shipped&lt;/code&gt;. Both facts come from the transition table.&lt;/p&gt;

&lt;p&gt;The same is true of payment capture. Its lifecycle rule comes from the table; the function remains responsible for checking and storing the payment argument.&lt;/p&gt;

&lt;p&gt;This is the separation we wanted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Existing-record consistency → validator

Lifecycle eligibility and destination → transition table

Operation-specific work → domain function
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have not removed the domain functions. They still provide the meaningful interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;capture_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;ship_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nor have we introduced a generic function with several optional arguments whose meanings depend on which command was passed. For two operations, the explicit functions remain clearer.&lt;/p&gt;

&lt;p&gt;All expected rejection checks still happen before mutation.&lt;/p&gt;

&lt;p&gt;Payment capture still makes two assignments. As in Part II, this is a local, single-writer example not an atomic transaction or a crash-recovery mechanism.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let the read path use the same lifecycle
&lt;/h3&gt;

&lt;p&gt;Previously, code displaying available operations could repeat the status checks.&lt;/p&gt;

&lt;p&gt;Now it can consult the same table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;available_actions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;OrderCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...]:&lt;/span&gt;
    &lt;span class="nf"&gt;validate_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;command&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;OrderCommand&lt;/span&gt;
        &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;TRANSITIONS&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function validates the record first. An inconsistent order is not presented as though it were ready for normal processing.&lt;/p&gt;

&lt;p&gt;Let’s follow one order through the complete sequence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;credit_card&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stripe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;payment_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;payment-81&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;captured_amount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;120.00&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order-66&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;customer_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;delivery_address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Istanbul&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;available_actions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;OrderCommand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAPTURE_PAYMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;capture_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAID&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;available_actions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;OrderCommand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SHIP_ORDER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;ship_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SHIPPED&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;available_actions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;validate_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The write path and the action listing now agree because they read the same lifecycle definition.&lt;/p&gt;

&lt;p&gt;But an available action is not a promise that a later call will succeed.&lt;/p&gt;

&lt;p&gt;The listing describes eligibility for the current record. It does not supply a valid &lt;code&gt;Payment&lt;/code&gt; argument, grant a user permission, or reserve the order against another change. The operation must still perform its checks when invoked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Displaying an action does not replace enforcing it.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Test the whole transition surface
&lt;/h3&gt;

&lt;p&gt;We now have a small, explicit surface to test: three states and two commands.&lt;/p&gt;

&lt;p&gt;Let’s write expected outcomes independently of &lt;code&gt;TRANSITIONS&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;expected_transitions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CREATED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;OrderCommand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAPTURE_PAYMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;OrderCommand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SHIP_ORDER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SHIPPED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;OrderCommand&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;expected_transitions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;InvalidOrderOperation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These assertions are test code, not production validation.&lt;/p&gt;

&lt;p&gt;The test exercises all six combinations, including the four that must be rejected. Its expected outcomes describe our business specification rather than being calculated from the implementation table.&lt;/p&gt;

&lt;p&gt;Simply iterating over &lt;code&gt;TRANSITIONS&lt;/code&gt; and asserting that the lookup returns its stored values would be much weaker. That could confirm that the dictionary works while overlooking an incorrectly permitted transition.&lt;/p&gt;

&lt;p&gt;We must also keep the record-level tests from Part II.&lt;/p&gt;

&lt;p&gt;For example, rejecting an unpaid shipment must preserve the order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;unpaid_order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order-67&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;customer_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;delivery_address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Istanbul&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;ship_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unpaid_order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;InvalidOrderOperation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;AssertionError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;An unpaid order was allowed to ship.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;unpaid_order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;OrderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CREATED&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;unpaid_order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The matrix test does not replace tests for missing payments, captured payments on &lt;code&gt;created&lt;/code&gt; orders, invalid payment arguments, or raw strings assigned to &lt;code&gt;status&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;They test different obligations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choosing a state is not the same as producing an output
&lt;/h3&gt;

&lt;p&gt;Our implementation now makes another distinction visible.&lt;/p&gt;

&lt;p&gt;The transition function selects a destination. The domain operation performs the work needed to reach it. A reader may then display information derived from the resulting state.&lt;/p&gt;

&lt;p&gt;These are related responsibilities, but they are not identical.&lt;/p&gt;

&lt;p&gt;This distinction also appears in early sequential-machine research. George Mealy’s 1955 paper developed systematic methods for synthesizing sequential circuits. The model bearing his name associates output with the current state and input the transition being taken.[4, 5]&lt;/p&gt;

&lt;p&gt;Edward Moore’s 1956 paper examined what could be inferred about finite machines through external experiments. In the machines he defined, the next state depended on the previous state and input, while observable output depended on the current state.[6]&lt;/p&gt;

&lt;p&gt;The conventional distinction is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mealy:
    output = f(state, input)

Moore:
    output = f(state)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For our application, consider two different outputs.&lt;/p&gt;

&lt;p&gt;A message reporting that a payment was just recorded belongs to the occurrence of that operation. A status label displaying “Paid” can be derived whenever someone reads the order.&lt;/p&gt;

&lt;p&gt;Reading the label must not record the payment again.&lt;/p&gt;

&lt;p&gt;These are application-level parallels, not a claim that our complete &lt;code&gt;Order&lt;/code&gt; object is a literal Mealy or Moore machine. Payment records and other supporting data remain outside the small control table.&lt;/p&gt;

&lt;p&gt;The useful historical lesson is to ask &lt;strong&gt;where an observable result belongs&lt;/strong&gt;: to handling an input, or to occupying a state.&lt;/p&gt;

&lt;p&gt;A state-derived display is also not automatically a one-time action executed on entry. Showing “Paid” repeatedly and capturing money repeatedly are very different behaviors.&lt;/p&gt;

&lt;h3&gt;
  
  
  What became authoritative?
&lt;/h3&gt;

&lt;p&gt;We can now point to one structure for the status-dependent lifecycle:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Changing its shipping entry changes both the destination selected by &lt;code&gt;ship_order()&lt;/code&gt; and the eligibility reported by &lt;code&gt;available_actions()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That is a meaningful improvement.&lt;/p&gt;

&lt;p&gt;It does not make the table the sole source of every business rule. Payment consistency still lives in validation. Payment-argument checks still live in the operation. A future change to the lifecycle must remain compatible with both.&lt;/p&gt;

&lt;p&gt;A transition table can also contain the wrong rule. Adding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATED + SHIP_ORDER → SHIPPED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;would not become correct merely because it was expressed declaratively.&lt;/p&gt;

&lt;p&gt;The benefit is that the rule is visible, shared, and directly testable.&lt;/p&gt;

&lt;p&gt;We also retain the mutation limitation from Part II. A caller can still assign &lt;code&gt;OrderState.SHIPPED&lt;/code&gt; directly and bypass the transition function. Using enum members does not establish an exclusive write boundary.&lt;/p&gt;

&lt;p&gt;For this implementation, the guarantee remains:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Through the controlled operations, a valid order follows a declared lifecycle transition or the request is rejected without changing it.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is narrower than “the system can never be wrong.” It is also a guarantee we can inspect and test.&lt;/p&gt;

&lt;h3&gt;
  
  
  Was the dictionary necessary?
&lt;/h3&gt;

&lt;p&gt;For three states and two operations, the earlier guarded functions remain a reasonable alternative.&lt;/p&gt;

&lt;p&gt;They may even be easier to read when no other component needs to inspect the lifecycle.&lt;/p&gt;

&lt;p&gt;The table becomes useful because we now have several consumers of the same rule: operations that change the order, code that reports available actions, and tests that examine the entire state–command surface.&lt;/p&gt;

&lt;p&gt;We have not replaced conditional logic because conditionals are bad. We have given shared lifecycle rules an explicit representation.&lt;/p&gt;

&lt;p&gt;The earlier functions already implemented state-machine behavior. This version makes that behavior a separate model.&lt;/p&gt;

&lt;h3&gt;
  
  
  But what happens when the next decision depends on more than status?
&lt;/h3&gt;

&lt;p&gt;Our table currently answers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PAID + SHIP_ORDER → SHIPPED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now suppose the business introduces a new requirement:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ship only to supported delivery addresses.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a proposed extension, not a rule our current code already enforces.&lt;/p&gt;

&lt;p&gt;Consider two internally consistent orders:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Order A:
    status = PAID
    payment = captured payment
    delivery_address = supported destination

Order B:
    status = PAID
    payment = captured payment
    delivery_address = unsupported destination
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both reach the same table entry.&lt;/p&gt;

&lt;p&gt;Yet the new rule requires different outcomes.&lt;/p&gt;

&lt;p&gt;We could create more states:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PAID_WITH_SUPPORTED_ADDRESS
PAID_WITH_UNSUPPORTED_ADDRESS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then another rule arrives about a payment provider, a retry limit, or a customer restriction. Should each combination become another state?&lt;/p&gt;

&lt;p&gt;The lifecycle table has solved the visibility problem. It has not removed the need for supporting data to influence decisions.&lt;/p&gt;

&lt;p&gt;We can now see the next boundary:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A lifecycle state identifies a behavioral mode. It does not necessarily contain every value needed to choose a transition.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But how do we let those values influence the decision without turning every combination into another lifecycle state?&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;[1]&lt;/strong&gt; Python Software Foundation, &lt;em&gt;&lt;a href="https://docs.python.org/3/library/enum.html" rel="noopener noreferrer"&gt;enum - Support for enumerations&lt;/a&gt;&lt;/em&gt;. Named members, values, and enum lookup behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[2]&lt;/strong&gt; Python Software Foundation, &lt;em&gt;&lt;a href="https://docs.python.org/3/library/dataclasses.html" rel="noopener noreferrer"&gt;dataclasses - Data Classes&lt;/a&gt;&lt;/em&gt;. Dataclass fields, generated methods, and the treatment of type annotations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[3]&lt;/strong&gt; Python Software Foundation, &lt;em&gt;&lt;a href="https://docs.python.org/3/library/types.html#types.MappingProxyType" rel="noopener noreferrer"&gt;types.MappingProxyType&lt;/a&gt;&lt;/em&gt;. Read-only access to a mapping.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[4]&lt;/strong&gt; Paul E. Black, &lt;a href="https://xlinux.nist.gov/dads/HTML/finiteStateMachine.html" rel="noopener noreferrer"&gt;“Finite State Machine”&lt;/a&gt;, NIST &lt;em&gt;Dictionary of Algorithms and Data Structures&lt;/em&gt;. State-machine components and the distinction between transition-associated and state-associated outputs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[5]&lt;/strong&gt; George H. Mealy, &lt;a href="https://www.nokia.com/bell-labs/publications-and-media/publications/a-method-for-synthesizing-sequential-circuits/" rel="noopener noreferrer"&gt;“A Method for Synthesizing Sequential Circuits”&lt;/a&gt;, &lt;em&gt;Bell System Technical Journal&lt;/em&gt;, 1955.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[6]&lt;/strong&gt; Edward F. Moore, &lt;a href="https://www.cs.cmu.edu/~cdm/resources/Moore1956-gedanken-experiments.pdf" rel="noopener noreferrer"&gt;“Gedanken-Experiments on Sequential Machines”&lt;/a&gt;, in &lt;em&gt;Automata Studies&lt;/em&gt;, edited by Claude E. Shannon and John McCarthy, Princeton University Press, 1956.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>statemachines</category>
      <category>programming</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Road to State Machines Part II - How Do We Prevent Impossible Changes?</title>
      <dc:creator>Can Burak Sofyalioglu</dc:creator>
      <pubDate>Wed, 30 Sep 2026 12:47:16 +0000</pubDate>
      <link>https://dev.to/canburaks/road-to-state-machines-part-ii-how-do-we-prevent-impossible-changes-3jib</link>
      <guid>https://dev.to/canburaks/road-to-state-machines-part-ii-how-do-we-prevent-impossible-changes-3jib</guid>
      <description>&lt;p&gt;Our model can now describe an order’s lifecycle state and retain the payment information that supports it. What it cannot do is enforce the rules we established.&lt;/p&gt;

&lt;p&gt;The status must be created, paid, or shipped. Payment capture may move an order from created to paid; shipping may move it from paid to shipped. The status and payment record must also agree. These were the unresolved requirements at the end of &lt;a href="https://x.com/cbsofyalioglu/status/2102824786657177803" rel="noopener noreferrer"&gt;Part 1&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;How do we move those rules from the explanation into the implementation?&lt;/p&gt;

&lt;p&gt;Let’s continue with the model we already have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;decimal&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;payment_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;captured_amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;customer_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;delivery_address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;created&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The operations are still simple assignments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;capture_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;
    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ship_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shipped&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both functions change the record without checking whether the change makes sense.&lt;br&gt;
We do not need a new framework to improve this. We need to make the first decision explicit.&lt;/p&gt;
&lt;h3&gt;
  
  
  Start by protecting the shipping operation
&lt;/h3&gt;

&lt;p&gt;Our shipping rule is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Only a paid order may be shipped.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The smallest change is to check the current status before assigning the next one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvalidOrderOperation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ship_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;InvalidOrderOperation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cannot ship an order while it is &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shipped&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now consider a newly created order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order-66&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;customer_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;delivery_address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Istanbul&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;ship_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function raises InvalidOrderOperation. The assignment never runs, so the order remains in the created state.&lt;/p&gt;

&lt;p&gt;We have changed more than just the amount of code. The operation now has two possible outcomes: perform the permitted change, or reject the request without changing the order.&lt;/p&gt;

&lt;p&gt;The condition &lt;code&gt;order.status == "paid"&lt;/code&gt; is a precondition: something that must hold for this operation to complete successfully. The check in the function enforces it.[2]&lt;/p&gt;

&lt;p&gt;This protects one path. But does it protect the whole model?&lt;/p&gt;

&lt;h3&gt;
  
  
  A valid status can belong to an invalid order
&lt;/h3&gt;

&lt;p&gt;Let’s construct the inconsistent order we encountered in &lt;a href="https://x.com/cbsofyalioglu/status/2102824786657177803" rel="noopener noreferrer"&gt;Part 1&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order-66&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;customer_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;delivery_address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Istanbul&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;ship_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# shipped None
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function accepts it.&lt;/p&gt;

&lt;p&gt;Its condition asks whether the status is paid, and the answer is yes. It never asks whether a payment record exists.&lt;/p&gt;

&lt;p&gt;Our first check is correct but insufficient. The order is eligible by its label, yet inconsistent with our business rules.&lt;/p&gt;

&lt;p&gt;These are two different questions:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is the current order a valid record?&lt;br&gt;
Is this operation allowed from that valid record?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Checking the second does not automatically answer the first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Make valid configurations explicit
&lt;/h3&gt;

&lt;p&gt;In &lt;a href="https://x.com/cbsofyalioglu/status/2102824786657177803" rel="noopener noreferrer"&gt;Part 1&lt;/a&gt;, we required a captured payment record for every paid or shipped order, and no captured payment record for a created order.&lt;/p&gt;

&lt;p&gt;That gives us a small set of combinations to consider:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;No payment record&lt;/th&gt;
&lt;th&gt;Captured payment record&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;created&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Valid&lt;/td&gt;
&lt;td&gt;Invalid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;paid&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Invalid&lt;/td&gt;
&lt;td&gt;Valid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;shipped&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Invalid&lt;/td&gt;
&lt;td&gt;Valid&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;An unknown status is invalid regardless of the payment field.&lt;/p&gt;

&lt;p&gt;Let’s put those checks in one function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvalidOrderState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;created&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shipped&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;InvalidOrderState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unknown order status: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;created&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;InvalidOrderState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A created order cannot contain a captured payment.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shipped&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;InvalidOrderState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;An order marked &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;must contain a Payment record.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first check enforces our vocabulary. In this implementation, the actual values are lowercase strings. &lt;code&gt;PAID&lt;/code&gt; is not silently converted to &lt;code&gt;paid&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The other checks enforce agreement between lifecycle state and supporting data.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;isinstance()&lt;/code&gt; check also prevents a string such as "payment-81" from being accepted in place of a Payment object. The annotation &lt;code&gt;Optional[Payment]&lt;/code&gt; describes the intended type, but a plain dataclass does not enforce that annotation at runtime.&lt;/p&gt;

&lt;p&gt;These checks have a deliberately limited scope. They validate the relationship between the order’s status and its payment record. They do not validate every field inside Payment, compare the captured amount with an order total, or prove that a provider captured money.&lt;/p&gt;

&lt;p&gt;Our model still assumes one full payment in one currency. We haven't added an order total or a provider integration, so we shouldn't claim to verify either.&lt;/p&gt;

&lt;h3&gt;
  
  
  These consistency rules are invariants
&lt;/h3&gt;

&lt;p&gt;The rules in &lt;code&gt;validate_order()&lt;/code&gt; are not specific to shipping. They describe what we consider a valid order.&lt;/p&gt;

&lt;p&gt;Let’s call that kind of rule an invariant.&lt;/p&gt;

&lt;p&gt;For this implementation, an invariant is a condition that must hold whenever an order is accepted for processing and after a successful operation returns.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A created order has no captured payment record.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A paid or shipped order retains its captured payment record.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The distinction from a precondition is useful:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Kind of rule&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Is this order valid?&lt;/td&gt;
&lt;td&gt;Invariant&lt;/td&gt;
&lt;td&gt;A paid order contains a payment record.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;May this operation run now?&lt;/td&gt;
&lt;td&gt;Precondition&lt;/td&gt;
&lt;td&gt;Shipping requires a paid order.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What must successful execution establish?&lt;/td&gt;
&lt;td&gt;Postcondition&lt;/td&gt;
&lt;td&gt;Shipping leaves the order shipped and retains its payment.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A postcondition describes what must hold after successful execution.&lt;/p&gt;

&lt;p&gt;The payment record’s continued presence matters. Shipping should change the lifecycle state, not erase the supporting information that made the operation valid.&lt;/p&gt;

&lt;p&gt;Valid endpoints do not prove a valid transition&lt;/p&gt;

&lt;p&gt;Our validator has a subtle limit.&lt;/p&gt;

&lt;p&gt;These two configurations both satisfy it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Before:
    status = created
    payment = None

After:
    status = shipped
    payment = a Payment record
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nevertheless, moving directly between them would skip the payment transition we defined.&lt;/p&gt;

&lt;p&gt;The destination is valid in isolation. Our lifecycle does not permit the move.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;validate_order()&lt;/code&gt; cannot determine whether the previous state was created, paid, or something else. It receives one record, not a record of how it reached that condition.&lt;/p&gt;

&lt;p&gt;We therefore need both kinds of checks:&lt;/p&gt;

&lt;p&gt;Configuration checks determine whether the fields describe an allowed condition.&lt;/p&gt;

&lt;p&gt;Transition checks determine whether a particular operation may move the order from its current condition to another.&lt;/p&gt;

&lt;p&gt;Neither replaces the other.&lt;/p&gt;

&lt;h3&gt;
  
  
  Put the checks before the changes
&lt;/h3&gt;

&lt;p&gt;Let’s revise both operations.&lt;/p&gt;

&lt;p&gt;First, we validate the existing order. Then we will check whether the requested operation is permitted. Only after those checks pass will we change any fields.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;capture_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;validate_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;created&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;InvalidOrderOperation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cannot record a captured payment &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;while the order is &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;payment must be a Payment record.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;
    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ship_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;validate_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;InvalidOrderOperation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cannot ship an order while it is &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shipped&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These definitions replace the earlier unguarded functions.&lt;/p&gt;

&lt;p&gt;The distinction between the exceptions is intentional.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;InvalidOrderState&lt;/code&gt; means the existing record contradicts our model. A paid order with no payment record belongs in this category.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;InvalidOrderOperation&lt;/code&gt; means the order is valid, but the requested operation is not permitted. A correctly formed created order receiving a shipping request belongs in this category.&lt;/p&gt;

&lt;p&gt;Neither case should be repaired by inventing missing information.&lt;/p&gt;

&lt;p&gt;If payment is absent, shipping must not construct a placeholder payment to satisfy the validator. If the status is unknown, the operation must not guess which known status was intended.&lt;/p&gt;

&lt;p&gt;The request stops at the failed check.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why check the current record first?
&lt;/h3&gt;

&lt;p&gt;Suppose we receive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;status = created
payment = an existing captured payment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without validating the current record, &lt;code&gt;capture_payment()&lt;/code&gt; could accept another payment, overwrite the existing record, and change the status to paid.&lt;/p&gt;

&lt;p&gt;The result would look consistent. But the operation would have hidden an inconsistent input by replacing information.&lt;/p&gt;

&lt;p&gt;Our revised function rejects the order before that happens.&lt;/p&gt;

&lt;p&gt;This gives us a useful rule:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do not use a normal lifecycle operation to silently repair a record that already violates the lifecycle.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A repair process may eventually be necessary. It should make its purpose explicit. We have not designed one here.&lt;/p&gt;

&lt;h3&gt;
  
  
  What successful operations now establish
&lt;/h3&gt;

&lt;p&gt;For &lt;code&gt;capture_payment()&lt;/code&gt;, the reasoning is:&lt;/p&gt;

&lt;p&gt;A valid created order has no payment. The function accepts a Payment record, stores it, and marks the order as paid. The resulting combination satisfies our consistency rules.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;ship_order()&lt;/code&gt;, the reasoning is:&lt;/p&gt;

&lt;p&gt;A valid paid order already contains a payment. The function changes only the status to shipped. The payment remains attached, so the resulting combination also satisfies the rules.&lt;/p&gt;

&lt;p&gt;All expected rejection conditions occur before either operation mutates the order.&lt;/p&gt;

&lt;p&gt;That placement matters. Changing fields and then raising an exception does not, by itself, undo the assignments.&lt;/p&gt;

&lt;p&gt;Our payment function still performs two separate assignments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;
&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Between them, the object temporarily contains a payment while its status is still being created. Under our current assumptions, no other writer, callback, or reader observes the object during that operation. The invariant applies at the operation boundary.&lt;/p&gt;

&lt;p&gt;This is not an atomic transaction or a concurrency guarantee. If another process can observe intermediate writes, or an external operation can fail between them, we will need a stronger boundary.&lt;/p&gt;

&lt;p&gt;For now, we are solving the local problem we actually have.&lt;/p&gt;

&lt;h3&gt;
  
  
  An older way of asking the same correctness question
&lt;/h3&gt;

&lt;p&gt;Once we describe what must be true before and after an operation, we are using a form of reasoning that has a long history.&lt;/p&gt;

&lt;p&gt;In his 1969 paper An Axiomatic Basis for Computer Programming, C. A. R. Hoare developed an approach to reasoning about programs through assertions about their initial and resulting conditions. A common notation is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{precondition} command {postcondition}    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For partial correctness, the claim is that when the precondition holds, a terminating execution establishes the postcondition.[2]&lt;/p&gt;

&lt;p&gt;Applied to our example, the intended contract is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{valid order, status is paid}
    ship_order(order)
{valid order, status is shipped, payment is retained}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This specifies what we want, not a formal proof of our Python implementation.&lt;/p&gt;

&lt;p&gt;Dijkstra’s later work on guarded commands made another relevant idea explicit: a command’s eligibility can depend on a Boolean condition placed before it.&lt;/p&gt;

&lt;p&gt;Our shipping check serves that limited purpose. It does not implement Dijkstra’s full calculus, but it follows the same useful discipline: describe when an action is eligible, rather than writing the action alone.&lt;/p&gt;

&lt;p&gt;The historical connection is practical. The important unit is not just the assignment. It is the assignment together with the conditions that make it correct.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check the behavior, including rejection
&lt;/h3&gt;

&lt;p&gt;Let’s run the intended sequence using the same kind of payment record as before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;credit_card&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stripe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;payment_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;payment-81&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;captured_amount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;120.00&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order-66&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;customer_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;delivery_address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Istanbul&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;capture_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;
&lt;span class="nf"&gt;validate_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;ship_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shipped&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;
&lt;span class="nf"&gt;validate_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The assertions check more than the final label. They also check that both operations retain the supplied payment record.&lt;/p&gt;

&lt;p&gt;Now test rejection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;unpaid_order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order-67&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;customer_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;delivery_address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Istanbul&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;ship_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unpaid_order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;InvalidOrderOperation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;AssertionError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;An unpaid order was allowed to ship.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;unpaid_order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;created&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;unpaid_order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final assertions matter.&lt;/p&gt;

&lt;p&gt;An operation that raises the expected exception after partially changing the record would still be wrong for this contract.&lt;/p&gt;

&lt;p&gt;For valid starting records, our two functions should behave as follows:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Starting status&lt;/th&gt;
&lt;th&gt;capture_payment()&lt;/th&gt;
&lt;th&gt;ship_order()&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;created&lt;/td&gt;
&lt;td&gt;Record payment; become&lt;br&gt;&lt;br&gt;paid&lt;/td&gt;
&lt;td&gt;Reject without changing the order&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;paid&lt;/td&gt;
&lt;td&gt;Reject without replacing the payment&lt;/td&gt;
&lt;td&gt;Become&lt;br&gt;&lt;br&gt;shipped&lt;br&gt;&lt;br&gt;; retain payment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;shipped&lt;/td&gt;
&lt;td&gt;Reject without replacing the payment&lt;/td&gt;
&lt;td&gt;Reject without changing the order&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Reject without replacing the payment&lt;/p&gt;

&lt;p&gt;Reject without changing the order&lt;/p&gt;

&lt;p&gt;For duplicate shipping, this implementation chooses the rejection policy discussed in &lt;a href="https://x.com/cbsofyalioglu/status/2102824786657177803" rel="noopener noreferrer"&gt;Part 1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;. Returning an existing shipment would require a shipment result we do not yet store.&lt;/p&gt;

&lt;p&gt;Similarly, &lt;code&gt;capture_payment()&lt;/code&gt; remains a simulation that records the supplied payment. It does not call Stripe, despite the provider name in the example. Rejecting a second call protects this local record; it does not guarantee against external charges.&lt;/p&gt;

&lt;h3&gt;
  
  
  But can another caller still bypass the rules?
&lt;/h3&gt;

&lt;p&gt;Yes.&lt;/p&gt;

&lt;p&gt;Our functions have improved. The dataclasses remain mutable, and their fields are still public.&lt;/p&gt;

&lt;p&gt;A caller can bypass both operations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order-66&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;customer_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;delivery_address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Istanbul&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shipped&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No validation runs automatically on that assignment. Nothing in our class definition invokes &lt;code&gt;validate_order()&lt;/code&gt;, either during construction or during later field changes.&lt;/p&gt;

&lt;p&gt;Calling the validator afterward will detect the missing payment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;validate_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Raises InvalidOrderState.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But detection is not prevention.&lt;/p&gt;

&lt;p&gt;There is a second bypass that configuration validation cannot detect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order-66&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;customer_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;delivery_address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Istanbul&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;
&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shipped&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="nf"&gt;validate_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Passes: the resulting configuration is internally valid.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The record is valid, but the writer skipped the required transition through paid.&lt;/p&gt;

&lt;p&gt;This is the difference between protecting an operation and protecting every possible write.&lt;/p&gt;

&lt;p&gt;Our guarantee must therefore remain specific:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Through these two functions, a valid order either makes a permitted change or the request is rejected without changing it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We have not made arbitrary mutation impossible.&lt;/p&gt;

&lt;p&gt;To rely on that guarantee, application writes must pass through the controlled operations. Restricting field assignment or introducing immutable records can help establish that boundary, but neither technique alone decides which lifecycle transitions are legal.&lt;/p&gt;

&lt;p&gt;The rules and the write boundary are separate responsibilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  What has improved and what is still implicit?
&lt;/h3&gt;

&lt;p&gt;We have now placed all three categories of rules into executable code.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;validate_order()&lt;/code&gt; checks recognized status values and consistent data. &lt;code&gt;capture_payment()&lt;/code&gt; and &lt;code&gt;ship_order()&lt;/code&gt; check the allowed changes. &lt;br&gt;
The operations keep their original names, work with the same Order and Payment models, and still need no external service or framework.&lt;/p&gt;

&lt;p&gt;This is manageable for two operations.&lt;/p&gt;

&lt;p&gt;But look at where the lifecycle is described.&lt;/p&gt;

&lt;p&gt;The valid statuses appear in the validator. The permitted source state for payment capture appears in one function. The permitted source state for shipping appears in another. Their target states appear in assignments.&lt;/p&gt;

&lt;p&gt;To answer “What can happen while an order is paid?”, a reader must inspect the operations.&lt;/p&gt;

&lt;p&gt;A user interface deciding whether to display a shipping action might write another check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;can_ship&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That check describes only status-based eligibility; it does not establish that the record is valid. The actual operation must still validate and reject when necessary.&lt;/p&gt;

&lt;p&gt;More importantly, the interface has begun repeating part of the lifecycle rule. If the shipping rule changes, the write path and the displayed action can drift apart.&lt;/p&gt;

&lt;p&gt;This is not a reason to add a framework immediately. Our current design is small, readable, and already contains state-machine behavior.&lt;/p&gt;

&lt;p&gt;It does reveal the next question.&lt;/p&gt;

&lt;p&gt;The behavior exists, but its complete description is distributed across validation checks, operation checks, and assignments. We reconstructed the table above by reading the functions; the table does not yet govern them.&lt;/p&gt;

&lt;p&gt;We have made individual changes conditional. We have not yet made the entire lifecycle one explicit contract.&lt;/p&gt;

&lt;p&gt;But how do we express that lifecycle in one place so the operations, their tests, and the code displaying available actions don't each maintain their own version of it?&lt;/p&gt;

</description>
      <category>python</category>
      <category>systemdesign</category>
      <category>statemachines</category>
      <category>ai</category>
    </item>
    <item>
      <title>Road to State Machines Part I</title>
      <dc:creator>Can Burak Sofyalioglu</dc:creator>
      <pubDate>Wed, 23 Sep 2026 18:56:44 +0000</pubDate>
      <link>https://dev.to/canburaks/road-to-state-machines-part-i-2d9k</link>
      <guid>https://dev.to/canburaks/road-to-state-machines-part-i-2d9k</guid>
      <description>&lt;p&gt;Let's begin with a very fundamental question whose answer is not so obvious. &lt;/p&gt;

&lt;p&gt;How to design software that always takes the correct action?&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1 — Designing Systems When the Past Determines What Is Allowed Next
&lt;/h2&gt;

&lt;p&gt;Let's assume we are developing an e-commerce store and are just implementing the shipping feature.&lt;/p&gt;

&lt;p&gt;A single operation that acts on a specific order.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ship_order(order)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What should it do?&lt;/p&gt;

&lt;p&gt;That depends on what has already happened:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If the order has just been created, shipping should be rejected because the customer has not paid.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once payment has been captured, the system should create a shipment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the order has already shipped, it should return the existing shipment or reject the duplicate request rather than create another one.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the customer has canceled the order, shipping must not happen at all.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;ship_order&lt;/code&gt; command remains the same, but its correct interpretation changes over time.&lt;/p&gt;

&lt;p&gt;This brings us to a situation where the command alone is therefore insufficient to determine the correct behavior. The system must also know something about what happened before.&lt;/p&gt;

&lt;p&gt;That is the basic problem from which state machines emerge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start with the smallest model
&lt;/h3&gt;

&lt;p&gt;Suppose we are building a basic order-fulfillment application.&lt;/p&gt;

&lt;p&gt;Let's start with the most basic implementation; Our very first model contains only an identifier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we can create an order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order-66&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the application receives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;ship_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Can it proceed?&lt;/p&gt;

&lt;p&gt;The object cannot answer because it tells us only which order we are discussing. It does not tell us whether the order was paid, canceled, shipped, or delivered.&lt;/p&gt;

&lt;p&gt;The smallest useful improvement is to retain the order’s current condition.\&lt;br&gt;
Let's improve our model a bit by adding a &lt;code&gt;status&lt;/code&gt; field so that our basic system can distinguish several stages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;created&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Their intended progression is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATED → PAID → SHIPPED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can implement that progression directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;capture_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ship_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shipped&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We never captured payment, yet the order is marked as shipped.&lt;/p&gt;

&lt;p&gt;The status field records the order’s current stage. It does not enforce the rules for reaching that stage.&lt;/p&gt;

&lt;h3&gt;
  
  
  What code does not show?
&lt;/h3&gt;

&lt;p&gt;The model now has two fields. However, they do not do the same work.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;id&lt;/code&gt; names the order. Change it, and you are talking about a different order. It does not change what &lt;code&gt;ship_order&lt;/code&gt; may do.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;status&lt;/code&gt; sits next to it, as if it were the same kind of value. It is not. It bears a role the field does not show. Change &lt;code&gt;created&lt;/code&gt; to &lt;code&gt;paid&lt;/code&gt;, and the system is allowed to ship. Change it to &lt;code&gt;shipped&lt;/code&gt;, and the same command must stop.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That role is invisible in the class.&lt;/p&gt;

&lt;p&gt;Both fields are strings, but our business rules give them different responsibilities. The status should influence whether shipping is allowed; our current code does not check it.&lt;/p&gt;

&lt;p&gt;Both fields actually store data, but one of them has a different responsibility.&lt;/p&gt;

&lt;p&gt;Let's call that role &lt;strong&gt;state&lt;/strong&gt;, for now. That is the role that changes how the system acts next.&lt;/p&gt;

&lt;p&gt;Let's improve the model a bit by adding a &lt;code&gt;customer_name&lt;/code&gt; field.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;customer_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;created&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three fields. Two of them still haven't decided what happens next.&lt;/p&gt;

&lt;p&gt;Changing the &lt;code&gt;customer_name&lt;/code&gt; from &lt;code&gt;Alice&lt;/code&gt; to &lt;code&gt;Alice Russel&lt;/code&gt; does not necessarily affect whether the order may be shipped. However, changing the &lt;code&gt;status&lt;/code&gt; from &lt;code&gt;created&lt;/code&gt; to &lt;code&gt;shipped&lt;/code&gt; does.&lt;/p&gt;

&lt;p&gt;Change &lt;code&gt;status&lt;/code&gt; from &lt;code&gt;created&lt;/code&gt; to &lt;code&gt;shipped&lt;/code&gt;, and shipping does care. That field is still doing the other job. That is still state.&lt;/p&gt;

&lt;p&gt;The status changes the set of valid future operations. That makes it a &lt;strong&gt;behavioral state&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A useful distinction is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Ordinary data: describes the entity&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Behavioral state: changes how the entity may respond&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But... Although it is useful, the boundaries of this distinction are not so rigid.&lt;/p&gt;

&lt;p&gt;Let me add one more field, &lt;code&gt;delivery_address&lt;/code&gt;, to our model to make my point clear.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;customer_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;delivery_address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;created&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A delivery address may initially be ordinary data. Once the package has been handed to a carrier, changing that address may become forbidden or require a separate process. The field itself has not changed, but its role in the system’s behavior has.&lt;/p&gt;

&lt;p&gt;State is therefore not an intrinsic property of a database column. It is a role information plays in deciding what may happen next.&lt;/p&gt;

&lt;p&gt;So the distinction is contextual.&lt;/p&gt;

&lt;h3&gt;
  
  
  A short name for a longer past
&lt;/h3&gt;

&lt;p&gt;The record says &lt;code&gt;status = "paid"&lt;/code&gt;. That is where the order is. It is not how the order got there.&lt;/p&gt;

&lt;p&gt;One order can be paid by card, while another can be paid by bank transfer.&lt;/p&gt;

&lt;p&gt;The paths differ, but both orders are marked as &lt;code&gt;PAID&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For shipping, the path may not matter. Paid is enough. The state hides the difference.&lt;/p&gt;

&lt;p&gt;Let's call the events we left behind &lt;strong&gt;history&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The state summarizes a relevant consequence of the past. It does not preserve everything that happened.&lt;/p&gt;

&lt;p&gt;We’ll use &lt;strong&gt;history&lt;/strong&gt; to mean the sequence of events that led to the current situation, whether or not we store that sequence explicitly.&lt;/p&gt;

&lt;p&gt;Whether a summary is sufficient depends on the decision we need to make. Consider a future refund operation. A &lt;code&gt;paid&lt;/code&gt; label alone would not give us the payment reference or amount needed to issue the refund.&lt;/p&gt;

&lt;p&gt;So, improve our system a bit more by adding a &lt;code&gt;Payment&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;decimal&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;payment_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;captured_amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;customer_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;delivery_address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;created&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this example, each order has at most one payment that covers the full amount, and all amounts use the same currency. We use Decimal to represent monetary values.&lt;/p&gt;

&lt;p&gt;A paid order might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;credit_card&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stripe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;payment_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;payment-81&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;captured_amount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;120.00&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order-66&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;customer_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;delivery_address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Istanbul&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payment&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;Now that the model includes payment details, our simulated payment function should store them too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;capture_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;
    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We now have three related concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lifecycle state&lt;/strong&gt; helps determine which operations are eligible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Supporting data&lt;/strong&gt; supplies details for those operations and may impose additional conditions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;History&lt;/strong&gt; describes the events that produced the current situation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  What the model still allows
&lt;/h3&gt;

&lt;p&gt;We have already shown an invalid change: shipping an unpaid order. Adding more fields leaves two further problems unresolved.&lt;/p&gt;

&lt;h4&gt;
  
  
  Inconsistent combinations
&lt;/h4&gt;

&lt;p&gt;For this simplified lifecycle, let’s require a captured payment record for every &lt;code&gt;paid&lt;/code&gt; or &lt;code&gt;shipped&lt;/code&gt; order, and no captured payment record for a &lt;code&gt;created&lt;/code&gt; order.&lt;/p&gt;

&lt;p&gt;The model does not enforce those rules. It accepts an order marked as paid without a payment record:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order-66&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;customer_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;delivery_address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Istanbul&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&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;It also accepts an order marked as created with the captured payment we constructed earlier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order-66&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;customer_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;delivery_address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Istanbul&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;created&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payment&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;These combinations contradict our stated rules. The additional fields give us a richer record, but no checks ensure that their values agree.&lt;/p&gt;

&lt;h4&gt;
  
  
  Unknown status values
&lt;/h4&gt;

&lt;p&gt;Because &lt;code&gt;status&lt;/code&gt; is an unrestricted string, the model also accepts values outside our intended lifecycle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shiped&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;some_unknown_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python accepts both assignments. Neither value belongs to the vocabulary we intended to use.&lt;/p&gt;

&lt;h3&gt;
  
  
  The record is our model of reality
&lt;/h3&gt;

&lt;p&gt;There is another boundary to keep in mind. A record marked &lt;code&gt;paid&lt;/code&gt; tells us what the application has stored. By itself, it does not prove that a payment provider captured the money.&lt;/p&gt;

&lt;p&gt;In a real integration, payment could succeed while the local update fails. Our records could then disagree with the provider.&lt;/p&gt;

&lt;p&gt;Those failures belong to later parts of the tutorial. Here, we are examining a simpler problem that already exists with one writer and no external services: the model accepts changes that violate our own rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remembering a condition and enforcing its rules
&lt;/h3&gt;

&lt;p&gt;The&amp;nbsp;&lt;code&gt;status&lt;/code&gt; field&amp;nbsp;can&amp;nbsp;tell&amp;nbsp;us&amp;nbsp;where&amp;nbsp;the&amp;nbsp;order&amp;nbsp;claims&amp;nbsp;to&amp;nbsp;be.&lt;/p&gt;

&lt;p&gt;It&amp;nbsp;cannot&amp;nbsp;say:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Which&amp;nbsp;values&amp;nbsp;are&amp;nbsp;valid? (such as "created" or "CREATED")&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Which&amp;nbsp;changes&amp;nbsp;are&amp;nbsp;allowed? (such as changing from "paid" to "shipped" requires a payment)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Which&amp;nbsp;condition&amp;nbsp;must&amp;nbsp;come&amp;nbsp;first? (such as changing from "created" to "paid" is allowed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Which&amp;nbsp;operations&amp;nbsp;must&amp;nbsp;be&amp;nbsp;rejected? (such as changing from "created" to "shipped" must be forbidden)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's&amp;nbsp;call&amp;nbsp;this&amp;nbsp;the&amp;nbsp;difference&amp;nbsp;between&amp;nbsp;the&amp;nbsp;&lt;strong&gt;memory&amp;nbsp;problem&lt;/strong&gt;&amp;nbsp;and&amp;nbsp;the&amp;nbsp;&lt;strong&gt;correctness&amp;nbsp;problem&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We can now distinguish two problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The memory problem:&lt;/strong&gt; retain enough information from the past to inform the next decision.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The correctness problem:&lt;/strong&gt; enforce the business rules governing valid conditions and changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We still need to enforce three kinds of rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Valid values:&lt;/strong&gt; the status must be &lt;code&gt;created&lt;/code&gt;, &lt;code&gt;paid&lt;/code&gt;, or &lt;code&gt;shipped&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Allowed transitions:&lt;/strong&gt; a simulated successful payment moves an order from &lt;code&gt;created&lt;/code&gt; to &lt;code&gt;paid&lt;/code&gt;; shipping moves it from &lt;code&gt;paid&lt;/code&gt; to &lt;code&gt;shipped&lt;/code&gt;. Shipping directly from &lt;code&gt;created&lt;/code&gt; must be rejected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consistent data:&lt;/strong&gt; a &lt;code&gt;paid&lt;/code&gt; or &lt;code&gt;shipped&lt;/code&gt; order must retain its captured payment record.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A transition is a change from one state to another. Recording the current state does not tell our code which transitions to allow.&lt;/p&gt;

&lt;p&gt;Our intended status values give us a vocabulary. Transition rules give us a grammar.&lt;/p&gt;

&lt;p&gt;We can name the stages an order may occupy, but our implementation still accepts paths that the business forbids. The rules exist in our explanation; they are not yet enforced by the code.&lt;/p&gt;

&lt;p&gt;The next step is to make those rules explicit and enforce them whenever the order changes.&lt;/p&gt;

&lt;p&gt;That is where we begin building a state machine.&lt;/p&gt;

</description>
      <category>python</category>
      <category>statemachines</category>
      <category>systemdesign</category>
      <category>ai</category>
    </item>
    <item>
      <title>Python Decorators: A Comprehensive Guide</title>
      <dc:creator>Can Burak Sofyalioglu</dc:creator>
      <pubDate>Fri, 03 Jan 2025 07:55:37 +0000</pubDate>
      <link>https://dev.to/canburaks/python-decorators-a-comprehensive-guide-43ke</link>
      <guid>https://dev.to/canburaks/python-decorators-a-comprehensive-guide-43ke</guid>
      <description>&lt;p&gt;When I started programming with Python, if I am not mistaken, the version was 3.3. Therefore, when I started programming, decorators had been available to the Python community for a long time.&lt;/p&gt;

&lt;p&gt;Function decorators came to Python with version 2.2 and Class decorators came to Python with version 2.6.&lt;/p&gt;

&lt;p&gt;Personally, I see Python's Decorator feature as a very powerful feature of the language.&lt;/p&gt;

&lt;p&gt;Actually, my aim is to make a series of articles about the most difficult to understand topics in Python. I plan to cover these topics, which are a little more than ten, one by one.&lt;/p&gt;

&lt;p&gt;In this article, I will try to touch on every part of the Decorators topic as much as I can.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Historical Context
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Early Days (Pre-Python 2.2):&lt;/strong&gt; Before decorators, modifying functions or classes often involved manual wrapping or monkey-patching, which was cumbersome and less readable.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Metaclasses (Python 2.2):&lt;/strong&gt; Metaclasses provided a way to control class creation, offering some of the functionality that decorators would later provide, but they were complex for simple modifications.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;PEP 318 (Python 2.4):&lt;/strong&gt;  Decorators were formally introduced in Python 2.4 through &lt;a href="https://peps.python.org/pep-0318/" rel="noopener noreferrer"&gt;PEP 318&lt;/a&gt;. The proposal was inspired by annotations in Java and aimed to provide a cleaner, more declarative way to modify functions and methods.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Class Decorators (Python 2.6):&lt;/strong&gt; Python 2.6 extended decorator support to classes, further enhancing their versatility.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Widespread Adoption:&lt;/strong&gt; Decorators quickly became a popular feature, used extensively in frameworks like Flask and Django for routing, authentication, and more.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. What are Decorators?
&lt;/h2&gt;

&lt;p&gt;In essence, &lt;a href="https://en.wikipedia.org/wiki/Decorator_pattern" rel="noopener noreferrer"&gt;a decorator is a design pattern&lt;/a&gt; in Python that allows you to modify the behavior of a function or a class without changing its core structure. Decorators are a form of metaprogramming, where you're essentially writing code that manipulates other code.&lt;/p&gt;

&lt;p&gt;You know &lt;a href="https://realpython.com/python-scope-legb-rule/" rel="noopener noreferrer"&gt;Python resolve names using the scope given in order below&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Local&lt;/li&gt;
&lt;li&gt;Enclosing&lt;/li&gt;
&lt;li&gt;Global&lt;/li&gt;
&lt;li&gt;Built-in&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Decorators are sit Enclosing scope, which is closely related to the &lt;a href="https://en.wikipedia.org/wiki/Closure_(computer_programming)" rel="noopener noreferrer"&gt;Closure concept&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Idea:&lt;/strong&gt; A decorator takes a function as input, adds some functionality to it, and returns a modified function.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analogy:&lt;/strong&gt; Think of a decorator as a gift wrapper. You have a gift (the original function), and you wrap it with decorative paper (the decorator) to make it look nicer or add extra features (like a bow or a card). The gift inside remains the same, but its presentation or associated actions are enhanced.&lt;/p&gt;

&lt;h2&gt;
  
  
  A) Decorator Variations: Function-based vs. Class-based
&lt;/h2&gt;

&lt;p&gt;Most decorators in Python are implemented using functions, but you can also create decorators using classes.&lt;br&gt;
Function-based decorators are more common and simpler, while class-based decorators offer additional flexibility.&lt;/p&gt;
&lt;h3&gt;
  
  
  Function-based Basic Decorator Syntax
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_decorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Do something before calling the decorated function
&lt;/span&gt;        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Before function call&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# Do something after calling the decorated function
&lt;/span&gt;        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;After function call&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;

&lt;span class="nd"&gt;@my_decorator&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;say_hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;say_hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;World&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;my_decorator&lt;/code&gt; is the decorator function. It takes the function func to be decorated as input.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;wrapper&lt;/code&gt; is an inner function that wraps the original function's call. It can execute code before and after the original function.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@my_decorator&lt;/code&gt; is the decorator syntax. It's equivalent to &lt;code&gt;say_hello = my_decorator(say_hello)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Class-based Basic Decorator Syntax
&lt;/h3&gt;

&lt;p&gt;These use classes instead of functions to define decorators.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyDecorator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__call__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Do something before calling the decorated function
&lt;/span&gt;        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Before function call&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# Do something after calling the decorated function
&lt;/span&gt;        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;After function call&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;

&lt;span class="nd"&gt;@MyDecorator&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;say_hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;say_hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;World&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;MyDecorator&lt;/code&gt; is a class that acts as a decorator.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;__init__&lt;/code&gt; method stores the function to be decorated.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;__call__&lt;/code&gt; method makes the class instance callable, allowing it to be used like a function.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  B) &lt;strong&gt;Implementing a Simple Decorator&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The fundamental concept of decorators is that they are functions that take another function as an argument and extend its behavior without explicitly modifying it.&lt;br&gt;
Here's the simplest form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_decorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Something is happening before the function is called.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Something is happening after the function is called.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;

&lt;span class="c1"&gt;# Using the decorator with @ syntax
&lt;/span&gt;&lt;span class="nd"&gt;@my_decorator&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;say_hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# When we call say_hello()
&lt;/span&gt;&lt;span class="nf"&gt;say_hello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# This is equivalent to:
# say_hello = my_decorator(say_hello)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  C) Implementing a Decorator with Arguments
&lt;/h2&gt;

&lt;p&gt;Let's create a decorator that logs the execution time of a function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decorator_with_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;    &lt;span class="c1"&gt;# Accept any number of arguments
&lt;/span&gt;        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Arguments received: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Pass arguments to the original function
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;

&lt;span class="nd"&gt;@decorator_with_args&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;greeting&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;greeting&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;greeting&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hi&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Prints arguments then "Hi, Alice!"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  D) Implementing a Parameterized Decorator
&lt;/h2&gt;

&lt;p&gt;These are decorators that can accept their own parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;decorator&lt;/span&gt;

&lt;span class="nd"&gt;@repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Done&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bob&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Prints "Hello Bob" three times
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  E) Implementing a Class Decorator
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;singleton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;instances&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;get_instance&lt;/span&gt;

&lt;span class="nd"&gt;@singleton&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Initializing database connection&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Creating multiple instances actually returns the same instance
&lt;/span&gt;&lt;span class="n"&gt;db1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# Prints initialization
&lt;/span&gt;&lt;span class="n"&gt;db2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# No initialization printed
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db1&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;db2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# True
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  F) Implementing Method Decorators
&lt;/h2&gt;

&lt;p&gt;These are specifically designed for class methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;debug_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Calling method &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; of &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__class__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nd"&gt;@debug_method&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;

&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;my_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  G) Implementing Decorator Chaining
&lt;/h2&gt;

&lt;p&gt;Multiple decorators can be applied to a single function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;b&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/b&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;italic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;i&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/i&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;

&lt;span class="nd"&gt;@bold&lt;/span&gt;
&lt;span class="nd"&gt;@italic&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;  &lt;span class="c1"&gt;# Outputs: &amp;lt;b&amp;gt;&amp;lt;i&amp;gt;Hello!&amp;lt;/i&amp;gt;&amp;lt;/b&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Decorators are applied from bottom to top.&lt;/li&gt;
&lt;li&gt;  It is more like in what we do in math: &lt;code&gt;f(g(x))&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;italic&lt;/code&gt; is applied first, then &lt;code&gt;bold&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  H) What happens if we don't use @functools.wraps ?
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;functools.wraps&lt;/code&gt; decorator, &lt;a href="https://docs.python.org/3/library/functools.html#functools.wraps" rel="noopener noreferrer"&gt;See docs&lt;/a&gt;, is a helper function that preserves the metadata of the original function (like its name, docstring, and signature) when you wrap it with a decorator. If you don't use it, you'll lose this important information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_decorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Wrapper docstring&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;

&lt;span class="nd"&gt;@my_decorator&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_function&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;My function docstring&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__doc__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wrapper
Wrapper docstring
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The original function's name (&lt;code&gt;my_function&lt;/code&gt;) and docstring ("My function docstring") are lost.&lt;/li&gt;
&lt;li&gt;  This can make debugging and introspection difficult.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution: Use &lt;code&gt;functools.wraps&lt;/code&gt;):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;functools&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_decorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nd"&gt;@functools.wraps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Wrapper docstring&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;

&lt;span class="nd"&gt;@my_decorator&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_function&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;My function docstring&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__doc__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my_function
My function docstring
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Benefits of &lt;code&gt;functools.wraps&lt;/code&gt;:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Preserves function metadata.&lt;/li&gt;
&lt;li&gt;  Improves code readability and maintainability.&lt;/li&gt;
&lt;li&gt;  Makes debugging easier.&lt;/li&gt;
&lt;li&gt;  Helps with introspection tools and documentation generators.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  I) Decorators with State
&lt;/h2&gt;

&lt;p&gt;Decorators can also maintain state between function calls. This is particularly useful for scenarios like caching or counting function calls.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;python&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count_calls&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;calls&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Call &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;calls&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; of &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;calls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;

&lt;span class="nd"&gt;@count_calls&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;say_hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;say_hello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# Call 1 of say_hello
&lt;/span&gt;&lt;span class="nf"&gt;say_hello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# Call 2 of say_hello
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Call 1 of say_hello
Hello!
Call 2 of say_hello
Hello!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explanation:&lt;/p&gt;

&lt;p&gt;The wrapper function maintains a counter (calls) that increments each time the decorated function is called.&lt;br&gt;
This is a simple example of how decorators can be used to maintain state.&lt;/p&gt;

&lt;h2&gt;
  
  
  J) Best Practices for Python Decorators
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Use &lt;code&gt;functools.wraps&lt;/code&gt;:&lt;/strong&gt; Always use &lt;code&gt;@functools.wraps&lt;/code&gt; in your decorators to preserve the original function's metadata.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Keep Decorators Simple:&lt;/strong&gt; Decorators should ideally do one specific thing and do it well. This makes them more reusable and easier to understand.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Document Your Decorators:&lt;/strong&gt; Explain what your decorator does, what arguments it takes, and what it returns.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Test Your Decorators:&lt;/strong&gt; Write unit tests to ensure your decorators work as expected in various scenarios.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Consider the Order of Chaining:&lt;/strong&gt; Be mindful of the order when chaining multiple decorators, as it affects the execution flow.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  K) Bad Implementations (Anti-Patterns)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Overly Complex Decorators:&lt;/strong&gt; Avoid creating decorators that are too complex or try to do too many things. This makes them hard to understand, maintain, and debug.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Ignoring &lt;code&gt;functools.wraps&lt;/code&gt;:&lt;/strong&gt; Forgetting to use &lt;code&gt;@functools.wraps&lt;/code&gt; leads to loss of function metadata, which can cause issues with introspection and debugging.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Side Effects:&lt;/strong&gt; Decorators should ideally not have unintended side effects outside of modifying the decorated function.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Hardcoding Values:&lt;/strong&gt; Avoid hardcoding values within decorators. Instead, use decorator factories to make them configurable.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Not Handling Arguments Properly:&lt;/strong&gt; Ensure your &lt;code&gt;wrapper&lt;/code&gt; function can handle any number of positional and keyword arguments using &lt;code&gt;*args&lt;/code&gt; and &lt;code&gt;**kwargs&lt;/code&gt; if the decorator is meant to be used with a variety of functions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  L) 10. Real-World Use Cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Logging:&lt;/strong&gt; Recording function calls, arguments, and return values for debugging or auditing.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Timing:&lt;/strong&gt; Measuring the execution time of functions for performance analysis.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Caching:&lt;/strong&gt; Storing the results of expensive function calls to avoid redundant computations (memoization).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Authentication and Authorization:&lt;/strong&gt; Verifying user credentials or permissions before executing a function.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Input Validation:&lt;/strong&gt; Checking if the arguments passed to a function meet certain criteria.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Rate Limiting:&lt;/strong&gt; Controlling the number of times a function can be called within a specific time period.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Retry Logic:&lt;/strong&gt; Automatically retrying a function call if it fails due to a temporary error.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Framework-Specific Tasks:&lt;/strong&gt; Frameworks like Flask and Django use decorators for routing (mapping URLs to functions), registering plugins, and more.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  M) Curated Lists of Python Decorators
&lt;/h2&gt;

&lt;p&gt;You can find a curated lists of Python decorators below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/lord63/awesome-python-decorator" rel="noopener noreferrer"&gt;Awesome Python Decorators&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.python.org/moin/PythonDecoratorLibrary" rel="noopener noreferrer"&gt;Python Decorator Library&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  N) 11. Conclusion
&lt;/h2&gt;

&lt;p&gt;Decorators are a powerful and elegant feature in Python that allows you to enhance functions and classes in a clean and declarative way.&lt;br&gt;
By understanding the principles, best practices, and potential pitfalls, you can effectively leverage decorators to write more modular, maintainable, and expressive code.&lt;br&gt;
They are a valuable tool in any Python programmer's arsenal, especially when working with frameworks or building reusable components.&lt;/p&gt;

</description>
      <category>python</category>
      <category>backend</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>A Beginner's Guide to Structure SEO-friendly URLs</title>
      <dc:creator>Can Burak Sofyalioglu</dc:creator>
      <pubDate>Thu, 28 Dec 2023 13:05:38 +0000</pubDate>
      <link>https://dev.to/canburaks/a-beginners-guide-to-structure-blog-post-urls-leg</link>
      <guid>https://dev.to/canburaks/a-beginners-guide-to-structure-blog-post-urls-leg</guid>
      <description>&lt;h1&gt;
  
  
  A Beginner's Guide to Structure Blog Post URLs
&lt;/h1&gt;

&lt;p&gt;Before sharing your first blog post, one of the things you should definitely pay attention to is how your blog posts and their URLs should be organized. I will talk about &lt;a href="https://bloggingplatforms.app/blog/beginners-guide-to-structure-blog-post-urls" rel="noopener noreferrer"&gt;how you should structure your blog posts URLs&lt;/a&gt;, best practices and the things you should avoid.&lt;/p&gt;

&lt;p&gt;Please do not skip this article if your intent is ranking on search engines. I have learned these lessons in a hard way. I wasted a great deal of time to fix my mistakes.&lt;/p&gt;

&lt;p&gt;Therefore, I definitely recommend reading this article before writing your first blog post.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Beginner’s Guide for an SEO-Friendly URL Structure
&lt;/h2&gt;

&lt;p&gt;Let's get started with the essential questions that clarify the importance of having a proper URL structure.&lt;/p&gt;

&lt;h3&gt;
  
  
  What happens when you don't have a proper URL structure?
&lt;/h3&gt;

&lt;p&gt;If you don't follow the practices here, it may be possible for Google to index a page differently than you thought. (We’ll discuss that later)&lt;/p&gt;

&lt;p&gt;You link to another article in one of your posts. Later, you realize the link targets a URL other than Google has indexed.&lt;/p&gt;

&lt;p&gt;If rankings on search engines are your concern, you should either change the link’s address to the address of what Google indexed or manually remove that page from Google search results. If you are dealing with many pages, such as an e-commerce website, it would take you many hours to fix that.&lt;/p&gt;

&lt;p&gt;You can watch &lt;a href="https://www.youtube.com/watch?v=FHjVmi1tkEw" rel="noopener noreferrer"&gt;the official answer of Google&lt;/a&gt; that mentions the potential adverse effects when you change your URL structure later on.&lt;/p&gt;

&lt;h3&gt;
  
  
  An Analogy to Understand a URL and a Domain Name
&lt;/h3&gt;

&lt;p&gt;Maybe an analogy explains better what a URL and a domain name are.&lt;/p&gt;

&lt;p&gt;URL is the abbreviation of Uniform Resource Locator (URL), colloquially known as a web page’s unique address.&lt;/p&gt;

&lt;p&gt;A URL has different parts, such as protocol, domain, TLD, subdirectory, slug, and URL parameters.&lt;/p&gt;

&lt;p&gt;The part after the TLD (Top Level Domain)  is customizable by you (if you are the registrant of that domain) and the main topic of this article is how you should customize that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzv53llhawt8j2whr41vd.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzv53llhawt8j2whr41vd.webp" alt="URL Parts" width="798" height="133"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Almost all of us have mobile phones. A mobile phone has a unique phone number similar to a website’s URL. It is difficult to remember phone numbers; thus, we save a phone number with a proper name, such as whose it belongs. After, when we try to call a friend in the contact list, the mobile device calls the number of that friend.&lt;/p&gt;

&lt;p&gt;This is similar to a website such as the one you are reading.  A website's actual address consists of several numbers that we call IP numbers.  IP numbers are also difficult to remember, like mobile phone numbers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5tstg45cdqs7mutpqfn8.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5tstg45cdqs7mutpqfn8.webp" alt="Mobile numbers and IP numbers" width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wouldn’t it be nice if we could save those IP numbers with a proper name?&lt;/p&gt;

&lt;p&gt;Yes, and we are doing that. Browsers do that for us in the background.&lt;/p&gt;

&lt;p&gt;The main difference between those two situations is to whom those records are available and accessible.&lt;/p&gt;

&lt;p&gt;A contact with a name and a phone number exists only on the registered device.&lt;/p&gt;

&lt;p&gt;On the other hand, when you buy (!) a domain name, you actually rent it for a limited time. More specifically, you become the domain holder and have the right to which IP address that domain name should point out.&lt;/p&gt;

&lt;p&gt;Moreover, the record that holds the domain name and the IP number it points out is globally available.&lt;/p&gt;

&lt;p&gt;How browsers know the IP number of any domain is the topic of &lt;a href="https://en.wikipedia.org/wiki/Public_recursive_name_server" rel="noopener noreferrer"&gt;public DNS (Domain Name System) resolver&lt;/a&gt; and it is out of the scope of this article.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part I: Make A Blog URL structure as SEO-friendly
&lt;/h2&gt;

&lt;p&gt;The first thing to understand is the ideal pattern for a blog post URL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which URL structure is Better: Flat or Hierarchical?
&lt;/h3&gt;

&lt;p&gt;At a higher level, you have two options to structure your blog post URLs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Flat URL structure&lt;/li&gt;
&lt;li&gt;Hierarchical URL structure (Top-down or Pyramid)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm5e6zerqlu4bb7v8hekn.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm5e6zerqlu4bb7v8hekn.webp" alt="URL Structures" width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;According to an &lt;a href="https://youtu.be/GAZ6j00geMk?si=xJpkTPwULiy2PQOf&amp;amp;t=98" rel="noopener noreferrer"&gt;official answer from Google&lt;/a&gt;, using a hierarchical URL rather than a flat one seems more beneficial.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are the Benefits of Using a Hierarchical URL structure
&lt;/h3&gt;

&lt;p&gt;It helps you to keep semantically related content together. By doing that, you signal a message to the crawlers. &lt;a href="https://youtu.be/wsrL6l2Fxvo?si=11AF5zOwaipc8GDf&amp;amp;t=3525" rel="noopener noreferrer"&gt;This helps search engines understand the context of the post better&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Moreover, separating blog posts according to their categories allows you to create different content silos for different topics.  Even &lt;a href="https://bloggingplatforms.app/blog/best-free-platforms-for-blogging" rel="noopener noreferrer"&gt;free blogging platforms&lt;/a&gt; support that feature.&lt;/p&gt;

&lt;p&gt;But what that means?  Let me explain.&lt;/p&gt;

&lt;h4&gt;
  
  
  What is a Content Silo?
&lt;/h4&gt;

&lt;p&gt;A content silo is a method of grouping related content together on your website to establish the site's keyword-based topical areas or themes. Think of it as organizing your website into different sections or "silos," each dedicated to a specific topic.&lt;/p&gt;

&lt;p&gt;This structure helps search engines understand the themes of your site, and it also enhances user experience by making navigation easier.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzz3fbd7sbu9ag6t9mx10.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzz3fbd7sbu9ag6t9mx10.webp" alt="Content Silos" width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In other words, content silos may play a role in being an authority on different topics.&lt;/p&gt;

&lt;p&gt;Another question is coming.&lt;/p&gt;

&lt;h4&gt;
  
  
  What does being an authority on a topic means?
&lt;/h4&gt;

&lt;p&gt;One of &lt;a href="https://developers.google.com/search/docs/fundamentals/creating-helpful-content#eat" rel="noopener noreferrer"&gt;the four pillars of search engine optimization (E-E-A-T) is being an authority (A)&lt;/a&gt; on the topic you want to rank for.  It means more than just knowledge. People with authority on a specific topic are trusted and influential people on that topic. They consistently provide value to others through their expertise.&lt;/p&gt;

&lt;p&gt;This concept is also known as topical authority.&lt;/p&gt;

&lt;h4&gt;
  
  
  What does topical authority mean?
&lt;/h4&gt;

&lt;p&gt;The term refers to the level of expertise or credibility a website or content creator has on a specific subject matter. It's like being the go-to source for information on that particular topic. The concept is rooted in the idea that search engines, like Google, favor sites that provide comprehensive and reliable information on specific topics.&lt;/p&gt;

&lt;p&gt;By consistently grouping related content under specific category slugs, you're showing search engines that you have multiple pieces of content revolving around this topic. This can help to establish your site as an authoritative source on that subject.&lt;/p&gt;

&lt;p&gt;If you need a deeper knowledge about that, I can suggest you to read these two articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://inlinks.com/insight/inlinks-a-tool-for-building-topical-authority/" rel="noopener noreferrer"&gt;Topical Authority for SEO: What it is and How to Build It&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.holisticseo.digital/theoretical-seo/topical-authority/" rel="noopener noreferrer"&gt;Importance of Topical Authority for SEO&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Considering the benefits I mentioned above, I can say that using a hierarchical URL structure is better.&lt;/p&gt;

&lt;p&gt;This means you should categorize your blog posts and insert the category’s slug between a&amp;nbsp; post slug and the domain, separated by a slash.&lt;/p&gt;

&lt;h3&gt;
  
  
  Preventing Duplicate Content
&lt;/h3&gt;

&lt;p&gt;However, if you are using the URL structure that follows &lt;code&gt;/category/post-slug&lt;/code&gt;, it is possible that you will have duplicate content issues.  Let me clarify.&lt;/p&gt;

&lt;p&gt;It is not a rare scenario for a post with multiple categories.&lt;/p&gt;

&lt;p&gt;This causes content duplication.&lt;/p&gt;

&lt;p&gt;To prevent this,  you must use &lt;a href="https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls" rel="noopener noreferrer"&gt;the canonical address method&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For a given post with multiple categories, you choose one of them as the canonical address and use that one in all versions of that post. By doing that, you tell Google to index only the canonical address and ignore others.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4keydeea5rhv8meub9io.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4keydeea5rhv8meub9io.webp" alt="Post with Multiple Categories" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, we can proceed to the next part.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part II: Making Blog Post URLs as SEO-friendly
&lt;/h2&gt;

&lt;p&gt;Keyword research is the first step in search engine optimization.&amp;nbsp; However, it is not the scope of this article.&lt;/p&gt;

&lt;p&gt;For the sake of the continuity of this article, I’ll assume that you did keyword research and decided to rank one of those keywords from the research.&lt;/p&gt;

&lt;p&gt;So, we have a keyword that we want to rank for.&lt;/p&gt;

&lt;p&gt;Before proceeding, I must mention one very important term: slug.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a slug?
&lt;/h3&gt;

&lt;p&gt;Slug is a part of the URL and makes a page distinct from another. The human-readable and URL-normalized version of the given text can be a category name or a post title.&amp;nbsp; The blogging platform you choose generally automates this text process but can be changed manually.&lt;/p&gt;

&lt;p&gt;For instance, in &lt;code&gt;www.example.com/books/fiction&lt;/code&gt;, the slug, 'books/fiction', is composed of the slugified version of category and the product names.&lt;/p&gt;

&lt;p&gt;This is the most important part of structuring your blog post URLs, and it must be applied to both the category and the post part of a URL.&lt;/p&gt;

&lt;p&gt;We have already decided which keyword we want to rank for.&lt;/p&gt;

&lt;p&gt;One of the best practices for search engine optimization is using the keyword in the URL. But why?&lt;/p&gt;

&lt;h3&gt;
  
  
  Does using keywords in URLs Affect Rankings?
&lt;/h3&gt;

&lt;p&gt;Yes, using keywords in URLs is a ranking factor. On the other hand, according to Google Search Advocate John Mueller, &lt;a href="https://youtu.be/kzM7fi43cMc?si=fngCc0it4QSiEHxF&amp;amp;t=3096" rel="noopener noreferrer"&gt;it has a very lightweight effect&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This means we will mention the keyword in the slug.&lt;/p&gt;

&lt;p&gt;In general, the post slug is auto-generated by your blogging platform. If it is auto-generated, you’ll see that the slug of the post is based on the title of the post. It is a common practice also.&lt;/p&gt;

&lt;p&gt;The more important part is how you customize that slug, either based on the title or not.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Best Practices for Structuring Blog Post URLs
&lt;/h3&gt;

&lt;p&gt;When structuring the URLs of your blog posts for optimal performance in search engine optimization (SEO), it is important to follow a set of best practices that make your URLs more readable and relevant to both users and search engines.&lt;/p&gt;

&lt;p&gt;To apply these practices, your blogging platform must support a category and tag system. Otherwise, you can check &lt;a href="https://bloggingplatforms.app/features/category-tag-system" rel="noopener noreferrer"&gt;the blogging platforms that support the category system&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here are some guidelines to structure your blog post URLs effectively:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Use Descriptive Keywords&lt;/strong&gt;: Incorporate the primary keyword related to your blog post into the URL to explain what the post is about. This helps with SEO and gives users an idea of what to expect before they click the link.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep it Simple and Specific&lt;/strong&gt;: Aim to keep your URL structure simple, short, and precise. Although &lt;a href="https://youtu.be/DVdOUqaBQ00?si=tZvBvk8nXONir4XV" rel="noopener noreferrer"&gt;the URL length does not affect rankings&lt;/a&gt;, it would be nice to avoid long and complex URLs. By following this practice, you can focus on the most important keywords that capture the essence of your blog post.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Hyphens to Separate Words&lt;/strong&gt;: Even though it doesn't affect rankings which one do you prefer, to enhance readability, use hyphens rather than underscores to separate words within your URL. You&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid Unnecessary Words&lt;/strong&gt;: Trim stop words like "and," "or," "but," "the," etc., as they add unnecessary length and don't contribute much to search engine understanding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Utilize Lowercase Letters&lt;/strong&gt;: URLs are case-sensitive by definition. Although it is possible to use all upper case, all lowercase, or maybe mixed case, it's a standard practice to use all lowercase letters in URLs to avoid confusion. &lt;a href="https://youtu.be/d1xb84T0olI?si=kKbR0DGGBx4u5acL" rel="noopener noreferrer"&gt;Google says its crawler can handle those variations&lt;/a&gt;, but it needs to be figured out first. Therefore, please follow all lowercase practice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Omit Special Characters&lt;/strong&gt;: Special characters and symbols can make URLs look cluttered and can cause issues with some browsers and servers. Use letters without the diacritical version. Stick to letters and numbers only if that number makes sense where possible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exclude Dates and Numbers&lt;/strong&gt;: Unless they're integral to the content, avoid including dates and excessive numbers, which can make your URL unnecessarily long and less evergreen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid Keyword Repetition&lt;/strong&gt;: Don't overuse keywords in the URL as this can look spammy and may not be beneficial for SEO.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foa7wneov5e5ib70mb41w.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foa7wneov5e5ib70mb41w.webp" alt="Slugifying" width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The image above shows an example slug of a post with a title "What types of Kyber Crystals Exists?" located under "Star Wars" category.&lt;/p&gt;

&lt;p&gt;You can also read the official guideline: &lt;a href="https://developers.google.com/search/docs/crawling-indexing/url-structure" rel="noopener noreferrer"&gt;URL structure best practices for Google&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By adhering to these practices, your blog post URLs will be well-optimized for search engines, contributing to a better user experience and potentially improving the visibility and ranking of your content in search results.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>beginners</category>
      <category>contentwriting</category>
      <category>writing</category>
    </item>
    <item>
      <title>How to Generate Income from Your Blog</title>
      <dc:creator>Can Burak Sofyalioglu</dc:creator>
      <pubDate>Mon, 01 May 2023 22:10:37 +0000</pubDate>
      <link>https://dev.to/canburaks/how-to-generate-income-from-your-blog-26cl</link>
      <guid>https://dev.to/canburaks/how-to-generate-income-from-your-blog-26cl</guid>
      <description>&lt;p&gt;In this article, I shared my findings and personal experiences about &lt;strong&gt;generating income with your blog&lt;/strong&gt; from a general perspective. I mentioned different monetization strategies and different useful tools that make your blogging journey easier.&lt;/p&gt;

&lt;p&gt;Suppose you have no idea how to generate revenue from your blog. In that case, this article gives you a general understanding of monetization methods which are also independent of the type of blog.&lt;/p&gt;

&lt;p&gt;If you have decided which platforms to use for your publishing, it is time to create remarkable content and generate revenue. &lt;/p&gt;

&lt;p&gt;If you didn't decide on the blogging platform, I suggest you check these options: &lt;a href="https://www.cbsofyalioglu.com/blogging/best-blogging-sites/" rel="noopener noreferrer"&gt;Best Blog Building Sites&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 1: Quality Content Creation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8b98wvn7l716bl56w1yk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8b98wvn7l716bl56w1yk.jpg" alt="Quality content creation" width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The value you realize from your published content depends on several variables, the most important of which is blog traffic. The more traffic your blog receives, the more value you realize. Consider it like having a billboard on a busy street. &lt;/p&gt;

&lt;p&gt;It can be said that it will be a billboard in the desert when you publish your first post. Therefore, it is vital to promote your content through Twitter, Facebook groups, Reddit, Medium etc.&lt;/p&gt;

&lt;p&gt;But… Even though promoting your content through social media is a necessary condition, it is not a sufficient one. &lt;/p&gt;

&lt;p&gt;The most critical factor that determines your income is providing good value to your audiences. In the year 2023, content is still king.&lt;/p&gt;

&lt;p&gt;In the long run, quality always beats quantity, and blogging is a long-run process.&lt;/p&gt;

&lt;p&gt;But…&lt;/p&gt;

&lt;h3&gt;
  
  
  What does quality content mean?
&lt;/h3&gt;

&lt;p&gt;Valuable, or quality content, is content that provides significant &lt;strong&gt;benefits to readers by addressing their needs, solving their problems, answering their questions, or entertaining them in a meaningful way&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Creating valuable content should be a priority for bloggers and content creators, as it helps build trust, credibility, and loyalty among readers, leading to increased engagement, social shares, and return visits.&lt;/p&gt;

&lt;p&gt;It is a fact that all of these returns will eventually comprise your income.&lt;/p&gt;

&lt;p&gt;To provide valuable content to your readers, consider the following tips:&lt;/p&gt;

&lt;h4&gt;
  
  
  Understand your audience
&lt;/h4&gt;

&lt;h5&gt;
  
  
  Research and identify your target audience's needs, preferences, and pain points
&lt;/h5&gt;

&lt;p&gt;Create reader personas to help you better understand and address their needs through your content. &lt;/p&gt;

&lt;p&gt;Contrary to average practice, Prioritize creating high-quality, well-researched, and in-depth content rather than churning out a large volume of superficial articles.&lt;/p&gt;

&lt;p&gt;Although this strategy consumes more time, it will put you in front of thousands of bloggers in the long-run. This may grow the size of your loyal readers.&lt;/p&gt;

&lt;p&gt;One of the best ways to understand your audience is by creating user personas.&lt;/p&gt;

&lt;h6&gt;
  
  
  What is a user persona?
&lt;/h6&gt;

&lt;p&gt;A persona is a fictional representation of your ideal customers. They give a clue about how they look, what they need, and what they want. &lt;br&gt;
A user persona is a combination of all the characteristics your audiences would possess. &lt;/p&gt;

&lt;p&gt;For instance, you can clone this Notion template to see a very basic representation of &lt;a href="https://webmeister.notion.site/simple-persona-template-5616b54268934611ab30a9a09fa6732e" rel="noopener noreferrer"&gt;a simple user persona&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;In different words, It helps you to create empathy for the real people and help you to put yourself in the shoes of your readers.&lt;/p&gt;

&lt;p&gt;You can use &lt;a href="https://answerthepublic.com/" rel="noopener noreferrer"&gt;Answer The Public&lt;/a&gt; to know which questions your audience asks. &lt;/p&gt;

&lt;h5&gt;
  
  
  Be informative and educational and create easily consumable content
&lt;/h5&gt;

&lt;p&gt;Sharing your knowledge and expertise in your niche topic is not an easy task. It can be improved with lots of practice.&lt;/p&gt;

&lt;p&gt;Moreover, providing insights, tips, and actionable advice that helps your readers solve problems or improve their lives is the key point of a successful blog. &lt;/p&gt;

&lt;p&gt;Use short paragraphs and concise sentences to make your content more readable and scannable. Include visuals such as images, infographics, and videos to break up text and enhance your content's appeal. &lt;/p&gt;

&lt;p&gt;Offer step-by-step guides, tutorials, or case studies to illustrate your points.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trends.google.com/trends/?geo=US" rel="noopener noreferrer"&gt;Google Trends&lt;/a&gt; and  &lt;a href="https://explodingtopics.com/" rel="noopener noreferrer"&gt;Exploding Topics&lt;/a&gt; are useful for trendy topics. Analyze the competition of your keywords and their monthly search volume.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.researchrabbitapp.com/" rel="noopener noreferrer"&gt;Research Rabbit&lt;/a&gt; is another useful tool for research papers if your niche is an academic topic. &lt;/p&gt;

&lt;p&gt;You may also find useful browser extensions to create step-by-step guides like &lt;a href="https://www.tango.us/" rel="noopener noreferrer"&gt;Tango&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Be original, authentic and create novel content
&lt;/h5&gt;

&lt;p&gt;Create unique content that showcases your voice, perspective, and experiences. Avoiding grammatical errors is also critical for your users. Avoid rehashing or duplicating content found elsewhere. &lt;/p&gt;

&lt;p&gt;Share personal stories and anecdotes to connect with your readers and make your content relatable. &lt;/p&gt;

&lt;p&gt;If you are not a native English writer, using tools like &lt;a href="https://languagetool.org/" rel="noopener noreferrer"&gt;LanguageTool&lt;/a&gt; could help a lot.&lt;/p&gt;

&lt;h5&gt;
  
  
  Promote your content through social media and optimize it for search engines
&lt;/h5&gt;

&lt;p&gt;Hyperlinks are great. It navigates your audiences to where you want. Share a tweet and navigate your users to your money page. &lt;/p&gt;

&lt;p&gt;Implementing search engine optimization best practices is crucial for successful bloggers. Organic search traffic is the most significant source of traffic for most blogs.&lt;/p&gt;

&lt;p&gt;It brings users without marketing such as keyword research, proper use of title tags and meta descriptions, and internal and external linking, to make your content more discoverable and accessible to potential readers. &lt;/p&gt;

&lt;p&gt;Google Ads has a very useful tool called &lt;a href="https://ads.google.com/" rel="noopener noreferrer"&gt;Keywords Planner&lt;/a&gt;. Extensively use it for your keyword research. &lt;br&gt;
&lt;a href="https://buffer.com/" rel="noopener noreferrer"&gt;Buffer&lt;/a&gt; like tools allow you to publish your work to multiple channels.&lt;/p&gt;

&lt;p&gt;If you are interested, you may check the &lt;a href="https://www.cbsofyalioglu.com/productivity/content-creation-tools/" rel="noopener noreferrer"&gt;list of content creation tools&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 2: Generating Revenue
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvuvn0iexcy9o1bz62jmv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvuvn0iexcy9o1bz62jmv.jpg" alt="Generate income from your blog" width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What are the ways of earning from your blog?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Ads&lt;/li&gt;
&lt;li&gt;Affiliations&lt;/li&gt;
&lt;li&gt;Subscriptions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Income from Ads
&lt;/h3&gt;

&lt;p&gt;Ad revenue depends on site traffic, and site traffic depends on making the blog visible. Numerous platforms are eager to show ads on your blog site if your site has a considerable amount of traffic. In other words, at the very beginning of your blogging days, it is difficult to be accepted as a publisher on those ad platforms.&lt;/p&gt;

&lt;p&gt;Even though you get income for impressions, the real income comes with user interactions for ads you show. In other words, you mostly earn by the number of clicks your ads get.  &lt;/p&gt;

&lt;p&gt;The income by click depends on many factors such as purchasing power, a product that appears in ads etc… It is reasonable to get more when you show an ad to a U.S. citizen rather than a citizen of a country where its citizens have much lower income.&lt;/p&gt;

&lt;p&gt;Here, the most popular ad platforms you can apply with your blog:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://adsense.google.com/i" rel="noopener noreferrer"&gt;Google AdSense&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.mediavine.com/" rel="noopener noreferrer"&gt;Media Vine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.media.net/" rel="noopener noreferrer"&gt;Media.net&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.carbonads.net/" rel="noopener noreferrer"&gt;Carbon Ads&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Affiliate Income
&lt;/h3&gt;

&lt;h4&gt;
  
  
  What is affiliate marketing?
&lt;/h4&gt;

&lt;p&gt;One of the most used ways to get income from your content is affiliations. Basically, you review some products and link to those products.&lt;/p&gt;

&lt;p&gt;The links have special fragments which detect new coming users that are acquired from your platform. &lt;/p&gt;

&lt;p&gt;In this way, honest reviews will be rewarded as growing audiences. Growing audiences increase your visibility and so your income. &lt;/p&gt;

&lt;p&gt;YouTube video reviews and other product reviews are examples of affiliation type of income. Those video links generally include Amazon affiliate links.&lt;/p&gt;

&lt;p&gt;In this type of income, in other words, partnership, the affiliate (you) earns a commission for generating sales, leads, or other desired actions for the merchant through their unique referral link.&lt;/p&gt;

&lt;p&gt;Let me draw a sample process for an affiliate marketing process. &lt;/p&gt;

&lt;h4&gt;
  
  
  How does affiliate marketing work?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Affiliates sign up for an affiliate program&lt;/strong&gt;: Affiliates join an affiliate network or an individual company's affiliate program that offers products or services relevant to their niche.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Affiliates receive unique referral links&lt;/strong&gt;: Once they've joined the program, affiliates receive unique referral links, which they can use to promote the merchant's products or services on their websites, blogs, social media platforms, or email campaigns.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Affiliates promote the products or services&lt;/strong&gt;: Affiliates create content, such as blog posts, reviews, tutorials, or social media posts, to promote the merchant's products or services using their referral links.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Customers click on the referral links&lt;/strong&gt;: When potential customers click on an affiliate's referral link and make a purchase or complete another desired action (e.g., signing up for a newsletter), the transaction is tracked and attributed to the affiliate.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Affiliates earn a commission&lt;/strong&gt;: Based on the agreed-upon commission structure, affiliates earn a percentage of the sale or a fixed amount for each lead or action generated through their referral links.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Affiliate marketing benefits both the merchant and the affiliate. Merchants gain access to a wider audience and only pay for results, while affiliates can generate passive income by promoting products or services they believe in.&lt;/p&gt;

&lt;p&gt;The most popular affiliate marketing program, affiliation platform, and curated lists are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://affiliate-program.amazon.com/" rel="noopener noreferrer"&gt;Amazon Associates&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://partnernetwork.ebay.com/" rel="noopener noreferrer"&gt;eBay Partner Network&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://partnerstack.com" rel="noopener noreferrer"&gt;Partner Stack&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bestaffiliateprograms.io/" rel="noopener noreferrer"&gt;Best Affiliate Programs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Income from Subscriptions
&lt;/h3&gt;

&lt;p&gt;We are living in a micro-creators era. If you believe that you have novel things to share, then subscription-based income would be a suitable option. &lt;/p&gt;

&lt;p&gt;When you specialize in your niche, you'll have a laser-targeted audience. This not only allows you to earn by subscriptions, but also with targeted ads.&lt;/p&gt;

&lt;p&gt;Furthermore, if you are writing on a profitable niche, then it means you'll have predictable income streams which is a must for full-time blogging.&lt;/p&gt;

&lt;p&gt;Putting your content behind a paywall is getting more popular in these days. &lt;/p&gt;

&lt;p&gt;Moreover, there are platforms to provide you with all the things you need, and they just cut a small portion of your monthly subscription income.&lt;/p&gt;

&lt;p&gt;If you are planning to earn by this way, the content you create would generally be blog posts or email newsletters. &lt;/p&gt;

&lt;p&gt;The most popular platforms to earn income by paywall are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ghost.org/" rel="noopener noreferrer"&gt;Ghost&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://substack.com/" rel="noopener noreferrer"&gt;Substack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://convertkit.com/" rel="noopener noreferrer"&gt;ConvertKit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.patreon.com/" rel="noopener noreferrer"&gt;Patreon&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you charge your audience with a relatively low price, it would be important to treat them well and provide them with unique and valuable content.&lt;/p&gt;

&lt;p&gt;As a bonus, here is another tool to add a membership feature to your blog.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.memberstack.com/" rel="noopener noreferrer"&gt;Memberstack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.memberspace.com/" rel="noopener noreferrer"&gt;Member Space&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As I said before, generating revenue is a long-run process. It is better to improve it iteratively. &lt;/p&gt;

&lt;p&gt;Typically, it is unclear that which action causes what due to the nature of abundance of factors. Thus, the iterative process makes you aware of your decisions.&lt;/p&gt;

</description>
      <category>writing</category>
      <category>tooling</category>
      <category>devjournal</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Exploring SolidJS - The Reactive Primitives (1)</title>
      <dc:creator>Can Burak Sofyalioglu</dc:creator>
      <pubDate>Wed, 06 Oct 2021 15:14:37 +0000</pubDate>
      <link>https://dev.to/canburaks/introduction-to-solidjs-and-reactive-primitives-1o6h</link>
      <guid>https://dev.to/canburaks/introduction-to-solidjs-and-reactive-primitives-1o6h</guid>
      <description>&lt;p&gt;SolidJS is a true reactive library that allows you to use JSX for your frontend projects. In this blog post, I'll share my first impressions on the &lt;em&gt;SolidJS UI library&lt;/em&gt; and its reactive primitives. The original article can be found here: &lt;a href="https://www.cbsofyalioglu.com/code/solidjs-and-reactive-primitives/" rel="noopener noreferrer"&gt;"Introduction to SolidJS"&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;I like the concept of reactivity when building frontend projects. Despite its name, React is not a truly reactive library. I also like the Svelte because of its reactivity. I previously wrote a tutorial about &lt;a href="https://www.cbsofyalioglu.com/post/django-and-modern-js-libraries-svelte/" rel="noopener noreferrer"&gt;Django and Svelte&lt;/a&gt;. However, I realized that writing projects with Svelte are not so scalable like React projects because React and JSX provide great modularity.&lt;/p&gt;

&lt;p&gt;However, SolidJS offers the best of both worlds.&lt;/p&gt;

&lt;h4&gt;
  
  
  Shameless promotion
&lt;/h4&gt;

&lt;p&gt;I'm currently not planning to do a real project with SolidJS until I become fluent in it. Currently, I'm building an e-commerce store, &lt;a href="https://www.filizguvenlik.com.tr/" rel="noopener noreferrer"&gt;İzmir Güvenlik Kamerası&lt;/a&gt; (Security Camera Systems) and &lt;a href="https://www.opendigitalgallery.com" rel="noopener noreferrer"&gt;Fine Art Print Store&lt;/a&gt;, and I would work with SolidJS for small projects. You can also check &lt;a href="https://www.cbsofyalioglu.com/blogging/best-blogging-sites/" rel="noopener noreferrer"&gt;the list of blogging sites&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;OK, let's dive into the topic. Before reviewing SolidJS, it is better to get familiar with the concepts. I'll shortly talk about &lt;em&gt;What are reactive systems?&lt;/em&gt; and &lt;em&gt;what are those reactive primitives?&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are reactive systems?
&lt;/h3&gt;

&lt;p&gt;According to &lt;a href="https://www.reactivemanifesto.org/" rel="noopener noreferrer"&gt;The Reactive Manifesto&lt;/a&gt;,  reactive systems are responsive, resilient, elastic, and message-driven. We call these Reactive Systems.&lt;/p&gt;

&lt;p&gt;Systems built as Reactive Systems are more flexible, loosely coupled, and scalable. This makes them easier to develop and amenable to change.&lt;/p&gt;

&lt;p&gt;They are significantly more tolerant of failure, and when failure does occur they meet it with elegance rather than a disaster.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Reactive Systems do
&lt;/h3&gt;

&lt;p&gt;There are numerous reactive libraries in many programming languages like SolidJS in JS.&lt;/p&gt;

&lt;p&gt;Reactive systems must react to data changes. Generally, these changes occur when new data is received or the old one is updated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Characteristics of Reactive Programming
&lt;/h3&gt;

&lt;p&gt;The reactive manifesto defines the key characteristics of it, like that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Responsive: Those systems respond on time. Here, of course, timely will differ depending upon the application and domain.&lt;/li&gt;
&lt;li&gt;Resilient. Reactive systems stay responsive in the face of failure.&lt;/li&gt;
&lt;li&gt;Elastic. As the workload grows, the system should continue to be responsive.&lt;/li&gt;
&lt;li&gt;Message Driven. Information is exchanged between elements of a reactive system using messages. This ensures loose coupling, isolation, and location transparency between these components.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What are the reactive primitives of SolidJS?
&lt;/h3&gt;

&lt;p&gt;In  SolidJS, the author of the library &lt;a href="https://dev.to/ryansolid/a-hands-on-introduction-to-fine-grained-reactivity-3ndf"&gt;Ryan Carniato&lt;/a&gt; defines them as much like network primitives rather than JavaScript's primitives.  As you will see later, Signals are basically observables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation of SolidJS Template
&lt;/h2&gt;

&lt;p&gt;You can easily install a starter &lt;em&gt;SolidJS&lt;/em&gt; template with degit. You can also check other official templates from here: &lt;a href="https://github.com/solidjs/templates" rel="noopener noreferrer"&gt;SolidJS Official Templates&lt;/a&gt;. I prefer a JS template rather than a TypeScript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Javascript template&lt;/span&gt;
npx degit solidjs/templates/js solid
&lt;span class="nb"&gt;cd &lt;/span&gt;solid

&lt;span class="c"&gt;# install the dependencies&lt;/span&gt;
yarn &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The template uses Vite as a development tool. Also, this is the first time I have used Vite. Vite is so super fast that I had to check twice that if it reloaded the rendered page. When the installation is done, the project directory looks like that:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fwp-content%2Fuploads%2F2021%2F09%2Fsolidjs-starter-template-direcotry.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fwp-content%2Fuploads%2F2021%2F09%2Fsolidjs-starter-template-direcotry.webp" alt="SolidJS directory" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is very similar to React in many cases. I will check some component rendering processes'.&lt;/p&gt;

&lt;p&gt;In this post, I am going to explore SolidJS in an introductory manner. I'll also create a Counter component first and check its re-render process.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Reactive JavaScript Library: SolidJS
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A) Reactive primitives: createSignal
&lt;/h3&gt;

&lt;p&gt;SolidJS has some basic reactive primitives, and Signals are one of them. It looks like it is a "useState" alternative of React Hooks. One difference to the "useState" hook is that a Signal returns two functions: a getter and a setter. Here is the official example of creating a signal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;createSignal function takes an initial value and returns an array with an access and update function.&lt;/li&gt;
&lt;li&gt;You should execute the getter function (access) in order to get the value.&lt;/li&gt;
&lt;li&gt;You can pass function to update function (set function). In this function, you can access the previous state also.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// read value&lt;/span&gt;
&lt;span class="nf"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// set value&lt;/span&gt;
&lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// set value with a function setter&lt;/span&gt;
&lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prev&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;prev&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fwp-content%2Fuploads%2F2021%2F09%2FSolidJS-Create-Signal-Component-2-1270x762.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fwp-content%2Fuploads%2F2021%2F09%2FSolidJS-Create-Signal-Component-2-1270x762.webp" alt="Solid JS createSignal" width="800" height="400"&gt;&lt;/a&gt;&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createSignal&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;solid-js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;initial&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initial&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Notice the usage of count! It is a function*/&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;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;h4&gt;
  
  
  1) Component State Access and Update
&lt;/h4&gt;

&lt;p&gt;SolidJS call the state elements as signals. However, I prefer to use state rather than signal.  Let's make a Counter component within the App component. Fill the &lt;code&gt;App.jsx&lt;/code&gt; file as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fwp-content%2Fuploads%2F2021%2F09%2FSolidJS-Component-State-Change-1-1270x681.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fwp-content%2Fuploads%2F2021%2F09%2FSolidJS-Component-State-Change-1-1270x681.webp" alt="SolidJS change state" width="" height=""&gt;&lt;/a&gt;&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;import&lt;/span&gt; &lt;span class="nx"&gt;logo&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;./logo.svg&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="nx"&gt;styles&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;./App.module.css&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;createSignal&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;solid-js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/**
     * CHECKPOINT
     * if the App component renders
     * it will print to console
     */&lt;/span&gt;
    &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App component rendered.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;logo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;logo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nx"&gt;Edit&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/code&amp;gt; and save to reload&lt;/span&gt;&lt;span class="err"&gt;.
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;
                    &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://github.com/solidjs/solid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                    &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_blank&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                    &lt;span class="nx"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;noopener noreferrer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nx"&gt;Learn&lt;/span&gt; &lt;span class="nx"&gt;Solid&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/a&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/header&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;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;function&lt;/span&gt; &lt;span class="nf"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;initial&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initial&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * CHECKPOINT
     * if the Counter component renders. it will print to console.
     * Also, I put another print statement for the count function.
     */&lt;/span&gt;
    &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Counter component rendered.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Counter component count value: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auto&lt;/span&gt;&lt;span class="dl"&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="cm"&gt;/* Notice the usage of count! It is a function*/&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&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="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c&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;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Increase&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&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="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c&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;c&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Decrease&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's check the browser and the first render of SolidJS. As you see, there is no extra component render. If it were React, we should have seen many times "Counter component rendered" text on the console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fwp-content%2Fuploads%2F2021%2F09%2Fsolidjs-reactivity.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fwp-content%2Fuploads%2F2021%2F09%2Fsolidjs-reactivity.gif" alt="SolidJS's Reactivity" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  2) Parent Component State Access and Update
&lt;/h4&gt;

&lt;p&gt;Let's make it further and pass the signal setter to the child component and use it from there. Change both App and Counter components like that:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fwp-content%2Fuploads%2F2021%2F09%2FSolidJS-Changing-State-of-the-Parent-Component-1-1270x681.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fwp-content%2Fuploads%2F2021%2F09%2FSolidJS-Changing-State-of-the-Parent-Component-1-1270x681.webp" alt="SolidJS change parent state" width="800" height="400"&gt;&lt;/a&gt;&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/**
     * CHECKPOINT
     * if the App component renders
     * it will print to console
     */&lt;/span&gt;
    &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;appCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAppCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App: count: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;appCount&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App component rendered.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;logo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;logo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nx"&gt;Edit&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/code&amp;gt; and save to reload&lt;/span&gt;&lt;span class="err"&gt;.
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;
                    &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://github.com/solidjs/solid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                    &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_blank&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                    &lt;span class="nx"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;noopener noreferrer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nx"&gt;Learn&lt;/span&gt; &lt;span class="nx"&gt;Solid&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/a&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* NEW */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;appCount&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Counter&lt;/span&gt;
                    &lt;span class="nx"&gt;initial&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;appCount&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
                    &lt;span class="nx"&gt;setAppCount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setAppCount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// NEW&lt;/span&gt;
                &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/header&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;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;function&lt;/span&gt; &lt;span class="nf"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAppCount&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initial&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * CHECKPOINT
     * if the Counter component renders. it will print to console.
     * Also, I put another print statement for the count function.
     */&lt;/span&gt;
    &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Counter component rendered.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Counter component count value: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auto&lt;/span&gt;&lt;span class="dl"&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="cm"&gt;/* Notice the usage of count! It is a function*/&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&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="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c&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;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Increase&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&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="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c&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;c&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Decrease&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;hr&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;

            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Buttons changes the signal value of its parent component */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&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="nf"&gt;setAppCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c&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;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nx"&gt;AppCount&lt;/span&gt; &lt;span class="nx"&gt;Increase&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&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="nf"&gt;setAppCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c&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;c&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nx"&gt;AppCount&lt;/span&gt; &lt;span class="nx"&gt;Decrease&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;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;As you can see, there is not any component re-rendering. It's awesome.🥳&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fwp-content%2Fuploads%2F2021%2F09%2Fsolidjs-change-state-of-parent-component.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fwp-content%2Fuploads%2F2021%2F09%2Fsolidjs-change-state-of-parent-component.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  B) Reactive primitives: createEffect
&lt;/h3&gt;

&lt;p&gt;As you might expect, &lt;code&gt;createEffect&lt;/code&gt; is the equivalent of the &lt;code&gt;useEffect&lt;/code&gt; hook in React. The official explanation and example are as follows:&lt;/p&gt;

&lt;p&gt;Creates a new computation that automatically tracks dependencies and runs after each render where a dependency has changed. Ideal for using&amp;nbsp;&lt;code&gt;ref&lt;/code&gt;s and managing other side effects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [a, setA] = createSignal(initialValue);

// effect that depends on signal `a`
createEffect(() =&amp;gt; doSideEffect(a()));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's time to play with this function. The official example returns a function (doSideEffect) that takes state value as its argument. Even if the returning function doesn't take the state value as its argument but as an inner value, the &lt;code&gt;createEffect&lt;/code&gt; function successfully makes a side-effect.&lt;/p&gt;

&lt;p&gt;Let's add those to the &lt;code&gt;App&lt;/code&gt; component.&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="c1"&gt;// The function creates side-effect&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;changeTitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&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="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`#App: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// effect that depends on signal `a`&lt;/span&gt;
    &lt;span class="nf"&gt;createEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;changeTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;appCount&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We created a function (changeTitle) responsible for the side-effect. It takes a value and changes the document title according to that. It also takes the state value of the App component which is appCount. Your app component should look like this.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;appCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAppCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App: count: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;appCount&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App component rendered.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// The function creates side-effect&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;changeTitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&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="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`#App: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// effect that depends on signal `a`&lt;/span&gt;
    &lt;span class="nf"&gt;createEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;changeTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;appCount&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;logo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;logo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nx"&gt;Edit&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/code&amp;gt; and save to reload&lt;/span&gt;&lt;span class="err"&gt;.
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;
                    &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://github.com/solidjs/solid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                    &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_blank&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                    &lt;span class="nx"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;noopener noreferrer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nx"&gt;Learn&lt;/span&gt; &lt;span class="nx"&gt;Solid&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/a&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* NEW */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;appCount&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Counter&lt;/span&gt;
                    &lt;span class="nx"&gt;initial&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;appCount&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
                    &lt;span class="nx"&gt;setAppCount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setAppCount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// NEW&lt;/span&gt;
                &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/header&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;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;You'll easily differentiate that when the app renders the first time, the document title was &lt;code&gt;App: 0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After, when I clicked and increased the appCount value, the document title also changed to the corresponding value. You'll also notice that there will be no component re-render.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fwp-content%2Fuploads%2F2021%2F09%2Fsolidjs-create-effect.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fwp-content%2Fuploads%2F2021%2F09%2Fsolidjs-create-effect.gif" alt="SolidJS createEffect" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  C) Reactive primitives: createMemo
&lt;/h3&gt;

&lt;p&gt;This reactive primitive returns a function that returns a read-only derived signal. Its value is recalculated whenever dependencies are updated. &lt;code&gt;createMemo&lt;/code&gt; primitive is the equivalent of &lt;code&gt;useMemo&lt;/code&gt; hook.&lt;/p&gt;

&lt;p&gt;Edt the App component according to those:&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="c1"&gt;// Add those to the App component&lt;/span&gt;
    &lt;span class="c1"&gt;// It recalculate the value whenever the dependencies are updates.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;makeDouble&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&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;val&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doubleCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createMemo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;makeDouble&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;appCount&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;doubleCount &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;doubleCount&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, update the content of the App component. By doing this, we can see the &lt;code&gt;doubleCount&lt;/code&gt; signal in work. You can also check the code location from the image below.&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Double&lt;/span&gt; &lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;doubleCount&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fwp-content%2Fuploads%2F2021%2F09%2FSolidJS-createMemo.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fwp-content%2Fuploads%2F2021%2F09%2FSolidJS-createMemo.gif" alt="SolidJS createMemo function" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  D) Reactive primitives: createResource
&lt;/h3&gt;

&lt;p&gt;This function creates a signal that is responsible for async requests. The official explanation and example are here:&lt;/p&gt;

&lt;p&gt;Creates a signal that can manage async requests. The&amp;nbsp;&lt;code&gt;fetcher&lt;/code&gt;&amp;nbsp;is an async function that accepts the return value of the&amp;nbsp;source&amp;nbsp;if provided, and returns a Promise whose resolved value is set in the resource. The fetcher is not reactive, so use the optional first argument if you want it to run more than once. If the source resolves to false, null, or undefined will not fetch. Also, &lt;code&gt;loading&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;error&lt;/code&gt;&amp;nbsp;are reactive getters and can be tracked.&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;mutate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;refetch&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// read value&lt;/span&gt;
&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// check if loading&lt;/span&gt;
&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// check if errored&lt;/span&gt;
&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// directly set value without creating promise&lt;/span&gt;
&lt;span class="nf"&gt;mutate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;optimisticValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// refetch last request just because&lt;/span&gt;
&lt;span class="nf"&gt;refetch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My first impressions of SolidJS are amazing. Up to this point, there is no overhead that you always face with React. I will be watching the development of SolidJS with interest.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>react</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Awesome Content Creation Tools</title>
      <dc:creator>Can Burak Sofyalioglu</dc:creator>
      <pubDate>Sun, 19 Sep 2021 19:00:13 +0000</pubDate>
      <link>https://dev.to/canburaks/awesome-content-creation-tools-2705</link>
      <guid>https://dev.to/canburaks/awesome-content-creation-tools-2705</guid>
      <description>&lt;p&gt;(Note: This post was updated on 15 December 2021)&lt;/p&gt;

&lt;p&gt;Creating quality content is a demanding and complex process. It is better to have a wide range of applications in your toolbox. Even though there is no one solution to fix it all, one can increase your productivity and save you time. Considering this, I will share my favorite content creation tools. These are both written content and visual content.&lt;/p&gt;

&lt;p&gt;You can also check the original post for updated resources: &lt;a href="https://www.cbsofyalioglu.com/productivity/content-creation-tools/" rel="noopener noreferrer"&gt;Content creation tools&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Great Content Creation Tools
&lt;/h2&gt;

&lt;p&gt;Using the appropriate tools can make &lt;strong&gt;content creation&lt;/strong&gt; so much easier and more successful. After the introduction, it is time to share the &lt;strong&gt;useful content marketers tools&lt;/strong&gt;. I hope those tools will make you more productive during your content creation process. Here are the super-useful &lt;strong&gt;content development tools&lt;/strong&gt;. You may also want to check &lt;a href="https://www.cbsofyalioglu.com/blogging/best-blogging-sites/" rel="noopener noreferrer"&gt;the ultimate list of blogging sites which includes more than 50 publishing sites&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Content Research Tools
&lt;/h3&gt;

&lt;p&gt;Research plays a huge role in what your readers think of your business, products, services, and website. Content creation can be as easy as digging up information or digging around on the internet.&lt;/p&gt;

&lt;p&gt;In this section, I’ll take you through some of the most useful tools out there so that you can get started on creating great content for your blog or website.&lt;/p&gt;

&lt;p&gt;Content research tools are essential when creating content because the internet is vast, and there’s hardly any limit to what you can find out about a subject matter.&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://search.carrot2.org/"&gt;Carrot&lt;/a&gt;: The short demo you watched above is from Carrot. It organizes your search results into topics. It clusters, categorizes and show them in different formats.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.occamm.com/"&gt;Occamm&lt;/a&gt;: Occam is another SERP organizer. It refines your search result and allows you to select based on the tags.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://entityexplorer.com/"&gt;Entity Explorer&lt;/a&gt;: Entity explorer finds related entities in a graph map. It makes easier to see connections between entities.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.researchrabbitapp.com/"&gt;Research Rabbit&lt;/a&gt;: This is one of my favorite research tools. A research and relationship visualization tool.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.semanticscholar.org/"&gt;Semantic Scholar&lt;/a&gt;: A free, AI-powered research tool for scientific literature.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://paperpanda.app/"&gt;Paper Panda&lt;/a&gt; and &lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://unpaywall.org/"&gt;Unpaywall&lt;/a&gt;: They both allow you to access millions of academic papers and researches for free.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://trends.google.com/trends/?geo=US"&gt;Google Trends&lt;/a&gt;: You probably know this tool. Google Trends shows the popularity of a term among Google Searchers.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://answerthepublic.com/"&gt;Answer The Public&lt;/a&gt;: Another useful tool to research people’s questions.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://miro.com/"&gt;Miro&lt;/a&gt;: Miro is actually a whiteboard app. It allows collaboratively working on your content ideas. There are plenty of project management frameworks that make your ideation process easier.&lt;/li&gt;
&lt;/ul&gt;





&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fposts%2Fcontent-saving-tools.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fposts%2Fcontent-saving-tools.webp" alt="Content saving tools" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Content Management Tools
&lt;/h3&gt;

&lt;p&gt;You need comprehensive document and knowledge management tools to get the most out of your content research. You can clip, capture, and annotate the content with these creation tools. There are a bunch of apps that you can use for this purpose. Most of those tools have browser extensions.&lt;/p&gt;

&lt;p&gt;Annotating is an excellent way to get your creative juices flowing. It allows you to take notes on what you’re reading or thinking, making it easy to revise later.&lt;/p&gt;

&lt;p&gt;I love using various notes apps or knowledge-saving tools and would recommend them to anyone looking to improve their writing skills.&lt;/p&gt;

&lt;p&gt;These content creation tools allow anyone to collect ideas, quotes, share knowledge and other content in an easy and intuitive way. These content saving/management tools save you time looking for relevant information while creating your blog posts and videos. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://bloggingplatforms.app/blog/best-free-platforms-for-blogging" rel="noopener noreferrer"&gt;Free Blogging Platforms&lt;/a&gt;: An article that mentions the best free blogging platforms.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://getpolarized.io/"&gt;Polar&lt;/a&gt;: You can manage and save your content from PDFs, EPUBs, and web pages in one place. It allows tagging, shows reading progress, and shows detailed document information.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.weavatools.com/"&gt;Weava&lt;/a&gt;: You can highlight, annotate, and organize the content in one place.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://getmemex.com/"&gt;Memex&lt;/a&gt;: It is a bookmark manager. It is an open-source tool that allows you to annotate, organize and share.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://justclip.co/"&gt;JustClip&lt;/a&gt;: A tool for collecting content that is suitable for individuals and teams. You can capture information and annotate content. You can easily build your knowledge connections and stay organized. &lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://wakelet.com/"&gt;Wakelet&lt;/a&gt;: Wakelet is a tool for collecting and curating content. It is particularly used by the education industry.It is one of my favorite tools. You can create a  &lt;a rel="nofollow noopener noreferrer" href="https://wakelet.com/wake/pdGmNjZditc00ivmmZscZ"&gt;Wakelet profile and a collection&lt;/a&gt; and publish your curated lists in various formats.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://getliner.com/en"&gt;Liner&lt;/a&gt;: Liner is another productivity tool that helps you find and learn reliable information faster. You can highlight web pages and PDF files. It suggests trusted content from other Liner users. &lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://obsidian.md/"&gt;Obsidian MD&lt;/a&gt;: It is also my favorite tool that I dumped every piece of note into it. It is offline-first meaning that your notes stay on your PC. It is a markdown editor and has a wiki-style backlink feature with built-in graph view options. There are other popular options for an alternative to Obsidian are &lt;a rel="nofollow noopener noreferrer" href="https://www.notion.so/"&gt;Notion&lt;/a&gt;, &lt;a rel="nofollow noopener noreferrer" href="https://nimbusweb.me/"&gt;Nimbus Note&lt;/a&gt;, and &lt;a rel="nofollow noopener noreferrer" href="https://roamresearch.com/"&gt;Roam Research&lt;/a&gt; and &lt;a href="https://monograph.notesnook.com/0eb6c655076e1a720f2a9a43" rel="noopener noreferrer"&gt;Notesnook&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://raindrop.io/"&gt;Raindrop&lt;/a&gt;: Raindrop is one of the best bookmark manager in the market. It has cross-platform apps/extensions, intuitive user-interface and a generous plan.&lt;/li&gt;
&lt;/ul&gt;





&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fposts%2Freadability-checker-tools.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fposts%2Freadability-checker-tools.webp" alt="Readability checker tools" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Readability Score Tools
&lt;/h3&gt;

&lt;p&gt;Readability is the ease with which a reader can understand a written text.&lt;/p&gt;

&lt;p&gt;It is an essential parameter for the user as well as for SEO.&lt;/p&gt;

&lt;p&gt;It is also known that artificial intelligence, and thus the Google crawler, is better at distinguishing short sentences than long ones.&lt;/p&gt;

&lt;p&gt;As a result, short sentences are easier to understand for both the reader and the Googlebot. Of course, you have to consider your readers.&lt;/p&gt;

&lt;p&gt;There will be no problem for them in writing complex articles on relatively tricky subjects if your readers are experts on your case.&lt;/p&gt;

&lt;p&gt;The content creation software in this section are applications that measure at least which age group can understand your articles. It is called &lt;em&gt;the readability score&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;There are some popular formulas and metrics calculating the readability score of your text.&lt;/p&gt;

&lt;p&gt;However, creating short and concise content can be hard to create. With the tools below, you can make your copy more readable and quickly shorten sentences. Run your written copy through the web app and you’ll see the opportunities to make it better for your readers in seconds.&lt;/p&gt;

&lt;p&gt;It should also be noted that most of them are either free or freemium with a generous plan.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://hemingwayapp.com/"&gt;Hemingway Editor&lt;/a&gt;: It is one of the most well-known content readability improvers. This popular readability tool judges the “grade level” of your text using the &lt;a rel="nofollow noopener noreferrer" href="https://en.wikipedia.org/wiki/Automated_readability_index"&gt;Automated Readability Index&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://typewipe.com/app"&gt;Typewipe&lt;/a&gt;: This helpful content creation program offers both readability analysis and helps you improve your content according to your keyword.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.twinword.com/writer/"&gt;Twinword Writer&lt;/a&gt;: Twinword Writer is a tool that analyzes the tone of your content. It highlights the words that have negative and positive impacts on the tone of your text.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Grammar and Punctuation Checker Tools
&lt;/h3&gt;

&lt;p&gt;The content creation tools in this section are handy for creating content in English. Those can be classified as &lt;strong&gt;grammar correction and punctuation checker tools&lt;/strong&gt;. Using these tools will help you write better content about topics that matter to you.&lt;br&gt; The tools in this section are awesome &lt;em&gt;grammar and punctuation checker&lt;/em&gt; tools. Those will help you finish your sentences, spot typos, and get the words right no matter how much time you have.&lt;br&gt; The most popular grammar tool on this list is Grammarly. It offers a good user experience along with rich suggestions.&lt;/p&gt;

&lt;p&gt;However, it should also be noted that Grammarly doesn’t improve its tool and features. There are various alternatives to that provide different writing features that Grammarly doesn’t provide.&lt;/p&gt;

&lt;p&gt;You can also read The &lt;a href="https://bloggingplatforms.app/blog/best-grammar-tools" rel="noopener noreferrer"&gt;Best Grammar Tools&lt;/a&gt; article, which reviews different tools for this purpose.&lt;/p&gt;

&lt;p&gt;Here are the best grammar and punctuation checker tools.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://app.grammarly.com/"&gt;Grammarly&lt;/a&gt;: It  is one of the most well-known grammar tools. Grammarly is the best tool for this task. It has a really intuitive interface and a lot of fun features. It has a desktop and mobile application. Those apps exist both for macOS and Windows.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://linguix.com/"&gt;Linguix&lt;/a&gt;: Another Grammarly alternative, this English content creation assistant also stands out with its paraphrase feature.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://prowritingaid.com/"&gt;ProWritingAid&lt;/a&gt;: Although this content creation software does not offer as good a user experience as Grammarly and Linguix, it has much more advanced features.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.atomicreach.com/atomic-ai-editor"&gt;Atomic Editor&lt;/a&gt;: It is an AI-assisted editor that boosts your writing productivity.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.slickwrite.com/"&gt;SlickWrite&lt;/a&gt;: A tool that shows grammatical corrections and useful statistics.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://ludwig.guru/"&gt;Ludwig&lt;/a&gt;: A search engine for sentences. You can find your sentence in the best contexts, get definitions, synonyms, and examples. Also, you can paraphrase your sentence.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.gingersoftware.com/"&gt;Ginger&lt;/a&gt;: Another Grammarly alternative tool that helps you correct grammar and punctuation.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://writer.com/"&gt;Writer&lt;/a&gt;: I just discovered the app. First, it has a great design. Moreover, Writer provides many useful features comparing its competitors like a more customizable style guide and a bunch of many other things. It also has a free plan. You can use its web app, browser extension, or outlook app.&lt;/li&gt;
&lt;/ul&gt;





&lt;h3&gt;
  
  
  Search Engine Optimized Content Creation Tools
&lt;/h3&gt;

&lt;p&gt;It is not easy to find both budget-friendly and skilled tools. Of course, I’m speaking particularly about marketing tools. Anyway, I’ll share my relatively budget-friendly and search-engine-optimized content creation tools.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://copywritely.com/"&gt;SEO Content Analyzer&lt;/a&gt;: It has a bunch of tools for copywriting.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.frase.io/"&gt;Frase&lt;/a&gt;: This is one of my favorite tools. An AI-based content creation tool. Moreover, advanced paraphrasing and question-based features.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.canirank.com/"&gt;CanIRank&lt;/a&gt;: My other favorite SEO content tool that optimizes your content for search engines. When the first analysis is complete, it shows pretty useful keyword opportunities. &lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://inkforall.com/"&gt;Ink&lt;/a&gt;: Another SEO web content writing editing tool that you can download.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fposts%2Fvisual-content-creation-tools.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fposts%2Fvisual-content-creation-tools.webp" alt="Visual content creation tools" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual Content Creation Tools
&lt;/h3&gt;

&lt;p&gt;I don’t remember who said it but it is true: “If content is king, then design is queen”. Whether you are creating visual content or written content, visually appealing content is preferable to the other. You can easily find the visual content creation tools you need such as:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
        Image Creation Tools/ Social Media Tools
    &lt;/li&gt;
    &lt;li&gt;Video Creation Tools&lt;/li&gt;
    &lt;li&gt;
        Infographic Creation Tools
    &lt;/li&gt;
    &lt;li&gt;
        Presentation Creation Tools
    &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are more interested in visual design resources, you can check my other curated list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.cbsofyalioglu.com/design/free-design-resources/" rel="noopener noreferrer"&gt;Free design resources&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s start our list of digital content creation with some tools focused on creating and editing visual content elements.&lt;/p&gt;

&lt;h4&gt;
  
  
  Image creation/editing tools
&lt;/h4&gt;

&lt;p&gt;There are a lot of free image editing tools out there. Some offer advanced editing features and others are more casual apps. But if you’re looking for a basic set of image editing tools that can help you get your job done, then here are some of our favorites.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://figma.com/"&gt;Figma&lt;/a&gt;: Oh great Figma. It is one of the greatest apps of the decade.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.canva.com/"&gt;Canva&lt;/a&gt;: Canva is the most popular and the most used image creation tool. It has both free and premium plans. If you need quick visual content for your social media marketing operations, Canva is one of the best design tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are also many image tools similar to Canva. Those are- &lt;a rel="nofollow noopener noreferrer" href="https://crello.com/"&gt;Crello&lt;/a&gt;,- &lt;a rel="nofollow noopener noreferrer" href="https://www.artify.co/"&gt;Artify&lt;/a&gt;,- &lt;a rel="nofollow noopener noreferrer" href="https://projector.com/"&gt;Projector&lt;/a&gt;,- &lt;a rel="nofollow noopener noreferrer" href="https://www.taler.app/"&gt;Taler&lt;/a&gt;,- &lt;a rel="nofollow noopener noreferrer" href="https://designs.ai/en"&gt;Design AI&lt;/a&gt;, etc.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.photopea.com/"&gt;Photopea&lt;/a&gt; is one of my favorite tools. It is a minified version of photoshop and it is working on a browser.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.remove.bg/"&gt;Remove.bg&lt;/a&gt; and- &lt;a rel="nofollow noopener noreferrer" href="https://www.erase.bg/en/"&gt;Erase.bg&lt;/a&gt;: A well-known background remover. You can extract people from an image.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Presentation tools
&lt;/h4&gt;

&lt;p&gt;Presentations are the core engine of any persuasive speaker. They establish credibility, inspire others, and move audiences emotionally. That’s why the first step in any persuasive presentation is to select the right tools.&lt;/p&gt;

&lt;p&gt;Presentations are a fundamental tool for any professional, whether they want to build a reputation or just sell products.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://pitch.com/"&gt;Pitch&lt;/a&gt;: This presentation creation tool allows you to collaboratively create your design asset.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://ludus.one/"&gt;Ludus&lt;/a&gt;: It is a collaborative presentation tool for creative teams&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://ludus.one/"&gt;Premast Plus&lt;/a&gt;: You can use its professional templates to design better presentations and with a faster way. Even if you don’t have any design experience. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fposts%2Finfographic-tools.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fposts%2Finfographic-tools.webp" alt="Infographic tools" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Infographic tools
&lt;/h4&gt;

&lt;p&gt;A well-designed infographic can go a long way towards convincing people to click through from a website or social media channel. Infographics are powerful, flexible, and can be used to achieve a wide range of results.&lt;/p&gt;

&lt;p&gt;They’re an effective tool for getting immediate attention – without creating an overwhelming feeling. If it is done correctly, infographics can be a backlink magnet.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.visme.co/"&gt;Visme&lt;/a&gt;: Visme is an online tool that allows you to easily create infographics. Those are very useful for visual explanations and building backlinks.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://infogram.com/"&gt;Infogram&lt;/a&gt;: Infogram is a visual creation tool that allows you to create infographics and visual stories with data.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://piktochart.com/"&gt;Piktochart&lt;/a&gt;: Piktochart is another super functional tool for the visual content creation process. It helps you to make gorgeous infographics, presentations, and reports.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://venngage.com/"&gt;Venngage&lt;/a&gt;: An infographic design solution.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://graficto.com/"&gt;Graficto&lt;/a&gt;: Graficto is an infographic maker tool that is recently launched&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fposts%2Fvideo-creation-tools.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fposts%2Fvideo-creation-tools.webp" alt="Video content creation tools" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Video creation tools
&lt;/h4&gt;

&lt;p&gt;Video content is consumed super-fast compared to written one. Therefore, it is widely popular among the mass. Having a useful instrument will definitely make your life easier.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel="nofollow noopener noreferrer" href="https://animoto.com/"&gt;Animoto&lt;/a&gt;: Animoto is a video creation tool with a drag-and-drop interface. It has templates that allows you start with pre-made graphics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel="nofollow noopener noreferrer" href="https://biteable.com/"&gt;Biteable&lt;/a&gt;: One of the favorite video creation tools of content marketers. Express any concept. Personalize colors to match your brand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel="nofollow noopener noreferrer" href="https://www.renderforest.com/"&gt;RenderForest&lt;/a&gt;: Another tools for creating video content.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel="nofollow noopener noreferrer" href="https://runwayml.com/sequel/"&gt;Runway ML&lt;/a&gt;: This tool is literally amazing. However, it has a steep learning curve because Runway has many features that use machine learning.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel="nofollow noopener noreferrer" href="https://www.hitpaw.com/"&gt;Powtoon&lt;/a&gt;: A suit of video creation tools. You can crop, rotate your videos. Powtoon also has a unique feature that &lt;strong&gt;removes watermarks from videos&lt;/strong&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;





&lt;h3&gt;
  
  
  Miscellaneous Tools
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.hubspot.com/make-my-persona"&gt;Buyer Persona&lt;/a&gt;: You should know who you are speaking if you have an intention to make your reader comfortable. This tool allows you to create a buyer persona. &lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://otter.ai/"&gt;Otter&lt;/a&gt;: A tool for generating notes from audio records.&lt;/li&gt;
&lt;li&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://giphy.com/"&gt;Giphy&lt;/a&gt;: Who doesn’t love GIFs. You can search and use millions of GIFs.&lt;/li&gt;
&lt;/ul&gt;





&lt;p&gt;As I said before, this post is a growing list of content creation tools. I’m trying to add great content development and content creation tools to here. Therefore, it is better to bookmark and come back later. &lt;/p&gt;

</description>
      <category>tooling</category>
      <category>design</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Exploring the Nx Framework: Next JS Development</title>
      <dc:creator>Can Burak Sofyalioglu</dc:creator>
      <pubDate>Mon, 30 Aug 2021 05:22:11 +0000</pubDate>
      <link>https://dev.to/canburaks/exploring-the-nx-framework-next-js-development-c5l</link>
      <guid>https://dev.to/canburaks/exploring-the-nx-framework-next-js-development-c5l</guid>
      <description>&lt;h2&gt;
  
  
  NX Workspace Introduction
&lt;/h2&gt;

&lt;p&gt;In this blog post series, I am going to explore the features that NX workspace that provides. The original post can be found on  &lt;a href="https://www.cbsofyalioglu.com/code/next-js-development-within-nx-workspace/" rel="noopener noreferrer"&gt;NextJS Tutorial with Nx Framework&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;In this blog post series, I am going to explore the features that NX workspace provides. I'm going to build a simple &lt;strong&gt;Next JS&lt;/strong&gt; web app with &lt;strong&gt;Tailwind CSS&lt;/strong&gt; styling within the &lt;strong&gt;Nx workspace&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Shameless promototion
&lt;/h4&gt;

&lt;p&gt;This post was written during the research process of Alarm systems guide (&lt;a href="https://alarmsistemleri.org/" rel="noopener noreferrer"&gt;Alarm sistemleri&lt;/a&gt; in Turkish). You can also check &lt;a href="https://www.cbsofyalioglu.com/blogging/best-blogging-sites/" rel="noopener noreferrer"&gt;the list of blogging sites&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NX&lt;/strong&gt;&amp;nbsp;is an advanced set of extensible dev tools for mono repositories, with a strong emphasis on modern full-stack web technologies.&lt;/p&gt;

&lt;h2&gt;
  
  
  1) Setup NextJS App on Nx Workspace
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; nx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install and create workspace&lt;/span&gt;
npx create-nx-workspace nx-tutorial
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Choose project types&lt;/span&gt;
✔ Workspace name &lt;span class="o"&gt;(&lt;/span&gt;e.g., org name&lt;span class="o"&gt;)&lt;/span&gt;     · nx-tutorial
? What to create &lt;span class="k"&gt;in &lt;/span&gt;the new workspace … 
❯ empty             &lt;span class="o"&gt;[&lt;/span&gt;an empty workspace with a layout that works best &lt;span class="k"&gt;for &lt;/span&gt;building apps]
  react             &lt;span class="o"&gt;[&lt;/span&gt;a workspace with a single React application]
  angular           &lt;span class="o"&gt;[&lt;/span&gt;a workspace with a single Angular application]
  next.js           &lt;span class="o"&gt;[&lt;/span&gt;a workspace with a single Next.js application]
  gatsby            &lt;span class="o"&gt;[&lt;/span&gt;a workspace with a single Gatsby application]
  nest              &lt;span class="o"&gt;[&lt;/span&gt;a workspace with a single Nest application]
  express           &lt;span class="o"&gt;[&lt;/span&gt;a workspace with a single Express application]
  web components    &lt;span class="o"&gt;[&lt;/span&gt;a workspace with a single app built using web components]
  react-express     &lt;span class="o"&gt;[&lt;/span&gt;a workspace with a full stack application &lt;span class="o"&gt;(&lt;/span&gt;React + Express&lt;span class="o"&gt;)]&lt;/span&gt;
  angular-nest      &lt;span class="o"&gt;[&lt;/span&gt;a workspace with a full stack application &lt;span class="o"&gt;(&lt;/span&gt;Angular + Nest&lt;span class="o"&gt;)]&lt;/span&gt;
  oss               &lt;span class="o"&gt;[&lt;/span&gt;an empty workspace with a layout that works best &lt;span class="k"&gt;for &lt;/span&gt;open-source projects]

&lt;span class="c"&gt;# Choose whether you'll use Nx Cloud or not&lt;/span&gt;
✔ Use Nx Cloud? &lt;span class="o"&gt;(&lt;/span&gt;It&lt;span class="s1"&gt;'s free and doesn'&lt;/span&gt;t require registration.&lt;span class="o"&gt;)&lt;/span&gt; · Yes
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  NX  Nx is creating your workspace.

&lt;span class="c"&gt;# get into the workspace&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;nx-tutorial

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

&lt;/div&gt;



&lt;p&gt;Nx Workspace directory structure&lt;/p&gt;




&lt;h3&gt;
  
  
  1.1) See the available plugins
&lt;/h3&gt;

&lt;p&gt;You can see all of the available plugins with nx list  command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# See the available plugins&lt;/span&gt;
nx list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  NX  Installed plugins:

  @nrwl/jest &lt;span class="o"&gt;(&lt;/span&gt;builders,generators&lt;span class="o"&gt;)&lt;/span&gt;
  @nrwl/linter &lt;span class="o"&gt;(&lt;/span&gt;builders&lt;span class="o"&gt;)&lt;/span&gt;
  @nrwl/workspace &lt;span class="o"&gt;(&lt;/span&gt;builders,generators&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  NX  Also available:

  @nrwl/angular &lt;span class="o"&gt;(&lt;/span&gt;generators&lt;span class="o"&gt;)&lt;/span&gt;
  @nrwl/cypress &lt;span class="o"&gt;(&lt;/span&gt;executors,generators&lt;span class="o"&gt;)&lt;/span&gt;
  @nrwl/express &lt;span class="o"&gt;(&lt;/span&gt;executors,generators&lt;span class="o"&gt;)&lt;/span&gt;
  @nrwl/nest &lt;span class="o"&gt;(&lt;/span&gt;executors,generators&lt;span class="o"&gt;)&lt;/span&gt;
  @nrwl/next &lt;span class="o"&gt;(&lt;/span&gt;executors,generators&lt;span class="o"&gt;)&lt;/span&gt;
  @nrwl/node &lt;span class="o"&gt;(&lt;/span&gt;executors,generators&lt;span class="o"&gt;)&lt;/span&gt;
  @nrwl/nx-plugin &lt;span class="o"&gt;(&lt;/span&gt;executors,generators&lt;span class="o"&gt;)&lt;/span&gt;
  @nrwl/react &lt;span class="o"&gt;(&lt;/span&gt;executors,generators&lt;span class="o"&gt;)&lt;/span&gt;
  @nrwl/storybook &lt;span class="o"&gt;(&lt;/span&gt;executors,generators&lt;span class="o"&gt;)&lt;/span&gt;
  @nrwl/web &lt;span class="o"&gt;(&lt;/span&gt;executors,generators&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  NX  Community plugins:

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  1.2) Installation of the Next plugin
&lt;/h3&gt;

&lt;p&gt;Now, install the Next plugin and see the options of it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install the plugin&lt;/span&gt;
yarn add @nrwl/next 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1.3) See the plugin options
&lt;/h3&gt;

&lt;p&gt;Let's see what we can do with the plugin. You'll see the available options for the plugin you choose. I am going to generate an application but first I need to see all options. We have options four options to generate and 3 to execute.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# See the options for the plugin&lt;/span&gt;
&lt;span class="c"&gt;# nx list [plugin]&lt;/span&gt;
nx list @nrwl/next
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  NX  Capabilities &lt;span class="k"&gt;in&lt;/span&gt; @nrwl/next:

  GENERATORS

  init : Initialize the @nrwl/next plugin
  application : Create a Next.js application
  page : Create a Next.js page component
  component : Create a React component

  EXECUTORS/BUILDERS

  build : Build a Next.js app
  server : Serve a Next.js app
  &lt;span class="nb"&gt;export&lt;/span&gt; : Export a Next.js app. The exported application is located at dist/&lt;span class="nv"&gt;$outputPath&lt;/span&gt;/exported.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1.4) See the options for generating a Next application
&lt;/h3&gt;

&lt;p&gt;Before generating the Next application, It will be better to see initial configuration options for generating an app. To do this, I must append help flag to the end of the command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# See the options for generating a Next application&lt;/span&gt;
nx generate @nrwl/next:application &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nx generate @nrwl/next:application &lt;span class="o"&gt;[&lt;/span&gt;name] &lt;span class="o"&gt;[&lt;/span&gt;options,...]

Options:
  &lt;span class="nt"&gt;--name&lt;/span&gt;                  The name of the application.
  &lt;span class="nt"&gt;--directory&lt;/span&gt;             The directory of the new application.
  &lt;span class="nt"&gt;--style&lt;/span&gt;                 The file extension to be used &lt;span class="k"&gt;for &lt;/span&gt;style files. &lt;span class="o"&gt;(&lt;/span&gt;default: css&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nt"&gt;--server&lt;/span&gt;                The server script path to be used with next.
  &lt;span class="nt"&gt;--linter&lt;/span&gt;                The tool to use &lt;span class="k"&gt;for &lt;/span&gt;running lint checks. &lt;span class="o"&gt;(&lt;/span&gt;default: eslint&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nt"&gt;--skipFormat&lt;/span&gt;            Skip formatting files
  &lt;span class="nt"&gt;--skipWorkspaceJson&lt;/span&gt;     Skip updating workspace.json with default options based on values provided to this app &lt;span class="o"&gt;(&lt;/span&gt;e.g. babel, style&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nt"&gt;--unitTestRunner&lt;/span&gt;        Test runner to use &lt;span class="k"&gt;for &lt;/span&gt;unit tests &lt;span class="o"&gt;(&lt;/span&gt;default: jest&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nt"&gt;--e2eTestRunner&lt;/span&gt;         Test runner to use &lt;span class="k"&gt;for &lt;/span&gt;end to end &lt;span class="o"&gt;(&lt;/span&gt;e2e&lt;span class="o"&gt;)&lt;/span&gt; tests &lt;span class="o"&gt;(&lt;/span&gt;default: cypress&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nt"&gt;--tags&lt;/span&gt;                  Add tags to the application &lt;span class="o"&gt;(&lt;/span&gt;used &lt;span class="k"&gt;for &lt;/span&gt;linting&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nt"&gt;--js&lt;/span&gt;                    Generate JavaScript files rather than TypeScript files.
  &lt;span class="nt"&gt;--setParserOptionsProjecWhether&lt;/span&gt; or not to configure the ESLint &lt;span class="s2"&gt;"parserOptions.project"&lt;/span&gt; option. We &lt;span class="k"&gt;do &lt;/span&gt;not &lt;span class="k"&gt;do &lt;/span&gt;this by default &lt;span class="k"&gt;for &lt;/span&gt;lint performance reasons.
  &lt;span class="nt"&gt;--standaloneConfig&lt;/span&gt;      Split the project configuration into &amp;lt;projectRoot&amp;gt;/project.json rather than including it inside workspace.json
  &lt;span class="nt"&gt;--dryRun&lt;/span&gt;                Runs through and reports activity without writing to disk.
  &lt;span class="nt"&gt;--skip-nx-cache&lt;/span&gt;         Skip the use of Nx cache.
  &lt;span class="nt"&gt;--help&lt;/span&gt;                  Show available options &lt;span class="k"&gt;for &lt;/span&gt;project target.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1.5) Generating a Next JS application
&lt;/h3&gt;

&lt;p&gt;It is better to use —dryRun flag on generating an application. Also, I need to give a name to my app. When I execute the command, some configuration options will be available to me. I'll stick with CSS styling option&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# I'll also choose the name of the app as "store"&lt;/span&gt;
nx generate @nrwl/next:application store
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;? Which stylesheet format would you like to use? … 
❯ CSS
  SASS&lt;span class="o"&gt;(&lt;/span&gt;.scss&lt;span class="o"&gt;)&lt;/span&gt;       &lt;span class="o"&gt;[&lt;/span&gt; http://sass-lang.com          &lt;span class="o"&gt;]&lt;/span&gt;
  Stylus&lt;span class="o"&gt;(&lt;/span&gt;.styl&lt;span class="o"&gt;)&lt;/span&gt;     &lt;span class="o"&gt;[&lt;/span&gt; http://stylus-lang.com        &lt;span class="o"&gt;]&lt;/span&gt;
  LESS              &lt;span class="o"&gt;[&lt;/span&gt; http://lesscss.org            &lt;span class="o"&gt;]&lt;/span&gt;
  styled-components &lt;span class="o"&gt;[&lt;/span&gt; https://styled-components.com &lt;span class="o"&gt;]&lt;/span&gt;
  emotion           &lt;span class="o"&gt;[&lt;/span&gt; https://emotion.sh            &lt;span class="o"&gt;]&lt;/span&gt;
  styled-jsx        &lt;span class="o"&gt;[&lt;/span&gt; https://www.npmjs.com/package/styled-jsx &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1.6) Start Next JS Application
&lt;/h3&gt;

&lt;p&gt;After setting up the Next application, let's open workspace.json file. In the file, you will see the target list under the store application. Those are the actions that I can do with the Next JS application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"version"&lt;/span&gt;: 2,
  &lt;span class="s2"&gt;"projects"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"store"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"root"&lt;/span&gt;: &lt;span class="s2"&gt;"apps/store"&lt;/span&gt;,
            &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt;
      &lt;span class="s2"&gt;"targets"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"build"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;,
        &lt;span class="s2"&gt;"serve"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;,
        &lt;span class="s2"&gt;"export"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;,
        &lt;span class="s2"&gt;"lint"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;,
    &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt;
    &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, I can start serving the app by the run command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Serving the app&lt;/span&gt;
&lt;span class="c"&gt;# nx run [project]:[target]&lt;/span&gt;
nx run store:serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, open your browser and navigate to &lt;a href="http://localhost:4200/" rel="noopener noreferrer"&gt;http://localhost:4200/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fwp-content%2Fuploads%2F2021%2F08%2F00-nx-directory-squashed.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.cbsofyalioglu.com%2Fwp-content%2Fuploads%2F2021%2F08%2F00-nx-directory-squashed.jpg" alt="01-nx-next-serving.jpg" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2) Installing Dependencies
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2.1) TailwindCSS Setup
&lt;/h3&gt;

&lt;p&gt;I am going to style the web app with Tailwind CSS. Let's add the dependencies of it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Tailwind CSS dependencies&lt;/span&gt;
yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; tailwindcss@latest postcss@latest autoprefixer@latest

&lt;span class="c"&gt;# Other styling libs&lt;/span&gt;
yarn add @heroicons/react @headlessui/react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Put tailwind config file in the app dir&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;apps/store
npx tailwindcss init &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// apps/store/postcss.config.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;tailwindcss&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./apps/store/tailwind.config.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;autoprefixer&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;&lt;a href="https://nx.dev/latest/react/guides/using-tailwind-css-in-react#introducing-nx-utility-for-better-tailwind-purging" rel="noopener noreferrer"&gt;According to the docs&lt;/a&gt;, Nx utility function should be used for purge property. This eliminates additional manual maintenance as your workspace progresses. Also, it should be noted that Nx only purges on production build.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// apps/site/tailwind.config.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;join&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// available since Nx v 12.5&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createGlobPatternsForDependencies&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nrwl/next/tailwind&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;purge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pages/**/*.{js,ts,jsx,tsx}&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="nf"&gt;createGlobPatternsForDependencies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;darkMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// or 'media' or 'class'&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&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="na"&gt;variants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&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="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.2) Import TailwindCSS Styles
&lt;/h3&gt;

&lt;p&gt;When I'm in the root folder, I'll create separate style file for tailwind.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# create tailwind.css file on pages dir&lt;/span&gt;
&lt;span class="nb"&gt;touch &lt;/span&gt;apps/store/pages/tailwind.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* apps/store/pages/tailwind.css */&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;utilities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* apps/store/pages/styles.css */&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s1"&gt;"./tailwind.css"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c"&gt;/* The rest of styles.css file */&lt;/span&gt;
&lt;span class="c"&gt;/* ----------------------------*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3) Create a  library
&lt;/h2&gt;

&lt;p&gt;Nx framework allows you to structure your project with apps and libs. In other words, we don't need to create app libraries specifically in the app directory. We can also create separate and publishable libraries.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh6cfbq2pkwhvl56ordit.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh6cfbq2pkwhvl56ordit.png" alt="CleanShot 2021-08-29 at 01.23.25.png" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are different types of libraries you can create:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.notion.so/3d06489a603e4aa3be4e3de33dfa5e09" rel="noopener noreferrer"&gt;Nx Library types&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can easily move the libraries using the @nrwl/workspace:move generator command&lt;/p&gt;

&lt;p&gt;We have two options for building libraries either —buildable or —publishable. Those are valid for Angular, React, NestJS and Node. Therefore, I am going to use React libraries as a separate standalone publishable library.&lt;/p&gt;

&lt;p&gt;You will also find useful options flag that you can pass to the CLI command.  You can find &lt;a href="https://nx.dev/latest/react/react/library" rel="noopener noreferrer"&gt;the full list of the react:library options&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.notion.so/88c3e7b9ba3e4bdbb1d676a73f586bfc" rel="noopener noreferrer"&gt;@nrwl/react:library flags&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a library wiht @nrwl/react package&lt;/span&gt;
&lt;span class="c"&gt;# See which files will be written to the disk &lt;/span&gt;
&lt;span class="c"&gt;# (output is not produced)&lt;/span&gt;
nx g @nrwl/react:lib tailwind-ui &lt;span class="nt"&gt;--dry-run&lt;/span&gt; 

&lt;span class="c"&gt;# Now create the library as publishable&lt;/span&gt;
&lt;span class="c"&gt;# publishable flag requires importPath=npmusername/libraryname &lt;/span&gt;
nx g @nrwl/react:lib tailwind-ui  &lt;span class="nt"&gt;--publishable&lt;/span&gt; &lt;span class="nt"&gt;--importPath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;@canburaks/tailwind-ui &lt;span class="nt"&gt;--globalCss&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="nt"&gt;--component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;

&lt;span class="c"&gt;# Also you can remove the library as like this&lt;/span&gt;
&lt;span class="c"&gt;# nx g remove tailwind-ui&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# You'll see the ouput like that&lt;/span&gt;
✔ Which stylesheet format would you like to use? · css
UPDATE workspace.json
UPDATE nx.json
CREATE libs/tailwind-ui/.eslintrc.json
CREATE libs/tailwind-ui/.babelrc
CREATE libs/tailwind-ui/README.md
CREATE libs/tailwind-ui/package.json
CREATE libs/tailwind-ui/src/index.ts
CREATE libs/tailwind-ui/tsconfig.json
CREATE libs/tailwind-ui/tsconfig.lib.json
UPDATE tsconfig.base.json
CREATE libs/tailwind-ui/jest.config.js
CREATE libs/tailwind-ui/tsconfig.spec.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4) Create a components
&lt;/h2&gt;

&lt;p&gt;Now, I generated a publishable user interface component library. I'm planning to populate this library with tailwind components.&lt;/p&gt;

&lt;p&gt;Additionally, style=none flag is added because components styling will be done by tailwind classes and there is no need to create extra style file. &lt;/p&gt;

&lt;p&gt;Also, the library will not include tailwindcss library, meaning that the library has a peer dependency of tailwindcss.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.notion.so/cc6fbe1cb65e4da197a637aca804ed2e" rel="noopener noreferrer"&gt;@nrwl/react:components flags&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4.1) Generate components for the library
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Navbar component&lt;/span&gt;
nx g @nrwl/next:component Navbar &lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tailwind-ui &lt;span class="nt"&gt;--style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;none &lt;span class="nt"&gt;--export&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;  

&lt;span class="c"&gt;# Footer component&lt;/span&gt;
nx g @nrwl/next:component Footer &lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tailwind-ui &lt;span class="nt"&gt;--style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;none &lt;span class="nt"&gt;--export&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4.2) Generate components for the app
&lt;/h3&gt;

&lt;p&gt;I generated the required files for the library components. It is a good practice to create Layou component for the NextJS apps. Let's create it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nx g @nrwl/next:component Layout &lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;store &lt;span class="nt"&gt;--style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;none
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, fill those files likes these:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// apps/store/components/layout/layout.tsx&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Navbar&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./navbar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Footer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./footer&lt;/span&gt;&lt;span class="dl"&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Navbar&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;main&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;children&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;main&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;Footer&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// libs/tailwind-ui/src/lib/navbar/navbar.tsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Navbar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"w-full px-8 text-gray-700 bg-white "&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;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"container flex flex-col flex-wrap items-center justify-between py-5 mx-auto md:flex-row max-w-7xl"&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;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"relative flex flex-col md:flex-row"&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;a&lt;/span&gt;
            &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;
            &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex items-center mb-5 font-medium text-gray-900 lg:w-auto lg:items-center lg:justify-center md:mb-0"&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;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mx-auto text-xl font-black leading-none text-gray-900 select-none"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              cbsofyalioglu&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-indigo-600"&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;span&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;span&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;a&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;nav&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex flex-wrap items-center mb-5 text-base md:mb-0 md:pl-8 md:ml-8 md:border-l md:border-gray-200"&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;a&lt;/span&gt;
              &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mr-5 font-medium leading-6 text-gray-600 hover:text-gray-900"&lt;/span&gt;
              &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/contact"&lt;/span&gt;
            &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              Contact
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&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;nav&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;div&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;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"inline-flex items-center ml-5 space-x-6 lg:justify-end"&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;a&lt;/span&gt;
            &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/login"&lt;/span&gt;
            &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-teal-600 px-8 py-2 border-teal-600  font-medium leading-6 border-2 rounded-lg transition ease-out duration-300 hover:text-blueGray-100 hover:bg-teal-600"&lt;/span&gt;
          &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            Login
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&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;div&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;div&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;section&lt;/span&gt;&lt;span class="p"&gt;&amp;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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// libs/tailwind-ui/src/lib/footer/footer.tsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Footer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-gray-700 bg-white body-font border-t-4 border-teal-800"&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;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"container flex flex-col items-center px-8 py-8 mx-auto max-w-7xl sm:flex-row"&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;a&lt;/span&gt;
          &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://www.filizguvenlik.com.tr"&lt;/span&gt;
          &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-xl font-black leading-none text-gray-900 select-none logo"&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          cbsofyalioglu&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-indigo-600"&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;span&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;a&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;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mt-4 text-sm text-gray-500 sm:ml-4 sm:pl-4 sm:border-l sm:border-gray-200 sm:mt-0"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          © 2021 -&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&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;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://webmeister.org"&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-xs"&lt;/span&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"noreferrer"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            Webmeister
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&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;p&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;div&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;section&lt;/span&gt;&lt;span class="p"&gt;&amp;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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// libs/tailwind-ui/src/index.tsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="o"&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;./lib/navbar/navbar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./lib/footer/footer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, I must build the library. By doing this, I'll be able to import the components to the app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# build library&lt;/span&gt;
nx run tailwind-ui:build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// apps/store/pages/_app.tsx&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;AppProps&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="s1"&gt;next/app&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="nx"&gt;Head&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/head&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./styles.css&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="nx"&gt;Layout&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/layout/layout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pageProps&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Layout&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;Component&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;pageProps&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;Layout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// // apps/store/pages/index.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"min-h-screen"&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;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;Now, restart the server.&lt;/p&gt;




&lt;h2&gt;
  
  
  4) Generate pages
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Generate a contact page&lt;/span&gt;
&lt;span class="nx"&gt;nx&lt;/span&gt; &lt;span class="nx"&gt;generate&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="nx"&gt;Contact&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// apps/store/pages/contact.tsx&lt;/span&gt;
&lt;span class="cm"&gt;/* eslint-disable react/no-unescaped-entities */&lt;/span&gt;
&lt;span class="cm"&gt;/* eslint-disable @next/next/no-img-element */&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Contact&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="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"container mx-auto mt-8 md:mt-0 md:space-x-10 md:grid grid-cols-3 justify-center md:py-40"&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;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"grid justify-center items-center order-1 col-span-1"&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;img&lt;/span&gt;
          &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"lg:h-80 md:h-64 h-40 rounded-full"&lt;/span&gt;
          &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://cbsofyalioglu.fra1.cdn.digitaloceanspaces.com/cbs/cbsofyalioglu-black.png"&lt;/span&gt;
          &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&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;div&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;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mt-8 md:mt-0 lg:justify-end col-span-2"&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;h1&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-4xl text-gray-800 text-center md:text-left font-bold mb-6"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Hi, I am Can Burak Sofyalioglu.
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&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;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-xl text-gray-800 text-center md:text-left"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          I'm an engineer.
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&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;div&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;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;






</description>
      <category>nextjs</category>
      <category>node</category>
      <category>react</category>
    </item>
    <item>
      <title>Free Design Tools - Generators, Graphics Templates, Prototyping ...</title>
      <dc:creator>Can Burak Sofyalioglu</dc:creator>
      <pubDate>Tue, 09 Feb 2021 07:52:27 +0000</pubDate>
      <link>https://dev.to/canburaks/free-design-tools-generators-graphic-templates-prototyping-4o70</link>
      <guid>https://dev.to/canburaks/free-design-tools-generators-graphic-templates-prototyping-4o70</guid>
      <description>&lt;p&gt;These resources will be updated frequently. Therefore, bookmarking is suggested. You can check the original and updated page by visiting: &lt;a href="https://www.cbsofyalioglu.com/design/free-design-resources/" rel="noopener noreferrer"&gt;Free Design Resources&lt;/a&gt; &lt;br&gt;
Another shameless plug of mine is the article that reviews &lt;a href="https://bloggingplatforms.app/blog/best-free-platforms-for-blogging" rel="noopener noreferrer"&gt;Best Free Platforms for Blogging&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Free Design Resources and Graphic Design Tools
&lt;/h1&gt;

&lt;p&gt;The collections of free design resources and graphic design tools. I listed many graphic design resources that make it possible to generate and create useful graphics.&lt;/p&gt;

&lt;p&gt;If you are also interested in not only design resources but also content creation tools, you can check my other curated list: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.cbsofyalioglu.com/en/content-creation-tools/" rel="noopener noreferrer"&gt;Visual and Written Content Creation Tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cbsofyalioglu.com/blogging/best-blogging-sites/" rel="noopener noreferrer"&gt;Ultimate list of blogging sites&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Free Design Resources Part I – Generator Apps
&lt;/h2&gt;

&lt;p&gt;These tools generate design resources for you. They are simple tools but generate effective patterns and code. Those are free design resources that you can tweak and use them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Magic Pattern
&lt;/h3&gt;

&lt;p&gt;Magic Pattern consists of a bunch of freemium tools. The link to the SVG wave generator is below; also check out other tools.&lt;br&gt;
&lt;a rel="noopener noreferrer" href="https://www.magicpattern.design/tools/wave-generator"&gt;Magic Pattern SVG Wave Generator&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Get Waves
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fn2dbweavvk7qbjtpd2t7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fn2dbweavvk7qbjtpd2t7.png" alt="Get Waves" width="799" height="309"&gt;&lt;/a&gt;&lt;br&gt;
A free SVG wave generator to make unique SVG waves for your next web design. Choose a curve, adjust complexity, randomize!&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://getwaves.io/"&gt;Get Waves&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  SVG Waves
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fuudxgzjjlgf6w2zu3e3h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fuudxgzjjlgf6w2zu3e3h.png" alt="SVG Waves" width="799" height="286"&gt;&lt;/a&gt;&lt;br&gt;
Another generator that produces wave patterns in SVG or PNG formats. SVG Wave is a minimal gradient svg wave generator with a lot of customization. It lets you the ability to generate and export pngs and svgs of beautiful waves. SVG wave also lets you layer multiple waves. Create SVGs for your website designs.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://svgwave.in/?ref=cbsofyalioglu"&gt;Svg Wave&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Faux Code Generator
&lt;/h3&gt;

&lt;p&gt;This app requires a link of any GitHub gist. When you provide the source code, the web app transforms it to faux code graphics.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="http://knutsynstad.com/fauxcode/?ref=cbsofyalioglu"&gt;Faux Code Generator&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Neumorphism CSS Generator
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhzm15cp85h8hbgisfp6r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhzm15cp85h8hbgisfp6r.png" alt="Neumorphism" width="800" height="275"&gt;&lt;/a&gt;&lt;br&gt;
This web app allows you to create neumorphism CSS code that you tweak visually.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://neumorphism.io/"&gt;Neumorphism CSS Generator&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Soft UI
&lt;/h3&gt;

&lt;p&gt;Another free design resource that makes it possible to build neumorphic style code.&lt;br&gt;
Explore the most advanced CSS box shadow generator for your UI. Create colors, gradients, elements in the neuromorphic design: fast, free, no ads.&lt;/p&gt;

&lt;p&gt;&lt;a rel="nofollow noopener noreferrer" href="https://www.softui.io/"&gt;Soft UI&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Glitch Art
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Foct86h6tjj5odztjrxs8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Foct86h6tjj5odztjrxs8.png" alt="Glitch Art" width="800" height="212"&gt;&lt;/a&gt;&lt;br&gt;
The glitch art generator produces glitch patterns.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://glitchart.io/"&gt;Glitch Art&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Fancy Border Generator
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4um84tuelwxhtseb7lyr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4um84tuelwxhtseb7lyr.png" alt="Fancy Border Generator" width="800" height="272"&gt;&lt;/a&gt;&lt;br&gt;
This online design resources allows you to make custom shape borders.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://9elements.github.io/fancy-border-radius/"&gt;Fancy Border Generator&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Components.ai
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffdqirzn5hq3d3fsu95bh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffdqirzn5hq3d3fsu95bh.png" alt="Components.ai" width="799" height="249"&gt;&lt;/a&gt;&lt;br&gt;
This design resource actually a suit. It consists of many design generator that is produced by machine learning algorithms. Gradients, color scales, voronoi, and bootstrap color palette generator.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://components.ai/"&gt;Components AI&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Material Shadow
&lt;/h3&gt;

&lt;p&gt;It allows you to add shadows to your icons. You can also select predefined material icons.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://android-material-icon-generator.bitdroid.de/"&gt;Material Shadow&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Technology Bullshit Generator
&lt;/h3&gt;

&lt;p&gt;If you need flashy words, then this app makes it for you. It creates a flashy but bullshit word generator.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.makebullshit.com/"&gt;Tech Bullshit Generator&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Squircley
&lt;/h3&gt;

&lt;p&gt;Squircley generate a shape neither square nor circle. You can tweak it as you want.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://squircley.app/"&gt;Squircley&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Shape Divider
&lt;/h3&gt;

&lt;p&gt;It divides the shape&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fs.w.org%2Fimages%2Fcore%2Femoji%2F13.0.1%2Fsvg%2F1f642.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fs.w.org%2Fimages%2Fcore%2Femoji%2F13.0.1%2Fsvg%2F1f642.svg" alt="🙂" width="36" height="36"&gt;&lt;/a&gt; You realized that some kind of divided shapes are well suited on landing pages. You can do those kind of shapes with this design resource.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.shapedivider.app/"&gt;Shape Divider App&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Blobs
&lt;/h3&gt;

&lt;p&gt;Decorative blob generator tool.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://blobs.app/"&gt;Blobs&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Omatsuri Suite
&lt;/h3&gt;

&lt;p&gt;Omatsuri is not a single graphic design tool. It is actually a free design resources suit. You can find many useful graphic design resources such as triangle generator, wave generator, color shades and color palette generators.&lt;br&gt;
Progressive Web Application with 12 open source frontend focused tools&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://omatsuri.app/https://getwaves.io/"&gt;Omatsuri Suite&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Blog Cover Generator
&lt;/h3&gt;

&lt;p&gt;Easy blog post cover generator.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://blogcover.now.sh/"&gt;Blog Cover Generator&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Patternico
&lt;/h3&gt;

&lt;p&gt;A pattern generator.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://patternico.com//"&gt;Patternico&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Doodad
&lt;/h3&gt;

&lt;p&gt;Yet another pattern generator&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://doodad.dev/pattern-generator//"&gt;Doodad&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Tabbied
&lt;/h3&gt;

&lt;p&gt;Doodle with generated patterns. &lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://tabbied.com/"&gt;Tabbied&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  BG Jar
&lt;/h3&gt;

&lt;p&gt;Very useful background pattern generator which can export your design in various formats such as CSS, SVG or PNG.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://bgjar.com/"&gt;BG Jar&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Free Design Resources Part II – Visual Content Creator Tools
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Canva
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frbaa6fg2bvmxnpelxu20.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frbaa6fg2bvmxnpelxu20.png" alt="Canva" width="800" height="195"&gt;&lt;/a&gt;&lt;br&gt;
Canva is the most popular and the most used graphic content creations site. It has both free and premium plans. If you need a quick visual content Canva is one of the best design resource.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.canva.com/"&gt;Canva&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Easil
&lt;/h3&gt;

&lt;p&gt;Easil is another Canva alternative that has limited features for free plan.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://about.easil.com/"&gt;Easil&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Visme
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F63999v7wchc57drqrnd7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F63999v7wchc57drqrnd7.png" alt="Alt Text" width="799" height="433"&gt;&lt;/a&gt;&lt;br&gt;
Visme is an online tool that allows you to easily create info-graphics. Those are very useful for visual explanations and building back-links.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.visme.co/"&gt;Visme&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Glorify
&lt;/h3&gt;

&lt;p&gt;Glorify is a Canva-like tool that specifically create graphics for different platforms such as Product Hunt, Shopify, Fiver etc…&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.glorifyapp.com/"&gt;Glorify&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Polotno Studio
&lt;/h3&gt;

&lt;p&gt;Polotno Studio allows you to edit your graphics.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://studio.polotno.dev/"&gt;Polotno Studio&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Projector
&lt;/h3&gt;

&lt;p&gt;Projector is also another free graphic template design tool.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://projector.com"&gt;Projector&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Taler
&lt;/h3&gt;

&lt;p&gt;Taler is relatively new tool comparing with other free design resources. It is also powered by e-commerce platform Shopify.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.taler.app/"&gt;Taler&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Crello
&lt;/h3&gt;

&lt;p&gt;It is very limited graphic design tool. Only 5 design downloads are permitted.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://crello.com/"&gt;Crello&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Artify
&lt;/h3&gt;

&lt;p&gt;I personally like the illustration of Artify. Once in a while, It does not respond. However, It is now working. I should also mention that attribution is required.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.artify.co/"&gt;Artify&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Free Design Resources Part III – Prototyping and Graphic Editing Tools
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Figma
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdlqh3w2b5cwcpr9go6lb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdlqh3w2b5cwcpr9go6lb.png" alt="Figma" width="799" height="306"&gt;&lt;/a&gt;&lt;br&gt;
Figma is awesome. It is a sketch alternative. Moreover, It is boosted by Web-Assembly technology that makes possible to do these stuff on your browser. It is great for teams and freelancers. It also allows you to graphically edit React components. In this way, Framer is a unique design tool.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://figma.com/"&gt;Figma&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Penpot
&lt;/h3&gt;

&lt;p&gt;Penpot is an open-source free prototyping and design tool that is currently at alpha stage.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://penpot.app/?ref=cbsofyalioglu"&gt;Penpot&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Framer
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fuvjm15jpmey5w1ylxhcl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fuvjm15jpmey5w1ylxhcl.png" alt="Alt Text" width="799" height="361"&gt;&lt;/a&gt;&lt;br&gt;
Framer stands out with its mobile and interaction prototype development. It has web version as long as MacOS versions. React developers may know &lt;a href="https://www.framer.com/motion/" rel="noopener noreferrer"&gt;Framer Motion&lt;/a&gt; library which is the product of Framer.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.framer.com/"&gt;Framer&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Lunacy
&lt;/h3&gt;

&lt;p&gt;Lunacy is a desktop software created by Icons8. Because of the creator company, it has built-in assets. Currently only available for Windows.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://icons8.com/lunacy"&gt;Lunacy&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Spline
&lt;/h3&gt;

&lt;p&gt;One of the best tools of 2020. Spline allows you to create 3D geometry. Moreover, It has Linux support.&lt;/p&gt;

&lt;p&gt;&lt;a rel="nofollow noopener noreferrer" href="https://spline.design/"&gt;Spline&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Free Design Resources IV – Design System Tools
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Toolabs Design System
&lt;/h3&gt;

&lt;p&gt;Toolabs is a very intuitive tools that allows you to create your design system and export it with various formats such as CSS, JSON etc.. Also, It creates a web page for your design system that you can access and share it easily.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.toolabs.com/"&gt;Toolabs DSM&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontify
&lt;/h3&gt;

&lt;p&gt;Frontify actually is more than a design system tool. It is a complete brand design suite. It has a free plan for freelancers. You can create your design guideline and design system. Frontify also allows you to create a web page in order to access and share your guideline. Moreover, you can develop and design a user-interface component and share the code easily. A sample guideline page can be seen below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ffra1.digitaloceanspaces.com%2Fcbsofyalioglu%2Fwordpress%2Fcbsofyalioglu%2FScreenshot-from-2021-02-09-08_03_15-scaled.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ffra1.digitaloceanspaces.com%2Fcbsofyalioglu%2Fwordpress%2Fcbsofyalioglu%2FScreenshot-from-2021-02-09-08_03_15-scaled.jpg" alt="Free Design Resources - Frontify " width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://www.frontify.com/"&gt;Frontify&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Diez
&lt;/h3&gt;

&lt;p&gt;Tokens are great when the case is design. Diez is a tool that is specialized in creating design tokens.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://diez.org/"&gt;Diez&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ZeroHeight
&lt;/h3&gt;

&lt;p&gt;You can create your design guidelines with Zeroheight and make it single source of truth. Because it includes both design and code assets, communication with designers and developers becomes less problematic.&lt;/p&gt;

&lt;p&gt;&lt;a rel="nofollow noopener noreferrer" href="https://zeroheight.com/"&gt;ZeroHeight&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Free Design Resources V – Miscellaneous
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Design Lobby
&lt;/h3&gt;

&lt;p&gt;It is nice looking asset manager. You can deploy your design assets such as typefaces, icons, images and colors. Currently in a beta phase.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://designlobby.app/"&gt;Design Lobby&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Squoosh
&lt;/h3&gt;

&lt;p&gt;Squoosh is a one page web app that is the easiest way to compress images. As we know, Google stated that fast opening is an important factor when ranking websites. Therefore, image compression is a must for websites that is aiming to rank higher. Considering the situation, Squoosh is an important free design resource.&lt;br&gt;
&lt;a rel="nofollow noopener noreferrer" href="https://squoosh.app/"&gt;Squoosh&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Currently the original post includes more than 70 &lt;a href="https://www.cbsofyalioglu.com/design/free-design-resources/" rel="noopener noreferrer"&gt;Free Design Resources and Graphic Design Tools&lt;/a&gt;&lt;/p&gt;

</description>
      <category>design</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Hosted Confluence Installation with Custom Domain</title>
      <dc:creator>Can Burak Sofyalioglu</dc:creator>
      <pubDate>Sun, 15 Nov 2020 19:12:51 +0000</pubDate>
      <link>https://dev.to/canburaks/self-hosted-confluence-installation-with-custom-domain-iip</link>
      <guid>https://dev.to/canburaks/self-hosted-confluence-installation-with-custom-domain-iip</guid>
      <description>&lt;p&gt;One of our customers from &lt;a href="https://istanbultransferexpert.com" rel="noopener noreferrer"&gt;Istanbul Private Airport Transfer&lt;/a&gt; and &lt;a href="https://privatetransfer.istanbul" rel="noopener noreferrer"&gt;Private Transfer in İstanbul&lt;/a&gt; ask the possibility of using Atlassian Confluence as a self-hosted wiki program. We look for solutions for a while. Later on, we discovered Cloudron app. In this article, We'll install Confluence with a custom domain on our servers. &lt;br&gt;
If your intentions using that as a blog platform, you may want to check &lt;a href="https://bloggingplatforms.app/blog/best-blogging-platforms-for-developers" rel="noopener noreferrer"&gt;Best Blogging Platforms for Developers&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  What is Confluence?
&lt;/h3&gt;

&lt;p&gt;Confluence is a team collaboration and wiki software developed by Australian software company Atlassian. &lt;br&gt;
It is a web-based application and written in Java programming language.It was released in 2004 (Voav) as an enterprise knowledge management software.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.fra1.digitaloceanspaces.com%2Fnote-images%2Fconfluence-installation%2Fconfluence-ss.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.fra1.digitaloceanspaces.com%2Fnote-images%2Fconfluence-installation%2Fconfluence-ss.jpg" alt="Confluence Screenshots" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;==You can use it as a team collaboration app, wiki, knowledgebase, blog, intranet etc==&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;If you read my articles written in Turkish, you realized that talented editor is a must for me in any platform I wrote. The editor of Confluence is one of the best editor in the universe. It has really advanced permission level. You can create many workspaces.&lt;/p&gt;

&lt;p&gt;However, Atlassian Cloud doesn’t allow us to use our custom domains and managed Confluence solutions is a bit complicated.&lt;/p&gt;

&lt;p&gt;Fortunately, Cloudron made it easier for us to use it on our own servers. By doing this, we can use our own custom domains with Atlassian Confluence app.&lt;/p&gt;

&lt;h3&gt;
  
  
  How much does it cost to use Self-Hosted Confluence?
&lt;/h3&gt;

&lt;p&gt;Confluence requires at least 4 GB RAM. Thus, the most expensive cost will the cloud instance.Cloudron is free for personal usage up to 2 apps which is completely sufficient for us.&lt;br&gt;
Therefore, the cost of using Confluence with a custom domain will be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;$20/month&lt;/strong&gt; Cloud Cost on Digital Ocean + one-time license fee of &lt;strong&gt;$10&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll share a referral links below that gives you some amount of free credits. Thus, It is free to follow this guideline.&lt;/p&gt;



&lt;h3&gt;
  
  
  What are the requirements?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Digital Ocean Account&lt;/strong&gt;: This is the platform that hosts our Confluence server. You can get &lt;strong&gt;free $100 credit&lt;/strong&gt; which is available 60 days if you register with this &lt;a href="https://m.do.co/c/7eab8594304f" rel="noopener noreferrer"&gt;referral link&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloudron Account&lt;/strong&gt;: Cloudron provides software solutions for hosting different applications on our servers. You can also get __ $30 free credit__ if you register with this &lt;a href="https://cloudron.io/?refcode=4c0c9d3f2a2daed6" rel="noopener noreferrer"&gt;referral link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain Name&lt;/strong&gt;: You'll need a custom domain.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1 - Create Droplet with Cloudron
&lt;/h2&gt;

&lt;p&gt;Our Confluence app will be hosted on the droplet which we will create now. A Droplet is basically a virtual server in Digital Ocean. &lt;/p&gt;

&lt;p&gt;I'm assuming that you have created an DA account and created a project. Now, we'll create a droplet with Cloudron app installed. &lt;/p&gt;

&lt;p&gt;On the left side, you'll find &lt;strong&gt;Marketplace&lt;/strong&gt; link under the &lt;strong&gt;Discover&lt;/strong&gt; section. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Click the marketplace link.  Search and select &lt;strong&gt;Cloudron&lt;/strong&gt;. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.fra1.digitaloceanspaces.com%2Fnote-images%2Fconfluence-installation%2F1-marketplace-selection.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.fra1.digitaloceanspaces.com%2Fnote-images%2Fconfluence-installation%2F1-marketplace-selection.jpg" alt="Cloudron on Digital Ocean" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;Create Couldron Droplet&lt;/strong&gt; button. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.fra1.digitaloceanspaces.com%2Fnote-images%2Fconfluence-installation%2F2-cloudron-selection.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.fra1.digitaloceanspaces.com%2Fnote-images%2Fconfluence-installation%2F2-cloudron-selection.jpg" alt="Create Cloudron Droplet" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now, you'll see the droplet settings page. As I told you before, Confluence requires minimum 4 GB RAM. Therefore, we should minimum select Basic plan which costs $20/month. Also, we'll choose the closest datacenter to us and create a password as an authentication method. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.fra1.digitaloceanspaces.com%2Fnote-images%2Fconfluence-installation%2F3-droplet-settings.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.fra1.digitaloceanspaces.com%2Fnote-images%2Fconfluence-installation%2F3-droplet-settings.jpg" alt="Cloudron droplet settings" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At the bottom of the page, we'll click the &lt;strong&gt;Create Droplet&lt;/strong&gt; button. It will start the installation of cloud instance and Cloudron application.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step - 2) Initial Configurations
&lt;/h2&gt;

&lt;p&gt;We are going to make some domain adjustments. There are two cases for your domain name provider. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The nameservers of your domain name are on Digital Ocean.&lt;/li&gt;
&lt;li&gt;Your nameservers are on another provider.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In either case, I'll follow the &lt;strong&gt;manual method&lt;/strong&gt; that fits every case. &lt;/p&gt;

&lt;h4&gt;
  
  
  DNS Settings
&lt;/h4&gt;

&lt;p&gt;First, visit the project page on Digital Ocean. If any IP number assigned to your instance, note it down. Otherwise, wait till the assignment. For example mine is &lt;code&gt;46.101.148.85&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.fra1.digitaloceanspaces.com%2Fnote-images%2Fconfluence-installation%2F4-droplet-ip.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.fra1.digitaloceanspaces.com%2Fnote-images%2Fconfluence-installation%2F4-droplet-ip.jpg" alt="droplet-ip" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To make illustration, Let say we have a domain &lt;a href="https://livicomturkiye.com/" rel="noopener noreferrer"&gt;livicomturkiye.com&lt;/a&gt;. We also decided to use a subdomain for the Confluence app, let's say &lt;strong&gt;notes.livicomturkiye.com&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Second, Whether your DNS provider is DA or not, visit your domain name provider's website. Go to DNS management page of your domain name. &lt;br&gt;
Add these two '&lt;strong&gt;A records&lt;/strong&gt;' that target the IP number we saved above.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Host&lt;/th&gt;
&lt;th&gt;Target&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;notes&lt;/td&gt;
&lt;td&gt;46.101.148.85&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;my.notes&lt;/td&gt;
&lt;td&gt;46.101.148.85&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;First one is the subdomain name you use with Confluence. Second one is the cloudron panel with a prefix of &lt;strong&gt;my.&lt;/strong&gt; &lt;br&gt;
Save the records. &lt;/p&gt;

&lt;p&gt;You can control whether your domain is pointing to correct IP by visiting &lt;strong&gt;dnschecker.org&lt;/strong&gt;. If the &lt;strong&gt;A record&lt;/strong&gt; points to the correct IP, you can proceed. DNS propagation can take some time. Therefore, this process can took time. &lt;/p&gt;

&lt;h4&gt;
  
  
  Cloudron settings
&lt;/h4&gt;

&lt;p&gt;Open your browser and paste the IP number of your instance on a new page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.fra1.digitaloceanspaces.com%2Fnote-images%2Fconfluence-installation%2F5-browser-warning.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.fra1.digitaloceanspaces.com%2Fnote-images%2Fconfluence-installation%2F5-browser-warning.jpg" alt="browser-security-warning" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(&lt;strong&gt;Note&lt;/strong&gt;: We have not any secure certificate now.Therefore, your browser will warn you about the privacy. This means your connection is not encrypted end-to-end. Open the advanced settings and proceed with unsafe method.)&lt;/p&gt;

&lt;p&gt;You'll see Cloudron setup page. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.fra1.digitaloceanspaces.com%2Fnote-images%2Fconfluence-installation%2F6-cloudron-domain-screen.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.fra1.digitaloceanspaces.com%2Fnote-images%2Fconfluence-installation%2F6-cloudron-domain-screen.jpg" alt="cloudron-domain-setup" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write down your domain/subdomain that will be used for Confluence app. &lt;/li&gt;
&lt;li&gt;Select Manual as DNS Provider. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Click Next. Now, Cloudron will start to make proper internal configurations. Whet it finishes, you'll fill the admin form. &lt;/p&gt;

&lt;h4&gt;
  
  
  Confluence Installation
&lt;/h4&gt;

&lt;p&gt;If we did everyhting right, we see an empt Cloudron page.&lt;br&gt;
On the upper right menu, click App Store. Before this, you fill the login form of Cloudron. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.fra1.digitaloceanspaces.com%2Fnote-images%2Fconfluence-installation%2F7-start-confluence.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.fra1.digitaloceanspaces.com%2Fnote-images%2Fconfluence-installation%2F7-start-confluence.jpg" alt="confluence-installed-cloudron" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Write your credentials and login.&lt;br&gt;
Search Confluence and install it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step - 3) Confluence Settings
&lt;/h2&gt;

&lt;p&gt;I assume that all the settings properly configured. Now, click Confluence app on Cloudron page. &lt;/p&gt;

&lt;p&gt;A setup page welcomes us. Follow the steps below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Select &lt;strong&gt;Product Installation&lt;/strong&gt;. If you need &lt;strong&gt;Concluence Questions&lt;/strong&gt; or &lt;strong&gt;Confluence Team Calendars&lt;/strong&gt;, please also select them. Click Next.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Press &lt;strong&gt;Get an evaluation license&lt;/strong&gt; link and get the license for Confluence Server. Click Next.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you have a database choose &lt;strong&gt;My own database&lt;/strong&gt;. Otherwise, you can use built-in database as a temporary solution. Click Next.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wait until the database settings are done. Then, create an empty site. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fill the System Administrator Account.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Give your space a name. For example: "Personal Wiki".&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.fra1.digitaloceanspaces.com%2Fnote-images%2Fconfluence-installation%2F8-final-screen.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.fra1.digitaloceanspaces.com%2Fnote-images%2Fconfluence-installation%2F8-final-screen.jpg" alt="confluence-empty-page" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, you can use Atlassian Confluence on your domain. You can create a redirection to your space or make your space public. Just configure them on General Configuration.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Django and Modern JS Libraries - Svelte (3)</title>
      <dc:creator>Can Burak Sofyalioglu</dc:creator>
      <pubDate>Mon, 22 Jun 2020 12:51:00 +0000</pubDate>
      <link>https://dev.to/canburaks/django-and-modern-js-libraries-svelte-3-4a98</link>
      <guid>https://dev.to/canburaks/django-and-modern-js-libraries-svelte-3-4a98</guid>
      <description>&lt;h1&gt;
  
  
  Django and Modern JS Libraries - Svelte
&lt;/h1&gt;

&lt;p&gt;(Note:This article is originally published on &lt;a href="https://www.cbsofyalioglu.com/post/django-and-modern-js-libraries-svelte" rel="noopener noreferrer"&gt;cbsofyalioglu.com&lt;/a&gt; while building the websites of &lt;a href="https://istanbultransferexpert.con" rel="noopener noreferrer"&gt;Istanbul private transfer&lt;/a&gt;, &lt;a href="https://istanbulcruisetransfer.com" rel="noopener noreferrer"&gt;Istanbul Cruise Port Transfer&lt;/a&gt; and &lt;a href="https://www.filizguvenlik.com.tr" rel="noopener noreferrer"&gt;Izmir alarm sistemleri&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Another shameless plug of mine is the article that reviews &lt;a href="https://bloggingplatforms.app/blog/best-blogging-platforms-for-developers" rel="noopener noreferrer"&gt;Best Blogging Platforms for Developers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the previous part, we built a Django backend and GraphQL API. In this part, we will integrate the Django project with Svelte.&lt;/p&gt;

&lt;p&gt;Thus, it's necessary to follow first part of the tutorial .&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Svelte and How it differs from React?
&lt;/h2&gt;

&lt;p&gt;I told that I like Python and its ecosystem. I also like Just-In-Time compilers and language supersets like Cython, which really boosts Python performance. When I learned that JavaScript is an interpreted language, I tried to look Cython equivalent of it. Because of different browser compilers, I couldn’t find what I want and it made a disappointment. Maybe it is the reason I feel excitement when I give Svelte a chance.&lt;/p&gt;

&lt;p&gt;If you didn't try Svelte before, you may give it a chance. Svelte's interactive API and tutorials are also worth to praise. Being familiar with &lt;a href="https://svelte.dev/tutorial/basics" rel="nofollow noreferrer noopener"&gt;Svelte API and Tutorials&lt;/a&gt; is definitely recommended.&lt;/p&gt;

&lt;p&gt;When I'm talking about Svelte, I'm strictly speaking about Svelte 3. It is another JavaScript library written by Rich Harris. What makes Svelte special is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  It is truly a reactive library and it doesn't use virtual DOM like React. Therefore, there is no VDOM diff calculations.&lt;/li&gt;
&lt;li&gt;  It has a compiler and when you build your application it produces optimized JavaScript code. In the end, Svelte code almost disappear and you have vanilla JavaScript.&lt;/li&gt;
&lt;li&gt;  You can write HTML, CSS and JavaScript in single file component and there will be no global CSS pollution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yes, React was revolutionary. However, how many times we have to deal with virtual DOM synchronization problems or the extra burden for even very small operations are the other side of the medallion.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.com%2Fimages%2Fpost-single-page-graphql-svelte.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.com%2Fimages%2Fpost-single-page-graphql-svelte.jpg" alt="Graphql and Svelte" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Svelte Configuration with Webpack from Scratch
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step - 1: Configuring development environment
&lt;/h3&gt;

&lt;p&gt;(Note: if you already installed the node, you can skip this part)&lt;/p&gt;

&lt;p&gt;We will use Node backend for the development environment. Therefore, we need to install Node and Node package manager npm. To prevent potential dependency problems, we will create a clean node environment. I will use NVM which is Node version manager, and it allows us to create isolated Node environments. In your terminal, run the code below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setup Node Environment with NVM&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In your terminal, run the code below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# install node version manager &lt;/span&gt;
wget &lt;span class="nt"&gt;-qO-&lt;/span&gt; https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash

&lt;span class="c"&gt;# check installation&lt;/span&gt;
&lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; nvm

&lt;span class="c"&gt;# should prints nvm, if it doesn't, restart your terminal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# install node&lt;/span&gt;
&lt;span class="c"&gt;# node" is an alias for the latest version&lt;/span&gt;

&lt;span class="c"&gt;# use the installed version&lt;/span&gt;
nvm use node
nvm &lt;span class="nb"&gt;install &lt;/span&gt;node 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can create frontend directory in Django project. Go to the root directory of the project.  &lt;strong&gt;'backend/'&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In your terminal copy and paste the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# create frontend directory&lt;/span&gt;
&lt;span class="nb"&gt;mkdir &lt;/span&gt;FRONTEND
&lt;span class="nb"&gt;cd &lt;/span&gt;FRONTEND

&lt;span class="c"&gt;# now your terminal directory should be&lt;/span&gt;
&lt;span class="c"&gt;# backend/FRONTEND &lt;/span&gt;
&lt;span class="c"&gt;# create a node project&lt;/span&gt;
npm init
&lt;span class="c"&gt;# you may fill the rest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can install front-end and development libraries .&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# install svelte and other libs &lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; svelte serve cross-env  graphql-svelte

&lt;span class="c"&gt;# install webpack and related libs&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; webpack webpack-cli webpack-dev-server

&lt;span class="c"&gt;# install webpack loaders and plugins &lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; style-loader css-loader svelte-loader mini-css-extract-plugin

npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save&lt;/span&gt; node-fetch svelte-routing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update  &lt;strong&gt;package.json&lt;/strong&gt; scripts part as below. Your file should look like this and ignore the versions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"django-svelte-template"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Django Svelte template. "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cross-env NODE_ENV=production webpack"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack-dev-server --content-base ../templates"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"devDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cross-env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^7.0.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"css-loader"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^3.5.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"graphql-svelte"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^1.1.9"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mini-css-extract-plugin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^0.9.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"serve"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^11.3.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"style-loader"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^1.2.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"svelte"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^3.22.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"svelte-loader"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^2.13.6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"webpack"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^4.43.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"webpack-cli"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^3.3.11"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"webpack-dev-server"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^3.11.0"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"node-fetch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^2.6.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"svelte-routing"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^1.4.2"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;p&gt;Let's create application necessary files and folders for Svelte. In the root directory of the project '&lt;strong&gt;backend/'&lt;/strong&gt;  , open your terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# create HTML file of the project&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;templates
&lt;span class="nb"&gt;touch &lt;/span&gt;index.html

&lt;span class="c"&gt;# change directory to backend/FRONTEND&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ../FRONTEND
&lt;span class="nb"&gt;mkdir &lt;/span&gt;src
&lt;span class="nb"&gt;touch &lt;/span&gt;index.js
&lt;span class="nb"&gt;touch &lt;/span&gt;webpack.config.js

&lt;span class="c"&gt;# change directory to backend/FRONTEND/src&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;src
&lt;span class="nb"&gt;touch &lt;/span&gt;App.svelte
&lt;span class="nb"&gt;touch &lt;/span&gt;MovieList.svelte
&lt;span class="nb"&gt;touch &lt;/span&gt;MoviePage.svelte
&lt;span class="nb"&gt;touch &lt;/span&gt;api.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2 - Webpack configuration
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What is webpack ?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Webpack is a module bundler and a task runner. We will bundle all our JavaScript application including CSS styling into two JavaScript files, if you prefer you can output only one file. Because of the rich plugins, you can also do many things with Webpack like compressing with different algorithms, eliminate unused CSS code, extracting your CSS to different files, uploading your bundle to cloud provider like S3 etc…&lt;/p&gt;

&lt;p&gt;I made two different Webpack settings in one file. One is for development environment, and the other one is for production environment. Also note that we do not optimize these configurations.&lt;/p&gt;

&lt;p&gt;Copy/Paste the following code into  *****&lt;strong&gt;&lt;em&gt;webpack.config.js&lt;/em&gt;&lt;/strong&gt;*****  file.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MiniCssExtractPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mini-css-extract-plugin&lt;/span&gt;&lt;span class="dl"&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;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&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;mode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;development&lt;/span&gt;&lt;span class="dl"&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;isEnvProduction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&lt;/span&gt;&lt;span class="dl"&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;productionSettings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;bundle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./index.js&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="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;svelte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node_modules&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&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="na"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.mjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;mainFields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;browser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;main&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="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../static&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;js/[name].js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;chunkFilename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;js/[name].[id].js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;optimization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;minimize&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="na"&gt;runtimeChunk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;rules&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="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;svelte$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="na"&gt;emitCss&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="na"&gt;hotReload&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="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;css$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                    &lt;span class="cm"&gt;/**
                     * MiniCssExtractPlugin doesn't support HMR.
                     * For developing, use 'style-loader' instead.
                     * */&lt;/span&gt;
                    &lt;span class="nx"&gt;MiniCssExtractPlugin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;css-loader&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="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;devtool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MiniCssExtractPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[name].css&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="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;devSettings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;bundle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./index.js&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="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;svelte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node_modules&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&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="na"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.mjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;mainFields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;browser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;main&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="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;publicPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;static/js/bundle.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;chunkFilename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;static/js/[name].chunk.js&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="na"&gt;devtool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;source-map&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;devServer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;historyApiFallback&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="na"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;minimal&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="na"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;rules&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="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;svelte$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="na"&gt;emitCss&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="na"&gt;hotReload&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="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;css$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                    &lt;span class="cm"&gt;/**
                     * MiniCssExtractPlugin doesn't support HMR.
                     * For developing, use 'style-loader' instead.
                     * */&lt;/span&gt;
                    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;style-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;css-loader&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="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isEnvProduction&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;productionSettings&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;devSettings&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3 - Create a Single-Page-App witth Svelte
&lt;/h3&gt;

&lt;p&gt;First, fill the '&lt;strong&gt;backend/FRONTEND/index.js'.&lt;/strong&gt;&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;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/App.svelte&lt;/span&gt;&lt;span class="dl"&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, fill the 'App.svelte' file with proper logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- App.svelte --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;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;Router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Route&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;svelte-routing&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="nx"&gt;MovieList&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;./MovieList.svelte&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="nx"&gt;MoviePage&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;./MoviePage.svelte&lt;/span&gt;&lt;span class="dl"&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;let&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;Router&lt;/span&gt; &lt;span class="na"&gt;url=&lt;/span&gt;&lt;span class="s"&gt;"{url}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;nav&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navbar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Link&lt;/span&gt; &lt;span class="na"&gt;to=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/Link&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"main-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Route&lt;/span&gt; &lt;span class="na"&gt;path=&lt;/span&gt;&lt;span class="s"&gt;"movie/:slug"&lt;/span&gt; &lt;span class="na"&gt;component=&lt;/span&gt;&lt;span class="s"&gt;"{MoviePage}"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Route&lt;/span&gt; &lt;span class="na"&gt;path=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;MovieList&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;/Route&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Router&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="nc"&gt;.navbar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0.6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt; &lt;span class="m"&gt;64px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nc"&gt;.main-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;32px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.15&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before routing pages, I will first write the client-side queries. Please open api.js and copy/paste the code below.&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GraphQLProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reportCacheErrors&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;graphql-svelte&lt;/span&gt;&lt;span class="dl"&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GraphQLProvider&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://127.0.0.1:8000/graphql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content-type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&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="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cache&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reportCacheErrors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;





&lt;span class="c1"&gt;// our first query will requests all movies&lt;/span&gt;
&lt;span class="c1"&gt;// with only given fields&lt;/span&gt;
&lt;span class="c1"&gt;// note the usage of string literals (`)&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;MOVIE_LIST_QUERY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
    query movieList{
        movieList{
            name, posterUrl, slug
        }
    }
`&lt;/span&gt;

&lt;span class="c1"&gt;// Note the usage of argument.&lt;/span&gt;
&lt;span class="c1"&gt;// the exclamation mark makes the slug argument as required&lt;/span&gt;
&lt;span class="c1"&gt;// without it , argument will be optional&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;MOVIE_QUERY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
    query movie($slug:String!){
        movie(slug:$slug){
            id, name, year, summary, posterUrl, slug
        }
    }
`&lt;/span&gt;

&lt;span class="c1"&gt;// This is generic query function&lt;/span&gt;
&lt;span class="c1"&gt;// We will use this with one of the above queries and&lt;/span&gt;
&lt;span class="c1"&gt;// variables if needed&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;variables&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;variables&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;response&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;



&lt;p&gt;Now, route pages: MovieList.svelte will be shown on homepage as we defined in the above. If user clicks any movie card, then MoviePage.svelte file will be rendered.&lt;/p&gt;

&lt;p&gt;Fill the MovieList.svelte.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;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;Router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Route&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;svelte-routing&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="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MOVIE_QUERY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MOVIE_LIST_QUERY&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;./api.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;movielist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MOVIE_LIST_QUERY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"wrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- promise is pending --&amp;gt;&lt;/span&gt;
    {#await movielist}
        loading

    &lt;span class="c"&gt;&amp;lt;!-- promise was fulfilled --&amp;gt;&lt;/span&gt;
    {:then response}
        {#if response.data.movieList.length &amp;gt; 0}
            {#each response.data.movieList as movie}
                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;Link&lt;/span&gt; &lt;span class="na"&gt;to=&lt;/span&gt;&lt;span class="s"&gt;{`/movie/${movie.slug}`}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"poster"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;{movie.name}&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;{movie.posterUrl}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"movie-title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{movie.name}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/Link&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            {/each}
        {/if}

    &lt;span class="c"&gt;&amp;lt;!-- promise was rejected --&amp;gt;&lt;/span&gt;
    {:catch error}
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Something went wrong: {error.message}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    {/await}
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="nc"&gt;.wrapper&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;flex-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;200px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;16px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nc"&gt;.poster&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nc"&gt;.movie-title&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;4px&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;



&lt;p&gt;Also fill MoviePage.svelte according to this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;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;Router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Route&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;svelte-routing&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="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MOVIE_QUERY&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;./api.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// acquired from dynamic route part =&amp;gt; /movie/:slug&lt;/span&gt;
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;slug&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;moviedata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MOVIE_QUERY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"wrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- promise is pending --&amp;gt;&lt;/span&gt;
    {#await moviedata}
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Movie {slug} is loading&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- promise was fulfilled --&amp;gt;&lt;/span&gt;
    {:then moviedata}
        {#if moviedata.data}
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"movie-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; 
                    &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;{moviedata.data.movie.posterUrl}&lt;/span&gt; 
                    &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;{`${moviedata.data.movie.name}&lt;/span&gt; &lt;span class="na"&gt;poster&lt;/span&gt;&lt;span class="err"&gt;`}&lt;/span&gt; 
                    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"movie-poster"&lt;/span&gt;
                &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-box"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"movie-title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{moviedata.data.movie.name}&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"movie-description"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{moviedata.data.movie.summary}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        {/if}

    &lt;span class="c"&gt;&amp;lt;!-- promise was rejected --&amp;gt;&lt;/span&gt;
    {:catch error}
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Something went wrong: {error.message}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    {/await}
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="nc"&gt;.wrapper&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nc"&gt;.movie-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;flex-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;500px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nc"&gt;.movie-poster&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;250px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nc"&gt;.text-box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;






&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.com%2Fimages%2Fpost-single-page-django-svelte-app-final.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.com%2Fimages%2Fpost-single-page-django-svelte-app-final.jpg" alt="Graphql and Svelte with Django" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Start Svelte App in Development Environment
&lt;/h2&gt;

&lt;p&gt;In the development environment we will run two different servers. When our Svelte app is running, it requests data from Django server. After the response come, Webpack Development server render the page with proper data. This is only for development stage.&lt;/p&gt;

&lt;p&gt;When we finish the front-end development, we will build and bundle client-side app. After then we will start Django server, and it will be the only server we will use in production environment, as I promise before.&lt;/p&gt;

&lt;p&gt;Go to the root folder of the Django project. '*&lt;strong&gt;&lt;em&gt;backend/'&lt;/em&gt;&lt;/strong&gt;*&lt;/p&gt;

&lt;p&gt;Execute the below command and make the Django server ready for front-end requests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# execute it on the root folder of Django 'backend/'
python manage.py runserver

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

&lt;/div&gt;



&lt;p&gt;Open another terminal and change the directory to the '&lt;strong&gt;backend/FRONTEND&lt;/strong&gt;'&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# On another terminal
npm run start

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

&lt;/div&gt;



&lt;p&gt;When Svelte app successfully compiled, open your browser 'localhost:8080/'.&lt;/p&gt;

&lt;p&gt;You should see similar screen like the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.com%2Fimages%2Fpost-MovieList.svelte.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.com%2Fimages%2Fpost-MovieList.svelte.jpg" alt="List of movies screen" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MovieList.svelte will render the screen&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.com%2Fimages%2Fpost-MoviePage.svelte.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcbsofyalioglu.com%2Fimages%2Fpost-MoviePage.svelte.jpg" alt="Movie page screen" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MoviePage.svelte screen will render this if the user clicks any movie card&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What will be happened at the moment?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At this moment,  &lt;strong&gt;“/“&lt;/strong&gt; root page will be rendered. Because of our routing configurations, MovieList.svelte file will be rendered first. If the user clicks any film card, then the MoviePage.svelte file will be rendered regarding its slug value.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;We succesfully integrated Django and Svelte. Now make the production build.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Django and Svelte Integration in Production Environment
&lt;/h2&gt;

&lt;p&gt;Now you can stop webpack server while  &lt;strong&gt;keeping the Django server alive&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the backend/FRONTEND/ directory, execute the command below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run build

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

&lt;/div&gt;



&lt;p&gt;This will build and bundle all your Svelte app in bundle.js file. When bundling process is over, go to the URL of Django server in your browser. --&amp;gt; "127.0.0.1:8000/"&lt;/p&gt;

&lt;p&gt;You should see the same screens above. Also note the static folder which has new files coming from webpack bundling.&lt;/p&gt;

&lt;p&gt;FINISHED&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/canburaks/django-and-modern-js-libraries" rel="noopener noreferrer"&gt;This is the code repo of all three parts.&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;(Note:This article is originally published on &lt;a href="https://www.cbsofyalioglu.com/post/django-and-modern-js-libraries-svelte" rel="noopener noreferrer"&gt;cbsofyalioglu.com&lt;/a&gt; while building the websites of &lt;a href="https://istanbultransferexpert.con" rel="noopener noreferrer"&gt;Istanbul Airport Transfer&lt;/a&gt;, &lt;a href="https://istanbulcruisetransfer.com" rel="noopener noreferrer"&gt;Istanbul Cruise Port Transfer&lt;/a&gt; and &lt;a href="https://istanbull.org" rel="noopener noreferrer"&gt;Istanbul Travel Guide&lt;/a&gt;)&lt;/p&gt;

</description>
      <category>django</category>
      <category>python</category>
      <category>svelte</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
