<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ code - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ code - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 23 May 2026 22:20:20 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/code/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Complete Flutter CI/CD Pipeline with Codemagic: From PR Quality Gates to Automated Store Releases ]]>
                </title>
                <description>
                    <![CDATA[ If you've spent any time shipping Flutter apps manually, you already know the drill. Someone on the team finishes a feature, builds the APK locally, signs it (hopefully with the right keystore), uploa ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-complete-flutter-ci-cd-pipeline-with-codemagic/</link>
                <guid isPermaLink="false">69c1dcba30a9b81e3ac436d8</guid>
                
                    <category>
                        <![CDATA[ code magic ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ci-cd ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mobile Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mobile app ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Flutter ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Dart ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwaseyi Fatunmole ]]>
                </dc:creator>
                <pubDate>Tue, 24 Mar 2026 00:37:14 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/914de6f3-5b7f-48ff-a092-1f8d095202e5.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you've spent any time shipping Flutter apps manually, you already know the drill. Someone on the team finishes a feature, builds the APK locally, signs it (hopefully with the right keystore), uploads it somewhere, and notifies the QA team. Repeat for iOS. Repeat for staging. Repeat for production.</p>
<p>And somewhere in that chain, something often goes wrong: an incorrect API key, a missed signing step, a build that worked on one machine and failed on another.</p>
<p>The solution is a properly configured CI/CD pipeline that takes that entire chain out of human hands. And in this article, we're building exactly that using Codemagic.</p>
<h2 id="heading-what-is-codemagic">What is Codemagic?</h2>
<p>Codemagic is a dedicated CI/CD platform built from the ground up specifically for mobile applications.</p>
<p>Unlike general-purpose CI platforms, Codemagic understands Flutter natively. It ships with Flutter pre-installed on its build machines, has dedicated support for Apple code signing, and integrates directly with both the Google Play Store and App Store Connect. This means less configuration noise and more focus on what actually matters , which is your deployment logic.</p>
<p>The pipeline we'll be building covers three distinct stages across both Android and iOS:</p>
<ul>
<li><p>A pull request gate that blocks unverified code from reaching your base branch</p>
</li>
<li><p>A staging pipeline that injects real environment config, builds signed artifacts, and ships them to testers via Firebase App Distribution and TestFlight</p>
</li>
<li><p>A production pipeline that obfuscates builds, uploads crash symbols to Sentry, and submits directly to the Play Store and App Store Connect</p>
</li>
</ul>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a href="#heading-understanding-codemagics-yaml-approach">Understanding Codemagic's YAML Approach</a></p>
</li>
<li><p><a href="#heading-pipeline-architecture">Pipeline Architecture</a></p>
</li>
<li><p><a href="#heading-the-helper-scripts">The Helper Scripts</a></p>
</li>
<li><p><a href="#heading-pr-quality-gate">PR Quality Gate</a></p>
</li>
<li><p><a href="#heading-android-pipeline">Android Pipeline</a></p>
</li>
<li><p><a href="#heading-ios-pipeline">iOS Pipeline</a></p>
</li>
<li><p><a href="#heading-environment-variables-and-secrets-reference">Environment Variables and Secrets Reference</a></p>
</li>
<li><p><a href="#heading-end-to-end-flow">End-to-End Flow</a></p>
</li>
<li><p><a href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>You'll need the following before starting:</p>
<ul>
<li><p>A Flutter app with functional Android and iOS builds</p>
</li>
<li><p>A Codemagic account with your repository connected</p>
</li>
<li><p>A Firebase project with App Distribution set up</p>
</li>
<li><p>A Sentry project configured for your app</p>
</li>
<li><p>A Google Play Console app with at least an internal track ready</p>
</li>
<li><p>An Apple Developer account with App Store Connect access</p>
</li>
<li><p>A Google Play service account with the necessary API permissions</p>
</li>
<li><p>Familiarity with writing Bash scripts</p>
</li>
</ul>
<h2 id="heading-understanding-codemagics-yaml-approach">Understanding Codemagic's YAML Approach</h2>
<p>Codemagic offers a visual workflow editor for teams that prefer a GUI – but we're not using that here. The <code>codemagic.yaml</code> approach gives you version-controlled, reviewable, fully reproducible pipeline definitions that live right alongside your application code. Any change to the pipeline goes through the same PR process as any other change. That matters in a team environment.</p>
<p>The file lives at the root of your project:</p>
<pre><code class="language-plaintext">your-flutter-app/
  codemagic.yaml     
  lib/
  android/
  ios/
  scripts/
</code></pre>
<p>Codemagic detects this file when a build is triggered and executes the appropriate workflow based on the rules you define. One file, multiple workflows, all environments – no duplication.</p>
<h2 id="heading-pipeline-architecture">Pipeline Architecture</h2>
<p>Before writing any YAML, it helps to define exactly what the pipeline needs to do. The use case here is a team with three protected branches: <code>develop</code>, <code>staging</code>, and <code>production</code>. Each branch represents a distinct stage in the release lifecycle, and the pipeline behaves differently depending on which branch triggered it.</p>
<p>Here is how the three environments map to pipeline behaviour:</p>
<p><strong>PR into develop</strong>: When a developer raises a pull request targeting the <code>develop</code> branch, a quality gate workflow fires. It runs code formatting checks, static analysis, the full test suite, and enforces a minimum coverage threshold. The PR cannot be considered clean until all of these pass.</p>
<p><strong>Push to develop or staging</strong>: When code lands on either of these branches, the platform-specific build pipelines trigger. They detect the target branch, inject the correct environment configuration (dev or staging API keys), build signed artifacts, and distribute them to the appropriate testing channels: Firebase App Distribution for Android, TestFlight for iOS.</p>
<p><strong>Push to production</strong>: When code reaches the production branch, the pipelines switch into release mode. Builds are obfuscated, debug symbols are uploaded to Sentry for crash observability, and the final artifacts are submitted directly to the Play Store and App Store Connect.</p>
<p>Your project structure will look like this:</p>
<pre><code class="language-plaintext">codemagic.yaml

scripts/
  generate_config.sh
  quality_checks.sh
  upload_symbols.sh

lib/
  core/
    env/
      env_ci.dart       
      env_ci.g.dart     
</code></pre>
<h2 id="heading-the-helper-scripts">The Helper Scripts</h2>
<p>Rather than cramming logic directly into YAML, this pipeline delegates its core operations to three Bash scripts that live in a <code>scripts/</code> folder at the project root. This keeps the YAML readable and, crucially, means you can run the exact same logic on your local machine that CI runs – eliminating an entire class of "works on my machine" issues.</p>
<p>Make all three scripts executable before committing them:</p>
<pre><code class="language-bash">chmod +x scripts/generate_config.sh
chmod +x scripts/quality_checks.sh
chmod +x scripts/upload_symbols.sh
</code></pre>
<h3 id="heading-generateconfigsh">generate_config.sh</h3>
<p>Injecting secrets safely is one of the hardest CI/CD problems in mobile development. The strategy here avoids committing credentials entirely: a Dart file with placeholder values is committed to source control, and at build time the script replaces those placeholders with real values sourced from Codemagic's encrypted secret storage.</p>
<pre><code class="language-bash">#!/usr/bin/env bash
set -euo pipefail

# Usage: ./scripts/generate_config.sh ENV_NAME BASE_URL ENCRYPTION_KEY
ENV_NAME=${1:-}
BASE_URL=${2:-}
ENCRYPTION_KEY=${3:-}

TEMPLATE="lib/core/env/env_ci.dart"
OUT="lib/core/env/env_ci.g.dart"

if [ -z "\(ENV_NAME" ] || [ -z "\)BASE_URL" ] || [ -z "$ENCRYPTION_KEY" ]; then
  echo "Usage: $0 &lt;env-name&gt; &lt;base-url&gt; &lt;encryption-key&gt;"
  exit 2
fi

sed -e "s|&lt;&lt;BASE_URL&gt;&gt;|$BASE_URL|g" \
    -e "s|&lt;&lt;ENCRYPTION_KEY&gt;&gt;|$ENCRYPTION_KEY|g" \
    -e "s|&lt;&lt;ENV_NAME&gt;&gt;|$ENV_NAME|g" \
    "\(TEMPLATE" &gt; "\)OUT"

echo "✅ Generated config for $ENV_NAME"
</code></pre>
<p><strong>How it works:</strong></p>
<p><code>set -euo pipefail</code> enforces strict failure behaviour. <code>-e</code> exits immediately on any failed command, <code>-u</code> exits on undefined variables, and <code>-o pipefail</code> catches failures anywhere in a pipeline – not just the last command. In CI, silent failures can produce broken builds that look like they succeeded. This line prevents that.</p>
<p>The script takes three positional arguments: the environment name (<code>dev</code>, <code>staging</code>, or <code>production</code>), the API base URL, and an encryption or API key. The <code>${1:-}</code> syntax defaults to an empty string if an argument is missing, which the validation block then catches explicitly with a clear usage message and an exit code of <code>2</code> (the conventional code for incorrect usage).</p>
<p>At the heart of the script, <code>sed</code> performs three placeholder replacements in a single pass over the template file, writing the result to <code>env_ci.g.dart</code>. That generated file must be added to <code>.gitignore</code>. It only ever exists inside a running build or on a developer's local machine after they run the script manually.</p>
<p>The two Dart files involved have completely different roles:</p>
<p><code>env_ci.dart</code> – committed to source control, contains only placeholders:</p>
<pre><code class="language-dart">// lib/core/env/env_ci.dart
class EnvConfig {
  static const String baseUrl = '&lt;&lt;BASE_URL&gt;&gt;';
  static const String encryptionKey = '&lt;&lt;ENCRYPTION_KEY&gt;&gt;';
  static const String environment = '&lt;&lt;ENV_NAME&gt;&gt;';
}
</code></pre>
<p><code>env_ci.g.dart</code> – generated at build time, contains real values, never committed:</p>
<pre><code class="language-dart">// lib/core/env/env_ci.g.dart
// GENERATED FILE — DO NOT COMMIT
class EnvConfig {
  static const String baseUrl = 'https://staging.api.example.com';
  static const String encryptionKey = 'sk_live_xxxxx';
  static const String environment = 'staging';
}
</code></pre>
<p>Add the generated file to <code>.gitignore</code>:</p>
<pre><code class="language-plaintext"># Generated environment config
lib/core/env/env_ci.g.dart
</code></pre>
<h3 id="heading-qualitycheckssh">quality_checks.sh</h3>
<p>This script defines what passing quality means for your codebase. Every check it runs is a gate: if any step fails, the script stops immediately and the build fails.</p>
<pre><code class="language-bash">#!/usr/bin/env bash
set -euo pipefail

echo "🚀 Running quality checks"

dart format --output=none --set-exit-if-changed .
flutter analyze
flutter test --no-pub --coverage

if command -v dart_code_metrics &gt;/dev/null 2&gt;&amp;1; then
  dart_code_metrics analyze lib --reporter=console || true
fi

echo "✅ Quality checks passed"
</code></pre>
<p><strong>What each step does:</strong></p>
<p><code>dart format --output=none --set-exit-if-changed .</code>: checks that all Dart files are formatted correctly without modifying them. If any file doesn't match the formatter's output, the command exits with a non-zero code, failing the build. Formatting is non-negotiable here.</p>
<p><code>flutter analyze</code>: runs Dart's static analyser across the entire project. It catches null safety violations, unused imports, missing awaits, dead code, and a wide range of structural issues before they reach a reviewer's eyes.</p>
<p><code>flutter test --no-pub --coverage</code>: runs the full test suite and generates a coverage report at <code>coverage/lcov.info</code>. The <code>--no-pub</code> flag skips <code>pub get</code> since dependencies are already installed. The coverage file is used downstream to enforce a minimum threshold.</p>
<p>The <code>dart_code_metrics</code> block is deliberately optional and non-blocking (<code>|| true</code>). The tool may not be installed in every environment, and its findings are advisory rather than hard failures. You can remove the <code>|| true</code> later to make it mandatory once your team has adopted the tool.</p>
<p>The final <code>echo</code> line only executes if every step above it passed , because <code>set -e</code> would have exited the script on any earlier failure. If you see it in the logs, the branch is clean.</p>
<h3 id="heading-uploadsymbolssh">upload_symbols.sh</h3>
<p>When Flutter production builds are compiled with <code>--obfuscate</code>, stack traces in crash reports become unreadable. This script uploads the debug symbol files that Sentry needs to reverse that obfuscation and show readable crash reports.</p>
<pre><code class="language-bash">#!/usr/bin/env bash
set -euo pipefail

RELEASE=${1:-}

[ -z "$RELEASE" ] &amp;&amp; exit 2

if ! command -v sentry-cli &gt;/dev/null 2&gt;&amp;1; then
  exit 0
fi

sentry-cli releases new "$RELEASE" || true
sentry-cli upload-dif build/symbols || true
sentry-cli releases finalize "$RELEASE" || true

echo "✅ Symbols uploaded for release $RELEASE"
</code></pre>
<p><strong>How it works:</strong></p>
<p>The script takes a single argument: a release identifier. In practice, this is always the short Git commit SHA, passed from the workflow as <code>$(git rev-parse --short HEAD)</code>. This ties the uploaded symbols, the deployed build, and the crash reports in Sentry to the exact same commit , which is essential for production debugging.</p>
<p>If <code>sentry-cli</code> is not installed in the environment, the script exits with <code>0</code> rather than failing. This makes symbol uploads environment-aware: production machines install the CLI, development environments skip the step cleanly without breaking the build.</p>
<p>Each <code>sentry-cli</code> command uses <code>|| true</code> for resilience. Symbol uploads should never block a deployment , if the upload encounters a transient issue, the build should still succeed and the symbols can be re-uploaded manually from the stored artifacts.</p>
<p>The three commands do the following in sequence: <code>releases new</code> registers the release version in Sentry, <code>upload-dif</code> sends the debug information files from <code>build/symbols</code> (generated by <code>--split-debug-info</code>), and <code>releases finalize</code> marks the release as deployed and ready to aggregate crash reports.</p>
<h2 id="heading-the-codemagicyaml-structure">The codemagic.yaml Structure</h2>
<p>A <code>codemagic.yaml</code> file is organized around workflows. Each workflow is an independent pipeline definition with its own trigger rules, environment configuration, build scripts, and publishing targets. Multiple workflows live inside the same file under a top-level <code>workflows</code> key.</p>
<p>The skeleton looks like this:</p>
<pre><code class="language-yaml">workflows:
  pr-quality-gate:
    # triggers on pull requests
    # runs quality checks only

  android-pipeline:
    # triggers on push to develop, staging, production
    # handles Android builds and distribution

  ios-pipeline:
    # triggers on push to develop, staging, production
    # handles iOS builds and distribution
</code></pre>
<p>Each workflow can define its own machine type, environment variables, triggering conditions, and step scripts. This is what makes a single <code>codemagic.yaml</code> powerful: you're not managing three separate files, but you still get complete isolation between pipeline stages.</p>
<h2 id="heading-pr-quality-gate">PR Quality Gate</h2>
<p>Every PR raised against <code>develop</code> must pass a quality gate before any merge is allowed. This workflow runs on Codemagic's Linux machines since it doesn't need to produce a signed artifact for any platform – it only needs to verify the code.</p>
<pre><code class="language-yaml">workflows:
  pr-quality-gate:
    name: PR Quality Gate
    max_build_duration: 30
    instance_type: linux_x2

    triggering:
      events:
        - pull_request
      branch_patterns:
        - pattern: develop
          include: true
          source: true

    environment:
      flutter: stable

    scripts:
      - name: Install dependencies
        script: flutter pub get

      - name: Run quality checks
        script: ./scripts/quality_checks.sh

      - name: Enforce coverage threshold
        script: |
          COVERAGE=\((lcov --summary coverage/lcov.info | grep lines | awk '{print \)2}' | sed 's/%//')
          if [ \((echo "\)COVERAGE &lt; 70" | bc) -eq 1 ]; then
            echo "Test coverage is at ${COVERAGE}% — minimum required is 70%"
            exit 1
          fi
          echo "Coverage at ${COVERAGE}% — threshold met"

    publishing:
      email:
        recipients:
          - your-team@example.com
        notify:
          success: true
          failure: true
</code></pre>
<p>Let's walk through what each section is doing.</p>
<p><code>instance_type: linux_x2</code></p>
<p>Codemagic offers different machine types for different workloads. For a quality gate that only needs to run Dart tooling, a Linux machine is perfectly sufficient and significantly cheaper than a macOS instance. You reserve the macOS machines for builds that actually need Xcode.</p>
<p><code>triggering</code></p>
<p>This is how Codemagic decides when to run a workflow. The <code>pull_request</code> event fires whenever a PR is opened or updated. The <code>branch_patterns</code> block tells Codemagic to watch for PRs targeting <code>develop</code> specifically. The <code>source: true</code> flag means this pattern applies to the target branch of the PR, not the source branch – so any branch raising a PR into <code>develop</code> will trigger this workflow.</p>
<p><code>environment</code></p>
<p>Codemagic's Flutter-aware machines come with multiple Flutter versions available. Setting <code>flutter: stable</code> pins the workflow to the current stable channel without requiring any manual SDK installation step. This is one of the areas where Codemagic saves setup time compared to a general-purpose runner.</p>
<p><strong>Quality checks script</strong></p>
<p>The workflow delegates to <code>quality_checks.sh</code> rather than inlining commands. This keeps the YAML readable and ensures the exact same logic runs when a developer calls the script locally. The script handles formatting, analysis, and test execution internally.</p>
<p><strong>Coverage enforcement</strong></p>
<p>After the tests run, <code>lcov</code> parses the coverage report generated by <code>flutter test --coverage</code> and extracts the line coverage percentage. If it falls below 70%, the build fails with a clear message. This threshold is something your team should agree on , 70% is a reasonable starting point for most projects.</p>
<p><code>publishing</code></p>
<p>Codemagic has native email notification support built in. Rather than scripting <code>echo</code> statements into CI logs, you declare recipients directly in the workflow and Codemagic handles delivery. Both success and failure states are covered.</p>
<h2 id="heading-android-pipeline">Android Pipeline</h2>
<p>The Android workflow handles all three environments in a single workflow definition, using Codemagic's environment variable groups and conditional scripting to behave differently depending on which branch triggered the build.</p>
<pre><code class="language-yaml">  android-pipeline:
    name: Android Build &amp; Release
    max_build_duration: 60
    instance_type: linux_x2

    triggering:
      events:
        - push
      branch_patterns:
        - pattern: develop
          include: true
        - pattern: staging
          include: true
        - pattern: production
          include: true

    environment:
      flutter: stable
      android_signing:
        - android_keystore
      groups:
        - staging_secrets
        - production_secrets
        - firebase_credentials
        - sentry_credentials

    scripts:
      - name: Install dependencies
        script: flutter pub get

      - name: Detect environment
        script: |
          BRANCH=$(git rev-parse --abbrev-ref HEAD)
          if [ "$BRANCH" = "develop" ]; then
            echo "ENV=dev" &gt;&gt; $CM_ENV
          elif [ "$BRANCH" = "staging" ]; then
            echo "ENV=staging" &gt;&gt; $CM_ENV
          else
            echo "ENV=production" &gt;&gt; $CM_ENV
          fi

      - name: Generate environment config
        script: |
          if [ "$ENV" = "dev" ]; then
            ./scripts/generate_config.sh dev "https://dev.api.example.com" "dev_dummy_key"
          elif [ "$ENV" = "staging" ]; then
            ./scripts/generate_config.sh staging "\(STAGING_BASE_URL" "\)STAGING_API_KEY"
          else
            ./scripts/generate_config.sh production "\(PROD_BASE_URL" "\)PROD_API_KEY"
          fi

      - name: Build Android artifact
        script: |
          if [ "$ENV" = "production" ]; then
            flutter build appbundle --release \
              --obfuscate \
              --split-debug-info=build/symbols
          else
            flutter build appbundle --release
          fi

      - name: Distribute to Firebase App Distribution
        script: |
          if [ "\(ENV" = "dev" ] || [ "\)ENV" = "staging" ]; then
            firebase appdistribution:distribute \
              build/app/outputs/bundle/release/app-release.aab \
              --app "$FIREBASE_ANDROID_APP_ID" \
              --groups "$FIREBASE_GROUPS" \
              --token "$FIREBASE_TOKEN"
          fi

      - name: Submit to Play Store
        script: |
          if [ "$ENV" = "production" ]; then
            echo "$GOOGLE_PLAY_SERVICE_ACCOUNT_JSON" &gt; /tmp/service_account.json
            flutter pub global activate fastlane 2&gt;/dev/null || true
            fastlane supply \
              --aab build/app/outputs/bundle/release/app-release.aab \
              --json_key /tmp/service_account.json \
              --package_name com.your.package \
              --track production
          fi

      - name: Upload Sentry symbols
        script: |
          if [ "$ENV" = "production" ]; then
            ./scripts/upload_symbols.sh $(git rev-parse --short HEAD)
          fi

    artifacts:
      - build/app/outputs/bundle/release/app-release.aab
      - build/symbols/**

    publishing:
      email:
        recipients:
          - your-team@example.com
        notify:
          success: true
          failure: true
</code></pre>
<p>Here is what each section is doing and why it's designed this way.</p>
<p><code>android_signing</code></p>
<p>This is one of Codemagic's most valuable features. Instead of manually decoding a Base64 keystore and writing it to disk inside a script, you upload your keystore file directly to Codemagic's encrypted key storage under Teams → Code signing identities → Android keystores. You give it a reference name – <code>android_keystore</code> in this case – and Codemagic handles decoding, placement, and <code>key.properties</code> generation automatically before your build scripts run.</p>
<p>This eliminates an entire category of signing-related build failures.</p>
<p><code>groups</code></p>
<p>Codemagic lets you organize secrets into named groups in the environment variables section of your team settings. Rather than declaring individual secrets inline, you reference groups. The groups used here are:</p>
<ul>
<li><p><code>staging_secrets</code>: contains <code>STAGING_BASE_URL</code> and <code>STAGING_API_KEY</code></p>
</li>
<li><p><code>production_secrets</code>: contains <code>PROD_BASE_URL</code> and <code>PROD_API_KEY</code></p>
</li>
<li><p><code>firebase_credentials</code>: contains <code>FIREBASE_TOKEN</code>, <code>FIREBASE_ANDROID_APP_ID</code>, <code>FIREBASE_GROUPS</code></p>
</li>
<li><p><code>sentry_credentials</code>: contains <code>SENTRY_AUTH_TOKEN</code>, <code>SENTRY_ORG</code>, <code>SENTRY_PROJECT</code></p>
</li>
</ul>
<p><strong>Environment detection with</strong> <code>$CM_ENV</code></p>
<p>Codemagic exposes a special file path via the <code>$CM_ENV</code> variable. Writing <code>KEY=VALUE</code> to this file makes that variable available to every subsequent script step in the same build. This is how the branch name gets translated into an environment label that the rest of the pipeline reads.</p>
<p><strong>Build differentiation</strong></p>
<p>Production builds use <code>--obfuscate</code> and <code>--split-debug-info=build/symbols</code>. Dev and staging builds skip both flags for faster compilation and readable local stack traces.</p>
<p><strong>Firebase distribution</strong></p>
<p>The Firebase CLI distributes dev and staging builds to testers. Because Codemagic's Linux machines come with Node.js available, you can install the Firebase CLI with <code>npm install -g firebase-tools</code> as a setup step if it is not already present, or invoke it via <code>npx</code>.</p>
<p><strong>Play Store submission</strong></p>
<p>Production app bundles go to the Play Store using Fastlane's <code>supply</code> command. The service account JSON is written to a temporary file from the environment variable and passed to Fastlane directly. Replace <code>com.your.package</code> with your actual application ID.</p>
<p><code>artifacts</code></p>
<p>The artifacts section tells Codemagic which files to preserve after the build completes. These files become downloadable from the Codemagic build dashboard. The debug symbols are captured here as well, which is useful for manual Sentry uploads if the automated step ever needs to be re-run.</p>
<h2 id="heading-ios-pipeline">iOS Pipeline</h2>
<p>iOS on Codemagic is where the platform's advantage becomes most visible. Apple code signing on a general-purpose runner requires a multi-step keychain dance involving <code>security</code> commands, certificate imports, and provisioning profile placement. Codemagic handles all of that automatically through its native signing integration.</p>
<pre><code class="language-yaml">  ios-pipeline:
    name: iOS Build &amp; Release
    max_build_duration: 90
    instance_type: mac_mini_m2

    triggering:
      events:
        - push
      branch_patterns:
        - pattern: develop
          include: true
        - pattern: staging
          include: true
        - pattern: production
          include: true

    environment:
      flutter: stable
      ios_signing:
        distribution_type: app_store
        bundle_identifier: com.your.bundle.id
      groups:
        - staging_secrets
        - production_secrets
        - app_store_credentials
        - sentry_credentials

    scripts:
      - name: Install dependencies
        script: flutter pub get

      - name: Install Fastlane dependencies
        script: |
          cd ios
          gem install bundler --user-install
          bundle install

      - name: Detect environment
        script: |
          BRANCH=$(git rev-parse --abbrev-ref HEAD)
          if [ "$BRANCH" = "develop" ]; then
            echo "ENV=dev" &gt;&gt; $CM_ENV
          elif [ "$BRANCH" = "staging" ]; then
            echo "ENV=staging" &gt;&gt; $CM_ENV
          else
            echo "ENV=production" &gt;&gt; $CM_ENV
          fi

      - name: Generate environment config
        script: |
          if [ "$ENV" = "dev" ]; then
            ./scripts/generate_config.sh dev "https://dev.api.example.com" "dev_dummy_key"
          elif [ "$ENV" = "staging" ]; then
            ./scripts/generate_config.sh staging "\(STAGING_BASE_URL" "\)STAGING_API_KEY"
          else
            ./scripts/generate_config.sh production "\(PROD_BASE_URL" "\)PROD_API_KEY"
          fi

      - name: Build iOS (dev — no signing)
        script: |
          if [ "$ENV" = "dev" ]; then
            flutter build ios --release --no-codesign
          fi

      - name: Build and ship to TestFlight (staging)
        script: |
          if [ "$ENV" = "staging" ]; then
            flutter build ipa --release \
              --export-options-plist=/Users/builder/export_options.plist
            cd ios &amp;&amp; bundle exec fastlane beta
          fi

      - name: Build and release to App Store (production)
        script: |
          if [ "$ENV" = "production" ]; then
            flutter build ipa --release \
              --obfuscate \
              --split-debug-info=build/symbols \
              --export-options-plist=/Users/builder/export_options.plist
            cd ios &amp;&amp; bundle exec fastlane release
          fi

      - name: Upload Sentry symbols
        script: |
          if [ "$ENV" = "production" ]; then
            ./scripts/upload_symbols.sh $(git rev-parse --short HEAD)
          fi

    artifacts:
      - build/ios/ipa/*.ipa
      - build/symbols/**
      - /tmp/xcodebuild_logs/*.log

    publishing:
      app_store_connect:
        api_key: $APP_STORE_CONNECT_PRIVATE_KEY
        key_id: $APP_STORE_CONNECT_KEY_IDENTIFIER
        issuer_id: $APP_STORE_CONNECT_ISSUER_ID
        submit_to_testflight: true
        submit_to_app_store: false
      email:
        recipients:
          - your-team@example.com
        notify:
          success: true
          failure: true
</code></pre>
<p>Here's what is different from the Android workflow and why.</p>
<p><code>mac_mini_m2</code></p>
<p>iOS builds require Xcode, which means they need macOS. Codemagic provides Apple Silicon Mac Mini instances. These are meaningfully faster than Intel-based runners for Flutter and Xcode workloads, and Codemagic provisions them on demand without any infrastructure management on your side.</p>
<p><code>ios_signing</code></p>
<p>This is the section that replaces the entire keychain setup sequence. You upload your distribution certificate and provisioning profile once to Codemagic's code signing identities under your team settings. The <code>distribution_type: app_store</code> tells Codemagic to use App Store distribution signing, and <code>bundle_identifier</code> ties it to your specific app. Before your scripts run, Codemagic installs the certificate and profile automatically on the build machine.</p>
<p>No <code>security</code> commands, no keychain creation, no Base64 decoding. It's handled internally.</p>
<p><code>flutter build ipa</code></p>
<p>On iOS, the build output is an <code>.ipa</code> file rather than an <code>.aab</code>. Flutter's <code>flutter build ipa</code> command produces this directly when provided with an export options plist. The plist tells Xcode how to sign and package the output. Codemagic generates this file automatically based on your <code>ios_signing</code> configuration and places it at <code>/Users/builder/export_options.plist</code>.</p>
<p><strong>Fastlane lanes</strong></p>
<p>Codemagic installs Fastlane via Bundler in the <code>ios/</code> directory, then calls the appropriate lane based on the detected environment. The <code>beta</code> lane uploads to TestFlight, and the <code>release</code> lane submits to the App Store.</p>
<p><code>publishing.app_store_connect</code></p>
<p>Codemagic has a native App Store Connect publisher. Rather than scripting the upload manually, you declare your API credentials in the publishing block and Codemagic handles the submission. The <code>submit_to_testflight: true</code> flag means staging builds are automatically available to TestFlight testers after the build completes. For production, you would flip <code>submit_to_app_store</code> to <code>true</code> instead.</p>
<p><strong>Xcode logs as artifacts</strong></p>
<p>The line <code>/tmp/xcodebuild_logs/*.log</code> captures raw Xcode build logs as downloadable artifacts. When an iOS build fails and the error message in the Codemagic dashboard is not specific enough, these logs are where you find the real cause.</p>
<h2 id="heading-environment-variables-and-secrets-reference">Environment Variables and Secrets Reference</h2>
<p>All secrets are configured in Codemagic under Teams → Environment variables. Group them logically so they can be referenced cleanly in the YAML.</p>
<p><strong>staging_secrets group</strong></p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td><code>STAGING_BASE_URL</code></td>
<td>Staging API base URL</td>
</tr>
<tr>
<td><code>STAGING_API_KEY</code></td>
<td>Staging API or encryption key</td>
</tr>
</tbody></table>
<p><strong>production_secrets group</strong></p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td><code>PROD_BASE_URL</code></td>
<td>Production API base URL</td>
</tr>
<tr>
<td><code>PROD_API_KEY</code></td>
<td>Production API or encryption key</td>
</tr>
</tbody></table>
<p><strong>firebase_credentials group</strong></p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td><code>FIREBASE_TOKEN</code></td>
<td>Generated via <code>firebase login:ci</code></td>
</tr>
<tr>
<td><code>FIREBASE_ANDROID_APP_ID</code></td>
<td>Android app ID from Firebase console</td>
</tr>
<tr>
<td><code>FIREBASE_GROUPS</code></td>
<td>Comma-separated tester group names</td>
</tr>
</tbody></table>
<p><strong>app_store_credentials group</strong></p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td><code>APP_STORE_CONNECT_PRIVATE_KEY</code></td>
<td>Contents of the <code>.p8</code> key file from App Store Connect</td>
</tr>
<tr>
<td><code>APP_STORE_CONNECT_KEY_IDENTIFIER</code></td>
<td>Key ID from App Store Connect</td>
</tr>
<tr>
<td><code>APP_STORE_CONNECT_ISSUER_ID</code></td>
<td>Issuer ID from App Store Connect</td>
</tr>
<tr>
<td><code>GOOGLE_PLAY_SERVICE_ACCOUNT_JSON</code></td>
<td>Full JSON of your Play Console service account</td>
</tr>
</tbody></table>
<p><strong>sentry_credentials group</strong></p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td><code>SENTRY_AUTH_TOKEN</code></td>
<td>Auth token from Sentry account settings</td>
</tr>
<tr>
<td><code>SENTRY_ORG</code></td>
<td>Your Sentry organization slug</td>
</tr>
<tr>
<td><code>SENTRY_PROJECT</code></td>
<td>Your Sentry project slug</td>
</tr>
</tbody></table>
<p>For Android code signing, upload your keystore directly under Teams → Code signing identities → Android keystores rather than storing it as an environment variable.</p>
<p>For iOS, upload your distribution certificate and provisioning profile under Teams → Code signing identities → iOS certificates.</p>
<h2 id="heading-end-to-end-flow">End-to-End Flow</h2>
<p>With the full <code>codemagic.yaml</code> in place, here is the complete picture of what happens across a typical release cycle.</p>
<p>A developer finishes a feature and raises a PR into <code>develop</code>. Codemagic detects the pull request event and triggers the <code>pr-quality-gate</code> workflow on a Linux machine. The quality checks script runs formatting, analysis, tests, and coverage threshold check. If anything fails, Codemagic marks the build as failed, sends the team an email, and the PR cannot be considered ready. The developer pushes a fix, Codemagic runs again, and only when everything passes does the PR move forward.</p>
<p>Once the PR merges into <code>develop</code>, both the <code>android-pipeline</code> and <code>ios-pipeline</code> trigger simultaneously. Each detects <code>develop</code> as the source branch, maps it to the dev environment, injects placeholder config, builds an unsigned release artifact, and ships it to Firebase App Distribution. Testers have an installable build within minutes of the merge completing.</p>
<p>When <code>develop</code> is merged into <code>staging</code>, the same two platform pipelines fire again. This time real secrets are injected , the staging API URL, the staging encryption key. Android builds are signed with the keystore Codemagic manages automatically. iOS builds go through Fastlane's <code>beta</code> lane to TestFlight. The Codemagic App Store Connect publisher handles the TestFlight upload natively. QA now has a properly signed, properly configured staging build to test against.</p>
<p>When <code>staging</code> is promoted to <code>production</code>, the pipelines enter release mode. Production secrets are injected. Android builds are obfuscated with debug symbols split into <code>build/symbols</code>. iOS builds go through <code>flutter build ipa</code> with obfuscation enabled. Both platform pipelines call <code>upload_symbols.sh</code> with the current commit SHA, linking the Sentry release to the exact code that shipped. The Android bundle goes to the Play Store via Fastlane. The iOS IPA is submitted to App Store Connect via Codemagic's native publisher. The team receives a success notification.</p>
<p>That's the full cycle. No terminal, no manual step, no shared Slack message saying "I think I deployed staging."</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The pipeline we just built covers the full release lifecycle: automated quality enforcement, environment-aware config injection, platform-specific signed builds, tester distribution, crash observability, and store submission , all from a single <code>codemagic.yaml</code> file.</p>
<p>What Codemagic brings to this setup is a tighter integration with the mobile ecosystem specifically. The keystore management, native App Store Connect publisher, pre-installed Flutter toolchain, and Apple Silicon Mac instances aren't add-ons you configure , they're part of the platform's core. This translates into fewer steps to maintain, fewer failure surfaces, and a pipeline that's easier to reason about when something does go wrong.</p>
<p>The scripts in your <code>scripts/</code> folder remain completely platform-agnostic. If your team ever needs to move pipelines, those scripts move with you unchanged. The YAML changes, but the logic doesn't.</p>
<p>What you have at the end of this setup is a release process your team can trust: one where "did it deploy?" is answered by a notification, not a question in Slack.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Develop with CodeIgniter on Ubuntu – Step-by-Step Environment Setup ]]>
                </title>
                <description>
                    <![CDATA[ CodeIgniter is a popular open-source PHP framework you can use to build dynamic and robust web applications. It’s simple to use, fast, and flexible. This makes it a good option for any developer who wants to have a light yet powerful framework that w... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-develop-with-codeigniter-on-ubuntu-environment-setup/</link>
                <guid isPermaLink="false">6793a7b71b1cdac77474f13a</guid>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ webdev ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ codeigniter ]]>
                    </category>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ valentine Gatwiri ]]>
                </dc:creator>
                <pubDate>Fri, 24 Jan 2025 14:46:15 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1737640002689/7c78cd9c-40ef-45b3-82f6-97bc33f713d7.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>CodeIgniter is a popular open-source PHP framework you can use to build dynamic and robust web applications. It’s simple to use, fast, and flexible. This makes it a good option for any developer who wants to have a light yet powerful framework that will let them prototype or develop scalable applications fast.</p>
<p>Also, CodeIgnitor’s MVC (Model-View-Controller) architecture makes the process of organizing code and separating business logic from the user interface a piece of cake, yielding cleaner and maintainable projects.</p>
<p>Whether you’re building a small website or a complex application, CodeIgniter has a bunch of tools, libraries, and helpers that make the development process easier. They help you handle common tasks like database queries, session management, and form validation. Many devs love this tool because of its ease of use, making it an ideal framework for both beginners and experienced coders.</p>
<p>In this guide, I’ll walk you through the process of configuring CodeIgniter step by step, ensuring that you have a fully functional setup for your project on your local development environment.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>Before getting started, make sure you meet the following requirements:</p>
<ul>
<li><p>Basic Knowledge of PHP: Understanding PHP syntax and basic programming concepts will help you follow along more easily.</p>
</li>
<li><p>Web Server (for example, Apache or NGINX): CodeIgniter needs a server to run. Make sure you have a working server set up on your local machine or hosting environment.</p>
</li>
<li><p>PHP Installed: You’ll need PHP 7.3 or higher (depending on the version of CodeIgniter you’re using).</p>
</li>
<li><p>Database System: CodeIgniter supports several databases, but MySQL is the most commonly used. Make sure you have access to a database system and know its credentials.</p>
</li>
<li><p>CodeIgniter Download: Download the latest version of CodeIgniter from the official website, GitHub repository, or use <code>composer</code> to install it.</p>
</li>
</ul>
<h2 id="heading-how-to-use-composer-to-install-codeigniter">How to Use Composer to Install CodeIgniter</h2>
<p>Now that you understand the prerequisites and have everything set up, let’s move on to installing CodeIgniter. One of the easiest and most efficient ways to install CodeIgniter is by using Composer, a popular dependency management tool for PHP. In this section, I’ll guide you through the steps to install CodeIgniter using Composer.</p>
<p>First, create a new directory using <code>mkdir my_project</code> then navigate to the directory using <code>cd my_project</code>. Run the following Composer command to install CodeIgniter. You can specify the version you want (e.g., <code>^4.0</code> for the latest version of CodeIgniter 4).</p>
<pre><code class="lang-bash">composer create-project codeigniter4/appstarter .
</code></pre>
<p>This command will download and install the latest version of CodeIgniter 4 and set up the project for you:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737222358773/c0be04da-c507-41cf-b98e-8c9126146b31.png" alt="CodeIgnitor download via composer output." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>After the installation is complete, you should see the CodeIgniter project structure in your directory. To check if everything is working, you can start the built-in PHP server by running:</p>
<pre><code class="lang-bash">php spark serve
</code></pre>
<p>Output:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737224950979/8e7ccdac-ce8b-4b71-b41b-5ee02dfd9970.png" alt="Php spark serve output." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Then, open your browser and go to <a target="_blank" href="http://localhost:8080"><code>http://localhost:8080</code></a>. You should see the CodeIgniter welcome page.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737225118799/c7a38536-62fa-4788-814d-cd246a973691.png" alt="CodeIgnitor welcome page." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-install-codeigniter-manually">How to Install CodeIgniter Manually</h2>
<p>If you prefer not to use Composer, or if you’re working in an environment where Composer isn’t available, you can manually install CodeIgniter. This method involves downloading the framework files directly and setting up your project manually. While it requires a few more steps than using Composer, it’s still straightforward and gives you full control over the installation process.</p>
<p>In this section, I’ll walk you through the steps to manually install CodeIgniter and configure it for your project.</p>
<p><strong>Download via Git:</strong></p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> /var/www/html
sudo git <span class="hljs-built_in">clone</span> https://github.com/bcit-ci/CodeIgniter.git codeigniter
</code></pre>
<p>Or <strong>download as ZIP (from CodeIgniter official website):</strong> <a target="_blank" href="https://www.codeigniter.com/download">Download here</a>. Extract it in <code>/var/www/html</code>. Whereby you can do so using the terminal or UI.</p>
<h3 id="heading-extracting-the-zip-file-via-the-ui">Extracting the ZIP File via the UI:</h3>
<p>If you’re not comfortable using command-line tools, you can easily extract the ZIP file using your computer’s graphical interface. Here's how:</p>
<p>Click on <code>files/Other Locations/computer</code> to access <code>/var/www/html</code>. Copy the <code>.Zip</code> file you downloaded earlier in the created folder and <code>right click</code>. Then click on <code>extract here</code> to unzip it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737210782723/25317e2b-151b-491e-8e83-89c32d9cf5ee.png" alt="ZIP Extraction image." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-extracting-the-zip-file-via-the-terminal">Extracting the ZIP File via the Terminal:</h3>
<p>If you’re comfortable using the command line, you can extract the CodeIgniter ZIP file directly via the terminal. This method is especially useful for Linux and macOS users or if you're working on a remote server without a graphical user interface.</p>
<p>First, ensure you have <code>unzip</code> installed on your Ubuntu system:</p>
<pre><code class="lang-bash">sudo apt update
sudo apt install unzip
</code></pre>
<p><strong>Check your permissions</strong> to ensure that you have the necessary access to the <code>/var/www/html</code> directory. If needed, use <code>sudo</code> for administrative privileges.</p>
<h3 id="heading-steps-to-extract-the-file">Steps to Extract the File</h3>
<p>Assuming your uploaded file is currently located in <code>downloads/data…</code>, move it to <code>/var/www/html</code>:</p>
<pre><code class="lang-bash">sudo mv /mnt/data/CodeIgniter.zip /var/www/html
</code></pre>
<p>Navigate to the <code>/var/www/html</code>directory:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> /var/www/html
</code></pre>
<p>Extract the ZIP file by using the <code>unzip</code> command to extract the contents:</p>
<pre><code class="lang-bash">sudo unzip CodeIgniter.zip
</code></pre>
<p>After extracting, set the correct ownership and permissions for web server access:</p>
<pre><code class="lang-bash">sudo chown -R www-data:www-data /var/www/html
sudo chmod -R 755 /var/www/html
</code></pre>
<blockquote>
<ul>
<li><p><code>www-data</code> (first part) → The <strong>user</strong>.</p>
</li>
<li><p><code>www-data</code> (second part) → The <strong>group</strong>.</p>
</li>
</ul>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737212632072/6240acc1-27bd-49fe-acd4-5b3f80a92163.png" alt="Extracted folder(Codeigniter-develop) image." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<blockquote>
<p>change <code>Codeigniter-develop /bcit-ci-CodeIgniter-bcb17eb/….</code>folder name to just codeigniter</p>
</blockquote>
<h3 id="heading-verify-extraction">Verify Extraction</h3>
<p>Visit your web server's URL (for example, <a target="_blank" href="http://localhost"><code>http://localhost</code></a>) to check if the contents are correctly deployed.</p>
<h3 id="heading-set-folder-permissions"><strong>Set Folder Permissions</strong></h3>
<p>After installing CodeIgniter, make sure you have the correct permissions for your directories, particularly <code>writable</code> and <code>cache</code> directories. This ensures that CodeIgniter can write logs, cache files, and session data.</p>
<p>Run the following commands to set the correct permissions:</p>
<pre><code class="lang-bash">sudo chmod -R 755 /var/www/html/codeigniter
</code></pre>
<h3 id="heading-configure-the-base-url"><strong>Configure the Base URL</strong></h3>
<p>The base URL for your project needs to be set up in <code>application/config/config.php</code>.</p>
<p>Open the <code>config.php</code> file:</p>
<pre><code class="lang-bash">sudo nano /var/www/html/codeigniter/application/config/config.php
</code></pre>
<p>Output:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737213372442/259f712f-2df4-4517-a382-88966b021950.png" alt="Config.php terminal image." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Set the <code>base_url</code> as follows:</p>
<pre><code class="lang-php">$config[<span class="hljs-string">'base_url'</span>] = <span class="hljs-string">'http://your-domain-or-ip/'</span>;
</code></pre>
<p>Replace <a target="_blank" href="http://your-domain-or-ip/"><code>http://your-domain-or-ip/</code></a> with your actual domain or IP address where the project will be accessible.</p>
<p>After making changes:</p>
<ul>
<li><p><strong>Save the file:</strong> Press <code>Ctrl + O</code> (Write Out).</p>
</li>
<li><p><strong>Confirm the filename:</strong> Press <code>Enter</code>.</p>
</li>
<li><p><strong>Exit the editor:</strong> Press <code>Ctrl + X</code>.</p>
</li>
</ul>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">You can also edit the files using UI by accessing them from <code>Other Locations//var/www/html/codeigniter</code></div>
</div>

<h3 id="heading-configure-the-database-if-applicable"><strong>Configure the Database (if Applicable)</strong></h3>
<p>If your project uses a database, you'll need to set up the database configuration in <code>application/config/database.php</code>.</p>
<p>To do this, open the database configuration file:</p>
<pre><code class="lang-bash">sudo nano /var/www/html/codeigniter/application/config/database.php
</code></pre>
<p>Configure the database connection by setting the following options:</p>
<pre><code class="lang-php">$db[<span class="hljs-string">'default'</span>] = <span class="hljs-keyword">array</span>(
    <span class="hljs-string">'dsn'</span>   =&gt; <span class="hljs-string">''</span>,
    <span class="hljs-string">'hostname'</span> =&gt; <span class="hljs-string">'localhost'</span>,
    <span class="hljs-string">'username'</span> =&gt; <span class="hljs-string">'your-db-username'</span>,
    <span class="hljs-string">'password'</span> =&gt; <span class="hljs-string">'your-db-password'</span>,
    <span class="hljs-string">'database'</span> =&gt; <span class="hljs-string">'your-database-name'</span>,
    <span class="hljs-string">'dbdriver'</span> =&gt; <span class="hljs-string">'mysqli'</span>,
    <span class="hljs-string">'dbprefix'</span> =&gt; <span class="hljs-string">''</span>,
    <span class="hljs-string">'pconnect'</span> =&gt; <span class="hljs-literal">FALSE</span>,
    <span class="hljs-string">'db_debug'</span> =&gt; (ENVIRONMENT !== <span class="hljs-string">'production'</span>),
    <span class="hljs-string">'cache_on'</span> =&gt; <span class="hljs-literal">FALSE</span>,
    <span class="hljs-string">'cachedir'</span> =&gt; <span class="hljs-string">''</span>,
    <span class="hljs-string">'char_set'</span> =&gt; <span class="hljs-string">'utf8'</span>,
    <span class="hljs-string">'dbcollat'</span> =&gt; <span class="hljs-string">'utf8_general_ci'</span>,
    <span class="hljs-string">'swap_pre'</span> =&gt; <span class="hljs-string">''</span>,
    <span class="hljs-string">'encrypt'</span> =&gt; <span class="hljs-literal">FALSE</span>,
    <span class="hljs-string">'compress'</span> =&gt; <span class="hljs-literal">FALSE</span>,
    <span class="hljs-string">'stricton'</span> =&gt; <span class="hljs-literal">FALSE</span>,
    <span class="hljs-string">'failover'</span> =&gt; <span class="hljs-keyword">array</span>(),
    <span class="hljs-string">'save_queries'</span> =&gt; <span class="hljs-literal">TRUE</span>
);
</code></pre>
<p>Replace <code>your-db-username</code>, <code>your-db-password</code>, and <code>your-database-name</code> with your actual database credentials.</p>
<h3 id="heading-set-the-environment"><strong>Set the Environment</strong></h3>
<p>CodeIgniter uses the environment setting to load different configuration files depending on the environment (for example, development, production).</p>
<p>To set the environment, open the <code>index.php</code> file in the root directory of your project:</p>
<pre><code class="lang-bash">sudo nano /var/www/html/codeigniter/index.php
</code></pre>
<p>Locate the following line:</p>
<pre><code class="lang-php">define(<span class="hljs-string">'ENVIRONMENT'</span>, <span class="hljs-string">'development'</span>);
</code></pre>
<p>You can set it to <code>production</code>, <code>testing</code>, or <code>development</code> depending on your setup. For development, it should be set to <code>development</code></p>
<h3 id="heading-autoload-libraries-helpers-or-config-files"><strong>Autoload Libraries, Helpers, or Config Files</strong></h3>
<p>You can specify which libraries, helpers, or config files to autoload in <code>application/config/autoload.php</code>. Open the autoload configuration file:</p>
<pre><code class="lang-bash">sudo nano /var/www/html/codeigniter/application/config/autoload.php
</code></pre>
<p>Modify the autoload array to load commonly used libraries and helpers:</p>
<pre><code class="lang-php">$autoload[<span class="hljs-string">'libraries'</span>] = <span class="hljs-keyword">array</span>(<span class="hljs-string">'database'</span>, <span class="hljs-string">'session'</span>, <span class="hljs-string">'form_validation'</span>);
$autoload[<span class="hljs-string">'helper'</span>] = <span class="hljs-keyword">array</span>(<span class="hljs-string">'url'</span>, <span class="hljs-string">'file'</span>);
</code></pre>
<h3 id="heading-enable-mod-rewrite-for-clean-urls"><strong>Enable Mod Rewrite (For Clean URLs)</strong></h3>
<p>If you want clean URLs, you need to enable <code>mod_rewrite</code> on Apache. Edit the Apache configuration file as follows:</p>
<pre><code class="lang-bash">sudo nano /etc/apache2/sites-available/000-default.conf
</code></pre>
<p>Ensure that the <code>AllowOverride</code> directive is set to <code>All</code> in the <code>&lt;Directory&gt;</code> section:</p>
<pre><code class="lang-bash">&lt;Directory /var/www/html&gt;
    AllowOverride All
&lt;/Directory&gt;
</code></pre>
<p>Enable mod_rewrite and restart Apache:</p>
<pre><code class="lang-bash">sudo a2enmod rewrite
sudo systemctl restart apache2
</code></pre>
<h3 id="heading-verify-codeigniter-directory-placement">Verify CodeIgniter Directory Placement</h3>
<p>If CodeIgniter is not in <code>/opt/lampp/htdocs</code>, move it there:</p>
<pre><code class="lang-bash">sudo mv /var/www/html/codeigniter /opt/lampp/htdocs/
</code></pre>
<h3 id="heading-test-codeigniter"><strong>Test CodeIgniter</strong></h3>
<p>Open your web browser and navigate to the base URL (<a target="_blank" href="http://your-domain-or-ip"><code>http://your-domain-or-ip</code></a>). You should see the default CodeIgniter welcome page if everything is set up correctly:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737218343140/7a41485a-152e-496e-9ba7-811e5c4b774b.png" alt="CodeIgniter welcome page." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Run <code>curl</code> <a target="_blank" href="http://ifconfig.me"><code>ifconfig.me</code></a> to find your public IP. If you're hosting CodeIgniter on a local machine (for example, in your home network), use the following command to check your local IP: <code>hostname -I</code>.</p>
<h2 id="heading-troubleshooting">Troubleshooting</h2>
<p>If you encounter any issues while setting up CodeIgniter, here are some common problems and how to resolve them:</p>
<h3 id="heading-set-codeigniter-as-the-default-app"><strong>Set CodeIgniter as the Default App</strong></h3>
<p>If you want CodeIgniter to load as the default app (instead of the XAMPP landing page if you have XAMPP installed), remove or rename the default <code>index.php</code> in the <code>htdocs</code> directory:</p>
<pre><code class="lang-bash">sudo mv /opt/lampp/htdocs/index.php /opt/lampp/htdocs/index.php.bak
</code></pre>
<p>Move the CodeIgniter files to the root of the <code>htdocs</code> folder:</p>
<pre><code class="lang-bash">sudo mv /opt/lampp/htdocs/codeigniter/* /opt/lampp/htdocs/
</code></pre>
<h3 id="heading-restart-apache"><strong>Restart Apache</strong></h3>
<p>After making changes, restart Apache to apply the configuration:</p>
<pre><code class="lang-bash">sudo /opt/lampp/lampp restart
</code></pre>
<h3 id="heading-creating-a-controller"><strong>Creating a Controller</strong></h3>
<p>To start developing your application, you can create a controller to handle requests.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737219751160/af7240e8-2793-45b9-9cff-1f9a74add34f.png" alt="Application folders." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Create a new controller in <code>application/controllers/</code> like this:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Welcome</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">CI_Controller</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">index</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">$this</span>-&gt;load-&gt;view(<span class="hljs-string">'welcome_message'</span>);
    }
}
</code></pre>
<p>Then create Views and Models. Views go into <code>application/views/</code> and models into <code>application/models/</code>. You can start adding your views and models accordingly.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Setting up a development environment for CodeIgniter on Ubuntu is an essential step to unlock the full potential of this lightweight yet powerful PHP framework.</p>
<p>By carefully following the outlined steps—from installing prerequisites, configuring file permissions, and customizing settings to creating controllers, views, and models—you are now equipped to start building dynamic web applications.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ CSS Transform Handbook – Complete Guide to CSS Transform Functions and Properties ]]>
                </title>
                <description>
                    <![CDATA[ CSS transform allows you to translate, rotate, skew, scale, or add perspective effects to HTML elements. This tutorial discusses everything you need to know to transform HTML elements like a pro. Table of Contents What is the CSS transform Property?... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/complete-guide-to-css-transform-functions-and-properties/</link>
                <guid isPermaLink="false">66ba0de37fb82b484b253a29</guid>
                
                    <category>
                        <![CDATA[ code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi Sofela ]]>
                </dc:creator>
                <pubDate>Mon, 19 Jun 2023 21:13:33 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738338625918/27521e84-35de-4453-a153-1d419e1d0e2b.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><strong>CSS transform</strong> allows you to translate, rotate, skew, scale, or add perspective effects to HTML elements.</p>
<p>This tutorial discusses everything you need to know to transform HTML elements like a pro.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-is-the-css-transform-property">What is the CSS <code>transform</code> Property?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-css-rotate-function">What is the CSS <code>rotate()</code> Function?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-css-rotatex-function">What is the CSS <code>rotateX()</code> Function?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-css-rotatey-function">What is the CSS <code>rotateY()</code> Function?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-css-rotatez-function">What is the CSS <code>rotateZ()</code> Function?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-css-rotate3d-function">What is the CSS <code>rotate3d()</code> Function?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-css-rotate-functions-vs-rotate-property-whats-the-difference">CSS Rotate Functions vs. <code>rotate</code> Property: What's the Difference?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-css-scale-function">What is the CSS <code>scale()</code> Function?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-css-scale-function-vs-scale-property-whats-the-difference">CSS <code>scale()</code> Function vs. <code>scale</code> Property: What's the Difference?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-css-scalez-function">What is the CSS <code>scaleZ()</code> Function?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-css-scale3d-function">What is the CSS <code>scale3d()</code> Function?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-css-skew-function">What is the CSS <code>skew()</code> Function?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-css-translate-function">What is the CSS <code>translate()</code> Function?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-css-translatez-function">What is the CSS <code>translateZ()</code> Function?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-css-translate3d-function">What is the CSS <code>translate3d()</code> Function?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-css-translate-functions-vs-translate-property-whats-the-difference">CSS Translate Functions vs. <code>translate</code> Property: What's the Difference?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-css-perspective-function">What is the CSS <code>perspective()</code> Function?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-css-perspective-function-vs-perspective-property-whats-the-difference">CSS <code>perspective()</code> Function vs. <code>perspective</code> Property: What's the Difference?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-css-matrix-function">What is the CSS <code>matrix()</code> Function?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-does-the-css-transform-functions-order-matter">Why Does the CSS Transform Functions' Order Matter?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-tools-for-converting-transform-functions-to-matrix">Tools for Converting Transform Functions to <code>matrix()</code></a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-important-stuff-to-know-about-transforming-elements-in-css">Important Stuff to Know about Transforming Elements in CSS</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-wrapping-up">Wrapping Up</a></p>
</li>
</ol>
<p>So, without further ado, let's discuss the CSS <code>transform</code> property.</p>
<h2 id="heading-what-is-the-css-transform-property">What Is the CSS <code>transform</code> Property?</h2>
<p>The CSS <code>transform</code> property specifies the transformational effect you wish to apply to an HTML element.</p>
<p><strong>Here's the syntax:</strong></p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html-element</span> {
  <span class="hljs-attribute">transform</span>: value;
}
</code></pre>
<p>The CSS <code>transform</code> property accepts the following values:</p>
<ul>
<li><p><code>inherit</code>: Transforms the element with its parent element's <code>transform</code> value.</p>
</li>
<li><p><code>initial</code>: Transforms the HTML element with its default <code>transform</code> value.</p>
</li>
<li><p><code>matrix()</code>: Transforms the element two-dimensionally with a matrix of six values.</p>
</li>
<li><p><code>matrix3d()</code>: Transforms the HTML element three-dimensionally with a 4x4 matrix of sixteen values.</p>
</li>
<li><p><code>none</code>: Applies <em>no</em> transformation to the HTML element.</p>
</li>
<li><p><code>perspective()</code>: Transforms a 3D transformed element with a perspective view.</p>
</li>
<li><p><code>rotate()</code>: Transforms the element by rotating it two-dimensionally.</p>
</li>
<li><p><code>rotate3d()</code>: Transforms the element by rotating it three-dimensionally.</p>
</li>
<li><p><code>rotateX()</code>: Transforms the element by rotating it three-dimensionally along the X-axis.</p>
</li>
<li><p><code>rotateY()</code>: Transforms the element by rotating it three-dimensionally along the Y-axis.</p>
</li>
<li><p><code>rotateZ()</code>: Transforms the HTML element by rotating it three-dimensionally along the Z-axis.</p>
</li>
<li><p><code>scale()</code>: Transforms the element by scaling it two-dimensionally.</p>
</li>
<li><p><code>scale3d()</code>: Transforms the element by scaling it three-dimensionally.</p>
</li>
<li><p><code>scaleX()</code>: Transforms the element by scaling it along the X-axis.</p>
</li>
<li><p><code>scaleY()</code>: Transforms the element by scaling it along the Y-axis.</p>
</li>
<li><p><code>scaleZ()</code>: Transforms the HTML element by scaling it three-dimensionally along the Z-axis.</p>
</li>
<li><p><code>skew()</code>: Transforms the element by skewing it two-dimensionally along the X- and Y-axis.</p>
</li>
<li><p><code>skewX()</code>: Transforms the element by skewing it two-dimensionally along the X-axis.</p>
</li>
<li><p><code>skewY()</code>: Transforms the element by skewing it two-dimensionally along the Y-axis.</p>
</li>
<li><p><code>translate()</code>: Transforms the HTML element by translating (moving) it two-dimensionally.</p>
</li>
<li><p><code>translate3d()</code>: Transforms the element by translating it three-dimensionally.</p>
</li>
<li><p><code>translateX()</code>: Transforms the element by translating it along the X-axis.</p>
</li>
<li><p><code>translateY()</code>: Transforms the element by translating it along the Y-axis.</p>
</li>
<li><p><code>translateZ()</code>: Transforms the element by translating it three-dimensionally along the Z-axis.</p>
</li>
</ul>
<p><strong>Note:</strong> The <code>transform</code> property accepts one or more <a target="_blank" href="https://codesweetly.com/web-tech-terms-c#css-transform-functions">CSS transform functions</a>. For instance, here's a valid <code>transform</code> declaration:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">perspective</span>(<span class="hljs-number">370px</span>) <span class="hljs-built_in">scaleZ</span>(<span class="hljs-number">5</span>) <span class="hljs-built_in">rotate</span>(<span class="hljs-number">17deg</span>);
}
</code></pre>
<p>In the snippet above, we assigned three transform functions to the <code>transform</code> property. Let's talk more about some of <code>transform</code>'s values.</p>
<h2 id="heading-what-is-the-css-rotate-function">What is the CSS <code>rotate()</code> Function?</h2>
<p><code>rotate()</code> transforms an element by rotating it two-dimensionally around a fixed point.</p>
<p><strong>Note:</strong></p>
<ul>
<li><p>"Transform origin" is the fixed point around which an element rotates.</p>
</li>
<li><p>You can define your element's fixed point using the CSS <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin"><code>transform-origin</code></a> property. But the default is <code>center</code>.</p>
</li>
</ul>
<h3 id="heading-syntax-of-the-css-rotate-function">Syntax of the CSS <code>rotate()</code> function</h3>
<p><code>rotate()</code> accepts a single <a target="_blank" href="https://codesweetly.com/javascript-arguments-vs-parameters">argument</a>. Here is the syntax:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">element</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotate</span>(angle);
}
</code></pre>
<p><strong>Note the following:</strong></p>
<ul>
<li><p>The <code>rotate(angle)</code> function is equivalent to <code>rotate3d(0, 0, 1, angle)</code> or <code>rotateZ(angle)</code>.</p>
</li>
<li><p>The <code>angle</code> argument specifies the element's angle of rotation.</p>
</li>
<li><p><code>angle</code> can be in <a target="_blank" href="https://en.wikipedia.org/wiki/Degree_%28angle%29">degrees</a>, <a target="_blank" href="https://en.wikipedia.org/wiki/Gradian">gradians</a>, <a target="_blank" href="https://en.wikipedia.org/wiki/Radian">radians</a>, or <a target="_blank" href="https://en.wikipedia.org/wiki/Turn_\(angle\)">turns</a>.</p>
</li>
<li><p>An <code>angle</code> argument consists of a number followed by the unit you wish to use—for instance, <code>45deg</code>.</p>
</li>
<li><p>Your browser's writing direction determines the element's direction of rotation.</p>
</li>
<li><p>A positive angle will rotate the element clockwise in a left-to-right writing direction. But a negative angle will do a counterclockwise rotation.</p>
</li>
<li><p>A positive angle will rotate the element counterclockwise in a right-to-left writing context. But a negative angle will do a clockwise rotation.</p>
</li>
</ul>
<h3 id="heading-examples-of-the-css-rotate-function">Examples of the CSS <code>rotate()</code> function</h3>
<p>Below are some examples of how the CSS <code>rotate()</code> function works.</p>
<h4 id="heading-how-to-do-a-zero-degree-rotation-in-css">How to do a zero-degree rotation in CSS:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotate</span>(<span class="hljs-number">0deg</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-zcgvaa?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>rotate()</code> function to specify a zero-degree (0⁰) rotation for the image element.</p>
<h4 id="heading-how-to-do-a-45-degree-rotation-in-css">How to do a 45-degree rotation in CSS:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotate</span>(<span class="hljs-number">45deg</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-86xhmx?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>rotate()</code> function to specify a forty-five-degree (45⁰) rotation for the image element.</p>
<h4 id="heading-how-to-do-a-negative-seventy-degree-rotation-in-css">How to do a negative seventy-degree rotation in CSS:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotate</span>(-<span class="hljs-number">70deg</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-3gb1my?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>rotate()</code> function to specify a negative seventy-degree (70⁰) rotation for the image element.</p>
<h2 id="heading-what-is-the-css-rotatex-function">What is the CSS <code>rotateX()</code> Function?</h2>
<p><code>rotateX()</code> transforms an element by rotating it three-dimensionally around the X-axis.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/cartesian-coordinate-system-three-dimensional-diagram-codesweetly.png" alt="Illustration of the 3D Cartesian coordinate system" width="600" height="400" loading="lazy"></p>
<p><em>A three-dimensional Cartesian coordinate system showing the X-, Y-, and Z-axis</em></p>
<h3 id="heading-syntax-of-the-css-rotatex-function">Syntax of the CSS <code>rotateX()</code> function</h3>
<p><code>rotateX()</code> accepts a single argument. Here is the syntax:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">element</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateX</span>(angle);
}
</code></pre>
<p><strong>Note the following:</strong></p>
<ul>
<li><p>The <code>rotateX(angle)</code> function is equivalent to <code>rotate3d(1, 0, 0, angle)</code>.</p>
</li>
<li><p>The <code>angle</code> argument specifies the element's angle of rotation.</p>
</li>
<li><p><code>angle</code> can be in degree, gradian, radian, or turn.</p>
</li>
<li><p>An <code>angle</code> argument consists of a number followed by the unit you wish to use—for instance, <code>45deg</code>.</p>
</li>
</ul>
<h3 id="heading-examples-of-the-css-rotatex-function">Examples of the CSS <code>rotateX()</code> function</h3>
<p>Below are some examples of how the CSS <code>rotateX()</code> function works.</p>
<h4 id="heading-how-to-do-a-zero-degree-rotation-around-the-x-axis">How to do a zero-degree rotation around the X-axis:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateX</span>(<span class="hljs-number">0deg</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-ej9ent?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>rotateX()</code> function to specify a zero-degree (0⁰) rotation for the image around the X-axis.</p>
<h4 id="heading-how-to-do-a-70-degree-rotation-around-the-x-axis">How to do a 70-degree rotation around the X-axis:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateX</span>(<span class="hljs-number">70deg</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-fvhyjx?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>rotateX()</code> function to specify a seventy-degree (70⁰) rotation for the image around the X-axis.</p>
<h2 id="heading-what-is-the-css-rotatey-function">What is the CSS <code>rotateY()</code> Function?</h2>
<p><code>rotateY()</code> transforms an element by rotating it three-dimensionally around the Y-axis.</p>
<h3 id="heading-syntax-of-the-css-rotatey-function">Syntax of the CSS <code>rotateY()</code> function</h3>
<p><code>rotateY()</code> accepts a single argument. Here is the syntax:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">element</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateY</span>(angle);
}
</code></pre>
<p><strong>Note the following:</strong></p>
<ul>
<li><p>The <code>rotateY(angle)</code> function is equivalent to <code>rotate3d(0, 1, 0, angle)</code>.</p>
</li>
<li><p>The <code>angle</code> argument specifies the element's angle of rotation.</p>
</li>
<li><p><code>angle</code> can be in degrees, gradians, radians, or turns.</p>
</li>
<li><p>An <code>angle</code> argument consists of a number followed by the unit you wish to use—for instance, <code>45deg</code>.</p>
</li>
</ul>
<h3 id="heading-examples-of-the-css-rotatey-function">Examples of the CSS <code>rotateY()</code> function</h3>
<p>Below are some examples of how the CSS <code>rotateY()</code> function works.</p>
<h4 id="heading-how-to-do-a-zero-degree-rotation-around-the-y-axis">How to do a zero-degree rotation around the Y-axis:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateY</span>(<span class="hljs-number">0deg</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-frg3ks?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>rotateY()</code> function to specify a zero-degree (0⁰) rotation for the image around the Y-axis.</p>
<h4 id="heading-how-to-do-a-70-degree-rotation-around-the-y-axis">How to do a 70-degree rotation around the Y-axis:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateY</span>(<span class="hljs-number">70deg</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-yvydga?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>rotateY()</code> function to specify a seventy-degree (70⁰) rotation for the image around the Y-axis.</p>
<h2 id="heading-what-is-the-css-rotatez-function">What is the CSS <code>rotateZ()</code> Function?</h2>
<p><code>rotateZ()</code> transforms an element by rotating it three-dimensionally around the Z-axis.</p>
<h3 id="heading-syntax-of-the-css-rotatez-function">Syntax of the CSS <code>rotateZ()</code> function</h3>
<p><code>rotateZ()</code> accepts a single argument. Here is the syntax:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">element</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateZ</span>(angle);
}
</code></pre>
<p><strong>Note the following:</strong></p>
<ul>
<li><p>The <code>rotateZ(angle)</code> function is equivalent to <code>rotate3d(0, 0, 1, angle)</code> or <code>rotate(angle)</code>.</p>
</li>
<li><p>The <code>angle</code> argument specifies the element's angle of rotation.</p>
</li>
<li><p><code>angle</code> can be in degrees, gradians, radians, or turns.</p>
</li>
<li><p>An <code>angle</code> argument consists of a number followed by the unit you wish to use—for instance, <code>45deg</code>.</p>
</li>
</ul>
<h3 id="heading-examples-of-the-css-rotatez-function">Examples of the CSS <code>rotateZ()</code> function</h3>
<p>Below are some examples of how the CSS <code>rotateZ()</code> function works.</p>
<h4 id="heading-how-to-do-a-zero-degree-rotation-around-the-z-axis">How to do a zero-degree rotation around the Z-axis:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateZ</span>(<span class="hljs-number">0deg</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-ozqupq?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>rotateZ()</code> function to specify a zero-degree (0⁰) rotation for the image around the Z-axis.</p>
<h4 id="heading-how-to-do-a-70-degree-rotation-around-the-z-axis">How to do a 70-degree rotation around the Z-axis:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateZ</span>(<span class="hljs-number">70deg</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-g6qrwc?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>rotateZ()</code> function to specify a seventy-degree (70⁰) rotation for the image around the Z-axis.</p>
<h2 id="heading-what-is-the-css-rotate3d-function">What is the CSS <code>rotate3d()</code> Function?</h2>
<p><code>rotate3d()</code> transforms an element by rotating it three-dimensionally around the x-, y-, and z-axis.</p>
<h3 id="heading-syntax-of-the-css-rotate3d-function">Syntax of the CSS <code>rotate3d()</code> function</h3>
<p><code>rotate3d()</code> accepts four arguments. Here is the syntax:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">element</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotate3d</span>(x, y, z, angle);
}
</code></pre>
<p><strong>Note the following:</strong></p>
<ul>
<li><p>The <code>x</code>, <code>y</code>, and <code>z</code> arguments are numbers specifying the x-, y-, and z-coordinates.</p>
</li>
<li><p>The coordinates are the axis around which the element will rotate.</p>
</li>
<li><p>The <code>angle</code> argument specifies the element's angle of rotation.</p>
</li>
<li><p><code>angle</code> can be in degrees, gradians, radians, or turns.</p>
</li>
<li><p>An <code>angle</code> argument consists of a number followed by the unit you wish to use—for instance, <code>45deg</code>.</p>
</li>
</ul>
<h3 id="heading-examples-of-the-css-rotate3d-function">Examples of the CSS <code>rotate3d()</code> function</h3>
<p>Below are some examples of how the CSS <code>rotate3d()</code> function works.</p>
<h4 id="heading-how-to-do-a-70-degree-rotation-around-the-z-axis-1">How to do a 70-degree rotation around the Z-axis:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotate3d</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">70deg</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-i6f9pr?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>rotate3d()</code> function to specify a seventy-degree (70⁰) rotation for the image around the Z-axis.</p>
<h4 id="heading-how-to-do-a-70-degree-rotation-around-the-x-y-and-z-axis">How to do a 70-degree rotation around the X-, Y-, and Z-axis:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotate3d</span>(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">70deg</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-ctws81?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>rotate3d()</code> function to specify a seventy-degree (70⁰) rotation for the image around the x-, y-, and z-axis.</p>
<h2 id="heading-css-rotate-functions-vs-rotate-property-whats-the-difference">CSS Rotate Functions vs. <code>rotate</code> Property: What's the Difference?</h2>
<p>CSS rotate functions and CSS <code>rotate</code> property provides two similar ways to specify rotation transformations.</p>
<p>The main differences between the two rotation techniques are as follows:</p>
<ul>
<li><p>The CSS <code>rotate</code> property allows rotating an element without using the CSS <code>transform</code> property.</p>
</li>
<li><p>The CSS <code>rotate</code> property's syntax is shorter than its function alternative.</p>
</li>
<li><p>The CSS <code>rotate</code> property saves you from remembering the specific order to position the <a target="_blank" href="https://codesweetly.com/web-tech-terms-c#css-transform-functions">transform functions</a>.</p>
</li>
<li><p>Browsers calculate the transform functions' matrix in the order you assigned them to the CSS <code>transform</code> property—from left to right.</p>
</li>
<li><p>Browsers calculate the transform properties' matrix in the following <a target="_blank" href="https://www.w3.org/TR/css-transforms-2/#ctm">transformation matrix order</a>:</p>
<ol>
<li><p><code>translate</code></p>
</li>
<li><p><code>rotate</code></p>
</li>
<li><p><code>scale</code></p>
</li>
</ol>
</li>
</ul>
<p>Below are some examples.</p>
<h3 id="heading-how-to-use-css-rotate-property-vs-function-to-do-a-45-degree-rotation">How to use CSS <code>rotate</code> property vs. function to do a 45-degree rotation</h3>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">rotate</span>: <span class="hljs-number">45deg</span>; <span class="hljs-comment">/* Equivalent to a transform: rotate(45deg) property */</span>
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-rdw9a5?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>rotate</code> property to specify a forty-five-degree (45⁰) rotation for the image element.</p>
<h3 id="heading-how-to-use-css-rotate-property-vs-function-to-do-a-70-degree-rotation-around-the-x-axis">How to use CSS <code>rotate</code> property vs. function to do a 70-degree rotation around the X-axis</h3>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">rotate</span>: x <span class="hljs-number">70deg</span>; <span class="hljs-comment">/* Equal to a transform: rotateX(70deg) property */</span>
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-pal1am?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>rotate</code> property to specify a seventy-degree (70⁰) rotation for the image around the X-axis.</p>
<h3 id="heading-how-to-use-css-rotate-property-vs-function-to-do-a-70-degree-rotation-around-the-y-axis">How to use CSS <code>rotate</code> property vs. function to do a 70-degree rotation around the Y-axis</h3>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">rotate</span>: y <span class="hljs-number">70deg</span>; <span class="hljs-comment">/* Equal to a transform: rotateY(70deg) property */</span>
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-ldnmfd?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>rotate</code> property to specify a seventy-degree (70⁰) rotation for the image around the Y-axis.</p>
<h3 id="heading-how-to-use-css-rotate-property-vs-function-to-do-a-70-degree-rotation-around-the-z-axis">How to use CSS <code>rotate</code> property vs. function to do a 70-degree rotation around the Z-axis</h3>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">rotate</span>: z <span class="hljs-number">70deg</span>; <span class="hljs-comment">/* Equal to a transform: rotateZ(70deg) property */</span>
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-stf9ty?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>rotate</code> property to specify a seventy-degree (70⁰) rotation for the image around the Z-axis.</p>
<h3 id="heading-how-to-use-css-rotate-property-vs-function-to-do-a-70-degree-rotation-around-the-x-y-and-z-axis">How to use CSS <code>rotate</code> property vs. function to do a 70-degree rotation around the X-, Y-, and Z-axis</h3>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">rotate</span>: <span class="hljs-number">1</span> <span class="hljs-number">1</span> <span class="hljs-number">1</span> <span class="hljs-number">70deg</span>; <span class="hljs-comment">/* Equal to a transform: rotate3d(1, 1, 1, 70deg) property */</span>
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-qfflxq?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>rotate</code> property to specify a seventy-degree (70⁰) rotation for the image around the x-, y-, and z-axis.</p>
<p><strong>Note:</strong> A <code>none</code> value tells browsers <em>not</em> to rotate the selected element.</p>
<h2 id="heading-what-is-the-css-scale-function">What is the CSS <code>scale()</code> Function?</h2>
<p><code>scale()</code> transforms an element by resizing (scaling) it two-dimensionally from a fixed point.</p>
<p><strong>Note:</strong></p>
<ul>
<li><p>"Transform origin" is the fixed point from which the computer scales an element.</p>
</li>
<li><p>You can define your element's fixed point using the CSS <code>transform-origin</code> property. But the default is <code>center</code>.</p>
</li>
</ul>
<h3 id="heading-syntax-of-the-css-scale-function">Syntax of the CSS <code>scale()</code> function</h3>
<p><code>scale()</code> accepts two arguments. Here is the syntax:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">element</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">scale</span>(x, y);
}
</code></pre>
<p><strong>Note the following:</strong></p>
<ul>
<li><p>The <code>x</code> argument can be a number or percentage. It specifies the element's scaling factor along the x-axis.</p>
</li>
<li><p>The <code>y</code> argument can also be a number or percentage. It defines the element's scaling factor along the y-axis.</p>
</li>
<li><p>Y-axis' default value is <code>x</code>. Therefore, if you do not provide a <code>y</code> argument, the browser automatically uses <code>x</code>'s value.</p>
</li>
<li><p>Suppose <code>x</code> and <code>y</code> are equal. In that case, browsers will scale your element uniformly and preserve its aspect ratio.</p>
</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/cartesian-coordinate-system-two-dimensional-diagram-codesweetly.png" alt="Illustration of the 2D Cartesian coordinate system" width="600" height="400" loading="lazy"></p>
<p><em>A two-dimensional Cartesian coordinate system showing the X- and Y-axis</em></p>
<h3 id="heading-examples-of-the-css-scale-function">Examples of the CSS <code>scale()</code> function</h3>
<p>Below are some examples of how the CSS <code>scale()</code> function works.</p>
<h4 id="heading-how-to-scale-an-element-uniformly-along-the-x-and-y-axis-in-css">How to scale an element uniformly along the X- and Y-axis in CSS:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">scale</span>(<span class="hljs-number">0.3</span>);
  <span class="hljs-attribute">transform-origin</span>: left;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-k3d6nm?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>scale()</code> function to specify a <code>0.3</code> scaling factor for the image element along the X- and Y-axis.</p>
<p><strong>Note:</strong></p>
<ul>
<li><p><code>scale(0.3)</code> is equivalent to <code>scale(0.3, 0.3)</code>.</p>
</li>
<li><p>The percentage equivalence of <code>scale(0.3)</code> is <code>scale(30%)</code>.</p>
</li>
</ul>
<h4 id="heading-how-to-scale-an-element-non-uniformly-along-the-x-and-y-axis-in-css">How to scale an element non-uniformly along the X- and Y-axis in CSS:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">scale</span>(<span class="hljs-number">0.3</span>, <span class="hljs-number">65%</span>);
  <span class="hljs-attribute">transform-origin</span>: top left;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-fxjhwb?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>scale()</code> function to specify a <code>0.3</code> scaling factor for the image along the X-axis and <code>65%</code> along the Y-axis.</p>
<h4 id="heading-how-to-scale-an-element-along-only-the-x-axis">How to scale an element along only the X-axis:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">scale</span>(<span class="hljs-number">0.3</span>, <span class="hljs-number">1</span>);
  <span class="hljs-attribute">transform-origin</span>: top left;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-7mwvto?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>scale()</code> function to specify a <code>0.3</code> scaling factor for the image along only the X-axis.</p>
<p><strong>Note:</strong></p>
<ul>
<li><p>A scale factor of <code>1</code> or <code>100%</code> tells browsers <em>not</em> to apply any scaling effect on the selected element.</p>
</li>
<li><p><code>scale(0.3, 1)</code> is equivalent to <code>scaleX(0.3)</code>.</p>
</li>
</ul>
<h4 id="heading-how-to-scale-an-element-along-only-the-y-axis">How to scale an element along only the Y-axis:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">scale</span>(<span class="hljs-number">100%</span>, <span class="hljs-number">0.2</span>);
  <span class="hljs-attribute">transform-origin</span>: top left;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-i5yrt4?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>scale()</code> function to specify a <code>0.2</code> scaling factor for the image along only the Y-axis.</p>
<p><strong>Note:</strong></p>
<ul>
<li><p>A <code>100%</code> or <code>1</code> scale factor tells browsers <em>not</em> to apply any scaling effect on the selected element.</p>
</li>
<li><p><code>scale(100%, 0.2)</code> is equivalent to <code>scaleY(0.2)</code>.</p>
</li>
</ul>
<h2 id="heading-css-scale-function-vs-scale-property-whats-the-difference">CSS <code>scale()</code> Function vs. <code>scale</code> Property: What's the Difference?</h2>
<p>The CSS <code>scale()</code> function and the CSS <code>scale</code> property provide two similar ways to specify a scale transformation.</p>
<p>The main differences between the two scaling techniques are as follows:</p>
<ul>
<li><p>The CSS <code>scale</code> property allows scaling an element without using the CSS <code>transform</code> property.</p>
</li>
<li><p>The CSS <code>scale</code> property's syntax is shorter than its function alternative.</p>
</li>
<li><p>The CSS <code>scale</code> property saves you from remembering the specific order to position the transform functions.</p>
</li>
<li><p>Browsers calculate the transform functions' matrix in the order you assigned them to the CSS <code>transform</code> property—from left to right.</p>
</li>
<li><p>Browsers calculate the transform properties' matrix in the following order:</p>
<ol>
<li><p><code>translate</code></p>
</li>
<li><p><code>rotate</code></p>
</li>
<li><p><code>scale</code></p>
</li>
</ol>
</li>
</ul>
<p><strong>Here's an example:</strong></p>
<p>Use the CSS <code>scale</code> property to scale an element nonuniformly along the X- and Y-axis.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">scale</span>: <span class="hljs-number">0.3</span> <span class="hljs-number">65%</span>; <span class="hljs-comment">/* Equal to a transform: scale(0.3, 65%) property */</span>
  <span class="hljs-attribute">transform-origin</span>: top left;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-exkib5?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>scale</code> property to specify a <code>0.3</code> scaling factor for the image along the X-axis and <code>65%</code> along the Y-axis.</p>
<p><strong>Note:</strong> A <code>none</code> value tells browsers <em>not</em> to scale the selected element.</p>
<h2 id="heading-what-is-the-css-scalez-function">What is the CSS <code>scaleZ()</code> Function?</h2>
<p><code>scaleZ()</code> transforms an element by resizing (scaling) it three-dimensionally from a fixed point along the z-axis.</p>
<p><strong>Note:</strong></p>
<ul>
<li><p>"Transform origin" is the fixed point from which the computer scales an element.</p>
</li>
<li><p>You can define your element's fixed point using the CSS <code>transform-origin</code> property. But the default is <code>center</code>.</p>
</li>
</ul>
<h3 id="heading-syntax-of-the-css-scalez-function">Syntax of the CSS <code>scaleZ()</code> function</h3>
<p><code>scaleZ()</code> accepts a single argument. Here is the syntax:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">element</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">scaleZ</span>(number);
}
</code></pre>
<p><strong>Note:</strong></p>
<ul>
<li><p>The <code>scaleZ(number)</code> function is equivalent to <code>scale3d(1, 1, number)</code>.</p>
</li>
<li><p>The <code>number</code> argument specifies the element's scaling factor along the z-axis.</p>
</li>
</ul>
<h3 id="heading-examples-of-the-css-scalez-function">Examples of the CSS <code>scaleZ()</code> function</h3>
<p>We often use <code>scaleZ()</code> with other CSS functions such as <code>perspective()</code>, <code>translateZ()</code>, and <code>rotateX()</code>. Below are some examples.</p>
<h4 id="heading-how-to-use-scalez-with-css-perspective-and-rotatex-functions">How to use <code>scaleZ()</code> with CSS <code>perspective()</code> and <code>rotateX()</code> functions:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">perspective</span>(<span class="hljs-number">370px</span>) <span class="hljs-built_in">scaleZ</span>(<span class="hljs-number">5</span>) <span class="hljs-built_in">rotateX</span>(<span class="hljs-number">17deg</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-kqmccz?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>Here's what we did in the snippet above:</p>
<ol>
<li><p>We used the <code>perspective()</code> function to define a <code>370px</code> distance between the user and the <a target="_blank" href="https://codesweetly.com/css-perspective-function#what-is-the-z0-plane">z=0 plane</a>.</p>
</li>
<li><p>The <code>scaleZ()</code> function specifies a scale factor of <code>5</code> for the image along the z-axis.</p>
</li>
<li><p>We used the <code>rotateX()</code> function to rotate the image seventeen-degree (17⁰) around the x-axis.</p>
</li>
</ol>
<p><strong>Note:</strong></p>
<ul>
<li><p>List <code>perspective()</code> first whenever you chain it with other <a target="_blank" href="https://codesweetly.com/web-tech-terms-c#css-transform-functions">CSS transform functions</a>. Otherwise, browsers might transform the selected element incorrectly.</p>
</li>
<li><p>List the <code>scaleZ()</code> function before <code>rotateX()</code>. Otherwise, the browser will <em>not</em> scale the element.</p>
</li>
</ul>
<h4 id="heading-how-to-use-scalez-with-css-perspective-and-translatez-functions">How to use <code>scaleZ()</code> with CSS <code>perspective()</code> and <code>translateZ()</code> functions:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">40%</span>;
}

<span class="hljs-selector-class">.second-image</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">perspective</span>(<span class="hljs-number">370px</span>) <span class="hljs-built_in">scaleZ</span>(<span class="hljs-number">5</span>) <span class="hljs-built_in">translateZ</span>(<span class="hljs-number">30px</span>);
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-uyw767?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>Here's what we did in the snippet above:</p>
<ol>
<li><p>We used the <code>perspective()</code> function to define a <code>370px</code> distance between the user and the z=0 plane.</p>
</li>
<li><p>The <code>scaleZ()</code> function specifies a scale factor of <code>5</code> for the image along the z-axis.</p>
</li>
<li><p>We used the <code>translateZ()</code> function to reposition the <code>second-image</code> thirty pixels (<code>30px</code>) away from its original position along the z-axis.</p>
</li>
</ol>
<h2 id="heading-what-is-the-css-scale3d-function">What is the CSS <code>scale3d()</code> Function?</h2>
<p><code>scale3d()</code> transforms an element by resizing (scaling) it three-dimensionally from a fixed point along the x-, y-, and z-axis.</p>
<p><strong>Note:</strong></p>
<ul>
<li><p>"Transform origin" is the fixed point from which the computer scales an element.</p>
</li>
<li><p>You can define your element's fixed point using the CSS <code>transform-origin</code> property. But the default is <code>center</code>.</p>
</li>
</ul>
<h3 id="heading-syntax-of-the-css-scale3d-function">Syntax of the CSS <code>scale3d()</code> function</h3>
<p><code>scale3d()</code> accepts three arguments. Here is the syntax:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">element</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">scale3d</span>(x, y, z);
}
</code></pre>
<p>The <code>x</code>, <code>y</code>, and <code>z</code> arguments are numbers specifying the x-, y-, and z-coordinates. The coordinates are the axis along which browsers will scale the element.</p>
<h3 id="heading-examples-of-the-css-scale3d-function">Examples of the CSS <code>scale3d()</code> function</h3>
<p>Below are some examples of how the CSS <code>scale3d()</code> function works.</p>
<h4 id="heading-how-to-use-scale3d-with-css-perspective-and-rotatex-functions">How to use <code>scale3d()</code> with CSS <code>perspective()</code> and <code>rotateX()</code> functions:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">perspective</span>(<span class="hljs-number">370px</span>) <span class="hljs-built_in">scale3d</span>(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">5</span>) <span class="hljs-built_in">rotateX</span>(<span class="hljs-number">17deg</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-inndft?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>Here's what we did in the snippet above:</p>
<ol>
<li><p>We used the <code>perspective()</code> function to define a <code>370px</code> distance between the user and the z=0 plane.</p>
</li>
<li><p>The <code>scale3d()</code> function specifies a scale factor of <code>1</code>, <code>1</code>, and <code>5</code> for the image along the x-, y-, and z-axis.</p>
</li>
<li><p>We used the <code>rotateX()</code> function to rotate the image seventeen-degrees (17⁰) around the x-axis.</p>
</li>
</ol>
<p><strong>Note:</strong></p>
<ul>
<li><p>A scale factor of <code>1</code> will apply <em>no</em> scaling effect on the element.</p>
</li>
<li><p>List <code>perspective()</code> first whenever you chain it with other CSS transform functions. Otherwise, browsers might transform the selected element incorrectly.</p>
</li>
<li><p>List the <code>scale3d()</code> function before <code>rotateX()</code>. Otherwise, the browser will <em>not</em> scale the element.</p>
</li>
</ul>
<h4 id="heading-how-to-scale-elements-three-dimensionally">How to scale elements three-dimensionally:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">40%</span>;
}

<span class="hljs-selector-class">.second-image</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">scale3d</span>(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>, <span class="hljs-number">0.05</span>);
  <span class="hljs-attribute">transform-origin</span>: top left;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-hq8kbr?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>We used the <code>scale3d()</code> function to specify a scale factor of <code>5</code>, <code>3</code>, and <code>0.05</code> for the image along the x-, y-, and z-axis.</p>
<h2 id="heading-what-is-the-css-skew-function">What is the CSS <code>skew()</code> Function?</h2>
<p><code>skew()</code> transforms an element by slanting (skewing) it two-dimensionally around a fixed point.</p>
<p><strong>Note:</strong></p>
<ul>
<li><p>"Transform origin" is the fixed point from which the computer skews an element.</p>
</li>
<li><p>You can define your element's fixed point using the CSS <code>transform-origin</code> property. But the default is <code>center</code>.</p>
</li>
</ul>
<h3 id="heading-syntax-of-the-css-skew-function">Syntax of the CSS <code>skew()</code> function</h3>
<p><code>skew()</code> accepts two arguments. Here is the syntax:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">element</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">skew</span>(aX, aY);
}
</code></pre>
<p><strong>Note the following:</strong></p>
<ul>
<li><p>The <code>aX</code> argument specifies the element's skewing angle along the x-axis.</p>
</li>
<li><p>The <code>aY</code> argument specifies the element's skewing angle along the y-axis.</p>
</li>
<li><p><code>aX</code> and <code>aY</code> can be in degrees, gradians, radians, or turns.</p>
</li>
<li><p>An <code>angle</code> argument consists of a number followed by the unit you wish to use—for instance, <code>45deg</code>.</p>
</li>
<li><p><code>aY</code> is an optional argument.</p>
</li>
</ul>
<h3 id="heading-examples-of-the-css-skew-function">Examples of the CSS <code>skew()</code> function</h3>
<p>Below are some examples of how the CSS <code>skew()</code> function works.</p>
<h4 id="heading-how-to-skew-an-element-along-only-the-x-axis">How to skew an element along only the X-axis:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">skew</span>(<span class="hljs-number">30deg</span>);
  <span class="hljs-attribute">transform-origin</span>: top;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-gx5dy4?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>skew()</code> function to apply a thirty-degree (30⁰) slant on the image along only the x-axis.</p>
<p><strong>Note:</strong> <code>skew(30deg)</code> is equivalent to <code>skewX(30deg)</code>.</p>
<h4 id="heading-how-to-skew-an-element-along-only-the-y-axis">How to skew an element along only the Y-axis:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">skew</span>(<span class="hljs-number">0</span>, <span class="hljs-number">40deg</span>);
  <span class="hljs-attribute">transform-origin</span>: top left;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-nbkjfj?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>skew()</code> function to apply a forty-degree (40⁰) slant on the image along only the y-axis.</p>
<p><strong>Note:</strong></p>
<ul>
<li><p>A zero (<code>0</code>) skew degree tells browsers <em>not</em> to apply any skewing effect on the selected element.</p>
</li>
<li><p><code>skew(0, 40deg)</code> is equivalent to <code>skewY(40deg)</code>.</p>
</li>
</ul>
<h4 id="heading-how-to-skew-an-element-along-the-x-and-y-axis">How to skew an element along the X- and Y-axis:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">skew</span>(<span class="hljs-number">30deg</span>, <span class="hljs-number">40deg</span>);
  <span class="hljs-attribute">transform-origin</span>: top left;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-ofrk9v?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>skew()</code> function to apply a thirty-degree (30⁰) slant on the image along the x-axis. And forty-degree (40⁰) along the y-axis.</p>
<h2 id="heading-what-is-the-css-translate-function">What is the CSS <code>translate()</code> Function?</h2>
<p><code>translate()</code> transforms an element by repositioning (translating) it two-dimensionally.</p>
<h3 id="heading-syntax-of-the-css-translate-function">Syntax of the CSS <code>translate()</code> function</h3>
<p><code>translate()</code> accepts two arguments. Here is the syntax:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">element</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translate</span>(x, y);
}
</code></pre>
<p><strong>Note the following:</strong></p>
<ul>
<li><p>The <code>x</code> argument can be a length or percentage value. It specifies the distance you wish to move the element from its original x-axis position.</p>
</li>
<li><p>The <code>y</code> argument can be a length or percentage value. It defines the distance you wish to move the element from its original y-axis position.</p>
</li>
<li><p><code>y</code> is an optional argument.</p>
</li>
</ul>
<h3 id="heading-examples-of-the-css-translate-function">Examples of the CSS <code>translate()</code> function</h3>
<p>Below are some examples of how the CSS <code>translate()</code> function works.</p>
<h4 id="heading-how-to-translate-an-element-along-only-the-x-axis">How to translate an element along only the X-axis:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translate</span>(<span class="hljs-number">150px</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-kuaqzz?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>translate()</code> function to reposition the image <code>150px</code> away from its original position along the x-axis.</p>
<p>You can also write it like this, specifying the <code>X</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translateX</span>(<span class="hljs-number">150px</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>
</code></pre>
<p><strong>Note:</strong> <code>translate(150px)</code> is equivalent to <code>translateX(150px)</code>.</p>
<h4 id="heading-how-to-translate-an-element-along-only-the-y-axis">How to translate an element along only the Y-axis:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translate</span>(<span class="hljs-number">0</span>, <span class="hljs-number">55%</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-2bchbd?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>translate()</code> function to reposition the image <code>55%</code> away from its original position along the y-axis.</p>
<p><strong>Note:</strong></p>
<ul>
<li><p>A zero (<code>0</code>) translate distance tells browsers <em>not</em> to apply any translating effect on the selected element.</p>
</li>
<li><p><code>translate(0, 55%)</code> is equivalent to <code>translateY(55%)</code>.</p>
</li>
</ul>
<h4 id="heading-how-to-translate-an-element-along-the-x-and-y-axis">How to translate an element along the X- and Y-axis:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translate</span>(<span class="hljs-number">60%</span>, <span class="hljs-number">300px</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-uwpvu4?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>translate()</code> function to reposition the image <code>60%</code> away from its original position along the x-axis and <code>300px</code> from its y-axis.</p>
<h2 id="heading-what-is-the-css-translatez-function">What is the CSS <code>translateZ()</code> Function?</h2>
<p><code>translateZ()</code> transforms an element by repositioning (translating) it three-dimensionally along the z-axis.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/cartesian-coordinate-system-three-dimensional-diagram-codesweetly-1.png" alt="Illustration of the 3D Cartesian coordinate system" width="600" height="400" loading="lazy"></p>
<p><em>A three-dimensional Cartesian coordinate system showing the X-, Y-, and Z-axis</em></p>
<h3 id="heading-syntax-of-the-css-translatez-function">Syntax of the CSS <code>translateZ()</code> function</h3>
<p><code>translateZ()</code> accepts a single argument. Here is the syntax:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">element</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translateZ</span>(length);
}
</code></pre>
<p>The <code>length</code> argument specifies the distance you wish to move the element from its original z-axis position.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/cartesian-coordinate-system-three-dimensional-length-diagram-codesweetly.png" alt="Illustration of the CSS translateZ's length argument" width="600" height="400" loading="lazy"></p>
<p><em>A three-dimensional Cartesian coordinate system with a red arrow defining the green plane's translateZ length</em></p>
<h3 id="heading-examples-of-the-css-translatez-function">Examples of the CSS <code>translateZ()</code> function</h3>
<p>We often use <code>translateZ()</code> with the <code>perspective()</code> function. Below are some examples.</p>
<h4 id="heading-how-to-use-translatez-with-the-css-perspective-function">How to use <code>translateZ()</code> with the CSS <code>perspective()</code> function:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">40%</span>;
}

<span class="hljs-selector-class">.second-image</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">perspective</span>(<span class="hljs-number">33px</span>) <span class="hljs-built_in">translateZ</span>(<span class="hljs-number">10px</span>);
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-hvf8bb?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>Here's what we did in the snippet above:</p>
<ol>
<li><p>We used the <code>perspective()</code> function to define a <code>33px</code> distance between the user and the <a target="_blank" href="https://codesweetly.com/css-perspective-function#what-is-the-z0-plane">z=0 plane</a>.</p>
</li>
<li><p>We used the <code>translateZ()</code> function to reposition the <code>second-image</code> ten pixels (<code>10px</code>) away from its original position along the z-axis.</p>
</li>
</ol>
<p><strong>Note:</strong></p>
<ul>
<li><p>Suppose the <code>second-image</code>'s z-axis position is larger than or equal to the <code>perspective()</code> function's <a target="_blank" href="https://codesweetly.com/javascript-arguments-vs-parameters">argument</a>. In that case, the image will disappear as though it is behind the user. In other words, the selected item disappears when the user is in the same position as the element (or when the element is behind the user).</p>
</li>
<li><p>The larger the user's distance to the element's z-axis position, the less intensive the perspective effect will be, and vice-versa.</p>
</li>
</ul>
<h4 id="heading-how-to-use-translatez-with-a-70px-perspective">How to use <code>translateZ()</code> with a <code>70px</code> perspective:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">40%</span>;
}

<span class="hljs-selector-class">.second-image</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">perspective</span>(<span class="hljs-number">70px</span>) <span class="hljs-built_in">translateZ</span>(<span class="hljs-number">10px</span>);
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-vqd7mm?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>Here's what we did in the snippet above:</p>
<ol>
<li><p>We used the <code>perspective()</code> function to define a <code>70px</code> distance between the user and the z=0 plane.</p>
</li>
<li><p>We used the <code>translateZ()</code> function to reposition the <code>second-image</code> ten pixels (<code>10px</code>) away from its original position along the z-axis.</p>
</li>
</ol>
<h2 id="heading-what-is-the-css-translate3d-function">What is the CSS <code>translate3d()</code> Function?</h2>
<p><code>translate3d()</code> transforms an element by repositioning (translating) it three-dimensionally along the x-, y-, and z-axis.</p>
<h3 id="heading-syntax-of-the-css-translate3d-function">Syntax of the CSS <code>translate3d()</code> function</h3>
<p><code>translate3d()</code> accepts three arguments. Here is the syntax:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">element</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translate3d</span>(x, y, z);
}
</code></pre>
<p><strong>Note the following:</strong></p>
<ul>
<li><p>The <code>x</code> argument can be a length or percentage value. It specifies the distance you wish to move the element from its original x-axis position.</p>
</li>
<li><p>The <code>y</code> argument can be a length or percentage value. It defines the distance you wish to move the element from its original y-axis position.</p>
</li>
<li><p><code>z</code> can only be a length—not a percentage. It defines the distance you wish to move the element from its original z-axis position.</p>
</li>
</ul>
<h3 id="heading-examples-of-the-css-translate3d-function">Examples of the CSS <code>translate3d()</code> function</h3>
<p>Below are some examples of how the CSS <code>translate3d()</code> function works.</p>
<h4 id="heading-how-to-translate-an-element-along-only-the-x-axis-1">How to translate an element along only the X-axis</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translate3d</span>(<span class="hljs-number">150px</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-qrxxmx?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>translate3d()</code> function to reposition the image <code>150px</code> away from its original position along the x-axis.</p>
<p><strong>Note:</strong> <code>translate3d(150px, 0, 0)</code> is equivalent to <code>translateX(150px)</code>.</p>
<h4 id="heading-how-to-translate-elements-three-dimensionally">How to translate elements three-dimensionally:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">40%</span>;
}

<span class="hljs-selector-class">.second-image</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">perspective</span>(<span class="hljs-number">300px</span>) <span class="hljs-built_in">translate3d</span>(<span class="hljs-number">15%</span>, <span class="hljs-number">45%</span>, <span class="hljs-number">200px</span>);
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-rksery?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>translate3d()</code> function to reposition the image <code>15%</code> away from its original position along the x-axis, <code>45%</code> from its y-axis, and <code>200px</code> from its z-axis.</p>
<h2 id="heading-css-translate-functions-vs-translate-property-whats-the-difference">CSS Translate Functions vs. <code>translate</code> Property: What's the Difference?</h2>
<p>The CSS translate functions and the CSS <code>translate</code> property provide two similar ways to specify a translation transformation.</p>
<p>The main differences between the two translation techniques are as follows:</p>
<ul>
<li><p>The CSS <code>translate</code> property allows translating an element without using the CSS <code>transform</code> property.</p>
</li>
<li><p>The CSS <code>translate</code> property's syntax is shorter than its function alternative.</p>
</li>
<li><p>The CSS <code>translate</code> property saves you from remembering the specific order to position the transform functions.</p>
</li>
<li><p>Browsers calculate the transform functions' matrix in the order you assigned them to the CSS <code>transform</code> property—from left to right.</p>
</li>
<li><p>Browsers calculate the transform properties' matrix in the following order:</p>
<ol>
<li><p><code>translate</code></p>
</li>
<li><p><code>rotate</code></p>
</li>
<li><p><code>scale</code></p>
</li>
</ol>
</li>
</ul>
<p>Below are some examples.</p>
<h3 id="heading-how-to-use-css-translate-property-vs-function-to-translate-an-element-along-the-x-and-y-axis">How to use CSS <code>translate</code> property vs. function to translate an element along the X- and Y-axis</h3>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">translate</span>: <span class="hljs-number">60%</span> <span class="hljs-number">300px</span>; <span class="hljs-comment">/* Equal to a transform: translate(60%, 300px) property */</span>
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-mhrmbj?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>translate</code> property to reposition the image <code>60%</code> away from its original position along the x-axis. And <code>300px</code> from its y-axis.</p>
<p><strong>Note:</strong> Suppose you wish to translate an element along the z-axis. In that case, set a <code>perspective</code> property on the "parent element" of the element you want to translate. Otherwise, the element will not move along its z-axis.</p>
<h3 id="heading-how-to-use-css-translate-property-vs-function-to-translate-an-element-along-the-z-axis">How to use CSS <code>translate</code> property vs. function to translate an element along the Z-axis</h3>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">40%</span>;
}

<span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">perspective</span>: <span class="hljs-number">35px</span>;
}

<span class="hljs-selector-class">.second-image</span> {
  <span class="hljs-attribute">translate</span>: <span class="hljs-number">0px</span> <span class="hljs-number">0px</span> <span class="hljs-number">17px</span>; <span class="hljs-comment">/* Equal to a transform: translateZ(17px) property */</span>
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-gjr5sl?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>Here's what we did in the snippet above:</p>
<ol>
<li><p>We used the <code>perspective</code> property to define a <code>35px</code> distance between the user and the z=0 plane.</p>
</li>
<li><p>We used the <code>translate</code> property to reposition the <code>second-image</code> seventeen pixels (<code>17px</code>) away from its original position along the z-axis.</p>
</li>
</ol>
<h3 id="heading-how-to-use-css-translate-property-vs-function-to-translate-an-element-three-dimensionally">How to use CSS <code>translate</code> property vs. function to translate an element three-dimensionally</h3>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">40%</span>;
}

<span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">perspective</span>: <span class="hljs-number">300px</span>;
}

<span class="hljs-selector-class">.second-image</span> {
  <span class="hljs-attribute">translate</span>: <span class="hljs-number">50%</span> <span class="hljs-number">25%</span> <span class="hljs-number">200px</span>; <span class="hljs-comment">/* Equal to a transform: translate3d(50%, 25%, 200px) property */</span>
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-pgqrgc?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The snippet above used the <code>translate</code> property to reposition the image <code>50%</code> away from its original position along the x-axis, <code>25%</code> from its y-axis, and <code>200px</code> from its z-axis.</p>
<p><strong>Note:</strong> A <code>none</code> value tells browsers <em>not</em> to translate the selected element.</p>
<h2 id="heading-what-is-the-css-perspective-function">What is the CSS <code>perspective()</code> Function?</h2>
<p><code>perspective()</code> transforms an element by adding some perspective effects to it.</p>
<h3 id="heading-syntax-of-the-css-perspective-function">Syntax of the CSS <code>perspective()</code> function</h3>
<p><code>perspective()</code> accepts only one argument. Here is the syntax:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">element</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">perspective</span>(length);
}
</code></pre>
<p>The <code>length</code> argument specifies the user's distance to the <a target="_blank" href="https://codesweetly.com/css-perspective-function#what-is-the-z0-plane">z=0 plane</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/cartesian-coordinate-system-perspective-method-illustration-codesweetly.png" alt="Illustration of the CSS perspective() method" width="600" height="400" loading="lazy"></p>
<p><em>A three dimensional Cartesian coordinate system with a red arrow defining the distance between the user and the z=0 plane</em></p>
<h3 id="heading-examples-of-the-css-perspective-function">Examples of the CSS <code>perspective()</code> function</h3>
<p>We often use <code>perspective()</code> with other CSS functions such as <code>translateZ()</code>, <code>rotateX()</code>, and <code>rotateY()</code>. Below are some examples.</p>
<h4 id="heading-how-to-use-perspective-with-the-css-translatez-function">How to use <code>perspective()</code> with the CSS <code>translateZ()</code> function:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">40%</span>;
}

<span class="hljs-selector-class">.second-image</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">perspective</span>(<span class="hljs-number">33px</span>) <span class="hljs-built_in">translateZ</span>(<span class="hljs-number">10px</span>);
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-hvf8bb?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>Here's what we did in the snippet above:</p>
<ol>
<li><p>We used the <code>perspective()</code> function to define a <code>33px</code> distance between the user and the z=0 plane.</p>
</li>
<li><p>We used the <code>translateZ()</code> function to reposition the <code>second-image</code> ten pixels (<code>10px</code>) away from its original position along the z-axis.</p>
</li>
</ol>
<p><strong>Note the following:</strong></p>
<ul>
<li><p>Suppose the <code>second-image</code>'s z-axis position is larger than or equal to the <code>perspective()</code> function's argument. In that case, the image will disappear as though it is behind the user. In other words, the selected item disappears when the user is in the same position as the element (or when the element is behind the user).</p>
</li>
<li><p>The larger the user's distance to the element's z-axis position, the less intensive the perspective effect will be, and vice-versa.</p>
</li>
</ul>
<h4 id="heading-how-to-use-perspective-with-the-css-rotatey-function">How to use <code>perspective()</code> with the CSS <code>rotateY()</code> function:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">40%</span>;
}

<span class="hljs-selector-class">.second-image</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">perspective</span>(<span class="hljs-number">33px</span>) <span class="hljs-built_in">rotateY</span>(-<span class="hljs-number">10deg</span>);
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-tptutx?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>Here's what we did in the snippet above:</p>
<ol>
<li><p>We used the <code>perspective()</code> function to define a <code>33px</code> distance between the user and the z=0 plane.</p>
</li>
<li><p>We used the <code>rotateY()</code> function to rotate the <code>second-image</code> negative ten-degree (-10⁰) around the y-axis.</p>
</li>
</ol>
<h4 id="heading-how-to-use-perspective-with-the-css-rotatex-function">How to use <code>perspective()</code> with the CSS <code>rotateX()</code> function:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">40%</span>;
}

<span class="hljs-selector-class">.second-image</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">perspective</span>(<span class="hljs-number">33px</span>) <span class="hljs-built_in">rotateX</span>(<span class="hljs-number">17deg</span>);
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-8ddydv?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>Here's what we did in the snippet above:</p>
<ol>
<li><p>We used the <code>perspective()</code> function to define a <code>33px</code> distance between the user and the z=0 plane.</p>
</li>
<li><p>We used the <code>rotateX()</code> function to rotate the <code>second-image</code> seventeen-degree (17⁰) around the x-axis.</p>
</li>
</ol>
<h2 id="heading-css-perspective-function-vs-perspective-property-whats-the-difference">CSS <code>perspective()</code> Function vs. <code>perspective</code> Property: What's the Difference?</h2>
<p>The CSS <code>perspective()</code> function and the <code>perspective</code> property provide two similar ways to add perspective effects to HTML elements.</p>
<p>The main differences between the two perspective techniques are as follows:</p>
<ul>
<li><p>We apply the <code>perspective()</code> function "directly on the element" we want to add some perspective effects to.</p>
</li>
<li><p>We apply the <code>perspective</code> property "on the parent element" of the element we want to add some perspective effects to.</p>
</li>
<li><p>The <code>perspective()</code> function works as a <code>transform</code> property's value.</p>
</li>
<li><p>The CSS <code>perspective</code> property allows you to create perspective effects without using the CSS <code>transform</code> property.</p>
</li>
</ul>
<p><strong>Here's an example:</strong></p>
<p>Use CSS <code>perspective</code> property to add perspective effect to a child element:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">40%</span>;
}

<span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">perspective</span>: <span class="hljs-number">33px</span>;
}

<span class="hljs-selector-class">.second-image</span> {
  <span class="hljs-attribute">rotate</span>: x <span class="hljs-number">17deg</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-psssbh?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>Here's what we did in the snippet above:</p>
<ol>
<li><p>We used the <code>perspective</code> property to define a <code>33px</code> distance between the user and the z=0 plane.</p>
</li>
<li><p>We used the <code>rotate</code> property to rotate the <code>second-image</code> seventeen-degree (17⁰) around the x-axis.</p>
</li>
</ol>
<p><strong>Note:</strong></p>
<ul>
<li><p>The CSS <code>perspective</code> property saves you from remembering the specific order to position the transform functions.</p>
</li>
<li><p>A <code>none</code> value tells browsers <em>not</em> to add any perspective effect to the selected element's children.</p>
</li>
</ul>
<h2 id="heading-what-is-the-css-matrix-function">What is the CSS <code>matrix()</code> Function?</h2>
<p>The CSS <code>matrix()</code> function is a shorthand for the following 2D transform functions:</p>
<ul>
<li><p><code>scaleX()</code></p>
</li>
<li><p><code>skewY()</code></p>
</li>
<li><p><code>skewX()</code></p>
</li>
<li><p><code>scaleY()</code></p>
</li>
<li><p><code>translateX()</code></p>
</li>
<li><p><code>translateY()</code></p>
</li>
</ul>
<p>In other words, instead of writing:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform-origin</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span>;
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translateX</span>(<span class="hljs-number">100px</span>) <span class="hljs-built_in">translateY</span>(<span class="hljs-number">250px</span>) <span class="hljs-built_in">scaleX</span>(<span class="hljs-number">2</span>) <span class="hljs-built_in">scaleY</span>(<span class="hljs-number">0.9</span>)
    <span class="hljs-built_in">skewX</span>(<span class="hljs-number">10deg</span>) <span class="hljs-built_in">skewY</span>(<span class="hljs-number">35deg</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-jquhyy?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>You can alternatively use the <code>matrix()</code> function to shorten your code like so:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform-origin</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span>;
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">matrix</span>(<span class="hljs-number">2.24693</span>, <span class="hljs-number">0.630187</span>, <span class="hljs-number">0.352654</span>, <span class="hljs-number">0.9</span>, <span class="hljs-number">100</span>, <span class="hljs-number">250</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-zzlwhn?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<h3 id="heading-the-css-matrix-functions-syntax">The CSS <code>matrix()</code> function's syntax</h3>
<p>The <code>matrix()</code> function accepts six values. Here's the syntax:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">matrix</span>(<span class="hljs-selector-tag">scaleX</span>(), <span class="hljs-selector-tag">skewY</span>(), <span class="hljs-selector-tag">skewX</span>(), <span class="hljs-selector-tag">scaleY</span>(), <span class="hljs-selector-tag">translateX</span>(), <span class="hljs-selector-tag">translateY</span>())
</code></pre>
<p>You can represent the CSS matrix's values as <a target="_blank" href="https://en.wikipedia.org/wiki/Homogeneous_coordinates">homogeneous coordinates</a> on <a target="_blank" href="https://en.wikipedia.org/wiki/Real_projective_space">ℝℙ<sup>2</sup></a> like so:</p>
<pre><code class="lang-txt">| scX skX tX | ← x-axis
| skY scY tY | ← y-axis
|  0   0   1 | ← constants
</code></pre>
<p><strong>Note the following:</strong></p>
<ul>
<li><p><code>scX</code> and <code>skX</code> are numbers describing an element's scale and skew linear transformation on the x-axis.</p>
</li>
<li><p><code>tX</code> is a number representing an element's translation on the x-axis.</p>
</li>
<li><p><code>skY</code> and <code>scY</code> are numbers describing an element's skew and scale linear transformation on the y-axis.</p>
</li>
<li><p><code>tY</code> is a number representing an element's translation on the y-axis.</p>
</li>
<li><p><code>0</code>, <code>0</code>, <code>1</code> are constants.</p>
</li>
<li><p>We do not pass the constants as <a target="_blank" href="https://codesweetly.com/javascript-arguments-vs-parameters">arguments</a> to the <code>matrix()</code> function because the computer implies them automatically.</p>
</li>
</ul>
<h3 id="heading-examples-of-the-css-matrix-function">Examples of the CSS <code>matrix()</code> function</h3>
<p>Below are some examples of the CSS <code>matrix()</code> function.</p>
<h4 id="heading-how-to-convert-scalex-to-matrix-function">How to convert <code>scaleX()</code> to <code>matrix()</code> function:</h4>
<p>Consider the following <code>transform</code> property:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform-origin</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span>;
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">scaleX</span>(<span class="hljs-number">2</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-9r2euo?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>Here is the <code>matrix()</code> equivalent of the above <code>scaleX()</code> function:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform-origin</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span>;
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">matrix</span>(<span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>); <span class="hljs-comment">/* scX, skY, skX, scY, tX, tY */</span>
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-bypfbf?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>Let's also represent the matrix's values as homogeneous coordinates on ℝℙ<sup>2</sup>:</p>
<pre><code class="lang-txt">| 2 0 0 | ← x-axis
| 0 1 0 | ← y-axis
| 0 0 1 | ← constants
</code></pre>
<p>Below is another example.</p>
<h4 id="heading-how-to-convert-translatey-to-matrix-function">How to convert <code>translateY()</code> to <code>matrix()</code> function:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform-origin</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span>;
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translateY</span>(<span class="hljs-number">250px</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-w25f3w?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>Here is the <code>matrix()</code> equivalent of the above <code>translateY()</code> function:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform-origin</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span>;
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">matrix</span>(<span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">250</span>); <span class="hljs-comment">/* scX, skY, skX, scY, tX, tY */</span>
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-1coxrt?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>Let's also represent the matrix's values as homogeneous coordinates on ℝℙ<sup>2</sup>:</p>
<pre><code class="lang-txt">| 1 0 0   | ← x-axis
| 0 1 250 | ← y-axis
| 0 0 1   | ← constants
</code></pre>
<p>Below is a third example.</p>
<h4 id="heading-how-to-convert-translatex-and-scale-to-matrix-function">How to convert <code>translateX()</code> and <code>scale()</code> to <code>matrix()</code> function:</h4>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform-origin</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span>;
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translateX</span>(<span class="hljs-number">100px</span>) <span class="hljs-built_in">scale</span>(<span class="hljs-number">2</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-wje2fa?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>Here is the syntax for converting the above <code>transform</code> property's value to <code>matrix()</code>:</p>
<pre><code class="lang-txt">matrix = (translateX's homogeneous coordinates) x (scale's homogeneous coordinates)
</code></pre>
<p>Let's begin the conversion by defining <code>translateX(100px)</code>'s homogeneous coordinates:</p>
<pre><code class="lang-txt">| 1 0 100 | ← x-axis
| 0 1 0   | ← y-axis
| 0 0 1   | ← constants
</code></pre>
<p>Let's also define <code>scale(2)</code>'s homogeneous coordinates:</p>
<pre><code class="lang-txt">| 2 0 0 | ← x-axis
| 0 2 0 | ← y-axis
| 0 0 1 | ← constants
</code></pre>
<p>It's now time to multiply the two homogeneous coordinates by using the following syntax:</p>
<pre><code class="lang-txt">| a d g |   | j m p |   | aj + dk + gl   am + dn + go   ap +dq  + gr |
| b e h | x | k n q | = | bj + ek + hl   bm + en + ho   bp + eq + hr |
| c f i |   | l o r |   | cj + fk + il   cm + fn + io   cp + fq + ir |
</code></pre>
<p>Let's implement the above syntax like so:</p>
<pre><code class="lang-txt">| 1 0 100 |   | 2 0 0 |   | 2 + 0 + 0   0 + 0 + 0   0 + 0 + 100 |
| 0 1  0  | x | 0 2 0 | = | 0 + 0 + 0   0 + 2 + 0   0 + 0 +  0  |
| 0 0  1  |   | 0 0 1 |   | 0 + 0 + 0   0 + 0 + 0   0 + 0 +  1  |
</code></pre>
<p>The next step is to resolve the addition. So, let's do that now.</p>
<pre><code class="lang-txt">| 1 0 100 |   | 2 0 0 |   | 2 0 100 |
| 0 1  0  | x | 0 2 0 | = | 0 2  0  |
| 0 0  1  |   | 0 0 1 |   | 0 0  1  |
</code></pre>
<p>The addition's result above gives us the homogeneous coordinates of the <code>transform: translateX(100px) scale(2)</code> property.</p>
<p>In other words, the product of <code>(translateX's homogeneous coordinates)</code> and <code>(scale's homogeneous coordinates)</code> equal:</p>
<pre><code class="lang-txt">| 2 0 100 | ← x-axis
| 0 2  0  | ← y-axis
| 0 0  1  | ← constants
</code></pre>
<p>Therefore, the matrix equivalence of <code>transform: translateX(100px) scale(2)</code> is <code>transform: matrix(2, 0, 0, 2, 100, 0)</code>.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform-origin</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span>;
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">matrix</span>(<span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">2</span>, <span class="hljs-number">100</span>, <span class="hljs-number">0</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-njrg4k?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>Please note that <code>transform: translateX(100px) scale(2)</code> and <code>transform: scale(2) translateX(100px)</code> return different matrixes. Let's see an example of the second arrangement below.</p>
<h4 id="heading-how-to-convert-scale-and-translatex-to-matrix-function">How to convert <code>scale()</code> and <code>translateX()</code> to <code>matrix()</code> function:</h4>
<p>Consider the following <code>transform</code> property:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform-origin</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span>;
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">scale</span>(<span class="hljs-number">2</span>) <span class="hljs-built_in">translateX</span>(<span class="hljs-number">100px</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-39trog?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>Here is the syntax for converting the above <code>transform</code> property's value to <code>matrix()</code>:</p>
<pre><code class="lang-txt">matrix = (scale's homogeneous coordinates) x (translateX's homogeneous coordinates)
</code></pre>
<p>Let's begin the conversion by defining <code>scale(2)</code>'s homogeneous coordinates:</p>
<pre><code class="lang-txt">| 2 0 0 | ← x-axis
| 0 2 0 | ← y-axis
| 0 0 1 | ← constants
</code></pre>
<p>Let's also define <code>translateX(100px)</code>'s homogeneous coordinates:</p>
<pre><code class="lang-txt">| 1 0 100 | ← x-axis
| 0 1  0  | ← y-axis
| 0 0  1  | ← constants
</code></pre>
<p>It's now time to multiply the two homogeneous coordinates by using the following syntax:</p>
<pre><code class="lang-txt">| a d g |   | j m p |   | aj + dk + gl   am + dn + go   ap +dq  + gr |
| b e h | x | k n q | = | bj + ek + hl   bm + en + ho   bp + eq + hr |
| c f i |   | l o r |   | cj + fk + il   cm + fn + io   cp + fq + ir |
</code></pre>
<p>Let's implement the above syntax like so:</p>
<pre><code class="lang-txt">| 2 0 0 |   | 1 0 100 |   | 2 + 0 + 0   0 + 0 + 0   200 + 0 + 0 |
| 0 2 0 | x | 0 1  0  | = | 0 + 0 + 0   0 + 2 + 0    0 + 0 + 0  |
| 0 0 1 |   | 0 0  1  |   | 0 + 0 + 0   0 + 0 + 0    0 + 0 + 1  |
</code></pre>
<p>The next step is to resolve the addition. So, let's do that now.</p>
<pre><code class="lang-txt">| 2 0 0 |   | 1 0 100 |   | 2 0 200 |
| 0 2 0 | x | 0 1  0  | = | 0 2  0  |
| 0 0 1 |   | 0 0  1  |   | 0 0  1  |
</code></pre>
<p>The addition's result above gives us the homogeneous coordinates of the <code>transform: scale(2) translateX(100px)</code> property.</p>
<p>In other words, the product of <code>(scale's homogeneous coordinates)</code> and <code>(translateX's homogeneous coordinates)</code> equal:</p>
<pre><code class="lang-txt">| 2 0 200 | ← x-axis
| 0 2  0  | ← y-axis
| 0 0  1  | ← constants
</code></pre>
<p>Therefore, the matrix equivalence of <code>transform: scale(2) translateX(100px)</code> is <code>transform: matrix(2, 0, 0, 2, 200, 0)</code>.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform-origin</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span>;
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">matrix</span>(<span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">2</span>, <span class="hljs-number">200</span>, <span class="hljs-number">0</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-3m4vgk?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>Notice that <code>transform: scale(2) translateX(100px)</code> equals <code>transform: matrix(2, 0, 0, 2, 200, 0)</code>. And <code>transform: translateX(100px) scale(2)</code> is equivalent to <code>transform: matrix(2, 0, 0, 2, 100, 0)</code>.</p>
<p>In other words, the order in which you write the transform functions matters. Let's discuss more on this below.</p>
<h2 id="heading-why-does-the-css-transform-functions-order-matter">Why Does the CSS Transform Functions' Order Matter?</h2>
<p>The order in which you write <a target="_blank" href="https://codesweetly.com/web-tech-terms-c#css-transform-functions">CSS transform functions</a> matters because of the way browsers calculate the matrix's values.</p>
<p>For instance, consider the following snippet:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">position</span>: absolute;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100px</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100px</span>;
  <span class="hljs-attribute">transform-origin</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span>;
}

<span class="hljs-selector-class">.red</span> {
  <span class="hljs-attribute">border</span>: <span class="hljs-number">3px</span> solid red;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">255</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.5</span>);
}

<span class="hljs-selector-class">.green</span> {
  <span class="hljs-attribute">border</span>: <span class="hljs-number">3px</span> solid green;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">128</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.5</span>);
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translateX</span>(<span class="hljs-number">100px</span>) <span class="hljs-built_in">scale</span>(<span class="hljs-number">2</span>);
}

<span class="hljs-selector-class">.blue</span> {
  <span class="hljs-attribute">border</span>: <span class="hljs-number">3px</span> solid blue;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">255</span>, <span class="hljs-number">0.5</span>);
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">scale</span>(<span class="hljs-number">2</span>) <span class="hljs-built_in">translateX</span>(<span class="hljs-number">100px</span>);
}
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-rvkagy?file=style.css"><strong>Try it on StackBlitz</strong></a></p>
<p>The only difference between the green and the blue <code>div</code>s is the order in which we wrote their transform functions.</p>
<p>However, the computer translated the two containers using different values (<code>100px</code> for the green <code>div</code> and <code>200px</code> for the blue one).</p>
<p>So, why did the transform functions' order affect the <code>div</code>s' translation values? Here's the reason:</p>
<ul>
<li>Browsers multiply each transform function's homogeneous coordinates in order—from left to right.</li>
</ul>
<p>In other words, the computer used the following syntax to compute the green <code>div</code>'s matrix:</p>
<ul>
<li><a class="post-section-overview" href="#how-to-convert-translatex-and-scale-to-matrix-function">Green <code>div</code>'s matrix</a> = (translateX's homogeneous coordinates) x (scale's homogeneous coordinates)</li>
</ul>
<p>And it used the following syntax to calculate the blue <code>div</code>'s matrix:</p>
<ul>
<li><a class="post-section-overview" href="#how-to-convert-scale-and-translatex-to-matrix-function">Blue <code>div</code>'s matrix</a> = (scale's homogeneous coordinates) x (translateX's homogeneous coordinates)</li>
</ul>
<p>Therefore, the position of the transform functions determined the matrix's <a target="_blank" href="https://codesweetly.com/javascript-arguments-vs-parameters">arguments</a> because browsers began the calculation in order from the leftmost function to the right.</p>
<p>Knowing how to convert transform functions to <code>matrix()</code> is beneficial. And having some conversion tools can come in handy. So, let's discuss some helpful tools you can use.</p>
<h2 id="heading-tools-for-converting-transform-functions-to-matrix">Tools for Converting Transform Functions to <code>matrix()</code></h2>
<p>The two tools you can use to do a quick conversion of transform functions to <code>matrix()</code> are:</p>
<ul>
<li><p>JavaScript's <code>window.getComputedStyle()</code> method</p>
</li>
<li><p>Eric Meyer and Aaron Gustafson's matrix resolution tool</p>
</li>
</ul>
<h3 id="heading-how-to-use-windowgetcomputedstyle-to-convert-transform-functions-to-matrix">How to use <code>window.getComputedStyle()</code> to convert transform functions to <code>matrix()</code></h3>
<p>Suppose you want to convert the following transform functions to matrix:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform-origin</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span>;
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">scale</span>(<span class="hljs-number">2</span>) <span class="hljs-built_in">translateX</span>(<span class="hljs-number">100px</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p>You will add an <code>id</code> attribute to the image element:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">img</span>
  <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.pixabay.com/photo/2022/09/26/23/26/african-american-7481724_960_720.jpg"</span>
  <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span>
  <span class="hljs-attr">id</span>=<span class="hljs-string">"image"</span>
/&gt;</span>
</code></pre>
<p>Then, in JavaScript, you will:</p>
<ol>
<li><p>Use the <code>id</code> attribute to get the image element.</p>
</li>
<li><p>Use the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle"><code>window.getComputedStyle()</code></a> method to get the image's <code>transform</code> property's value.</p>
</li>
</ol>
<p><strong>Here's the code:</strong></p>
<pre><code class="lang-js"><span class="hljs-comment">// Get the image element by its id name:</span>
<span class="hljs-keyword">const</span> image = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"image"</span>);

<span class="hljs-comment">// Get the image element's transform property's value:</span>
<span class="hljs-keyword">const</span> matrix = <span class="hljs-built_in">window</span>.getComputedStyle(image).getPropertyValue(<span class="hljs-string">"transform"</span>);

<span class="hljs-comment">// Log the matrix variable's value to the console:</span>
<span class="hljs-built_in">console</span>.log(matrix);
</code></pre>
<p><a target="_blank" href="https://stackblitz.com/edit/js-39trog?devToolsHeight=33&amp;file=index.js"><strong>Try it on StackBlitz</strong></a></p>
<p>Browsers, by default, convert a CSS <code>transform</code> property's value to its matrix equivalent. So, the snippet above returned the image's computed value.</p>
<p>Let's now discuss the second conversion tool.</p>
<h3 id="heading-how-to-use-the-matrix-resolutions-tool-to-convert-transform-functions-to-matrix">How to use the matrix resolutions tool to convert transform functions to <code>matrix()</code></h3>
<p>Suppose you want to convert the following transform functions to a <code>matrix()</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">transform-origin</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span>;
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">scale</span>(<span class="hljs-number">2</span>) <span class="hljs-built_in">translateX</span>(<span class="hljs-number">100px</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
}
</code></pre>
<p>You will do the following:</p>
<ol>
<li><p>Go to The Matrix Resolutions website: <a target="_blank" href="https://meyerweb.com/eric/tools/matrix/">https://meyerweb.com/eric/tools/matrix/</a>.</p>
</li>
<li><p>Paste your transform functions (<code>scale(2) translateX(100px)</code>) into the first text field.</p>
</li>
<li><p>Click "The Red Pill" button to generate the transform functions' matrix equivalence.</p>
</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/how-to-use-the-matrix-resolutions-tool-codesweetly.jpg" alt="The matrix resolutions tool's screenshot" width="600" height="400" loading="lazy"></p>
<p><em>Click the red pill button to convert CSS transform functions to a matrix() function</em></p>
<p><strong>Tip:</strong> Use <a target="_blank" href="https://codesweetly.com/css-matrix3d-function">matrix3d()</a> to create a 3D transformation matrix.</p>
<h2 id="heading-important-stuff-to-know-about-transforming-elements-in-css">Important Stuff to Know about Transforming Elements in CSS</h2>
<p>Here are three essential facts to remember when you transform elements in CSS.</p>
<h3 id="heading-1-transform-creates-a-stacking-context">1. Transform creates a stacking context</h3>
<p>Suppose you set the <code>transform</code> property to any value other than <code>none</code>. In that case, the browser will create a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context">stacking context</a>. And the transformed element will serve as a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block">containing block</a> to any <a target="_blank" href="https://codesweetly.com/css-position-property#what-is-position-absolute-in-css">absolute</a> or <a target="_blank" href="https://codesweetly.com/css-position-property#what-is-position-fixed-in-css">fixed</a> positioned elements it contains.</p>
<h3 id="heading-2-scaling-and-zooming-animations-cause-accessibility-issues">2. Scaling and zooming animations cause accessibility issues</h3>
<p>Whenever you include scaling or zooming animations in your app, provide users an option to turn off animations. This option is necessary because scaling and zooming animations cause <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform#accessibility_concerns">accessibility issues</a>.</p>
<h3 id="heading-3-not-all-elements-are-transformable">3. Not all elements are transformable</h3>
<p>You cannot transform the following <a target="_blank" href="https://codesweetly.com/css-box-model">box models</a>:</p>
<ul>
<li><p><a target="_blank" href="https://codesweetly.com/css-transform-property#non-replaced-vs-replaced-elements-whats-the-difference">Non-replaced</a> inline elements</p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/col">table-column</a> boxes</p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/colgroup">table-column-group</a></p>
</li>
</ul>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>In this article, we discussed all the CSS transform tools you need to translate, rotate, skew, scale, or add perspective effects to HTML elements.</p>
<p>I hope you've found this article helpful.</p>
<h3 id="heading-thanks-for-reading">Thanks for reading!</h3>
<p>If you like this tutorial, you will enjoy my <a target="_blank" href="https://amzn.to/3N3XUws">CSS Flexbox book</a>. It is a handy quick reference guide that uses images and live examples to explain Flexbox.</p>
<p><a target="_blank" href="https://amzn.to/3N3XUws"><img src="https://www.freecodecamp.org/news/content/images/2023/06/css-flexbox-book-get-banner-codesweetly.png" alt="Get CodeSweetly's CSS Flexbox book at Amazon" width="600" height="400" loading="lazy"></a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Front End Developer vs Back End Developer – Definition and Meaning In Practice ]]>
                </title>
                <description>
                    <![CDATA[ Websites and applications are complex! Buttons and images are just the tip of the iceberg. With this kind of complexity, you need people to manage it, but which parts are the front end developers and back end developers responsible for? [The many la... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/front-end-developer-vs-back-end-developer-definition-and-meaning-in-practice/</link>
                <guid isPermaLink="false">66b8e3260cedc1f2a4f70691</guid>
                
                    <category>
                        <![CDATA[ Back end development  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ backend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Backend Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Cloud Computing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ front end ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Thu, 18 Jun 2020 14:45:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/06/front-end-back-end.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Websites and applications are complex! Buttons and images are just the tip of the iceberg. With this kind of complexity, you need people to manage it, but which parts are the front end developers and back end developers responsible for?</p>
<ul>
<li>[The many layers of development](#The many layers of development)</li>
<li><a class="post-section-overview" href="#heading-but-were-not-all-full-stack">But we’re not all full stack</a></li>
<li><a class="post-section-overview" href="#heading-so-what-is-the-difference-between-front-end-development-and-back-end-development">So what is the difference between Front End Development and Back End Development?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-front-end-development">What is Front End Development?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-back-end-development">What is Back End Development?</a></li>
<li><a class="post-section-overview" href="#heading-where-things-get-fuzzy">Where things get fuzzy</a></li>
<li><a class="post-section-overview" href="#heading-resources-to-learn">Resources to learn</a></li>
</ul>
<h2 id="heading-the-many-layers-of-development">The many layers of development</h2>
<p>Whether you’re working on a website or a native iOS app, all development environments share a common theme — there’s a front end to an application and a back end.</p>
<p>This line can get blurry, especially given the rise of javascript and the <a target="_blank" href="https://en.wikipedia.org/wiki/Serverless_computing">serverless</a> world. With the tooling somewhat merging together, we might sometimes wonder if we’re a <a target="_blank" href="https://www.colbyfayock.com/2020/02/how-to-become-a-full-stack-web-developer-in-2020/">full stack developer</a>.</p>
<div class="embed-wrapper">
        <blockquote class="twitter-tweet">
          <a href="https://twitter.com/holtbt/status/977419276251430912"></a>
        </blockquote>
        <script defer="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></div>
<h2 id="heading-but-were-not-all-full-stack">But we’re not all full stack</h2>
<p>As much as we might all <a target="_blank" href="https://full-stack.netlify.app/">want to be</a>, we’re not all full stack developers. Personally, I find myself able to be productive in the back end of an application, but it’s not my strength and I much prefer to be heads down building UIs.</p>
<p>And some people are the opposite, where they are strongest dealing with building APIs in the back end of an application and while they can build out a UI, it might be more of a prototype-like experience than a fleshed out application.</p>
<h2 id="heading-so-what-is-the-difference-between-front-end-development-and-back-end-development">So what is the difference between Front End Development and Back End Development?</h2>
<p>Even if you are a full stack developer, that doesn’t mean there’s not a division of responsibilities.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/front-end-vs-back-end-engineer-2.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Front End Engineer vs Back End Engineer</em></p>
<p>So what do those look like?</p>
<h2 id="heading-what-is-front-end-development">What is Front End Development?</h2>
<p>The front end of an application typically refers to the layer that represents the UI (user interface). This can include anything from a static site with HTML and CSS to a full <a target="_blank" href="https://reactjs.org/">React</a> app that powers the UI.</p>
<h3 id="heading-what-did-front-end-development-traditionally-look-like">What did Front End Development traditionally look like?</h3>
<p>Javascript currently rules the front end web, but that wasn’t always the case. While it could have been used to add little bits of interaction to a site, typically front ends were rendered using server-side templating languages like framework-driven <a target="_blank" href="https://www.php.net/">PHP</a> and <a target="_blank" href="http://www.template-toolkit.org/">Template Toolkit</a> (<a target="_blank" href="https://www.perl.org/">Perl</a>).</p>
<p>This grew to be super popular in practice with home grown frameworks or tools like <a target="_blank" href="https://wordpress.org/">Wordpress</a> that used PHP to drive a massive community of developers who built their websites with those tools.</p>
<p>The way it worked was the templating language was able to get its data straight from the server as it was rendered. When a browser requested the page directly from the origin (the server itself), whatever data the template would need, the application logic would provide at that time.</p>
<p>Some of the more traditional front end tools include:</p>
<ul>
<li>Libraries like <a target="_blank" href="https://jquery.com/">jQuery</a> or <a target="_blank" href="https://mootools.net/">MooTools</a></li>
<li>Website frameworks like <a target="_blank" href="https://wordpress.com/">Wordpress</a></li>
<li>Plain <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS">CSS</a></li>
<li>Abundant use of <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table">Table</a> elements</li>
</ul>
<p>But as time went on, javascript kept getting more mature as a language and browsers kept getting more powerful, which led to the idea that we could move more of that work to the browser to build faster and more interactive experiences.</p>
<h3 id="heading-what-does-front-end-development-look-like-now">What does Front End Development look like now?</h3>
<p>Now it’s common to see javascript-heavy websites and apps built using UI frameworks like <a target="_blank" href="https://reactjs.org/">React</a>, <a target="_blank" href="https://vuejs.org/">Vue</a>, and <a target="_blank" href="https://angular.io/">Angular</a>. These tools provide abstractions that allow developers to build complex UIs with reusable patterns like components.</p>
<p>When the browser loads the page, the page receives an initial HTML document that also includes the script tag to the javascript (same as always). But once that javascript loads, it reaches out to APIs using browser requests that when completed, update the page to fill in any kind of dynamic data that you’d typically get along with that first HTML document.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/building-website-with-more-steps.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>It's like building a website... with more steps</em></p>
<p>While it sounds like more steps, it commonly provides a faster initial page load and render, not to mention it has a great developer experience. By delivering less on that first request and prioritizing what loads after that, it usually ends up as a better user experience.</p>
<p>Some of the front end tools that are more common and growing in popularity  include:</p>
<ul>
<li>UI frameworks like <a target="_blank" href="https://reactjs.org/">React</a> or <a target="_blank" href="https://vuejs.org/">Vue</a></li>
<li>Web frameworks like <a target="_blank" href="https://www.gatsbyjs.org/">Gatsby</a></li>
<li>Compilers like <a target="_blank" href="https://babeljs.io/">Babel</a></li>
<li>Bundlers like <a target="_blank" href="https://webpack.js.org/">Webpack</a></li>
<li>CSS tools like <a target="_blank" href="https://sass-lang.com/">Sass</a></li>
</ul>
<p>But those APIs, whether ones we pay for or create ourselves, need to be built <em>somewhere</em>. That’s where the back end comes in.</p>
<h2 id="heading-what-is-back-end-development">What is Back End Development?</h2>
<p>The back end layer is usually where the business logic occurs. This can be super complex like the rules that determine revenue for an e-commerce company or something more common like a user profile.</p>
<h3 id="heading-what-did-back-end-development-traditionally-look-like">What did Back End Development traditionally look like?</h3>
<p>The back ends of applications were historically built using server-side languages like <a target="_blank" href="https://www.php.net/">PHP</a> or <a target="_blank" href="https://www.ruby-lang.org/en/">Ruby</a>. The idea is that you have a server that you need to perform complex operations on, so the way to do that is with a language that server would understand.</p>
<p>On each request to the server, the backend would perform the full stack of the operations, including rendering out the front end. By using frameworks or DIY architectures, the back end would accept the request, figure out what it should do with that request, run any business logic needed with the request, and provide the front end any data that it would need to display a response to that request.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/front-end-back-end-500-error.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Back end giving the front end a 500 Internal Server Error</em></p>
<p>Some of the more traditional back end tools include:</p>
<ul>
<li>On-premise or remotely managed servers like <a target="_blank" href="https://www.rackspace.com/">Rackspace</a></li>
<li>HTTP servers using <a target="_blank" href="https://httpd.apache.org/">Apache</a></li>
<li>Databases like <a target="_blank" href="https://www.mysql.com/">MySQL</a></li>
<li>Server side languages like <a target="_blank" href="https://www.php.net/">PHP</a> or <a target="_blank" href="https://www.perl.org/">Perl</a></li>
<li>Application frameworks like <a target="_blank" href="https://rubyonrails.org/">Ruby on Rails</a></li>
</ul>
<h3 id="heading-what-does-back-end-development-look-like-now">What does Back End Development look like now?</h3>
<p>Back end stacks look somewhat similar to the way they did before, aside from newer code patterns, except more often you’ll see the back ends provide data through APIs via HTTP requests instead of directly to the templates the front end team are working on.</p>
<p>While the foundation isn’t super different, it actually be comes increasingly complex as you have to deal with different security implications that could compromise your system if not properly configured such as leaving an API open to the public that returns sensitive user data.</p>
<p>But also how the server operates can be completely different. While previously, we might run our python on our own managed server (we still can), we can now make use of serverless functions with tools like <a target="_blank" href="https://aws.amazon.com/lambda/">AWS Lambda</a> that simplify how we manage code.</p>
<p>While “<a target="_blank" href="https://en.wikipedia.org/wiki/Serverless_computing">serverless</a>” doesn’t necessarily mean there are literally no servers, it means that as a service, the developer doesn’t have to worry about maintaining that server and can instead just focus on the code they need to run.</p>
<p>Some of the back end tools that are more common and growing in popularity include:</p>
<ul>
<li>Cloud servers like <a target="_blank" href="https://aws.amazon.com/ec2/">AWS EC2</a></li>
<li>Serverless services like <a target="_blank" href="https://aws.amazon.com/lambda/">AWS Lambda</a></li>
<li>NoSQL databases like <a target="_blank" href="https://www.mongodb.com/">MongoDB</a></li>
<li>Languages like <a target="_blank" href="https://www.python.org/">Python</a> or javascript via <a target="_blank" href="https://nodejs.org/">NodeJS</a></li>
<li>Web application frameworks like <a target="_blank" href="https://www.serverless.com/">Serverless Framework</a></li>
</ul>
<h2 id="heading-where-things-get-fuzzy">Where things get fuzzy</h2>
<p>Part of the twist with back ends is now you can write your back end with javascript. With the inception of <a target="_blank" href="https://nodejs.org/en/">Node.js</a>, developers were given the ability to use their favorite browser language to do most of the same things they were used to and familiar with but now on a server.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/nodejs-never-stopped-to-think-if-should.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Never stopped to think if we should write JS on a server</em></p>
<p>While not everyone is fond of running javascript as a server side language, it became a little easier to use the same language to write the full stack of an application. This changed the game a bit as far as front ends and back ends were concerned.</p>
<p>But it’s also started to come full circle where you now see systems that build APIs right <a target="_blank" href="https://redwoodjs.com/tutorial/redwood-file-structure">next to the front end</a> similar to what you might see in a traditional stack.</p>
<h2 id="heading-front-end-vs-back-end">Front End vs Back End</h2>
<p>Regardless of the stack, there will always be the separation of concerns. The UI and all of the interaction, whether rendered on the server or in the browser, is what makes the front end the front end and the data and business logic, whether coming from the server in your company’s closet or a managed function, is what makes the back end the back end.</p>
<p>Whether you prefer to work on the user facing features or build the logic that lets them do things, there are plenty of resources to get started.</p>
<h2 id="heading-resources-to-learn">Resources to learn</h2>
<h3 id="heading-front-end">Front End</h3>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/learn/">freecodecamp.org Responsive Web Design Certification</a> (freecodecamp.org)</li>
<li><a target="_blank" href="https://beginnerjavascript.com/">Beginner Javascript</a> (beginnerjavascript.com - Wes Bos)</li>
<li><a target="_blank" href="https://www.youtube.com/watch?v=Ke90Tje7VS0">React Tutorial for Beginners</a> (youtube.com - Programming with Mosh)</li>
<li><a target="_blank" href="https://frontendmasters.com/">Front End Masters</a> (frontendmasters.com)</li>
</ul>
<h3 id="heading-back-end">Back End</h3>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/learn">freecodecamp.org APIs and Microservices Certification</a> (freecodecamp.org)</li>
<li><a target="_blank" href="https://kentcdodds.com/blog/super-simple-start-to-serverless/">Super simple start to serverless</a> (kentcdodds.com)</li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/aws-certified-cloud-practitioner-training-2019-free-video-course/">AWS Certified Cloud Practitioner Training 2019 - A Free 4-hour Video Course</a> (freecodecamp.org)</li>
<li><a target="_blank" href="https://www.edx.org/course/cs50s-introduction-to-computer-science">CS50's Introduction to Computer Science</a> (edx.org)</li>
</ul>
<h3 id="heading-all-the-above">All the above</h3>
<ul>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/02/how-to-become-a-full-stack-web-developer-in-2020/">How to Become a Full Stack Web Developer in 2020</a> (colbyfayock.com)</li>
<li><a target="_blank" href="https://egghead.io/?af=atzgap">Egghead.io</a> (egghead.io)</li>
<li><a target="_blank" href="https://www.100daysofcode.com/">100 Days of Code</a> (100daysofcode.com)</li>
<li><a target="_blank" href="https://www.udemy.com/course/the-web-developer-bootcamp/">The Web Developer Bootcamp</a> (udemy.com - Colt Steele)</li>
</ul>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">?️ Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Sync VS Code Settings Between Multiple Devices and Environments ]]>
                </title>
                <description>
                    <![CDATA[ All developers like their text editor a certain way, but it can be tough to make sure all of your environments have the same configuration. How can we make sure our VS Code configuration is the same wherever we use it? What is VS Code? What will we ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-sync-vs-code-settings-between-multiple-devices-and-environments/</link>
                <guid isPermaLink="false">66b8e36c682e4a25eed261a2</guid>
                
                    <category>
                        <![CDATA[ code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer Tools ]]>
                    </category>
                
                    <category>
                        <![CDATA[ editor ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ programing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tools ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Visual Studio Code ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Tue, 16 Jun 2020 14:45:45 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/06/vs-code-settings-sync.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>All developers like their text editor a certain way, but it can be tough to make sure all of your environments have the same configuration. How can we make sure our VS Code configuration is the same wherever we use it?</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-vs-code">What is VS Code?</a></li>
<li><a class="post-section-overview" href="#heading-what-will-we-use">What will we use?</a></li>
<li><a class="post-section-overview" href="#heading-how-does-it-work">How does it work?</a></li>
<li><a class="post-section-overview" href="#heading-step-1-install-settings-sync">Step 1: Install Settings Sync</a></li>
<li><a class="post-section-overview" href="#heading-step-2-authorize-access-to-github">Step 2: Authorize access to Github</a></li>
<li><a class="post-section-overview" href="#heading-step-3-upload-your-current-settings">Step 3: Upload your current settings</a></li>
<li><a class="post-section-overview" href="#heading-step-4-syncing-your-configuration-to-another-environment">Step 4: Syncing your configuration to another environment</a></li>
<li><a class="post-section-overview" href="#heading-step-5-updating-your-configuration">Step 5: Updating your configuration</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/TR2va67cVkQ" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-is-vs-code">What is VS Code?</h2>
<p><a target="_blank" href="https://code.visualstudio.com/">Visual Studio Code</a>, or VS Code, is an all-inclusive code editor that takes all of the features you want out of working with code and puts them in one editor to make you ultra productive.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/visual-studio-code-editor.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>VS Code editor</em></p>
<p>It’s been the “cool kid on the block” for a little while now and has been increasingly growing in popularity at least in the JavaScript community. Microsoft has put a lot of effort into making it something people want to use (and they’re doing a great job at that).</p>
<h2 id="heading-what-will-we-use">What will we use?</h2>
<p>We’re going to use a VS Code extension called <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=Shan.code-settings-sync">Settings Sync</a> that makes use of Github’s <a target="_blank" href="https://gist.github.com/">Gist</a> feature to store a private JSON configuration file in the cloud.</p>
<h2 id="heading-how-does-it-work">How does it work?</h2>
<p>The extension uses Github’s OAuth to log in to your Github account. Once approved, VS Code obtains an access token and reaches out to both store and download your settings file to a private Github Gist.</p>
<p>Once it’s set up, you can then configure the extension on any other instance of VS Code and immediately download your configuration to sync up your editor.</p>
<h2 id="heading-step-0-vs-code">Step 0: VS Code</h2>
<p>We’ll assume for this walkthrough you have VS Code already installed. While you don’t need to have any special configuration, having something different than the default (like a <a target="_blank" href="https://code.visualstudio.com/docs/getstarted/themes">color theme</a>) will help you see it work.</p>
<p>Let’s get started!</p>
<h2 id="heading-step-1-install-settings-sync">Step 1: Install Settings Sync</h2>
<p>The first thing we need to do is install the extension. You can do this <a target="_blank" href="https://code.visualstudio.com/docs/editor/extension-gallery">a few ways</a> — you can visit <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=Shan.code-settings-sync">the webpage</a> and hit <strong>Install</strong> which will open up VS Code or you can search for the extension in the Extensions panel.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/vs-code-settings-sync-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>VS Code Settings Sync extension</em></p>
<p>Once installed, it will open up a new tab with the Settings Sync dashboard.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/vs-code-settings-sync-dashboard.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Settings Sync dashboard after installation</em></p>
<h2 id="heading-step-2-authorize-access-to-github">Step 2: Authorize access to Github</h2>
<p>To get started with Github, click the <strong>Login with Github</strong> button in the Settings Sync dashboard.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/vs-code-settings-sync-login-with-github.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Log in to Settings Sync with Github</em></p>
<p>This will open up Github in your default web browser and ask you to log in. While you can use any Github account you want, it would probably make most sense to use your personal account.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/vs-code-login-success.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Successful Github login to Settings Sync</em></p>
<p>Once you’re logged in, you should now see <strong>Success!</strong> in your browser.</p>
<h2 id="heading-step-3-upload-your-current-settings">Step 3: Upload your current settings</h2>
<p>Now that you’re connected to Github, you’re ready to upload your settings.</p>
<p>Open up your <a target="_blank" href="https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette">Command Palette</a> with CMD+Shift+P (on Mac) or navigate to View and Command Palette. Type “Sync Upload” which will filter the commands and hit enter once the <strong>Sync: Update/Upload Settings</strong> option is selected.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/vs-code-settings-sync-upload-update-command.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Update/Upload Settings command in Settings Sync</em></p>
<p>When doing this, you might be prompted with screen that asks if you want to force upload — press <strong>Yes</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/vs-code-settings-sync-force-upload.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Force upload new settings in Settings Sync</em></p>
<p>At this point, Settings Sync will create a new Gist in your Github account with your configuration settings. Once it’s done you should see a success message.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/vs-code-settings-sync-successful-upload.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Successful settings upload in Settings Sync</em></p>
<p>You should now be able to visit <a target="_blank" href="https://gist.github.com/">gist.github.com</a> and find a new private <code>cloudSettings</code> Gist that includes all of your VS Code settings!</p>
<h2 id="heading-step-4-syncing-your-configuration-to-another-environment">Step 4: Syncing your configuration to another environment</h2>
<p>To sync your VS Code configuration to another computer or VS Code environment, you want to first follow steps 1 and 2 above — installing the extension and logging in to Github.</p>
<p>The difference is this time, you’ll want to configure VS Code to download your settings instead of upload them.</p>
<p>To get started, first open back up your Sync Settings dashboard. If this is a new installation like we’re assuming here, you can open up the Command Palette and type “sync download” and hit enter which will open up that dashboard. Here, click <strong>Edit Configuration</strong> this time.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/vs-code-settings-sync-edit-configuration.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Edit Settings Sync configuration</em></p>
<p>On this screen, you should see your <strong>Github Access Token</strong>, but you should also see an empty field for Gist ID. Here, we want to first grab the ID from our cloudSettings Gist URL:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/vs-code-settings-github-gist.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>VS Code cloudSettings Gist ID</em></p>
<p>And then paste that value inside of our <strong>Gist ID</strong> input in VS Code.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/vs-code-settings-sync-gist-id-configuration-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Adding Gist ID to Settings Sync configuration</em></p>
<p>Once it’s there, you can open the Command Palette again, type “sync download”, and hit enter, and Sync Settings will fetch your VS Code configuration from the Gist and update your local settings with that configuration!</p>
<h2 id="heading-step-5-updating-your-configuration">Step 5: Updating your configuration</h2>
<p>From here on, any time you want to make a new change to your stored configuration, you’ll want to use both the Update/Upload and Download features like we used above.</p>
<p>To update a new tweak to your configuration, type “sync update”  and hit enter:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/vs-code-settings-sync-update-settings.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Update command for Settings Sync</em></p>
<p>And to download your configuration to sync up another editor, type “sync download” and hit enter:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/vs-code-settings-sync-download-command.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Download settings command for Settings Sync</em></p>
<p>These commands will both update your cloudSettings Gist and download from it to sync up your VS Code instances</p>
<h2 id="heading-whats-your-favorite-vs-code-trick">What’s your favorite VS Code trick?</h2>
<p><a target="_blank" href="https://twitter.com/colbyfayock">Share it with me on Twitter!</a></p>
<h2 id="heading-join-the-conversation">Join the conversation</h2>
<div class="embed-wrapper">
        <blockquote class="twitter-tweet">
          <a href="https://twitter.com/colbyfayock/status/1272906851005366274"></a>
        </blockquote>
        <script defer="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></div>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">?️ Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Todo API in Deno and Oak ]]>
                </title>
                <description>
                    <![CDATA[ By Adeel Imran I am a JavaScript/Node developer who secretly likes (actually, loves and adores) Deno. I have been a huge fan of Deno ever since it was announced and I've been wanting to play with it.  This tutorial focuses on creating a set of REST A... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/create-a-todo-api-in-deno-written-by-a-guy-coming-from-node/</link>
                <guid isPermaLink="false">66d45d5d51f567b42d9f8413</guid>
                
                    <category>
                        <![CDATA[ 2020 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Deno ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Middleware ]]>
                    </category>
                
                    <category>
                        <![CDATA[ REST API ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 29 May 2020 11:33:00 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9ab6740569d1a4ca273d.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Adeel Imran</p>
<p>I am a JavaScript/Node developer who secretly likes (actually, loves and adores) Deno. I have been a huge fan of Deno ever since it was announced and I've been wanting to play with it. </p>
<p>This tutorial focuses on creating a set of REST APIs for a Todo application. Keep in mind that I did not touch on the database here – I will cover that <a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-mysql-in-deno-oak/">in another article</a>.</p>
<p>At any point if you feel lost or want to check a reference, here is the entire source code of this tutorial: <strong><a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak">Chapter 1: Oak</a>.</strong></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/image-171.png" alt="Image" width="600" height="400" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/@bernardtheclerk?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"&gt;Bernard de Clerk / &lt;a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm<em>campaign=api-credit)</em></p>
<h3 id="heading-things-we-will-cover">Things we will cover</h3>
<ul>
<li>Create a basic server</li>
<li>Create 5 APIs (routes/controller)</li>
<li>Create a middleware to log API requests as they are made in the console</li>
<li>Create a not found (404) middleware when the user tries to access an unknown API</li>
</ul>
<h3 id="heading-what-will-we-need">What will we need</h3>
<ul>
<li>An installed version of Deno (don't worry I'll walk you through it)</li>
<li>A tiny bit of knowledge of Typescript</li>
<li>Would be awesome if you have worked with Node/Express before (don't worry if you haven't — this tutorial is very basic)</li>
</ul>
<h2 id="heading-lets-get-started">Let's get started</h2>
<p>First things first let's install Deno. I am on a Mac computer so I am using brew. Simply open your terminal and type:</p>
<pre><code>$ brew install deno
</code></pre><p>But if you are using a different operating system, just head over to <a target="_blank" href="https://deno.land/#installation"><strong>deno.land installation</strong></a><strong>.</strong> They have a lot of ways you can easily install it on your machine.</p>
<p>Once you have it installed, close the terminal, open a new one, and type:</p>
<pre><code>$ deno --version
</code></pre><p>It should output something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-28-at-22.34.24.png" alt="Image" width="600" height="400" loading="lazy">
<em>running command "deno --version" to see which version of deno is installed</em></p>
<p>Awesome! With this we are almost done with 10% of this tutorial. </p>
<p>Let's move ahead and create the backend API for our Todo app.</p>
<h3 id="heading-setting-up-the-project">Setting up the project</h3>
<p>Before you move on, here is the entire source code of this tutorial: <strong><a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak">Chapter 1: Oak</a>.</strong></p>
<p>Let's get started:</p>
<ul>
<li>Create a new folder and call it <strong>chapter_1:oak</strong> (but you can call it anything you want)</li>
<li>Once you create a folder simply <code>cd</code> into your new project. Create a file called <strong>server.ts</strong> and write the following code in it:</li>
</ul>
<pre><code class="lang-server.ts">import { Application } from "https://deno.land/x/oak/mod.ts";

const app = new Application();
const port: number = 8080;

console.log('running on port ', port);
await app.listen({ port });
</code></pre>
<p>Let's run this file. Open your terminal and in your project root folder type:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>I will talk about what the <code>--allow-net</code> flag does, but for now just bear with me ?.</p>
<p>You should get something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-28-at-22.33.28.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>What we have done so far is create a server which listens on port 8080. It doesn't do much right now besides being able to run on port 8080.</p>
<p>If you have used JavaScript before, one thing you might have noticed is we are importing packages in a different way. We have to do something like:</p>
<pre><code><span class="hljs-keyword">import</span> { Application } <span class="hljs-keyword">from</span> <span class="hljs-string">"https://deno.land/x/oak/mod.ts"</span>;
</code></pre><p>When you run <code>deno run ---allow-net &lt;file_name&gt;</code> in your terminal, Deno will look at all your imports and install them locally in your machine if they are not there. </p>
<p>The first time you run this it will go to this URL <code>https://deno.land/x/oak/mod.ts</code> and install the <code>oak</code> package. Oak is basically a Deno framework for writing API's. It will put it somewhere locally in your cache.</p>
<p>In the next line we do this:</p>
<pre><code><span class="hljs-keyword">const</span> app = <span class="hljs-keyword">new</span> Application();
</code></pre><p>This creates a new instance of our application, and it will be the basis of everything as you progress further in this tutorial. You can add routes to the application instance, attach middleware like API logging, write a 404 not found, and so on.</p>
<p>Then we write:</p>
<pre><code><span class="hljs-keyword">const</span> port: number = <span class="hljs-number">8080</span>;
<span class="hljs-comment">// const port = 8080; // =&gt; can also be written like this</span>
</code></pre><p>Both are the same and do the same thing. The only difference is writing <code>const port: number = 8080</code> tells Typescript that <code>port</code> variable is of type number.</p>
<p>If you were to write <code>const port: number = "8080"</code>, this would throw an error in your terminal, as port is of type <code>number</code>. But we are trying to assign it a <code>string</code> of value "8080". </p>
<p>If you want to learn more about different types of types (pun intended) check out this very easy and basic guide on <a target="_blank" href="https://www.typescriptlang.org/docs/handbook/basic-types.html"><strong>Basic types by Typescript</strong></a>. Just give it a quick glance for 2-3 minutes and head back here.</p>
<p>And in the end we have:</p>
<pre><code><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'running on port '</span>, port);
<span class="hljs-keyword">await</span> app.listen({ port });
</code></pre><p>We simply console here the port number and tell Deno to listen to the port, which is 8080.</p>
<p>It isn't doing much right now. Let's make it do something basic like show a <em>JSON</em> message in your browser when you go to http:localhost:8080<em>.</em></p>
<p>Add the following to your <strong>server.ts</strong> file:</p>
<pre><code class="lang-server.ts">import { Application, Router } from "https://deno.land/x/oak/mod.ts";

const app = new Application();
const port: number = 8080;

const router = new Router();
router.get("/", ({ response }: { response: any }) =&gt; {
  response.body = {
    message: "hello world",
  };
});
app.use(router.routes());
app.use(router.allowedMethods());

console.log('running on port ', port);
await app.listen({ port });
</code></pre>
<p>The new thing added here is that we are now also importing <code>Router</code> along with <code>Application</code> from <code>oak</code> in line 1.</p>
<p>Next what we do is:</p>
<pre><code><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> Router();
router.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">{ response }: { response: any }</span>) =&gt;</span> {
  response.body = {
    <span class="hljs-attr">message</span>: <span class="hljs-string">"hello world"</span>,
  };
});
app.use(router.routes());
app.use(router.allowedMethods());
</code></pre><p>We create a new router instance by doing <code>const router = new Router()</code> and then we create a new route called <code>/</code> which is of type <code>get</code>.</p>
<p>Let's break this down:</p>
<pre><code>router.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">{ response }: { response: any }</span>) =&gt;</span> {
  response.body = {
    <span class="hljs-attr">message</span>: <span class="hljs-string">"hello world"</span>,
  };
});
</code></pre><p><code>router.get</code> takes 2 parameters. The first is route which we have set to <code>/</code> and the second is function. The function itself takes an argument which is an object. What I am doing here is <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">destructuring</a> the object and getting only <code>response</code>.</p>
<p>Next I am type checking <code>response</code> similar to how I did <code>const port: number = 8080;</code>. All I am doing is <code>{ response }: { response: any }</code> which is telling TypeScript here that the <code>response</code> which I have destructed can be of type <code>any</code>.</p>
<p><code>any</code> helps you avoid type checking in TypeScript. You can read more about it <a target="_blank" href="https://www.typescriptlang.org/docs/handbook/basic-types.html#any">here</a>.</p>
<p>Then all I am doing is taking that <code>response</code> object and setting <code>response.body.message = "hello world";</code>.</p>
<pre><code>response.body = {
  <span class="hljs-attr">message</span>: <span class="hljs-string">"hello world"</span>,
};
</code></pre><p>Last but not least, we just add these two lines:</p>
<pre><code>app.use(router.routes());
app.use(router.allowedMethods());
</code></pre><p>This tells Deno to include all routes by our router (currently we only have one) and the next line tells Deno to allow all methods for this route(s) like <code>GET, POST, PUT, DELETE</code>.</p>
<p>And now we are done. ✅ Let's run this and see what we have:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>The <code>---allow-net</code> property tells Deno that this app gives the user the permission to access its content via the port opened up.</p>
<p>Now open your favorite browser and go to <code>http://localhost:8080</code>. You will see something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-28-at-23.11.08.png" alt="Image" width="600" height="400" loading="lazy">
<em>Result of running localhost:8080 on your browser</em></p>
<p>Honestly the hardest part is done. Conceptually we are 60% there.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/images.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>Master Yoda approves</em></p>
<p>Awesome.</p>
<p>Just one last thing before we start with our Todo API. Let's replace:</p>
<pre><code><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'running on port '</span>, port);
<span class="hljs-keyword">await</span> app.listen({ port });
</code></pre><p>with:</p>
<pre><code class="lang-server.ts">app.addEventListener("listen", ({ secure, hostname, port }) =&gt; {
  const protocol = secure ? "https://" : "http://";
  const url = `${protocol}${hostname ?? "localhost"}:${port}`;
  console.log(`Listening on: ${port}`);
});

await app.listen({ port });
</code></pre>
<p>The code we had before was not very accurate, because we were simply console logging a message and then waiting for the app to start listening on a port.</p>
<p>With the later version we wait for the app to start listening on <code>port</code> and we can listen by adding an event listener to our <code>app</code> instance with the following: <code>app_.addEventListener_("listen", ({ secure, hostname, port }) =&gt; {}</code>. </p>
<p>The first param is the event we want to listen for (which is <code>listen</code> ?) and then the second param is an object which we destruct to <code>{ secure, hostname, port }</code>. Secure is a boolean, hostname is a string, and port is a number.</p>
<p>Now when we start our app, it will only console the message once the app actually starts listening on port.</p>
<p>We can just go one step ahead and make it more colorful. Let's add a new module to the top of the file in <code>server.ts</code>:</p>
<pre><code><span class="hljs-keyword">import</span> { green, yellow } <span class="hljs-keyword">from</span> <span class="hljs-string">"https://deno.land/std@0.53.0/fmt/colors.ts"</span>;
</code></pre><p>And then inside our event listener method we can replace:</p>
<pre><code><span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Listening on: <span class="hljs-subst">${port}</span>`</span>);
</code></pre><p>with:</p>
<pre><code><span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${yellow(<span class="hljs-string">"Listening on:"</span>)}</span> <span class="hljs-subst">${green(url)}</span>`</span>);
</code></pre><p>Now when we do:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>it will show this in our console:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-28-at-23.34.29.png" alt="Image" width="600" height="400" loading="lazy">
<em>Cool, now we have a colourful console.</em></p>
<p>If you get stuck anywhere you can simply go to the source code of this tutorial <a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak"><strong>here</strong></a>.</p>
<p>Let's create our Todo API's routes next.</p>
<ul>
<li>Create a new folder in your root folder called <code>routes</code> and inside that folder create a file called <code>todo.ts</code></li>
<li>At the same time in your root folder create a new folder called <code>controllers</code> and inside that folder create a file called <code>todo.ts</code></li>
</ul>
<p>Let's first touch the <code>controllers/todo.ts</code> file:</p>
<pre><code class="lang-controllers/todo.ts">export default {
  getAllTodos: () =&gt; {},
  createTodo: async () =&gt; {},
  getTodoById: () =&gt; {},
  updateTodoById: async () =&gt; {},
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>We are simply exporting an object here with some named functions which are empty (for now).</p>
<p>Next go inside your file <code>routes/todo.ts</code> and type this:</p>
<pre><code class="lang-routes/todo.ts">import { Router } from "https://deno.land/x/oak/mod.ts";

const router = new Router();
// controller
import todoController from "../controllers/todo.ts";

router
  .get("/todos", todoController.getAllTodos)
  .post("/todos", todoController.createTodo)
  .get("/todos/:id", todoController.getTodoById)
  .put("/todos/:id", todoController.updateTodoById)
  .delete("/todos/:id", todoController.deleteTodoById);

export default router;
</code></pre>
<p>This might look familiar to people who have worked with Node and Express. </p>
<p>All we are doing here is importing <code>Route</code> from <code>oak</code> and then setting up a new instance of Router by doing <code>const router = new Router();</code>.</p>
<p>Next we import our controllers by doing:</p>
<pre><code><span class="hljs-keyword">import</span> todoController <span class="hljs-keyword">from</span> <span class="hljs-string">"../controllers/todo.ts"</span>;
</code></pre><p>One thing to notice here in Deno is every time we import a local file in our Deno project we have to provide the file extension. This is because Deno doesn't know whether the file being imported is a <code>.js</code> or <code>.ts</code> file.</p>
<p>Moving forward we simply set all of our routes according to REST conventions:</p>
<pre><code class="lang-routes/todo.ts">router
  .get("/todos", todoController.getAllTodos)
  .post("/todos", todoController.createTodo)
  .get("/todos/:id", todoController.getTodoById)
  .put("/todos/:id", todoController.updateTodoById)
  .delete("/todos/:id", todoController.deleteTodoById);
</code></pre>
<p>The code above will translate to our API definition like this:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>TYPE</td><td>API ROUTE</td><td></td><td></td><td></td></tr>
</thead>
<tbody>
<tr>
<td>GET</td><td>/todos</td><td></td><td></td><td></td></tr>
<tr>
<td>GET</td><td>/todos/:id</td><td></td><td></td><td></td></tr>
<tr>
<td>POST</td><td>/todos</td><td></td><td></td><td></td></tr>
<tr>
<td>PUT</td><td>/todos/:id</td><td></td><td></td><td></td></tr>
<tr>
<td>DELETE</td><td>/todos/:id</td><td></td><td></td></tr>
</tbody>
</table>
</div><p>and at the end we simply export our router by doing <code>_export_ _default_ router;</code>.</p>
<p>We are done with creating our routes structure. (Now, each route doesn't do anything because our controllers are empty, we will add functionality to them in a bit.)</p>
<p>Here's the last piece of the puzzle before we start adding functionality to each route controller. We need to attach this <code>router</code> to our <code>app</code> instance.</p>
<p>So head over to <code>server.ts</code> file and do the following:</p>
<ul>
<li>Add this to the very top:</li>
</ul>
<pre><code><span class="hljs-comment">// routes</span>
<span class="hljs-keyword">import</span> todoRouter <span class="hljs-keyword">from</span> <span class="hljs-string">"./routes/todo.ts"</span>;
</code></pre><ul>
<li>Remove this piece of code:</li>
</ul>
<pre><code><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> Router();
router.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">{ response }: { response: any }</span>) =&gt;</span> {
  response.body = {
    <span class="hljs-attr">message</span>: <span class="hljs-string">"hello world"</span>,
  };
});
app.use(router.routes());
app.use(router.allowedMethods());
</code></pre><ul>
<li>Replace it with:</li>
</ul>
<pre><code>app.use(todoRouter.routes());
app.use(todoRouter.allowedMethods());
</code></pre><p>This is it – we are done. Your <code>server.ts</code> file should look like this now:</p>
<pre><code class="lang-server.ts">import { Application } from "https://deno.land/x/oak/mod.ts";
import { green, yellow } from "https://deno.land/std@0.53.0/fmt/colors.ts";

// routes
import todoRouter from "./routes/todo.ts";

const app = new Application();
const port: number = 8080;

app.use(todoRouter.routes());
app.use(todoRouter.allowedMethods());

app.addEventListener("listen", ({ secure, hostname, port }) =&gt; {
  const protocol = secure ? "https://" : "http://";
  const url = `${protocol}${hostname ?? "localhost"}:${port}`;
  console.log(
    `${yellow("Listening on:")} ${green(url)}`,
  );
});

await app.listen({ port });
</code></pre>
<p>If you got stuck anywhere while following this, simple head over to the source code of this tutorial <strong><a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak">here</a>.</strong></p>
<p>Awesome, now we have our routes with no functionality at the moment. So let's add that functionality in our controllers.</p>
<p>But before we do that we have to create 2 more (tiny) files.</p>
<ul>
<li>In your root folder create a new folder called <code>interfaces</code> and inside that folder create a file called <code>Todo.ts</code> (make sure Todo is capitalized, as it won't give any syntax error here if you don't – these are just conventions.)</li>
<li>Also in your root folder create a new folder called <code>stubs</code> and inside that folder create a file called <code>todos.ts</code></li>
</ul>
<p>Let's create an interface in our <code>interfaces/Todo.ts</code> file. Simply add the following code:</p>
<pre><code class="lang-interfaces/todo.ts">export default interface Todo {
  id: string,
  todo: string,
  isCompleted: boolean,
}
</code></pre>
<p>What is an interface?</p>
<p>One of the core things in TypeScript is checking the shape that value has. Similar to <code>const port: number = 8080</code> or <code>{ response }: { response : any }</code>, we can also type check an object. </p>
<p>In TypeScript, interfaces fill the role of naming these types, and are a powerful way of <strong>defining contracts within</strong> your code as well as <strong>contracts with code outside</strong> of your project. </p>
<p>Here is an another example of an interface:</p>
<pre><code class="lang-ts"><span class="hljs-comment">// We have an interface</span>
<span class="hljs-keyword">interface</span> LabeledValue {
  label: <span class="hljs-built_in">string</span>;
}

<span class="hljs-comment">// the arg passed to this function labeledObj is </span>
<span class="hljs-comment">// of type LabeledValue (interface)</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">printLabel</span>(<span class="hljs-params">labeledObj: LabeledValue</span>) </span>{
  <span class="hljs-built_in">console</span>.log(labeledObj.label);
}

<span class="hljs-keyword">let</span> myObj = {label: <span class="hljs-string">"Size 10 Object"</span>};
printLabel(myObj);
</code></pre>
<p>Hopefully this example gives you a bit more insight into interfaces. If you want more detailed information check out the docs on <a target="_blank" href="https://www.typescriptlang.org/docs/handbook/interfaces.html">interfaces here</a>.</p>
<p>Now that our interface is ready, let's mock some data (since we don't have an actual database for this tutorial).</p>
<p>Let's create a mock list of todos first in our <code>stubs/todos.ts</code> file. Simply add the following:</p>
<pre><code class="lang-stubs/todos.ts">import { v4 } from "https://deno.land/std/uuid/mod.ts";
// interface
import Todo from '../interfaces/Todo.ts';

let todos: Todo[] = [
  {
    id: v4.generate(),
    todo: 'walk dog',
    isCompleted: true,
  },
  {
    id: v4.generate(),
    todo: 'eat food',
    isCompleted: false,
  },
];

export default todos;
</code></pre>
<ul>
<li>Two things to notice here: we add a new package and use its method <code>v4</code> by doing <code>_import_ { v4 } _from_ "https://deno.land/std/uuid/mod.ts";</code>. Then every time we use <code>v4.generate()</code> it will create a new random string of <code>id</code>.  </li>
</ul>
<p>The <code>id</code> can not be a <code>number</code>, only a <code>string</code> because in our <code>Todo</code> interface we have defined <code>id</code> as a string.</p>
<ul>
<li>The other thing to focus on here is <code>let _todos_: _Todo_[]</code> = []. This basically tells Deno that our todos array is of type <code>Todo</code> (which is awesome, our compiler now <em>automagically</em> knows that each item in our array can only have <code>{**id**: _string_, **todo**: _string_ &amp; **isCompleted**: _boolean_}</code> it will not accept any other key).</li>
</ul>
<p>If you want to learn more about <code>interfaces</code> in TypeScript check out this amazing detailed documentation on interfaces <strong><a target="_blank" href="https://www.typescriptlang.org/docs/handbook/interfaces.html">here</a>.</strong></p>
<p>Awesome. If you have come this far, give yourself a pat on the back. Good job everyone.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/download-1.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>The Rock appreciates all the effort you are doing</em></p>
<h2 id="heading-lets-work-on-our-controllers">Let's work on our controllers</h2>
<p>In your file <code>controllers/todo.ts</code>:</p>
<pre><code class="lang-controllers/todos.ts">export default {
  getAllTodos: () =&gt; {},
  createTodo: async () =&gt; {},
  getTodoById: () =&gt; {},
  updateTodoById: async () =&gt; {},
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>Let's write the controller for <code>getAllTodos</code>:</p>
<pre><code class="lang-controllers/todos.ts">// stubs
import todos from "../stubs/todos.ts";

export default {
  /**
   * @description Get all todos
   * @route GET /todos
   */
  getAllTodos: ({ response }: { response: any }) =&gt; {
    response.status = 200;
    response.body = {
      success: true,
      data: todos,
    };
  },
  createTodo: async () =&gt; {},
  getTodoById: () =&gt; {},
  updateTodoById: async () =&gt; {},
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>Before I begin on this block of code, let me explain that every controller has an argument – let's call it <code>context</code>.</p>
<p>So we can deconstruct <code>_getAllTodos_: (context) =&gt; {}</code> to:</p>
<pre><code>getAllTodos: <span class="hljs-function">(<span class="hljs-params">{ request, response, params }</span>) =&gt;</span> {}
</code></pre><p>And since we are using <code>typescript</code> we have to add type checking to all of these variables:</p>
<pre><code>getAllTodos: <span class="hljs-function">(<span class="hljs-params">
  { request, response, params }: { 
    request: any, 
    response: any, 
    params: { id: string },
  },
</span>) =&gt;</span> {}
</code></pre><p>So we have added type checks to all 3 <code>{ request, response, params }</code></p>
<ul>
<li><code>request</code> is what the user sends us (information like headers and JSON data)</li>
<li><code>response</code> is what we send the user back in the API response</li>
<li><code>params</code> is what we define in our router routes, that is:</li>
</ul>
<pre><code class="lang-ts">.get(<span class="hljs-string">"/todos/:id"</span>, <span class="hljs-function">(<span class="hljs-params">{ params}: { params: { id: <span class="hljs-built_in">string</span> } }</span>) =&gt;</span> {})
</code></pre>
<p>So the <code>:id</code> in <code>/todos/:id</code> is the param. Params are a way to get information from the URL. In this example we know that we have an <code>/:id</code> . So when the user tries to access this API (that is, <code>/todos/756</code>) <strong>756</strong> is basically the <strong>:id</strong> param. Since it is in the URL we know it is of type <code>string</code>.</p>
<p>Now that we have our basic definitions defined let's get back to our todos controller:</p>
<pre><code class="lang-controllers/todos.ts">// stubs
import todos from "../stubs/todos.ts";

export default {
  /**
   * @description Get all todos
   * @route GET /todos
   */
  getAllTodos: ({ response }: { response: any }) =&gt; {
    response.status = 200;
    response.body = {
      success: true,
      data: todos,
    };
  },
  createTodo: async () =&gt; {},
  getTodoById: () =&gt; {},
  updateTodoById: async () =&gt; {},
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>For <code>getAllTodos</code> we only need <code>response</code> . If you remember, <code>response</code> is what is needed to send data back to the user.</p>
<p>For people coming from a Node and Express background, one big thing that is different here is that we don't need to <code>return</code> the response object. Deno does this for us automatically.</p>
<p>All we have to do is set <code>response.status</code> which in this case is <code>200</code>.</p>
<p>More on response statuses <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"><strong>here</strong></a><strong>.</strong></p>
<p>The other thing we set is the <code>response.body</code> which in this case is an object:</p>
<pre><code class="lang-ts">{
  success: <span class="hljs-literal">true</span>,
  data: todos
}
</code></pre>
<p>I will go ahead and run my server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><blockquote>
<p><strong>Revision:</strong> The <code>---allow-net</code> property tells Deno that this app gives the user permission to access its content via the port opened up.</p>
</blockquote>
<p>Once your server is running, you can access the <code>GET /todos</code> API. I am using <code>postman</code> which is a Google Chrome extension and can be downloaded <a target="_blank" href="https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop//%40">here</a>.</p>
<p>You can use whatever rest client you like. I like using <code>postman</code> because I think it is very easy.</p>
<p>In Postman, open up a new tab. Set the request to type <code>GET</code> and in the <code>URL</code> bar type <code>http://localhost:8080/todos</code>. Hit <code>Send</code> and this is what you see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-02.01.11.png" alt="Image" width="600" height="400" loading="lazy">
<em>GET /todos API response</em></p>
<p>Cool! 1 API done, 4 more to go. ??</p>
<p>If you feel stuck anywhere just have sneak peak at the source code directly <a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak"><strong>here</strong></a><strong>.</strong></p>
<p>Let's move on to our next controller:</p>
<pre><code class="lang-controllers/todos.ts">import { v4 } from "https://deno.land/std/uuid/mod.ts";
// interfaces
import Todo from "../interfaces/Todo.ts";
// stubs
import todos from "../stubs/todos.ts";

export default {
  getAllTodos: () =&gt; {},
  /**
   * @description Add a new todo
   * @route POST /todos
   */
  createTodo: async (
    { request, response }: { request: any; response: any },
  ) =&gt; {
    const body = await request.body();
    if (!request.hasBody) {
      response.status = 400;
      response.body = {
        success: false,
        message: "No data provided",
      };
      return;
    }

    // if everything is fine then perform
    // operation and return todos with the
    // new data added.
    let newTodo: Todo = {
      id: v4.generate(),
      todo: body.value.todo,
      isCompleted: false,
    };
    let data = [...todos, newTodo];
    response.body = {
      success: true,
      data,
    };
  },
  getTodoById: () =&gt; {},
  updateTodoById: async () =&gt; {},
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>Since we are going to be adding a new Todo to our list, I have imported 2 modules in the controller file.</p>
<ul>
<li><code>import { v4 } from</code><a target="_blank" href="https://deno.land/std/uuid/mod.ts">https://deno.land/std/uuid/mod.ts</a><code>;</code> this will be used to create a new unique one for the todo being created</li>
<li><code>import Todo from "../interfaces/Todo.ts";</code> this will be used to ensure that the new todo that is being created follows the same structure.</li>
</ul>
<p>Our <code>createTodo</code> controller is <code>async</code> meaning there are some promises used inside the controller. </p>
<p>Let's break it into smaller parts:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">const</span> body = <span class="hljs-keyword">await</span> request.body();
<span class="hljs-keyword">if</span> (!request.hasBody) {
      response.status = <span class="hljs-number">400</span>;
      response.body = {
        success: <span class="hljs-literal">false</span>,
        message: <span class="hljs-string">"No data provided"</span>,
      };
      <span class="hljs-keyword">return</span>;
}
</code></pre>
<p>First we get the content of the JSON body that the user has sent us. Then we use <code>oak's</code> built-in method called <code>request.hasBody</code> to check if the user has even sent any content. If not then we can do <code>if (!request_._hasBody) {}</code> inside this <code>if</code> block. </p>
<p>We set the status to <code>400</code> (400 means that the user did something they were not suppose to do) and the body is set to <code>{success: false, message: "no data provided }</code>. Then we simple add <code>return;</code> to ensure that no further code below is executed.</p>
<p>Next we do this:</p>
<pre><code><span class="hljs-comment">// if everything is fine then perform</span>
<span class="hljs-comment">// operation and return todos with the</span>
<span class="hljs-comment">// new data added.</span>
<span class="hljs-keyword">let</span> newTodo: Todo = {
  <span class="hljs-attr">id</span>: v4.generate(),
  <span class="hljs-attr">todo</span>: body.value.todo,
  <span class="hljs-attr">isCompleted</span>: <span class="hljs-literal">false</span>,
};
<span class="hljs-keyword">let</span> data = [...todos, newTodo];
response.body = {
  <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
  data,
};
</code></pre><p>We create a new todo by doing this:</p>
<pre><code><span class="hljs-keyword">let</span> newTodo: Todo = {
  <span class="hljs-attr">id</span>: v4.generate(),
  <span class="hljs-attr">todo</span>: body.value.todo,
  <span class="hljs-attr">isCompleted</span>: <span class="hljs-literal">false</span>,
};
</code></pre><p><code>let newTodo: Todo = {}</code> ensures that <code>newTodo</code> follows the same structure as the rest of the todos. We then assign a random id by using <code>v4.generate()</code>, set todo to <code>body.value.todo</code> and <code>isCompleted</code> to  <code>false</code>.</p>
<p>The thing to notice here is all the data the user sends us we can access from <code>body.value</code> in <code>oak</code>.</p>
<p>Next we do the following:</p>
<pre><code><span class="hljs-keyword">let</span> data = [...todos, newTodo];
response.body = {
  <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
  data,
};
</code></pre><p>Append the <code>newTodo</code> to our current list of todos and simply set the body to <code>{success: true &amp; data: data</code>.</p>
<p>And we are done ✅ with this controller as well.</p>
<p>Let's restart our server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>In my postman, I open up a new tab. Set the request to <code>POST</code> type and in the <code>URL</code> bar type <code>http://localhost:8080/todos</code>. Then hit <code>Send</code> and this is what you see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-02.24.00.png" alt="Image" width="600" height="400" loading="lazy">
<em>I send an empty request and get a 400 status error code along with an error message</em></p>
<p>Then I send some content in the body of the request payload and try again:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-02.24.15.png" alt="Image" width="600" height="400" loading="lazy">
<em>Awesome, POST /todos with body content { todo: "eat a lamma" } is success &amp; we can see content appended to our current todo list</em></p>
<p>Cool, we can see that our API is working as expected.</p>
<p>Two APIs down, three more to go. </p>
<p>We are almost there. Most of the hard work is done. ☺️ ? ? ?</p>
<p>Let's move on to our third API:</p>
<pre><code class="lang-controllers/todos.ts">import { v4 } from "https://deno.land/std/uuid/mod.ts";
// interfaces
import Todo from "../interfaces/Todo.ts";
// stubs
import todos from "../stubs/todos.ts";

export default {
  getAllTodos: () =&gt; {},
  createTodo: async () =&gt; {},
  /**
   * @description Get todo by id
   * @route GET todos/:id
   */
  getTodoById: (
    { params, response }: { params: { id: string }; response: any },
  ) =&gt; {
    const todo: Todo | undefined = todos.find((t) =&gt; {
      return t.id === params.id;
    });
    if (!todo) {
      response.status = 404;
      response.body = {
        success: false,
        message: "No todo found",
      };
      return;
    }

    // If todo is found
    response.status = 200;
    response.body = {
      success: true,
      data: todo,
    };
  },
  updateTodoById: async () =&gt; {},
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>Let's talk about our controller for <code>GET todos/:id</code>. This will get us a todo by ID.</p>
<p>Let's break this down into smaller parts and discuss it:</p>
<pre><code><span class="hljs-keyword">const</span> todo: Todo | <span class="hljs-literal">undefined</span> = todos.find(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> t.id === params.id);
<span class="hljs-keyword">if</span> (!todo) {
  response.status = <span class="hljs-number">404</span>;
  response.body = {
    <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">message</span>: <span class="hljs-string">"No todo found"</span>,
  };
  <span class="hljs-keyword">return</span>;
}
</code></pre><p>In the first part we set a new <code>const todo</code> and set its type to either <code>Todo</code> or <code>undefined</code>. So <code>todo</code> will either be an object with the <code>Todo</code> interface shape or it will be <code>undefined</code> – it can not be anything else.</p>
<p>We then <code>_todos.find_((_t_)</code> =&gt; <em>t.id</em> === <em>params.id</em>); use <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find">Array.find()</a> to find the <code>todo</code> with the id provided in <code>params.id</code>. If it matches we get a <code>Todo</code> with shape <code>todo</code>, otherwise <code>undefined</code>.</p>
<p>If <code>todo</code> is undefined, it means that this <code>if</code> block will run:</p>
<pre><code><span class="hljs-keyword">if</span> (!todo) {
  response.status = <span class="hljs-number">404</span>;
  response.body = {
    <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">message</span>: <span class="hljs-string">"No todo found"</span>,
  };
  <span class="hljs-keyword">return</span>;
}
</code></pre><p>Here we simply set the status to <code>404</code> which means <code>not found</code> along with our standard failure response or <code>{ status, message }</code></p>
<p>Cool, right? ?</p>
<p>Next we simply do this:</p>
<pre><code><span class="hljs-comment">// If todo is found</span>
response.status = <span class="hljs-number">200</span>;
response.body = {
  <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">data</span>: todo,
};
</code></pre><p>Set a <code>200</code> success response and in our response body we set <code>success: true &amp; data: todo</code>.</p>
<p>Let's run this in our postman.</p>
<p>Let's restart our server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>In my postman, I open up a new tab. Set the request to <code>GET</code> type and in the <code>URL</code> bar type <code>http://localhost:8080/todos/:id</code>, then hit <code>Send</code>.</p>
<p>Since we are generating ID's randomly, first get all todos by hitting theget all todos API. Then from any todo get one of its ID to test this newly created API.<br>Every time you restart this Deno application, new ID's will be generated.</p>
<p>Let's go:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-02.40.52.png" alt="Image" width="600" height="400" loading="lazy">
<em>404 status, no record found case</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-02.41.36.png" alt="Image" width="600" height="400" loading="lazy">
<em>Provided it a known ID and it returned the todo associated with that ID along with status 200</em></p>
<p>If you need to reference the original source code of this tutorial go <a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak"><strong>here</strong></a>.</p>
<p>Great, 3 APIs done, 2 more to go.</p>
<pre><code class="lang-controllers/todos.ts">import { v4 } from "https://deno.land/std/uuid/mod.ts";
// interfaces
import Todo from "../interfaces/Todo.ts";
// stubs
import todos from "../stubs/todos.ts";

export default {
  getAllTodos: () =&gt; {},
  createTodo: async () =&gt; {},
  getTodoById: () =&gt; {},
  /**
   * @description Update todo by id
   * @route PUT todos/:id
   */
  updateTodoById: async (
    { params, request, response }: {
      params: { id: string },
      request: any,
      response: any,
    },
  ) =&gt; {
    const todo: Todo | undefined = todos.find((t) =&gt; t.id === params.id);
    if (!todo) {
      response.status = 404;
      response.body = {
        success: false,
        message: "No todo found",
      };
      return;
    }

    // if todo found then update todo
    const body = await request.body();
    const updatedData: { todo?: string; isCompleted?: boolean } = body.value;
    let newTodos = todos.map((t) =&gt; {
      return t.id === params.id ? { ...t, ...updatedData } : t;
    });
    response.status = 200;
    response.body = {
      success: true,
      data: newTodos,
    };
  },
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>Let's talk about our controller for <code>PUT todos/:id</code>. This will update a todo by ID.</p>
<p>Let's break this down into smaller bits:</p>
<pre><code><span class="hljs-keyword">const</span> todo: Todo | <span class="hljs-literal">undefined</span> = todos.find(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> t.id === params.id);
<span class="hljs-keyword">if</span> (!todo) {
  response.status = <span class="hljs-number">404</span>;
  response.body = {
    <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">message</span>: <span class="hljs-string">"No todo found"</span>,
  };
  <span class="hljs-keyword">return</span>;
}
</code></pre><p>This is something we did exactly the same with the previous controller as well, so I won't go into much detail here.</p>
<p>Pro tip here: You can if you want make this piece of code a generic code block and then use it in both controllers.</p>
<p>Next we do this:</p>
<pre><code><span class="hljs-comment">// if todo found then update todo</span>
<span class="hljs-keyword">const</span> body = <span class="hljs-keyword">await</span> request.body();
<span class="hljs-keyword">const</span> updatedData: { todo?: string; isCompleted?: boolean } = body.value;
<span class="hljs-keyword">let</span> newTodos = todos.map(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> t.id === params.id ? { ...t, ...updatedData } : t;
});
response.status = <span class="hljs-number">200</span>;
response.body = {
  <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">data</span>: newTodos,
};
</code></pre><p>The piece of code I want to talk about here is the following:</p>
<pre><code><span class="hljs-keyword">const</span> updatedData: { todo?: string; isCompleted?: boolean } = body.value;
<span class="hljs-keyword">let</span> newTodos = todos.map(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> t.id === params.id ? { ...t, ...updatedData } : t;
});
</code></pre><p>First we do <code>const updatedData = body.value</code> and then add type checking to <code>updatedData</code> like the following:</p>
<pre><code>updatedData: { todo?: string; isCompleted?: boolean }
</code></pre><p>This piece of code is telling TS that <code>updatedData</code> is an object which can <code>have/not have</code> <em>todo: string and</em> also can <code>have/not have</code> <em>isCompleted: boolean.</em></p>
<p>Then we simply map over all todos like this:</p>
<pre><code><span class="hljs-keyword">let</span> newTodos = todos.map(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> t.id === params.id ? { ...t, ...updatedData } : t;
});
</code></pre><p>And where <code>params.id</code> match with <code>t.id</code> we simply append everything to that object we get from the user.</p>
<p>We are done with this API as well. </p>
<p>Let's restart our server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>Open up a new tab in Postman. Set the request to <code>PUT</code> and in the <code>URL</code> bar type in <code>http://localhost:8080/todos/:id</code>, then hit <code>Send</code>:</p>
<p>Since we are generating ID's randomly,  first get all todos by hitting get all todos API. Then from any todo get one of its ID to test this newly created API.<br>Every time you restart this Deno application, new ID's will be generated.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-02.59.39.png" alt="Image" width="600" height="400" loading="lazy">
<em>404 status returned and no todo found error message given</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-03.00.21.png" alt="Image" width="600" height="400" loading="lazy">
<em>Provided a known ID, updated todo content in body. It returned the updated todo along with all the other todos</em></p>
<p>This is amazing – four APIs done and just one more to go.</p>
<pre><code class="lang-controllers/todos.ts">import { v4 } from "https://deno.land/std/uuid/mod.ts";
// interfaces
import Todo from "../interfaces/Todo.ts";
// stubs
import todos from "../stubs/todos.ts";

export default {
  getAllTodos: () =&gt; {},
  createTodo: async () =&gt; {},
  getTodoById: () =&gt; {},
  updateTodoById: async () =&gt; {},
  /**
   * @description Delete todo by id
   * @route DELETE todos/:id
   */
  deleteTodoById: (
    { params, response }: { params: { id: string }; response: any },
  ) =&gt; {
    const allTodos = todos.filter((t) =&gt; t.id !== params.id);

    // remove the todo w.r.t id and return
    // remaining todos
    response.status = 200;
    response.body = {
      success: true,
      data: allTodos,
    };
  },
};
</code></pre>
<p>Let's talk about our controller for <code>Delete todos/:id</code> this will delete a todo by ID.</p>
<p>We simply run a filter on all todos:</p>
<pre><code><span class="hljs-keyword">const</span> allTodos = todos.filter(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> t.id !== params.id);
</code></pre><p>Remove the <code>todo.id</code> that matches with <code>params.id</code> and return the rest.</p>
<p>Then we do this:</p>
<pre><code><span class="hljs-comment">// remove the todo w.r.t id and return</span>
<span class="hljs-comment">// remaining todos</span>
response.status = <span class="hljs-number">200</span>;
response.body = {
  <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">data</span>: allTodos,
};
</code></pre><p>Simply return all the todos left which do not have the same todo.id.</p>
<p>Let's restart our server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>Open up a new tab in Postman. This time set the request to <code>DELETE</code> and in the <code>URL</code> bar type <code>http://localhost:8080/todos/:id</code> and hit <code>Send</code>.</p>
<p>Since we are generating ID's randomly,  first get all todos by hitting get all todos API. Then from any todo get one of its ID to test this newly created API.<br>Every time you restart this Deno application, new ID's will be generated.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-03.07.54.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>With this we are all done with all five APIs.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/75bdf06df3fd6ddd9d3311d8cb2be029.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<hr>
<p>Now we only have two things remaining:</p>
<ul>
<li>Add a not found route middleware so that when the user tries to access an unknown route it gives an error.</li>
<li>Add a logger API that consoles the response time it took to return data from one API endpoint.</li>
</ul>
<h2 id="heading-creating-a-route-middleware-for-routes-that-arent-found">Creating a route middleware for routes that aren't found</h2>
<p>In your root folder create a new folder called <code>middlewares</code>. Inside that folder create a file called <code>notFound.ts</code> and inside this file add this code:</p>
<pre><code class="lang-middlwares/notfound.ts">export default ({ response }: { response: any }) =&gt; {
  response.status = 404;
  response.body = {
    success: false,
    message: "404 - Not found.",
  };
};
</code></pre>
<p>Here we aren't doing anything new – it is very similar to our controllers structure. Just returning a status <code>404</code> (which means not found) along with a JSON object for <code>{ success, message }</code>.</p>
<p>Next go in your <code>server.ts</code> file and add the following content:</p>
<ul>
<li>Add this import somewhere at the top:</li>
</ul>
<pre><code class="lang-server.ts">// not found
import notFound from './middlewares/notFound.ts';
</code></pre>
<ul>
<li>And then just below your <code>app.use(todoRouter.allowedMethods())</code> add this line like this:</li>
</ul>
<pre><code class="lang-server.ts">app.use(todoRouter.routes());
app.use(todoRouter.allowedMethods());

// 404 page
app.use(notFound);
</code></pre>
<p>The order of execution is important here: every time we try to access an API end point it will first match/check routes from our <code>todoRouter</code>. If none are found, it will then execute <code>app_.use_(notFound);</code>. </p>
<p>Let's see if this works.</p>
<p>Restart the server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>Open up a new tab in Postman. Set the request to <code>GET</code> and in the <code>URL</code> bar type <code>http://localhost:8080/something-unknown</code>, then hit <code>Send</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-12.28.10.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>So we now have a route middleware that we put at the end of our routes in <code>server.ts</code> as <code>app_.use_(notFound);</code>. If no route matches this middleware it will execute and return a <code>404</code> status code (which means not found). Then we simply send a response message like always which is <code>{success, message}</code>.</p>
<p><strong>Pro tip:</strong> We have decided that <code>{success, message}</code> is what we return in failed scenarios and <code>{success, data}</code> is what we return to user in success scenarios. So we can even make these to object/shapes as interfaces and add them to our project to ensure consistency and safe type checking.</p>
<p>Cool, now we are done with one of our middlewares – let's add the other middleware for logging our APIs in the console.</p>
<p><strong>Reminder:</strong> If you get stuck anywhere you can use the <a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak">source code here</a>.</p>
<h2 id="heading-logging-apis-in-console">Logging APIs in console</h2>
<p>In your <code>middlewares</code> folder create a new file called <code>logger.ts</code> and enter the following code:</p>
<pre><code class="lang-middlewares/logger.ts">import {
  green,
  cyan,
  white,
  bgRed,
} from "https://deno.land/std@0.53.0/fmt/colors.ts";

const X_RESPONSE_TIME: string = "X-Response-Time";

export default {
  logger: async (
    { response, request }: { response: any, request: any },
    next: Function,
  ) =&gt; {
    await next();
    const responseTime = response.headers.get(X_RESPONSE_TIME);
    console.log(`${green(request.method)} ${cyan(request.url.pathname)}`);
    console.log(`${bgRed(white(String(responseTime)))}`);
  },
  responseTime: async (
    { response }: { response: any },
    next: Function,
  ) =&gt; {
    const start = Date.now();
    await next();
    const ms: number = Date.now() - start;
    response.headers.set(X_RESPONSE_TIME, `${ms}ms`)
  },
};
</code></pre>
<p>In your <code>server.ts</code> file add this code:</p>
<ul>
<li>Import this somewhere at the top:</li>
</ul>
<pre><code class="lang-server.ts">// logger
import logger from './middlewares/logger.ts';
</code></pre>
<ul>
<li>Just above your <code>todoRouter</code> code add these middlewares like this:</li>
</ul>
<pre><code><span class="hljs-comment">// order of execution is important;</span>
app.use(logger.logger);
app.use(logger.responseTime);

app.use(todoRouter.routes());
app.use(todoRouter.allowedMethods());
</code></pre><p>Now let's discuss what we just did.</p>
<p>Let's talk about the <code>logger.ts</code> file and break it down into bits:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> {
  green,
  cyan,
  white,
  bgRed,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"https://deno.land/std@0.53.0/fmt/colors.ts"</span>;
</code></pre>
<p>I am importing some console colors and console background colors that I want to use in API logging.</p>
<p>This is similar to what we did in our <code>eventListener</code> in our <code>server.ts</code> file. We will use colors in our console to log API requests.</p>
<p>Next I set <code>const X_RESPONSE_TIME: string = "X-Response-Time";</code>. This is the header we will inject in our API requests as they come into our server. I am calling this <code>X_RESPONSE_TIME</code> and its value is <code>X-Response-Time</code>. I will demonstrate its usage in a bit.</p>
<p>Next we simply export an object like this:</p>
<pre><code class="lang-middlewares/logger.ts">export default {
    logger: async ({ response, request }, next) {}
    responseTime: async ({ response }, next) {}
};
</code></pre>
<p>And then we simply use it inside our <code>server.ts</code> file like this:</p>
<pre><code class="lang-server.ts">// order of execution is important;
app.use(logger.logger);
app.use(logger.responseTime);
</code></pre>
<p>Let's now discuss what is happening in our logger middleware code and discuss it execution style using <code>next()</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-12.51.36.png" alt="Image" width="600" height="400" loading="lazy">
<em>Execution of order of logging middleware when GET /todos API is called.</em></p>
<p>The only difference here and in the controllers we had before is the use of the <code>next()</code> function. This functions helps us jump from one controller to the other as shown in the image below.</p>
<p>So in:</p>
<pre><code class="lang-middlewares/logger.ts">export default {
  logger: async (
    { response, request }: { response: any, request: any },
    next: Function,
  ) =&gt; {
    await next();
    const responseTime = response.headers.get(X_RESPONSE_TIME);
    console.log(`${green(request.method)} ${cyan(request.url.pathname)}`);
    console.log(`${bgRed(white(String(responseTime)))}`);
  },
  responseTime: async (
    { response }: { response: any },
    next: Function,
  ) =&gt; {
    const start = Date.now();
    await next();
    const ms: number = Date.now() - start;
    response.headers.set(X_RESPONSE_TIME, `${ms}ms`)
  },
};
</code></pre>
<p>Keep in mind that this is what we have in our <code>server.ts</code> file:</p>
<pre><code class="lang-server.ts">// order of execution is important;
app.use(logger.logger);
app.use(logger.responseTime);

app.use(todoRouter.routes());
app.use(todoRouter.allowedMethods());
</code></pre>
<p>The order of execution is as follows:</p>
<ul>
<li>logger.logger middleware</li>
<li>logger.responseTime middleware</li>
<li>todoRouter controller (whatever path is called by the user, for the purpose of explanation I am assuming that the user called <code>GET /todos</code> API to get all todos.)</li>
</ul>
<p>So it will first execute logger.logger middleware which is this:</p>
<pre><code class="lang-middlewares/logger.ts">logger: async (
    { response, request }: { response: any, request: any },
    next: Function,
  ) =&gt; {
    await next();
    const responseTime = response.headers.get(X_RESPONSE_TIME);
    console.log(`${green(request.method)} ${cyan(request.url.pathname)}`);
    console.log(`${bgRed(white(String(responseTime)))}`);
  },
</code></pre>
<p>It will come inside this function and immediately as it reads <code>await next()</code> it quickly jumps to the next middleware which is <code>responseTime</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-12.51.36-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Sharing the image above again for revision.</em></p>
<p>Inside <code>responseTime</code>, it only executes two lines which are (look at execution order 2 in image above):</p>
<pre><code class="lang-middlewares/logger.ts">const start = Date.now();
await next();
</code></pre>
<p>before jumping to the <code>getAllTodos</code> controller. Once it goes inside <code>getAllTodos</code> it will run the entire code inside that controller. </p>
<p>Since in that controller we are not using <code>next()</code> it will simply return the flow of logic back to <code>responseTime</code> controller. There it will run the following:</p>
<pre><code class="lang-middlewares/logger.ts">const ms: number = Date.now() - start;
response.headers.set(X_RESPONSE_TIME, `${ms}ms`)
</code></pre>
<p>Now keeping in perspective of the order of execution which is <code>2, 3, 4</code> (look at the image above).</p>
<p>This is what happens:</p>
<ul>
<li>We capture the data in <code>ms</code> by doing <code>const</code> <em><code>start</code></em> <code>=</code> <em><code>Date.now</code></em><code>();</code>. Then we immediately call <code>next()</code> which goes to <code>getAllTodos</code> controller and runs the entire code. Then it comes back in the <code>responseTime</code> controller.</li>
<li>We then subtract that <code>start</code> date with whatever the date is at that moment by doing <code>const _ms_: _number_ = _Date.now_()</code> - <em>start</em>; <code>ms</code>. Here it will return a number which is basically the difference in milliseconds that will tell us all the time it took Deno to execute our <code>getAllTodos</code> controller.</li>
</ul>
<p>Sharing the image once again for review:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-12.51.36-2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<ul>
<li>Next we simply set headers in our <code>response</code> like this:</li>
</ul>
<pre><code>response.headers.set(X_RESPONSE_TIME, <span class="hljs-string">`<span class="hljs-subst">${ms}</span>ms`</span>)
</code></pre><p>Which just sets the header value <code>X-Response-Time</code> to the milliseconds it took Deno to execute our API.</p>
<ul>
<li>Then from execution order <code>4</code> we move back to execution order <code>5</code> (have a look at the image above for reference).</li>
</ul>
<p>Here we simply do:</p>
<pre><code class="lang-middlwares/logger.ts">const responseTime = response.headers.get(X_RESPONSE_TIME);
console.log(`${green(request.method)} ${cyan(request.url.pathname)}`);
console.log(`${bgRed(white(String(responseTime)))}`);
</code></pre>
<ul>
<li>We get the time we passed in the <code>X-Response-Time</code></li>
<li>Then we take that time and simply console it colourfully in the console.</li>
</ul>
<p><code>request.method</code> tells us the method used to call our API, that is  <code>GET, PUT etc</code> while <code>request.url.pathname</code> will tell the API which path the user used i.e, <code>/todos</code></p>
<p>Let's see if this works.</p>
<p>Restart the server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>Open up a new tab in Postman. Set the request to <code>GET</code>, type in <code>http://localhost:8080/todos</code>, and hit <code>Send</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-13.17.13.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Hit the API a couple of times in Postman. Then when you go back to the console, you should see something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-13.21.03.png" alt="Image" width="600" height="400" loading="lazy">
<em>API being logged in our console</em></p>
<p>This is it – we are done.</p>
<p>If you still feel stuck, take a look at the entire source code for this tutorial here: <a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak">github.com/adeelibr/deno-playground/tree/master/chapter_1:oak</a></p>
<p>I hope that you found this article useful and that it was able to help you learn something today.</p>
<p>If you liked it, please do share it on social media. If you want to have a discussion about it, reach out to me on <a target="_blank" href="https://twitter.com/adeelibr">Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Overcome Your Fear of Writing and Find Motivation to Start ]]>
                </title>
                <description>
                    <![CDATA[ Writing about our work is one of those things that most of us have on our to-do list. But whether it's due to procrastination or fear, we never actually get to it. Here's some more motivation and reasons why you should give it a shot! Why should we w... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/overcoming-your-fear-of-writing-and-how-you-can-find-motivation/</link>
                <guid isPermaLink="false">66bee941dceb56d88f491c64</guid>
                
                    <category>
                        <![CDATA[ Blogging ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ education ]]>
                    </category>
                
                    <category>
                        <![CDATA[ goal-setting ]]>
                    </category>
                
                    <category>
                        <![CDATA[ goals ]]>
                    </category>
                
                    <category>
                        <![CDATA[ learn to code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ learning to code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ motivation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ self-improvement  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ teaching ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technical writing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ writing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ writing tips ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Thu, 30 Apr 2020 14:45:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/04/writing-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Writing about our work is one of those things that most of us have on our to-do list. But whether it's due to procrastination or fear, we never actually get to it. Here's some more motivation and reasons why you should give it a shot!</p>
<h2 id="heading-why-should-we-write-in-the-first-place">Why should we write in the first place?</h2>
<p>Maybe you've never thought about writing before or maybe you're looking for a little more motivation. Whatever the case, there are a lot of good reasons why writing can help us grow.</p>
<h3 id="heading-helping-others-to-learn">Helping others to learn</h3>
<p>Coding can be tough. And we all started somewhere at the beginning.</p>
<p>It's a long journey that each of us go through and it's even harder to go at it alone. Luckily, we've had websites like <a target="_blank" href="https://www.freecodecamp.org/">freecodecamp.org</a> and <a target="_blank" href="https://css-tricks.com/">css-tricks.com</a> along the way that have made that journey more manageable, but there's always going to be a challenge that just doesn't make sense.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/css-tricks-around-2011.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>CSS-Tricks around 2011 when I got my first official coding job via <a target="_blank" href="https://web.archive.org/web/20110701022701/http://css-tricks.com/">Way Back Machine</a></em></p>
<p>This is where we have an opportunity to share our experiences to help others grow. While our favorite coding sites have tons of amazing tutorials, maybe they're missing a key point someone needed to fully grasp the solution. </p>
<p>Whether you're at the beginning or middle of your journey, every experience, big or small, can help another developer on their own journey.</p>
<p>And this is where it can be rewarding. One of my favorite parts of writing has been getting a <a target="_blank" href="https://twitter.com/colbyfayock">Twitter</a> DM from someone about how <a target="_blank" href="https://www.freecodecamp.org/news/author/colbyfayock/">one of my tutorials</a> helped them learn. It's a great feeling knowing you helped someone else on their journey.</p>
<p>Take this as a way for you to give back to the community that helped you learn and grow.</p>
<h3 id="heading-reinforcing-your-learning">Reinforcing your learning</h3>
<p>Thinking back to your grade school Spanish class, one of the tricks to helping the students learn was to reinforce learning. Teachers use different methods like reading, writing, speaking, flashcards, or even that Cinco de Mayo fiesta where you learned about and celebrated Mexico's heritage to help make the language stick.</p>
<p>This applies to development concepts as well. While your solution is still fresh in your head, write it down! Being able to teach what you've learned by writing about it will help those concepts stick in your head.</p>
<p>And just because you write it, it doesn't mean you have to share it. If you're not comfortable sharing it with the world, just keep a copy in a private notebook. You'll always be able to reference it yourself and still reinforce what you know by writing it down.</p>
<h3 id="heading-documenting-our-experiences">Documenting our experiences</h3>
<p>Doubling up on reinforcing your learning, by writing about your experiences, you're kind of creating your own personal <a target="_blank" href="https://stackoverflow.com/">StackOverflow</a> with a list of problems you've already solved.</p>
<p>As much as we had hoped we would remember how to speak Spanish from the classes we took, 10 years goes by pretty quickly and you suddenly realize you can only correctly say "hola" in Spanish.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/hola-sign.jpg" alt="Image" width="600" height="400" loading="lazy">
_Hola sign from Jon Tyson on <a target="_blank" href="https://unsplash.com/photos/8MMtYM_3xMY">Unsplash</a>_</p>
<p>If you were the ambitious type, maybe you saved all of your notes. If not, maybe you remember a good website that has flashcards.</p>
<p>Either way, having resources to go back to, whether it's your own notes or that website you still have bookmarked, helps us to quickly reference challenges we've already come across. By writing down your experiences, you're adding to that digital notebook that you know you can always use to remember that quirk you fixed.</p>
<h3 id="heading-growing-your-personal-network">Growing your personal network</h3>
<p>Everyone has their own reasons for wanting to write and share content – and that's okay! While some of us might be doing this to help others learn, others might be simply trying to get a job or grow their Twitter following.</p>
<p>One of the benefits of sharing your experiences is that you're immediately growing the network of developers that have a little more insight into who you are and the work you've done.</p>
<p>This doesn't guarantee a job, but it certainly can help. All teams are a little different in how they recruit. Smaller teams tend to include other developers more in the beginning of the process who are probably more likely to open your blog and not only read a little bit, but actually understand it.</p>
<p>But even if you don't immediately get hired, you're playing the long game. Opportunities will start to come in small ways that lead to bigger opportunities down the road.</p>
<h2 id="heading-why-you-might-be-hesitating-and-how-we-can-look-at-it-another-way">Why you might be hesitating and how we can look at it another way</h2>
<p>Sometimes motivation isn't enough. We all have our personal challenges that might prevent us from doing something we want to do. But sometimes it's a matter of finding a different perspective to give you that bit of inspiration to finally dive in.</p>
<h3 id="heading-imposter-syndrome-who-am-i-to-write-about-this">Imposter syndrome – who am I to write about this?</h3>
<p>This is something I've personally struggled with for the majority of my career. Whether I was confident in my ability to do my job or not, I never felt like it was enough to be one of the people writing guides for others.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/colby-fayock-personal-website.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://www.colbyfayock.com/">My website and blog</a></em></p>
<p>It wasn't until another team member brought another perspective to this argument (thanks Marquet) – everyone learns differently and maybe my way of telling a story can help someone learn. </p>
<p>If someone doesn't read my work, what are the consequences beyond a little bit of wasted time? On the other hand, maybe my blog post resonated with someone in a way that other blog posts didn't and they were finally able to solve their problem.</p>
<p>And this goes for any level of experience. As <a target="_blank" href="https://twitter.com/swyx">Swyx</a> says, <a target="_blank" href="https://www.swyx.io/writing/learn-in-public/">the fastest way to learn is in public</a>. If you're not helping someone else, you're at least helping yourself grow.</p>
<h3 id="heading-finding-time-it-takes-a-while-to-write-a-post">Finding time – it takes a while to write a post</h3>
<p>Time is a funny thing – it becomes an excuse that we use when we don't want to admit the real reason we're holding back.</p>
<p>Of course that's not always the case. Realistically a lot of us have a ton on our plates already whether we work, take care of a family, or are volunteering to help others. It can be a struggle to not want to just sit on the couch after a hard day's work.</p>
<p>But consider the free time you do have. Can you spare 10 minutes jotting down a few notes or even starting an outline of some things you want to say?</p>
<p>While 10 minutes won't write a whole post, if you start the habit and write another paragraph or two every day, you'll slowly end up with a blog post that you can feel good about sharing.</p>
<p>Just don't set the bar too high. If you start off with an unrealistic goal, you're likely to burn out fast and end up back in the same position you're at now.</p>
<h3 id="heading-no-topic-not-knowing-what-to-write-about">No topic – not knowing what to write about</h3>
<p>From speaking with other developers, I've noticed this seems to be tied a little bit to imposter syndrome. Maybe you're getting confident enough that you're more willing to write, but you're struggling to find what to write about. Is it because you can't think of a topic or is it because every topic you think about, you don't think you're enough of an expert to write about it?</p>
<p>Not having a topic can be a legitimate problem, but there's inspiration all around us. If you're working every day as a developer, you're working on problems that you ultimately need to solve. Why not write about those problems? And if you can't write about the problems due to contract concerns, what about writing about them in an abstract way without any sensitive information?</p>
<p>Inspiration for me comes from my experience talking with others. I'm lucky to be on a team that encourages growth of junior developers and during my time helping them out, their questions lead me to think about topics that I took for granted.</p>
<p>Whenever a topic like that comes up, I immediately note it down for later. This topic was on that list! Over time, my list of topics has grown to a point where I don't think I'll even finish it by the end of the year.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/list-of-topic-ideas.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>My personal list of topic ideas</em></p>
<p>While that could feel overwhelming, it's also motivates me to have a bigger selection of what I'm in the mood to write about rather than forcing myself to both think of a new topic and write about something I don't want to write about each week.</p>
<p>Whatever the case, find your source of inspiration. You don't need to be an expert on it. It doesn't matter if someone more experienced already wrote about it. Write what you know. Share your experiences. Maybe you'll help someone see the problem from a different perspective.</p>
<h2 id="heading-finding-what-motivates-you">Finding what motivates you</h2>
<p>At the end of the day, writing is something that each of us will need to find our own motivation to do.</p>
<p>Try to evaluate your goals. What are you looking to achieve? If writing is something you truly want to do, you'll need to find your own source of inspiration.</p>
<p>While some reasons might be more valid than others, it's easier to find reasons not to do something than it is to do it.</p>
<p>You got this! ?</p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">?️ Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Set Your Future Self Up for Success with Good Coding Habits ]]>
                </title>
                <description>
                    <![CDATA[ Think before you code. You have the power to make your future self's life Heaven on Earth or a living hell. In this article we'll explore what kinds of things you can do to make it a little easier on your future self. Revisiting "prior art" We've all... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/set-future-you-up-for-success-with-good-coding-habits/</link>
                <guid isPermaLink="false">66bee9536769d2581da6f951</guid>
                
                    <category>
                        <![CDATA[ Self-awareness ]]>
                    </category>
                
                    <category>
                        <![CDATA[ 100Days100Projects ]]>
                    </category>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Code Quality ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code review ]]>
                    </category>
                
                    <category>
                        <![CDATA[ fundamentals ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ learn to code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Self Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ self-improvement  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Thu, 16 Apr 2020 14:45:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/04/set-up-for-success.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Think before you code. You have the power to make your future self's life Heaven on Earth or a living hell.</p>
<p>In this article we'll explore what kinds of things you can do to make it a little easier on your future self.</p>
<h2 id="heading-revisiting-prior-art">Revisiting "prior art"</h2>
<p>We've all been there. Six months into a project, you're trying to squash a bug, and what you find is shocking. You might be asking yourself, "who would write this kind of code?"</p>
<p>So you dig through your <a target="_blank" href="https://git-scm.com/">git</a> commit history using <code>git log -p filename.js</code> showing changes for a specific file, trying to see who would come up with something like that. And then your heart drops – you're the one who wrote it!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/tituss-burgess-shocked.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Tituss Burgess shocked</em></p>
<p>This is a common scenario for any developer, experienced or new. If you haven't hit that scenario, I promise if you stick with coding long enough, you will.</p>
<h2 id="heading-becoming-more-conscious-about-our-coding-habits">Becoming more conscious about our coding habits</h2>
<p>That six month reflection point is inevitable. That's a lot of time which you've most likely been using to work on other parts of the project or another project completely. Chances are, you've leveled up which has changed the way you write code.</p>
<p>On the other hand, sometimes it takes stepping outside of the code to see the bigger picture and get a better look at how all the pieces fit together. We can naturally dig ourselves too deep into a solution and can become a little narrowly focused as we work to solve those challenges.</p>
<p>But either way, while part of the code journey will simply be gaining more experience and learning more about your craft, there are other small habits you can get used to early on that will help you down the road.</p>
<p>So let's jump in.</p>
<h2 id="heading-improving-the-readability-of-your-code">Improving the readability of your code</h2>
<h3 id="heading-what-is-the-challenge">What is the challenge?</h3>
<p>Part of the fun about our craft is there are a ton of ways you can do the same thing. Think an <code>if</code> statement is too many lines? Well we can write it <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator">ternary</a> style!</p>
<pre><code class="lang-js"><span class="hljs-comment">// Example ternary statement</span>
<span class="hljs-keyword">const</span> isFreezing = temperature &lt;= <span class="hljs-number">32</span> ? <span class="hljs-literal">true</span> : <span class="hljs-literal">false</span>;
</code></pre>
<p>But sometimes this takes a toll on the readability of your code. While it might seem like it looks nice and super clean on one line, imagine that as that ternary gets more complex, someone will have to spend more time understanding what it means.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> minutes = <span class="hljs-number">30</span>;
<span class="hljs-keyword">const</span> cookie = {
  <span class="hljs-attr">color</span>: <span class="hljs-string">'black'</span>
};

<span class="hljs-keyword">const</span> cookieStatus = minutes &gt; <span class="hljs-number">20</span> ? cookie.color === <span class="hljs-string">'black'</span> ? <span class="hljs-string">'burned'</span> : <span class="hljs-string">'done'</span> : <span class="hljs-string">'not done'</span>;
</code></pre>
<h3 id="heading-what-can-we-do-better">What can we do better?</h3>
<p>Now I would imagine most of us can figure out what <code>cookieStatus</code> is in this example (spoilers: <code>burned</code>). But think about the time you spent figuring it out. Whether an extra 1s or 2s, it forces you to spend additional cognitive energy to read through the code.</p>
<p>On the other hand:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> minutes = <span class="hljs-number">30</span>;
<span class="hljs-keyword">const</span> cookie = {
  <span class="hljs-attr">color</span>: <span class="hljs-string">'black'</span>
};
<span class="hljs-keyword">let</span> cookieStatus;

<span class="hljs-keyword">if</span> ( minutes &lt;= <span class="hljs-number">20</span> ) {
  cookieStatus = <span class="hljs-string">'not done'</span>;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( cookie.color === <span class="hljs-string">'black'</span> ) {
  cookieStatus = <span class="hljs-string">'burned'</span>;
} <span class="hljs-keyword">else</span> {
  cookieStatus = <span class="hljs-string">'done'</span>;
}
</code></pre>
<p>No, it may not be as clean or clever as the 1-line ternary statement, but the next time you visit it, the less you'll have to think about what the answer is. </p>
<p>It's also going to make it that much easier for bugs to creep up and get past your code reviewers when all of your code changes are in a 1-line git diff.</p>
<p>And yes, this is a simple example. But imagine this in a real world scenario with important business logic where you could run into these situations frequently.  </p>
<p>Say you need to add another condition – that ternary is just going to keep getting more complex! You're just making it more difficult to debug or extend, where the <code>if</code> statements can continue on in an easily readable way.</p>
<p>For what it's worth, ternaries and other shortcuts can be simple and effective in code, but don't abuse that effectiveness and end up making things more difficult.</p>
<h2 id="heading-keeping-things-consistent">Keeping things consistent</h2>
<h3 id="heading-what-is-the-challenge-1">What is the challenge?</h3>
<p>We all have our favorite way to code. Though I'd argue not including a semicolon at the end of your JavaScript is just completely wrong, you might prefer to write your code the wrong way without them.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// Jim's code style</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyComponent</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleOnClick</span>(<span class="hljs-params"></span>) </span>{
    alert(<span class="hljs-string">'Click!'</span>)
  }
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleOnClick}</span>&gt;</span>My Button<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
  )
}

<span class="hljs-comment">// Creed's code style</span>

<span class="hljs-keyword">const</span> MyComponent = <span class="hljs-function">() =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> alert('Click!')}&gt;My Button<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>;
</code></pre>
<p>But it's not always about what <em>you</em> prefer. When working with a team, chances are, everyone's opinion on how code should look is slightly different. You might agree about the semi-colon, but disagree about whitespace.</p>
<p>And no one is wrong (except for the non-semi-coloners)! There are valid arguments to most code styles, whether for or against, but the solution isn't for everyone to write their code their own way.</p>
<h3 id="heading-what-can-we-do-better-1">What can we do better?</h3>
<p>Keeping code consistent is important to maintain code health. A typical goal is to "make the codebase look like one person wrote it."</p>
<p>The point isn't that one person gets their way, it's that the team came to a conclusion about a set of rules they would use that everyone would follow. Having this consistency provides less cognitive overhead as people work through the code. It gives everyone the ability to know what to expect when reading the code.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/linting-code.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Errors from linting code</em></p>
<p>And achieving this doesn't need to be hard. There are tools that can simply <a target="_blank" href="https://www.colbyfayock.com/2019/10/what-is-linting-and-how-can-it-save-you-time">check for these inconsistencies</a> like <a target="_blank" href="https://eslint.org/">Eslint</a> for Javascript. And even better, there is another level of tools like <a target="_blank" href="https://prettier.io/">Prettier</a> that <a target="_blank" href="https://www.colbyfayock.com/2019/11/dont-just-lint-your-code-fix-it-with-prettier">will fix it for you</a>!</p>
<h2 id="heading-commenting-your-code">Commenting your code</h2>
<h3 id="heading-what-is-the-challenge-2">What is the challenge?</h3>
<p>Keeping up with commenting your code is an important way to put context to complex logic. As much as we all want our code to be self-documenting, that's rarely the case.</p>
<p>Too often we find ourselves dealing with a block of code that just doesn't make sense. And even if it makes sense on its own, we might not be able to figure out how it fits in to the rest of the application.</p>
<h3 id="heading-what-can-we-do-better-2">What can we do better?</h3>
<p>By providing a good set of comments, you're setting up the next person who touches that code to have a better understanding of what the code is doing before they make a change.</p>
<pre><code class="lang-js"><span class="hljs-comment">// DONT CHANGE - WILL STOP MAKING MONEY</span>

<span class="hljs-keyword">const</span> shouldMakeMoney = <span class="hljs-literal">true</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">makeMoney</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span> ( shouldMakeMoney ) {
    <span class="hljs-keyword">return</span> noMoney;
  }
  <span class="hljs-keyword">return</span> moreMoney;
}
</code></pre>
<p>While this is a silly example, it brings up a real world case. Businesses are increasingly dependent on being able to maintain a reliable website to make money. Whether this is as an ecommerce business or an ad giant, these websites rely on business logic that determine things like cost, taxes, discounts, and other math related things we tend to not want to think about, but could make or break a business on the internet.</p>
<p>But it's not all about the company you work for. Touching old code can be scary. It's even scarier when no one on your team was around when it was written, so no one knows what it does!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/patton-oswalt-hands-over-mouth.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Patton Oswalt hands over mouth</em></p>
<p>While you might not be the next person who touches that code, try to help out your future friend who's tackling the next ticket involving that code. Because there's also a good chance you will be that person and you'll wish you remembered how it worked.</p>
<h2 id="heading-documenting-your-solutions">Documenting your solutions</h2>
<h3 id="heading-what-is-the-challenge-3">What is the challenge?</h3>
<p>Documentation is similar to commenting your code, but from a different perspective. Documentation and commenting are both about finding ways to describe a solution in a human-readable way that will ultimately give more context. But documentation is more about the overall solution rather than the implementation details.</p>
<p>Having a high performing application is everyone's goal. But how did we get there? There's a realistic chance that someone will have to be working on the same project you are like onboarding a new team member. How will they be able to maintain that high performance if they don't know how it works?</p>
<h3 id="heading-what-can-we-do-better-3">What can we do better?</h3>
<p>Whether it's introducing that new team member to the project or trying to share knowledge with another project team, documentation is an important part of maintaining a project. It helps keep everyone on the same page so we all confidently know what we're working towards.</p>
<p>For example, if we're still working with our ecommerce project with our business logic, there will be rules that the code needs to implement. While commenting might give details inline about how the rules were implemented, the documentation would define those rules.</p>
<pre><code class="lang-js"><span class="hljs-comment">/**
 * DOCUMENTATION
 * Order Total &gt;= 25: Discount %10
 * Order Total &gt;= 50: Discount %15
 * Order Total &gt;= 100: Discount %20
 * Order Total &gt;= 75: Free Shipping
 */</span>

<span class="hljs-keyword">const</span> orderSubTotal = <span class="hljs-number">84.00</span>;
<span class="hljs-keyword">let</span> orderTotal = orderSubTotal;

<span class="hljs-comment">// If the order total is under 75, apply shipping discount</span>

<span class="hljs-keyword">if</span> ( orderTotal &lt; <span class="hljs-number">75</span> ) {
  orderTotal = addShipping(orderTotal);
}

<span class="hljs-comment">// If the order total reaches a threshold, apply given discount</span>

<span class="hljs-keyword">if</span> ( orderTotal &gt;= <span class="hljs-number">100</span>) {
  orderTotal = applyDiscount(orderTotal, <span class="hljs-number">.2</span>);
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( orderTotal &gt;= <span class="hljs-number">50</span> ) {
  orderTotal = applyDiscount(orderTotal, <span class="hljs-number">.15</span>);
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( orderTotal &gt;= <span class="hljs-number">25</span> ) {
  orderTotal = applyDiscount(orderTotal, <span class="hljs-number">.1</span>);
}
</code></pre>
<p>This is a minimal example, but we can see the difference between the rules at the top and how we apply them. The documentation should clearly explain what the rules are, but it shouldn't care about how those rules were implemented.</p>
<p>On the other hand, the comments might not care about what the rules are, but need to implement them in an efficient and logical way. We should be able to update the code with the business rules, such as changing the top level discount tier from $100 to $80, without having to rework the code.</p>
<p>But documentation is much more than business rules – it's providing a way for anyone to understand your work from a higher level. This could include anything from architectural diagrams to the theory behind your core algorithm.</p>
<p>While maybe code isn't the best place for details like this to live, it's really important information that can help instill confidence in your project and give others an opportunity to understand more about the work.</p>
<h2 id="heading-creating-effective-pull-requests">Creating effective Pull Requests</h2>
<h3 id="heading-what-is-the-challenge-4">What is the challenge?</h3>
<p>Pull requests (or merge requests) are a core part of any development team's project lifecycle. It provides a way to package and present your code in a consumable way for your peers to review and understand your work.</p>
<p>There's a lot that can go into a pull request from a single commit to the entirety of the next version of your website. That's a lot of context to expect someone to understand by reading through the commits alone.</p>
<h3 id="heading-what-can-we-do-better-4">What can we do better?</h3>
<p>Pull requests don't need to be an art. There should be one primary goal of the preparation you put into it – providing context into your changes. At a minimum, it should answer the questions of "what" and "why".</p>
<p>We can even use tools like pull request templates to push us in the right direction. <a target="_blank" href="https://www.freecodecamp.org/news/why-you-should-write-merge-requests-like-youre-posting-to-instagram-765e32a3ec9c/">Define an outline</a> of what you want explained and chances are, people will follow that outline. This helps avoid the 1-line "closes [ticket]" description or even worse, an empty description.</p>
<p>With my projects, I hope to have a few questions answered before I dive into a code review:</p>
<ul>
<li>What is the change?</li>
<li>What does it impact?</li>
<li>How do I reproduce or test the change?</li>
</ul>
<p>Just a few details around the change set can provide much needed context for those reviewing your code. It's easy to look at code, but it's harder to understand it without knowing how it fits into the bigger picture.</p>
<h2 id="heading-hardening-your-code-with-tests">Hardening your code with tests</h2>
<h3 id="heading-what-is-the-challenge-5">What is the challenge?</h3>
<p>Tests are a way to ensure your code runs the same way each time. Being able to prove that the same input will always have the same output will help provide you and your team with a higher level of confidence that your application won't come crashing down with the next small change.</p>
<p>Without them, we're left with human error, where no matter how good your QA Engineer is (shoutout to my testers out there), something will always slip through. And that's not to say your tests will always catch every problem, but we can use the tools available to help prevent it.</p>
<h3 id="heading-what-can-we-do-better-5">What can we do better?</h3>
<p>Where comments are a way of providing the context of how something works, test are a way to ensure they work. Providing test cases that are repeatable helps enforce that.</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">applyDiscount</span>(<span class="hljs-params">value, discount</span>) </span>{
  <span class="hljs-keyword">const</span> discountAmount = value * discount;
  <span class="hljs-keyword">return</span> value - discountAmount;
}

expect(applyDiscount(<span class="hljs-number">10</span>, <span class="hljs-number">.1</span>)).toEqual(<span class="hljs-number">.9</span>);
expect(applyDiscount(<span class="hljs-number">532151235</span>, <span class="hljs-number">.1054</span>)).toEqual(<span class="hljs-number">476062494.831</span>);
</code></pre>
<p>If I fudge the math on our <code>applyDiscount</code> function above, there's a high probability that the test would fail (never say never).</p>
<p>But testing doesn't need to be hard. There are many tools out there that help from different perspectives. For example, you might use <a target="_blank" href="https://jestjs.io/">Jest</a> to run your unit tests or add <a target="_blank" href="https://enzymejs.github.io/enzyme/">Enzyme</a> on top to test your React components. But you can also bring in <a target="_blank" href="https://www.cypress.io/">Cypress</a> as an integration test solution that will work like a robot clicking through your application to make sure all the components actually work together.</p>
<p>There's also different methodologies of testing. While you probably see most teams write their tests after they have a working solution, some people swear by <a target="_blank" href="https://en.wikipedia.org/wiki/Test-driven_development">test-driven development</a>. They might write their tests first where the code has to pass the tests rather than the other way around. This is a great way to define the requirements of the code before diving right in.</p>
<p>Whatever the method, capture the points that are most likely to break or the functions that add the most business value. You'll be helping to prevent a potential business loss or even simpler, a headache.</p>
<h2 id="heading-what-can-we-learn-from-this">What can we learn from this?</h2>
<p>That might be a lot to digest, but they're important points to consider as you grow as a developer. Starting these habits early in your career will help you naturally build these skills and work that way by default.</p>
<p>And if you're late in your career, it's never too late to start. We should all want to strive to be the best developer we can be and do our best to help make our teammate's lives easier, as we're all in this together.</p>
<h2 id="heading-looking-for-more-to-learn">Looking for more to learn?</h2>
<ul>
<li><a target="_blank" href="https://www.colbyfayock.com/2019/08/put-down-the-javascript-learn-html-css">Put Down the Javascript - Learn HTML &amp; CSS</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/02/how-to-become-a-full-stack-web-developer-in-2020">How to Become a Full Stack Web Developer in 2020</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/02/what-is-the-jamstack-and-how-do-i-get-started">What is the JAMstack and how do I get started?</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2019/10/what-is-linting-and-how-can-it-save-you-time">What is linting and how can it save you time?</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/why-you-should-write-merge-requests-like-youre-posting-to-instagram-765e32a3ec9c/">Why you should write merge requests like you’re posting to Instagram</a></li>
</ul>
<h2 id="heading-whats-your-advice-for-growing-as-a-developer">What’s your advice for growing as a developer?</h2>
<p><a target="_blank" href="https://twitter.com/colbyfayock">Share with me on Twitter!</a></p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">?️ Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How I did NOT code a collaborative writing app ]]>
                </title>
                <description>
                    <![CDATA[ By Eric Burel Twaikura, haikus but funnier As easy as ABC: some stranger on the Internet starts a 120 characters story, some stranger on the Internet finishes it. And that makes a Twaiku (tweet + haiku). Twaikus can be funny, serious, artistic, it’s ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-i-did-not-code-a-collaborative-writing-app/</link>
                <guid isPermaLink="false">66d45e3f4a7504b7409c3382</guid>
                
                    <category>
                        <![CDATA[ bubble ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Entrepreneurship ]]>
                    </category>
                
                    <category>
                        <![CDATA[ lean startup ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 18 Feb 2020 17:19:33 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/02/code-free-1200-2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Eric Burel</p>
<h2 id="heading-twaikura-haikus-but-funnier">Twaikura, haikus but funnier</h2>
<p>As easy as ABC: some stranger on the Internet starts a 120 characters story, some stranger on the Internet finishes it. And that makes a Twaiku (tweet + haiku). Twaikus can be funny, serious, artistic, it’s up to you. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/logo_256.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/twaiku.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>So, as a developer, implementing something like that shouldn't be hard, right? Yes, but no. Here is the story of how it took me multiple years to create Twaikura and how you could do the same in a matter of hours.</p>
<h2 id="heading-back-to-twentyparts-and-why-it-never-came-to-existence">Back to TwentyParts and why it never came to existence</h2>
<p>TwentyParts was my first “entrepreneurial concept” back in 2015. As you may guess, the idea is to write a story in 20 parts, with each part written by a different author. </p>
<p>I was a CS student at the time and it took me 2 months to release a first draft. The result was disastrous. I didn’t even know about the concept of a “framework”, picture the code. The concept was too complex, the interface unusable.</p>
<p>I did not give up. A few months later, in 2016, I came up with a simplified version of TwentyParts, HiKoo.  I limited the length of a story to 3 tweets. And instead of rushing to development, I created mocks using a marvelous tool named MarvelApp.</p>
<p>Now I had a great UI and all, but no working code. One more app that never came to existence.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/hikoo.png" alt="Image" width="600" height="400" loading="lazy">
<em>Looks good, doesn't work</em></p>
<p>Fast forward to now. I’ve graduated. I’ve built my consulting company, LBKE. I’ve developed complex SaaS platforms for multiple clients. And I've kept this question running in my head:</p>
<blockquote>
<p>What prevents me from recreating TwentyParts, now I am fast and skilled and over-confident?</p>
</blockquote>
<p>After all, it would only take a full work week nowadays. Yet there’s a problem: I am not a student anymore. With one spare hour here and there, a “full work week“ can span over a few months. Too slow.</p>
<h2 id="heading-how-to-code-fast-dont">How to code fast: don’t.</h2>
<p>I’ve explored thoroughly the realms of fast web development. You may have read my previous articles on freeCodeCamp about <a target="_blank" href="https://www.freecodecamp.org/news/how-i-built-an-app-with-vulcan-js-in-four-days-6368814077b1/">Vulcan, a framework based on Meteor that makes me very productive.</a></p>
<p>Those researches all lead me to the same conclusion: the best code is the code you don’t write. </p>
<p>There are a lot of ways NOT to write code, even for a developer. Scaffolding, declarative programming, using snippets, or using an ORM are all methods to circumvent writing code. Using open source is another great example. Some may even think that developers are a bit lazy – but aren't they?</p>
<p>Yet minimal skills in web development are still necessary. That means careful thinking, lots of doc reading, debugging and so on. In the end, the time needed to create a fully functional app can only be reduced this much.</p>
<p>You know what? Using a massive framework to speed up developments feels like cheating sometimes. What if I did not have those skills? What if I was not a developer? I would have no other choice than embracing the “no-code way”. And that’s what I’ve done.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/code-free-1200.png" alt="Image" width="600" height="400" loading="lazy">
<em>Relax, Code will be on vacation for the remainder of this article</em></p>
<h2 id="heading-sparkling-innovations-for-web-non-developers">Sparkling innovations for web non-developers</h2>
<p>No-code solutions have been pretty bad in the past. Limited, difficult to extend, proprietary, expensive, the list is long. But some recent tools are starting to be worthy enough.</p>
<p>I will focus specifically on Bubble. Its plugin system coupled with its data management features makes it the most complete solution on the market currently. Here are a few key features and how I used them to build Twaikura.</p>
<h3 id="heading-the-ui-editor">The UI editor</h3>
<p>Bubble proposes a WYSIWYG editor (What You See Is What You Get) to create the app user interface. You put your blocks of content wherever you want, and configure their content.</p>
<p>It’s grid-based so you can have pixel perfect alignment. It handles responsiveness. So you should be able to create designs as complex as you wish.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/ui-bubble.png" alt="Image" width="600" height="400" loading="lazy">
<em>Building Twaikura's interface using the WYSIWYG editor.</em></p>
<p>But I’ll be honest, I am not the hugest fan. More precisely, I am not very good with it. It’s very different both from writing HTML/CSS and from using web-based design tools like Figma, so there is a learning curve.</p>
<p>I ended up sticking myself to an old school Windows 98-ish style. With a little bit of imagination you could even believe it has some “V a p o r w a v e” aesthetic.</p>
<h3 id="heading-thinking-in-workflows">Thinking in workflows</h3>
<p>The most impressive feature of Bubble to me is its “Workflows”. It lets you describe complex process in a visual language. It can mix data management (validating and storing a Twaiku, sending an email) and user experience (resetting a form, refreshing the page) transparently. You don’t need to mentally split the workflow between frontend and backend as you would do in a traditional web app.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/workflows.png" alt="Image" width="600" height="400" loading="lazy">
<em>Twaiku creation workflow</em></p>
<p>This example workflow is triggered when the user wants to submit the second part of a Twaiku. It will create a "Twaiku End" in the database, link it with a "Twaiku Begin", and reset the form. I could also display a success message, send a mail to a moderator and so on. Visualizing the full workflow in a single timeline is very intuitive.</p>
<h3 id="heading-complete-data-management">Complete data management</h3>
<p>Bubbles comes with a relational database and complete filtering features. That means you can easily create both forms and list of data. For example, the “Read latest Twaikus” block will load all valid Twaikus.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/twaikus-list.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Plugins can help secure your content. For example, there is a ReCaptcha plugin to add CAPTCHAs to your form in a matter of minutes. This is important as security is usually left behind in the prototyping steps. Malevolent bots and hackers don't care that you are a "lean startup-er", and they won't miss an opportunity to spam or hack your website.</p>
<h2 id="heading-a-few-hours-of-work-for-an-app-that-works">A few hours of work for an app that works</h2>
<p>I won’t describe all features of Bubble, because it has a lot more. The conclusion is that it's been powerful enough to write an app like Twaikura. Instead of writing tons of crappy code that will end up in a dumpster, instead of creating a visual prototype as lively as Frankenstein’s Creature, I just created something that works.</p>
<p>Is my website great? Honestly, not yet. Does it do the job? Hell yes. I had fun creating it, it cost me no more than a few hours, and I am able to test the concept in the most direct possible way. The longest part was writing this article.</p>
<p>I especially recommend no-code tools for people who want to learn web development. Taking a lot of time to produce simple features can feel frustrating at first. Using a no-code tool alongside traditional programming is a way to keep having fun. It's instructive too, because, even if you don't write code, you still have to think like a developer: designing conditional workflows, structuring a database, validating forms... That's a win-win.</p>
<p>I won't become a no-code evangelist, but Bubble is a great addition to my tool belt. And it could be great addition to yours too!</p>
<p>Thanks for the read. If you liked this article, come try a Bubble app by creating your first Twaiku on <a target="_blank" href="http://twaikura.com">twaikura.com</a>!</p>
<p><a href="https://twitter.com/lbke_fr">
<img src="https://www.freecodecamp.org/news/content/images/2019/10/Medium-follow-2019.png" alt="LBKE banner twitter" width="600" height="400" loading="lazy">
</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Do You Solve Programming Problems or Complete Exercises? (The Difference Matters.) ]]>
                </title>
                <description>
                    <![CDATA[ By Amy Haddad People tend to use the terms “problems” and “exercises” interchangeably. But there’s a difference—and it matters. Professor Paul Zeitz makes the distinction. Take 5 × 5. That’s easy, and that’s an exercise. So is 5,490,900 × 496. It’s a... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/do-you-solve-programming-problems-or-complete-exercises-the-difference-matters/</link>
                <guid isPermaLink="false">66d45d9b3bc3ab877dae21f6</guid>
                
                    <category>
                        <![CDATA[ code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Problem Solving ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ programing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 11 Feb 2020 13:59:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/02/amy-haddad-article.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Amy Haddad</p>
<p>People tend to use the terms “problems” and “exercises” interchangeably. But there’s a difference—and it matters.</p>
<p>Professor Paul Zeitz makes the distinction.</p>
<p>Take 5 × 5. That’s easy, and that’s an exercise. So is 5,490,900 × 496. It’s a bit harder and will take you more time to solve, but you know what to do. That’s the key point.</p>
<p>“An exercise is a mathematical question that you immediately know how to answer,” explains Zeitz in a <a target="_blank" href="https://www.thegreatcoursesplus.com/show/art_and_craft_of_mathematical_problem_solving">lecture series on problem-solving</a>. “You may not answer it correctly, in fact you may never answer it correctly...but there’s no doubt about how to proceed.”</p>
<p>Not so with problems. A problem, according to Zeitz, “is a mathematical question that you do not know how to answer, at least initially.” </p>
<p>He defines problems and exercises through the lens of mathematical problem-solving, but they’re applicable to programming as well. </p>
<p>Each day we put our <a target="_blank" href="https://www.freecodecamp.org/news/how-to-be-a-great-programmer-34939494996d/">problem-solving</a> skills to work as programmers: debugging code, learning a new topic, or even solving a problem. Exercises have their place, but as a programmer there’s no replacement for solving problems.</p>
<h2 id="heading-exercise-with-exercises">Exercise with Exercises</h2>
<p>There are two ways you can benefit from exercises. First, they’re helpful when learning a new topic. </p>
<p>I’m learning JavaScript right now and using a mix of exercises and problems to do so. The exercises help me see patterns and get comfortable with concepts and syntax. </p>
<p>Here’s an example of an exercise from a <a target="_blank" href="https://github.com/LambdaSchool/JS-Exercise-Functions-Arrays-Objects">project</a> that asked me to write a function, which took an array of cars.</p>
<pre><code><span class="hljs-keyword">const</span> cars = [
  { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">car_make</span>: <span class="hljs-string">"Lincoln"</span>, <span class="hljs-attr">car_model</span>: <span class="hljs-string">"Navigator"</span>, <span class="hljs-attr">car_year</span>: <span class="hljs-number">2009</span> },
  { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">car_make</span>: <span class="hljs-string">"Mazda"</span>, <span class="hljs-attr">car_model</span>: <span class="hljs-string">"Miata MX-5"</span>, <span class="hljs-attr">car_year</span>: <span class="hljs-number">2001</span> },
  { <span class="hljs-attr">id</span>: <span class="hljs-number">3</span>, <span class="hljs-attr">car_make</span>: <span class="hljs-string">"Land Rover"</span>, <span class="hljs-attr">car_model</span>: <span class="hljs-string">"Defender Ice Edition"</span>, <span class="hljs-attr">car_year</span>: <span class="hljs-number">2010</span> },
  ...
 ]
</code></pre><p>I had to sort the array of objects by the <code>car_model</code> key, in ascending order.</p>
<p>It’s not to say this exercise was a breeze—it wasn’t. It took me time and I got my fair share of error messages. </p>
<p>However, it qualifies as an exercise because I knew what I needed to do from the start. </p>
<p>I’d recently learned about arrays in JavaScript. I was familiar with sorting data from my experience with Python, though I had to research how to do this in JavaScript. The explicit directions helped, too. </p>
<p>But the concepts were still new. I needed practice putting them together, which is why this exercise was valuable. Repetition breeds familiarity, and the concepts began to solidify in my mind.</p>
<h2 id="heading-maintain-what-youve-gained">Maintain What You’ve Gained</h2>
<p>Exercises also help keep learned information fresh. </p>
<p>As I learn JavaScript, I don’t want to forget everything I’ve learned about the first language I learned, Python. So I use Anki, a flashcard program, multiple times per day. </p>
<p>In this context, exercises help you keep a mountain of material straight, remind you of important concepts, and get more comfortable using a particular data structure or approach. It’s maintenance work on the body of knowledge you’ve gained so far. </p>
<p>I have over 1,000 cards that are filled with material I’ve seen many times before. Some cards have questions about syntax. Others ask me to write SQL queries or command-line or Git commands. Many others are filled with exercises, like “rotate a list of numbers to the right by one place value.”</p>
<p>It’s important to note that this exercise was once a problem for me. If you do a problem enough, it can become an exercise. At the same time, you can make an exercise a problem by <a target="_blank" href="https://www.freecodecamp.org/news/why-i-recycle-programming-problems-7785e04e451d/">adding a constraint</a>. </p>
<p>Exercises are a slippery slope. On the one hand, they’re useful for learning purposes. On the other, it’s easy to get comfortable by sticking with exercises exclusively.</p>
<p>That’s the downside: staying in your comfort zone.</p>
<h2 id="heading-dealing-with-ambiguity">Dealing with Ambiguity</h2>
<p>Programming is about problem-solving. And solving problems will take you <em>outside</em> of your comfort zone. This is a good thing. </p>
<p>For me, problems have two distinctive qualities. The first is ambiguity. Problem-solving is largely about how to effectively deal with ambiguity.   </p>
<ul>
<li>An error message appears each time your program runs. Why? What’s going on? Where’s the bug? How can you fix it? </li>
<li>You pull up a new problem statement. You read it and re-read it. At first glance, you’ve got no idea what’s going on, let alone what you need to do to solve it. You may even get the “deer in headlights” sensation that’s accompanied by a pit in the bottom of your stomach. (You picked a good problem!)</li>
<li>You need to learn about relational databases. That’s pretty broad. How are you going to go about it? What to focus on first? What matters most? What do you really need to know right <em>now</em>?</li>
</ul>
<p>These examples all involve ambiguity. And all of them require solving <em>problems</em>, whether that’s finding and trouble-shooting a bug, solving an actual problem, or learning a new topic.  </p>
<p>To make progress, you research, experiment, pull out the facts, create a plan, and apply a variety of problem-solving tactics. In short, you learn to figure it out. The more time you spend with a problem and the <a target="_blank" href="https://amymhaddad.com/the-art-of-problem-solving">different perspectives you gain</a>, the more layers it reveals and the closer you get to the “aha” moment.</p>
<h2 id="heading-embrace-the-struggle">Embrace the Struggle</h2>
<p>The other difference with problems is the struggle. It’s real.</p>
<p>Problem-solving will test your mental stamina and patience. Progress can be slow, and the process tedious. I’ve toiled away at problems for hours, days, and even weeks.</p>
<p>It’s not to say that exercises won’t challenge you. They can. It’s one thing when you know that you need to use a particular method; you just need to get it to work properly. That’s a challenge, which can sometimes be downright frustrating.</p>
<p>But it’s something else entirely when you have no idea what to do from the start, which may happen multiple times when solving a problem. To me, problems are a struggle.</p>
<p>The best solution is to endure it and get yourself <a target="_blank" href="https://www.freecodecamp.org/news/how-to-get-unstuck/">unstuck</a>. In my experience, the struggle means I’m learning a lot and the breakthrough is usually around the corner. </p>
<p>As you push through the mental discomfort, you’ll find yourself thinking creatively and devising solutions you never thought of before. (You surprise and impress yourself—you know more than you think!) You’re becoming a stronger programmer.</p>
<p>You’ll even find yourself having fun. Problem-solving is challenging, to be sure, and even frustrating at times. But it’s also incredibly rewarding. </p>
<p>It’s like crossing the finish line of a half-marathon. No doubt the past 13.1 miles were grueling, but crossing the finish line was worth it and I’d do it again. Solving a problem feels the same way.</p>
<h2 id="heading-which-is-it-problems-or-exercises">Which Is It: Problems or Exercises?</h2>
<p>When you crack open your laptop, are you going to solve problems or complete exercises?  </p>
<p>Exercises have benefits, and it’s fine to incorporate them into your programming sessions. I use exercises as a warm-up prior to a programming session. I’ll flip through an Anki flashcard deck for ten or fifteen minutes and work through some exercises. If I’m learning something new, like JavaScript, I may have an entire programming session devoted to exercises. </p>
<p>However, I devote time each day to solving <em>problems</em>—no matter what else I’m learning or building. Even on the days when I allocate a large chunk of time to exercises, I allocate plenty of time to solving problems, too.  </p>
<p>So when you’re about to start a programming session, be aware what you’re setting out to do: exercises or problems. And no matter what, make time for solving problems.</p>
<p>Problem-solving is a skill that takes a lot of practice and time to develop. The only way to get better is to work at it each day. It’s that important, and for good reason.</p>
<p>We solve problems each day as programmers, and in a variety of ways. Making time to problem-solve is a no-brainer; our work as programmers depends on it.</p>
<p><em>I write about learning to program, and the best ways to go about it</em> (<a target="_blank" href="https://amymhaddad.com/">amymhaddad.com</a>).</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Conquer Job Interview Coding Challenges ]]>
                </title>
                <description>
                    <![CDATA[ By Jonathan Sexton As many of you know, I have been applying for a job in web development for a few weeks and I thought it would be a good idea to share some of the coding challenges I've encountered. Not only that but I'll share the ways I went ]]>
                </description>
                <link>https://www.freecodecamp.org/news/conquering-job-interview-code-challenges-v1-0/</link>
                <guid isPermaLink="false">66d45f64a326133d124409f1</guid>
                
                    <category>
                        <![CDATA[ challenge ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code challenge ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding interview ]]>
                    </category>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                    <category>
                        <![CDATA[ interview ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Interviewing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ job ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Job Hunting ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Job Interview ]]>
                    </category>
                
                    <category>
                        <![CDATA[ learn to code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ learning to code ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sat, 17 Aug 2019 03:33:34 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/08/le-tan-nsexDkLGC-c-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Jonathan Sexton</p>
<p>As many of you know, I have been applying for a job in web development for a few weeks and I thought it would be a good idea to share some of the coding challenges I've encountered.</p>
<p>Not only that but I'll share the ways I went about solving these challenges.  Granted, there are many ways to solve these challenges but these are the ways I went about it.  If you have different ways that's awesome and I'd love for you to share them with me!</p>
<p>I will not share any identifiable information about the companies or specifics on the interview process of said company to preserve process integrity.</p>
<p>Alright, let's get to it then.</p>
<h2 id="heading-the-challenge">The Challenge</h2>
<p>This is a challenge I was given recently that I felt good about solving:</p>
<p><em><strong>Task: Return a basic styled list of posts from an endpoint in reverse chronological order</strong></em></p>
<p>To protect the company and their information, I will not share the URL from which I returned the information but instead will have a generic link from <a target="_blank" href="https://jsonplaceholder.typicode.com/">JSONPlaceholder</a> (a great, free, open source API for developers when you need to get some generic outside data) in the code below.</p>
<p>Here's the HTML I started with so we have something to display our results in:</p>
<p><img src="https://jonathansexton.me/blog/wp-content/uploads/2019/05/image-3.png" alt="a code example showing HTML" width="600" height="400" loading="lazy">
<em>Basic HTML boilerplate</em></p>
<p>The <em></em></p><ul></ul> tag has an id so we can style it later in the process.<p></p>
<h2 id="heading-fetching-data-from-the-endpoint">Fetching Data From the Endpoint</h2>
<p>Alright, let's dig into the <strong>JavaScript</strong> portion of this challenge.  First, I like to set my output and display variables:</p>
<p><img src="https://jonathansexton.me/blog/wp-content/uploads/2019/05/image-4.png" alt="JavaScript code showing two variables being declared" width="600" height="400" loading="lazy">
<em>Our variables used when displaying the returned code</em></p>
<p>I use <em>let</em> for the <em>output</em> variable and set it to <em>null</em> because we will change it's value later in the code.  The <em>list</em> variable is declared with <em>const</em> because it's value will not be changing.</p>
<p><img src="https://jonathansexton.me/blog/wp-content/uploads/2019/05/image-12.png" alt="javascript code showing a fetch function" width="600" height="400" loading="lazy">
<em>Fetching data from the endpoint</em></p>
<p>In the above example, we’re declaring an <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions">arrow function</a> named <em>getData</em> wrapped in a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch">try…catch</a> block (This is a cleaner/easier to use/read syntax that uses <em>tries</em> some code and <em>catches</em> errors if they happen — you’ll also see the <em>catch</em> portion below).  Because we're getting data asynchronously we also need to make use of <em><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await">async/await</a></em> to fetch data.  This is the method I'm most comfortable with but I know there are many other ways to get data from an endpoint so feel free to share yours :D</p>
<p>Once we've declared our <em>data</em> variable, the next thing is to set a variable to turn the returned data to a JSON object so we can get it in a usable form.  We do that with the <em><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Body/json">.json()</a></em> method.  We're awaiting the data as well because if we were to omit the <em>await</em> keyword, JavaScript would try to turn the <em>data</em> variable into JSON but the data would not be there yet because it's coming from an asynchronous API.</p>
<p><img src="https://jonathansexton.me/blog/wp-content/uploads/2019/05/image-9.png" alt="a console log of a javascript array " width="600" height="400" loading="lazy">
<em>Our glorious data!</em></p>
<p>As the very last line in the section, we <em>console.log</em> our data that we get back from the API endpoint just to make sure we're getting everything we wanted.  We have an array full of objects.  You'll also notice that the key _published<em>at</em> holds our dates and they are not in any type of order.  Their format is also not a simple four digit number representing the year which would make it easy to filter them into <em><strong>reverse chronological order</strong></em>.  We'll need to take care of that.</p>
<h2 id="heading-manipulating-our-data">Manipulating Our Data</h2>
<p><img src="https://jonathansexton.me/blog/wp-content/uploads/2019/05/image-7.png" alt="javascript code that's copying a variable" width="600" height="400" loading="lazy">
<em>Making a copy of our data variable</em></p>
<p>Here we declare the variable <em>dataCopy</em> which points to the <em>dataJSON</em> variable mutated into an array via the _<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax">spread operator(...)</a>_.  Essentially, we are copying our returned JSON data so we aren't manipulating the original (bad practice) while making it into an array so that we can iterate over it.</p>
<p>After, we _<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort">sort</a>_ the array.  Sort is an extremely useful array method that will put our array indices into the order of our choosing based on the function we pass into <em>sort.</em></p>
<p>Typically, we might want to sort the data based on value (largest to smallest) so we subtract the parameter <em><strong>a</strong></em> from parameter <em><strong>b</strong></em>.  But because we need to display our results in <em><strong>reverse chronological order</strong></em> I decided to produce a new date (accomplished with the <em><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new">new</a></em> operator and the JavaScript built in method _<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date">Date</a><em> that creates a new platform independent formatted instance of a date.  Now, because </em><strong>a</strong><em> and </em><strong>b</strong>_ represent our objects sitting inside our array indices, we can access the key/value pairs held within said objects.  So, we subtract _b.published<em>at</em> from _a.published<em>at</em> and this should give us our dates in <em><strong>reverse chronological order</strong></em>.</p>
<h2 id="heading-displaying-the-fruits-of-our-labor">Displaying the Fruits of Our Labor</h2>
<p>Remember that <em>output</em> variable we set to <em>null</em> at the very top of our program?  Well now is it's time to shine!</p>
<p><img src="https://jonathansexton.me/blog/wp-content/uploads/2019/05/image-10.png" alt="javascript code showing an output variable being changed" width="600" height="400" loading="lazy">
<em>That output variable is earning it's keep now!</em></p>
<p>So, there's a few things going on here.  First, we're setting our <em>output</em> variable to a new value by mapping over our <em>dataCopy</em> variable using the _<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>_ method.  This method returns a new array with the results of calling the provided function once for each index.  The <em>item</em> parameter represents our objects inside of our array that was returned from the endpoint and thus has access to all of their properties such as <em>title</em> and _published<em>at</em>.</p>
<p>We return two list elements with a <em><span></span></em> inside each one (for styling purposes), as well as a string for the <strong>Title</strong> and <strong>Date Published</strong> headings.  Inside of those, we have our variables that use <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals">template literals</a> to set the title and the date for each post.</p>
<p>Then, we set our <em>list</em> variable's <em><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML">innerHTML</a></em> equal to that of our <em>output</em> variable.</p>
<p>Finally, we have the closing bracket and error handling of our <em>try...catch</em> block as well as our function call:</p>
<p><img src="https://jonathansexton.me/blog/wp-content/uploads/2019/05/image-11.png" alt="javascript code showing error handling for a fetch request" width="600" height="400" loading="lazy">
<em>This code will handle any errors and display them in the console</em></p>
<h2 id="heading-final-code">Final Code</h2>
<p>Here is what our full code body looks like now:</p>
<p><img src="https://jonathansexton.me/blog/wp-content/uploads/2019/05/image-13.png" alt="javascript code " width="600" height="400" loading="lazy">
<em>The entirety of our code base</em></p>
<p>And here is our basic CSS styling:</p>
<p><img src="https://jonathansexton.me/blog/wp-content/uploads/2019/05/image-14.png" alt="css code showing basic styling of an element" width="600" height="400" loading="lazy">
<em>Did I say basic styling? I meant basic :D</em></p>
<p>And here is the result of our work with it's very basic styling:</p>
<p><img src="https://jonathansexton.me/blog/wp-content/uploads/2019/05/image-15.png" alt="a list of posts in reverse chronological order" width="600" height="400" loading="lazy">
<em>Isn't it beautiful?</em></p>
<p>As you can see, we accomplished what we set out to do and in fact the list is in <em><strong>reverse chronological order</strong></em>. Yay!</p>
<hr>
<p>I hope you've enjoyed this walk through of my thought process and of how I solved this challenge.  Granted, there are many ways of completing this so feel free to share yours with me!  I'm excited to keep this series going and will post another after I've gone through another challenge!</p>
<p>Also, I cross post most of my articles on great platforms like <a target="_blank" href="https://dev.to/jsgoose">Dev.to</a> and <a target="_blank" href="https://medium.com/@joncsexton">Medium</a> so you can find my work there as well. This article was originally posted on my <a target="_blank" href="https://jonathansexton.me/blog">blog</a> on May 27, 2019. </p>
<p>While you’re here why not <a target="_blank" href="https://jonathansexton.me/blog/">sign up for my <strong>Newsletter</strong></a>.  I promise I’ll never  spam your inbox and your information will not be shared with  anyone/site.  I like to occasionally send out interesting resources I  find, articles about web development, and a list of my newest posts.</p>
<p>Have an awesome day filled with love, joy, and coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 10 External Python packages you are going to love ]]>
                </title>
                <description>
                    <![CDATA[ By Adam Goldschmidt Python is an experiment in how much freedom programmers need. Too much freedom and nobody can read another’s code; too little and expressiveness is endangered. - Guido van Rossum This freedom that Guido talks about is part of wh... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/these-python-packages-will-help-accelerate-your-development-process-d4b3f170b1ea/</link>
                <guid isPermaLink="false">66c362f81a1cf73cbc81f139</guid>
                
                    <category>
                        <![CDATA[ code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ open source ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 09 Apr 2019 15:22:39 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/0*Metg2GPm6OTYWKZh" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Adam Goldschmidt</p>
<blockquote>
<p>Python is an experiment in how much freedom programmers need. Too much freedom and nobody can read another’s code; too little and expressiveness is endangered. - Guido van Rossum</p>
</blockquote>
<p>This freedom that Guido talks about is part of what makes Python so popular. That popularity, among other, is what attracts more and more developers to use the language - eventually leading to some really amazing open source projects.</p>
<p>I usually find myself project hunting on GitHub once a day. Throughout this article, I will try to cover 10 wonderful packages that you may or may not be familiar with. I will start from the less trendy and end up with… well, Flask.</p>
<h3 id="heading-lets-begin">Let’s begin!</h3>
<p><img src="https://cdn-media-1.freecodecamp.org/images/oGpPuDrsAM6KYONzQCrIZXv1xAEIv-oVuIUT" alt="Image" width="400" height="225" loading="lazy"></p>
<h4 id="heading-loguruhttpsgithubcomdelganloguru-logging-made-easy"><a target="_blank" href="https://github.com/Delgan/loguru">Loguru</a> — Logging made easy</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/DWrohhPZvoWbH4s8apMbg8nXZOtf3m0lAhvk" alt="Image" width="507" height="150" loading="lazy"></p>
<p>This is a really awesome package I regularly use in my projects. It describes itself as “a library which aims to bring enjoyable logging in Python”. This package just lets you easily configure your logs out of the box.</p>
<p>All you have to do after installing is to import the module:</p>
<pre><code><span class="hljs-keyword">from</span> loguru <span class="hljs-keyword">import</span> logger
</code></pre><p>And you’re free to use it out of the box:</p>
<pre><code>logger.debug(<span class="hljs-string">"Hello, cool debugger"</span>)
</code></pre><p>The documentation is good and there are many customization options.</p>
<h4 id="heading-more-itertoolshttpsgithubcomerikrosemore-itertools"><a target="_blank" href="https://github.com/erikrose/more-itertools">more-itertools</a></h4>
<p>A variety of interesting methods that could sometimes come very useful, such as <code>peekable</code>:</p>
<pre><code>&gt;&gt;&gt; p = peekable([<span class="hljs-string">'a'</span>, <span class="hljs-string">'b'</span>])&gt;&gt;&gt; p.peek()<span class="hljs-string">'a'</span>&gt;&gt;&gt; next(p)<span class="hljs-string">'a'</span>
</code></pre><p>or <code>chunked</code>:</p>
<pre><code>&gt;&gt;&gt; list(chunked([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>], <span class="hljs-number">3</span>))[[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], [<span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>]]
</code></pre><h4 id="heading-monkeytypehttpsgithubcominstagrammonkeytype-static-type-annotations-generator"><a target="_blank" href="https://github.com/Instagram/MonkeyType">MonkeyType</a> — Static type annotations generator</h4>
<pre><code>monkeytype run myscript.py
</code></pre><p>This package automatically generates type annotations for you, either in a stub file or in the source code itself, by collecting runtime types. Right, Python doesn’t enforce you to use annotations — but I believe they are very important for readability of the code (and sometimes for avoiding errors), which is also why there are 2 more packages in this list that are handling type annotations :)</p>
<h4 id="heading-pyrighthttpsgithubcommicrosoftpyright-static-type-checker"><a target="_blank" href="https://github.com/Microsoft/pyright">Pyright</a> — Static type checker</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/B5KVRNqA90q0PqVY18dvfvc7m7rbjYYVf1EP" alt="Image" width="565" height="234" loading="lazy"></p>
<p>Exciting new package coming from Microsoft. The inital commit was just 17 days ago! This package is the competitor of Mypy (also on this list). To be honest, I haven’t yet had the chance to use it, but I definitely plan to. I currently use mypy as a type checker, but I’ll give this one a try!</p>
<h4 id="heading-requests-asynchttpsgithubcomencoderequests-async-support-for-asyncawait-syntax-for-requests"><a target="_blank" href="https://github.com/encode/requests-async">requests-async</a> — support for <code>async</code>/<code>await</code> syntax for <code>requests</code></h4>
<p>This is a new package I discovered the other day on GitHub, and it seems pretty promising. We all know the <a target="_blank" href="https://github.com/kennethreitz/requests">requests</a> package, that lets us easily handle HTTP requests in our code. Well, this package implements <code>async</code> and <code>await</code> words for these requests:</p>
<pre><code><span class="hljs-keyword">import</span> requests_async <span class="hljs-keyword">as</span> requests​response = <span class="hljs-keyword">await</span> requests.get(<span class="hljs-string">'https://example.org'</span>)print(response.status_code)print(response.text)
</code></pre><p>Pretty cool right?</p>
<h4 id="heading-httpiehttpsgithubcomjakubroztocilhttpie-modern-command-line-curl"><a target="_blank" href="https://github.com/jakubroztocil/httpie">HTTPie</a> — Modern command line cURL</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/UAD--5ZtcqjDRRKA4Y1oXEWzob6GTM94sXGa" alt="Image" width="1024" height="512" loading="lazy"></p>
<p>Those of you who have used cURL before, must know it’s not that fun. Having to remember the parameters names, making sure your data is encapsulated… Well, HTTPie aims to make this much easier. Here’s one of their examples, of submitting form data:</p>
<pre><code>http -f POST example.org hello=World
</code></pre><h4 id="heading-pipenvhttpsgithubcompypapipenv-better-packaging-for-python"><a target="_blank" href="https://github.com/pypa/pipenv">pipenv</a> — Better packaging for Python</h4>
<p>When I start a new project, I always create a new <code>virtualenv</code> and install some basic packages with <code>pip</code>. I then need to save these packages names in a file, be it <code>setup.py</code> or <code>requirements.txt</code>. Those of you who have worked with <code>npm</code>, know it's much simpler there. All you need to do is write <code>npm —save</code> and the package name is saved in your <code>package.json</code>. That's why I first created <a target="_blank" href="https://github.com/AdamGold/pypkgfreeze">pypkgfreeze</a>, a simple package to "freeze" the versions of your currently used <code>pip</code> packages into <code>setup.py</code>.</p>
<p>Anyway, pipenv is an interesting solution that aims to merge the two worlds - They describe it best in their repo page:</p>
<p>It automatically creates and manages a virtualenv for your projects, as well as adds/removes packages from your <code>Pipfile</code> as you install/uninstall packages. It also generates the ever-important <code>Pipfile.lock</code>, which is used to produce deterministic builds.</p>
<p>You can try it out <a target="_blank" href="https://rootnroll.com/d/pipenv/">here</a>.</p>
<h4 id="heading-mypyhttpsgithubcompythonmypy-static-type-checker"><a target="_blank" href="https://github.com/python/mypy">mypy</a> — Static type checker</h4>
<p>As I said before, this is the package I currently use as my standard static type checker. It helps me keep my code readable and elegant (I think).</p>
<h4 id="heading-blackhttpsgithubcomambvblack"><a target="_blank" href="https://github.com/ambv/black">black</a></h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/dQoUny7l5N6sWs2GCECZKHALf59t9398hNNp" alt="Image" width="800" height="293" loading="lazy"></p>
<p>I have tried many Python formatters, and <code>black</code> is clearly my favourite. The syntax looks neat, and the command line runs quick and can either check the files or actually edit them - very useful for CI/CD. You can even try it <a target="_blank" href="https://www.freecodecamp.org/news/these-python-packages-will-help-accelerate-your-development-process-d4b3f170b1ea/%5Bhttps://black.now.sh%5D(https://black.now.sh/)">here!</a></p>
<h4 id="heading-flaskhttpsgithubcompalletsflask"><a target="_blank" href="https://github.com/pallets/flask">flask</a></h4>
<p>Not sure if I have anything to write here that hasn’t been written before. You are probably familiar with this astonishing micro framework, and if you’re not.. you definitely should check it out.</p>
<h3 id="heading-before-you-go">Before you go…</h3>
<p>Thanks for reading! You can follow my <a target="_blank" href="https://github.com/AdamGold">GitHub</a> account for more cool repos. I tend to star every cool thing that I see :)</p>
<p>If you enjoyed this article, please hold down the clap button ? to help others find it. The longer you hold it, the more claps you give!</p>
<p>And do not hesitate to share your thoughts in the comments below.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Awesome Python modules you probably aren’t using (but should be) ]]>
                </title>
                <description>
                    <![CDATA[ By Adam Goldschmidt Python is a beautiful language, and it contains many built-in modules that aim to help us write better, prettier code. Objective Throughout this article, we will use some lesser-known modules and methods that I think can improve ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/awesome-python-modules-you-probably-arent-using-but-should-be-ec926da27439/</link>
                <guid isPermaLink="false">66c3452f27a84175a22f3c44</guid>
                
                    <category>
                        <![CDATA[ code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 15 Mar 2019 15:35:50 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/0*oG_N_s-TEk-wMau5" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Adam Goldschmidt</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*_qzk08ccorLRF4zS6EwBBQ.png" alt="Image" width="800" height="421" loading="lazy"></p>
<p><strong>Python</strong> is a beautiful language, and it contains many built-in modules that aim to help us write better, prettier code.</p>
<h3 id="heading-objective">Objective</h3>
<p>Throughout this article, we will use some lesser-known modules and methods that I think can improve the way we code - both in visibility and in efficiency.</p>
<h3 id="heading-namedtuple">NamedTuple</h3>
<p>I believe that some of you already know the more popular <code>namedtuple</code> from the <code>collections</code> module (if you don't - <a target="_blank" href="https://docs.python.org/3.6/library/collections.html#collections.namedtuple">check it out</a>), but since Python 3.6, a new class is available in the <code>typing</code> module: <code>NamedTuple</code>. Both are designed to help you quickly create readable immutable objects.</p>
<p><code>NamedTuple</code> is actually a typed version of <code>namedtuple</code>, and in my opinion, is much more readable:</p>
<p>Here’s the <code>namedtuple</code> alternative:</p>
<h3 id="heading-arrayarray">array.array</h3>
<blockquote>
<p><em>Efficient arrays of numeric values. Arrays are sequence types and behave very much like lists, except that the type of objects stored in them is constrained. — <a target="_blank" href="https://docs.python.org/3.6/library/array.html">Python docs</a></em></p>
</blockquote>
<p>When using the <code>array</code> module, we need to instantiate it with a typecode, which is the type all of its elements will use. Let's compare time efficiency with a normal list, writing many integers to a file (using <code>[pickle](https://docs.python.org/3.7/library/pickle.html)</code> module for a regular list):</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*vPfWDCLXCikKuJOuWj5Xkg.png" alt="Image" width="800" height="478" loading="lazy">
_[https://gist.github.com/AdamGold/961758c66cdfe92642eabb61d9ce9866](https://gist.github.com/AdamGold/961758c66cdfe92642eabb61d9ce9866" rel="noopener" target="<em>blank" title=")</em></p>
<p><strong>14 times</strong> faster. That’s a lot. Of course it also depends on the <code>pickle</code> module, but still - the array is way more compact than the list. So if you are using simple numeric values, you should consider using the <code>array</code> module.</p>
<h3 id="heading-itertoolscombinations">itertools.combinations</h3>
<p><code>itertools</code> is an impressive module. It has so many different time-saving methods, all of them are listed <a target="_blank" href="https://docs.python.org/3/library/itertools.html">here</a>. There's even a GitHub repository containing <a target="_blank" href="https://github.com/erikrose/more-itertools">more itertools</a>!</p>
<p>I got to use the <code>combinations</code> method this week and I thought I'd share it. This method takes an iterable and an integer as arguments, and creates a generator consisting of all possible combinations of the iterable with a maximum length of the integer given, without duplication:</p>
<h3 id="heading-dictfromkeys">dict.fromkeys</h3>
<p>A quick and beautiful way of creating a dict with default values:</p>
<h3 id="heading-last-but-not-least-the-dis-module">Last but not least - the <code>dis</code> module</h3>
<blockquote>
<p><em>The <code>[dis](https://docs.python.org/3/library/dis.html#module-dis)</code> module supports the analysis of CPython <a target="_blank" href="https://docs.python.org/3/glossary.html#term-bytecode">bytecode</a> by disassembling it.</em></p>
</blockquote>
<p>As you may or may not know, Python compiles source code to a set of instructions called “bytecode”. The <code>dis</code> module helps us handle these instructions, and it's a great debugging tool.</p>
<p>Here’s an example from the <a target="_blank" href="http://shop.oreilly.com/product/0636920032519.do">Fluent Python book</a>:</p>
<p>We got an error — but the operation still succeeded. How come? Well, if we look at the bytecode (I added comments near the important parts):</p>
<h3 id="heading-before-you-go">Before you go…</h3>
<p>Thanks for reading! For more Python related articles and other cool stuff, you can follow me on <a target="_blank" href="https://medium.com/@adamgoldschmidt">Medium</a> or <a target="_blank" href="https://github.com/AdamGold">GitHub</a> (I star some awesome repos!).</p>
<p>If you enjoyed this article, please hold down the clap button ? to help others find it. The longer you hold it, the more claps you give!</p>
<p>And do not hesitate to share more Python hidden gems in the comments below.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to automate Code Reviews on Github ]]>
                </title>
                <description>
                    <![CDATA[ By Mukesh Thawani Creating pull requests and reviewing them are two of the most common tasks in a developer’s daily schedule. Most projects have common guidelines which developers need to follow while creating and reviewing the pull requests. Now, it... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-automate-code-reviews-on-github-41be46250712/</link>
                <guid isPermaLink="false">66c34f04912fb29c4f156c17</guid>
                
                    <category>
                        <![CDATA[ #chatbots ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GitHub ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 24 Jan 2019 22:22:14 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*i_C4bry8eP6mlT3OqVo45A.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Mukesh Thawani</p>
<p>Creating pull requests and reviewing them are two of the most common tasks in a developer’s daily schedule. Most projects have common guidelines which developers need to follow while creating and reviewing the pull requests.</p>
<p>Now, it is hard for developers to remember every guideline while making a pull request. It is even more difficult for reviewers to ensure that every line of code is compliant to the set guidelines.</p>
<p>We faced the same problem with our projects and solved it by automating the major part of the manual rote work. This made the lives of our developers and reviewers a lot easier. They spent more time improving code quality and less on common chores.</p>
<p>In this article, I will describe exactly how we did it, what all aspects of the process we automated and the tools we used for this.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Kxybxb-zIXEpPgFUVpgyt5xnrnPhjVk-YG14" alt="Image" width="699" height="261" loading="lazy">
<em>200 million plus pull requests created on Github. Source: Octoverse</em></p>
<h3 id="heading-automate-styling-issues">Automate styling issues</h3>
<p>We don’t want our reviewers asking the contributors to add the corresponding Jira issue number and description whenever they make a pull request. Instead, we have deployed a bot that does all the regular checks. This helps contributors to follow project guidelines.</p>
<p>Yes, a bot can verify if the description is present or not by checking the body of the pull request. It can comment on a pull request if the description is missing.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/h7n4CPzzBvjkUfIT30AQ48qJ0ksUOCYrv-La" alt="Image" width="782" height="407" loading="lazy">
<em>Applozic Bot commenting on pull requests.</em></p>
<p>We can also add a <a target="_blank" href="https://help.github.com/articles/creating-a-pull-request-template-for-your-repository/">pull request template</a> to get some of the information related to the pull request. But this approach increases the friction required to create a pull request. When we add rules, we need to make sure that the experience of a new developer will be as frictionless as possible. At the same time, we need to maintain the code quality.</p>
<p>Now let’s look at the steps required in creating such a bot.</p>
<h3 id="heading-danger-to-the-rescue">‘Danger’ to the rescue</h3>
<blockquote>
<p><a target="_blank" href="http://danger.systems/"><em>Danger</em></a> <em>runs during your CI process, and gives teams the chance to automate common code review chores. This provides another logical step in your build, through this Danger can help lint your rote tasks in daily code review.</em></p>
<p><em>You can use Danger to codify your team’s norms. Leaving humans to think about harder problems. She does this by leaving messages inside your PRs based on rules that you create with the Ruby scripting language. Over time, as rules are adhered to, the message is amended to reflect the current state of the code review.</em></p>
<p><em>Danger is used in all sorts of projects: ruby gems, python apps, Xcode projects, blogs, npm websites and modules.</em></p>
</blockquote>
<p>It will give you an abstraction on top of Github’s API to get details related to a pull request and perform the necessary checks. It is created and maintained by Orta and many other awesome contributors. After installation, you need to create a file named Dangerfile which will contain all the rules. This file should be present in the root of your project.</p>
<p>After adding this file you are all set with the rules. Now you need to run Danger every time someone creates a pull request.</p>
<h3 id="heading-adding-it-to-your-ci-workflow">Adding it to your CI workflow</h3>
<p>We use Bitrise in our mobile SDK projects. It’s a Continuous Integration and Continuous Delivery service for mobile Apps. If you are using a different CI service then, you can check this <a target="_blank" href="https://danger.systems/guides/getting_started.html#continuous-integration">guide</a> on how you can integrate Danger with that service. There is a detailed <a target="_blank" href="https://blog.bitrise.io/danger-danger-uh-that-is-using-danger-with-bitrise">blog post</a> on integrating Danger with Bitrise. I will summarise it in five points:</p>
<ul>
<li>Install bundler, create a Gemfile and add the Danger gem to the Gemfile.</li>
<li>Create a Dangerfile for your project.</li>
<li>Create a bot user on Github and a Personal Access Token for the bot.</li>
<li>Then add the generated token on Bitrise.</li>
<li>Add a script step in the project’s workflow. That’s it! ?</li>
</ul>
<h3 id="heading-rules-which-we-can-automate">Rules which we can Automate</h3>
<p>One of the ways to identify what rules we can automate is by looking at Github’s pull request API response. By comparing the API response with our pull request checklist or guideline, we can get an idea of the possibilities that are there. This is how the response looks like:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/svTngozizNzNJo2tIyJDAFWyppgAL-dLHRgW" alt="Image" width="644" height="752" loading="lazy">
<em>Response from Github’s pull request API</em></p>
<ul>
<li>It returns almost all the information you see on GitHub’s pull request webpage like title, description, assignee, reviewers, labels etc.</li>
<li>There’s one more API to fetch a list of changed files. For each file, it will return the name of the file, the number of additions to the file, the number of deletions to the file.</li>
<li>We don’t have to use this APIs as we will be using Danger which gives us an easy way to interact with this data.</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/3eWH5zzgFStXBVRrFH0wGwaf7BcdDO4M3gOV" alt="Image" width="642" height="316" loading="lazy">
<em>Response from Github’s list pull requests files API</em></p>
<h3 id="heading-list-of-rules-we-automated">List of Rules we Automated</h3>
<p>When we were adding Danger to our repository we looked at our requirements and some of the other projects which were using Danger. Below are <strong>some of the checks</strong> that we have in our projects.</p>
<ul>
<li><strong>Warn if it’s a big PR</strong>: We tend to make this mistake of pushing a lot of changes in one PR. Reviewing such PRs is a difficult task. We added a warning which shows up when the number of lines updated in a PR is more than 500.</li>
<li><strong>Encourage pull request descriptions</strong>: Sometimes developers think that description is not necessary or we forget to add. Even though you mentioned the issue number, a brief description always helps and gives a context to the pull request. To see if the description is empty or not we can check the body length:</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/cIc1nvWw2LtsPkplGfFyTYfVHIHbo3knjsL1" alt="Image" width="565" height="91" loading="lazy"></p>
<ul>
<li><strong>Check if the tests are missing</strong>: We all know tests are important and yet we tend to skip this step. Whenever we do any modification in the source code, we should add tests if possible. So, now it warns if there are any changes in the source code and the tests folder is not modified, which means new tests are missing.</li>
<li><strong>Update Changelog</strong>: Added a new feature or fixed a bug — update the Changelog with the details. We made it mandatory to add a Changelog entry if the change is nontrivial. If the Changelog is not updated and pull request is not marked as trivial, then our CI fails the build. Now, we don’t have to keep track whether the Changelog was updated.</li>
<li><strong>Encourage rebase not merge commits</strong>: As the project grows it’s always recommended that we should avoid ‘merge’ commits so that the project has a clean history. We prefer using rebase instead of merging different branches. We can add a check for messages of this format: “Merge branch ‘master’” to avoid the merge commits.</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/LHJv16-BauUBZd5Xt0QybFyE9aNkABawaXUu" alt="Image" width="519" height="87" loading="lazy"></p>
<h3 id="heading-where-to-go-next">Where to go next</h3>
<p>For reference, you can check <a target="_blank" href="https://github.com/AppLozic/ApplozicSwift/blob/master/Dangerfile">ApplozicSwift’s Dangerfile</a> or in some of the other popular open source projects like <a target="_blank" href="https://github.com/facebook/react-native/blob/master/bots/dangerfile.js">React Native</a> or <a target="_blank" href="https://github.com/CocoaPods/CocoaPods/blob/master/Dangerfile">CocoaPods</a>. I discovered while writing this blog post that projects like React Native and React were also using danger. This shows us how this process of automating these checks has become part of the common pull requests workflow.</p>
<p><em>Liked the story? Hit that clap button and follow me on <a target="_blank" href="https://medium.com/@MukeshThawani">Medium</a>. Thanks for reading! This article was originally published on <a target="_blank" href="https://www.kommunicate.io/blog/automate-code-reviews-on-github-using-a-chatbot/">Kommunicate blog</a>.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Solve the Tower of Hanoi Problem - An Illustrated Algorithm Guide ]]>
                </title>
                <description>
                    <![CDATA[ By Dipto Karmakar Before getting started, let’s talk about what the Tower of Hanoi problem is. Well, this is a fun puzzle game where the objective is to move an entire stack of disks from the source position to another position. Three simple rules ar... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/analyzing-the-algorithm-to-solve-the-tower-of-hanoi-problem-686685f032e3/</link>
                <guid isPermaLink="false">66d45e3d47a8245f78752a28</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Ruby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 03 Jan 2019 16:55:19 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9ca6e9740569d1a4ca739a.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Dipto Karmakar</p>
<p>Before getting started, let’s talk about what the Tower of Hanoi problem is. Well, this is a fun puzzle game where the objective is to move an entire stack of disks from the source position to another position. Three simple rules are followed:</p>
<ol>
<li>Only one disk can be moved at a time.</li>
<li>Each move consists of taking the upper disk from one of the stacks and placing it on top of another stack. In other words, a disk can only be moved if it is the uppermost disk on a stack.</li>
<li>No larger disk may be placed on top of a smaller disk.</li>
</ol>
<p>Now, let’s try to imagine a scenario. Suppose we have a stack of three disks. Our job is to move this stack from <strong>source A</strong> to <strong>destination C</strong>. How do we do this?</p>
<p>Before we can get there, let’s imagine there is an <strong>intermediate point B</strong>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*UB4f9VNg1RRs4k93.png" alt="Image" width="500" height="375" loading="lazy">
_[Three disks](http://www.texample.net/tikz/examples/towers-of-hanoi/" rel="noopener" target="<em>blank" title=").</em></p>
<p>We can use B as a helper to finish this job. We are now ready to move on. Let’s go through each of the steps:</p>
<ol>
<li>Move the first disk from A to C</li>
<li>Move the first disk from A to B</li>
<li>Move the first disk from C to B</li>
<li>Move the first disk from A to C</li>
<li>Move the first disk from B to A</li>
<li>Move the first disk from B to C</li>
<li>Move the first disk from A to C</li>
</ol>
<p>Boom! We have solved our problem.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*fLOJ9bbxmHuFgYCeeRslhA.gif" alt="Image" width="320" height="98" loading="lazy">
_Tower of Hanoi for 3 disks. [<strong>Wikipedia</strong>](https://en.wikipedia.org/wiki/Tower_of_Hanoi" rel="noopener" target="<em>blank" title=")</em></p>
<p>You can see the animated image above for a better understanding.</p>
<p>Now, let’s try to build the algorithm to solve the problem. Wait, we have a new word here: “<strong>Algorithm</strong>”. What is that? Any idea? No problem, let’s see.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*B4f6VtfIxmB04Od1" alt="Image" width="800" height="533" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/@brucemars?utm_source=medium&amp;utm_medium=referral" rel="noopener" target="_blank" title=""&gt;bruce mars on &lt;a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral" rel="noopener" target="<em>blank" title=")</em></p>
<h3 id="heading-what-is-an-algorithm">What is an algorithm?</h3>
<p>An algorithm is one of the most important concepts for a software developer. In fact, I think it’s not only important for software development or programming, but for everyone. Algorithms affect us in our everyday life. Let’s see how.</p>
<p>Suppose you work in an office. So every morning you do a series of tasks in a sequence: first you wake up, then you go to the washroom, eat breakfast, get prepared for the office, leave home, then you may take a taxi or bus or start walking towards the office and, after a certain time, you reach your office. You can say all those steps form an <strong>algorithm</strong>.</p>
<p>In simple terms, an algorithm is a set of tasks. I hope you haven’t forgotten those steps we did to move three disk stack from A to C. You can also say that those steps are the algorithm to solve the Tower of Hanoi problem.</p>
<blockquote>
<p><em>In mathematics and computer science, an algorithm is an unambiguous specification of how to solve a class of problems. Algorithms can perform calculation, data processing and automated reasoning tasks. — <a target="_blank" href="https://en.wikipedia.org/wiki/Algorithm">Wikipedia</a></em></p>
</blockquote>
<p>If you take a look at those steps you can see that we were doing the same task multiple times — moving disks from one stack to another. We can call these steps inside steps <strong>recursion</strong>.</p>
<h3 id="heading-recursion">Recursion</h3>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*fsYHEgadIdn0fJt-cBXDHQ.gif" alt="Image" width="384" height="312" loading="lazy">
_Recursion — [giphy](https://giphy.com/gifs/homer-simpson-the-simpsons-3ov9jQX2Ow4bM5xxuM" rel="noopener" target="<em>blank" title=")</em></p>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Recursion_(computer_science)"><strong>Recursion</strong></a> is calling the same action from that action. Just like the above picture.</p>
<p>So there is one rule for doing any recursive work: there must be a condition to stop that action executing. I hope you understand the basics about recursion.</p>
<p>Now, let’s try to build a procedure which helps us to solve the Tower of Hanoi problem. We are trying to build the solution using pseudocode<strong>.</strong> Pseudocode is a method of writing out computer code using the English language.</p>
<pre><code>tower(disk, source, intermediate, destination)
{

}
</code></pre><p>This is the skeleton of our solution. We take the total disks number as an argument. Then we need to pass source, intermediate place, and the destination so that we can understand the map which we will use to complete the job.</p>
<p>Now we need to find a <strong>terminal state</strong>. The terminal state is the state where we are not going to call this function anymore.</p>
<pre><code>IF disk is equal <span class="hljs-number">1</span>
</code></pre><p>In our case, this would be our terminal state. Because when there will be one disk in our stack then it is easy to just do that final step and after that our task will be done. Don’t worry if it’s not clear to you. When we reach the end, this concept will be clearer.</p>
<p>Alright, we have found our terminal state point where we move our disk to the destination like this:</p>
<pre><code>move disk <span class="hljs-keyword">from</span> source to destination
</code></pre><p>Now we call our function again by passing these arguments. In that case, we divide the stack of disks in two parts. The largest disk (<strong>nth</strong> disk) is in one part and all other (<strong>n-1</strong>) disks are in the second part. There we call the method two times for -(n-1).</p>
<pre><code>tower(disk - <span class="hljs-number">1</span>, source, destination, intermediate)
</code></pre><p>As we said we pass <strong>total_disks_on_stack — 1</strong> as an argument. And then again we move our disk like this:</p>
<pre><code>move disk <span class="hljs-keyword">from</span> source to destination
</code></pre><p>After that we again call our method like this:</p>
<pre><code>tower(disk - <span class="hljs-number">1</span>, intermediate, source, destination)
</code></pre><p>Let’s see our full pseudocode:</p>
<pre><code>tower(disk, source, inter, dest)

IF disk is equal <span class="hljs-number">1</span>, THEN
      move disk <span class="hljs-keyword">from</span> source to destination
   ELSE
      tower(disk - <span class="hljs-number">1</span>, source, destination, intermediate)   <span class="hljs-comment">// Step 1</span>
      move disk <span class="hljs-keyword">from</span> source to destination                 <span class="hljs-comment">// Step 2</span>
      tower(disk - <span class="hljs-number">1</span>, intermediate, source, destination)   <span class="hljs-comment">// Step 3</span>
   END IF

END
</code></pre><p>This is the tree for three disks:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*LEkUpm8-CoxGko2f84gjOg.jpeg" alt="Image" width="800" height="315" loading="lazy">
<em>Tree of tower of hanoi (3 disks)</em></p>
<p>This is the full code in Ruby:</p>
<pre><code class="lang-rb"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">tower</span><span class="hljs-params">(disk_numbers, source, auxilary, destination)</span></span>
  <span class="hljs-keyword">if</span> disk_numbers == <span class="hljs-number">1</span>
    puts <span class="hljs-string">"<span class="hljs-subst">#{source}</span> -&gt; <span class="hljs-subst">#{destination}</span>"</span>
    <span class="hljs-keyword">return</span>
  <span class="hljs-keyword">end</span>
  tower(disk_numbers - <span class="hljs-number">1</span>, source, destination, auxilary)
  puts <span class="hljs-string">"<span class="hljs-subst">#{source}</span> -&gt; <span class="hljs-subst">#{destination}</span>"</span>
  tower(disk_numbers - <span class="hljs-number">1</span>, auxilary, source, destination)
  <span class="hljs-literal">nil</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>Call <code>tower(3, 'source','aux','dest')</code></p>
<p>Output:</p>
<pre><code>source -&gt; dest
source -&gt; aux
dest -&gt; aux
source -&gt; dest
aux -&gt; source
aux -&gt; dest
source -&gt; dest
</code></pre><p>It took seven steps for three disks to reach the destination. We call this a <strong>recursive method</strong>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*VXmzOesqL7l18gAr" alt="Image" width="800" height="533" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/@aronvisuals?utm_source=medium&amp;utm_medium=referral" rel="noopener" target="_blank" title=""&gt;Aron Visuals on &lt;a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral" rel="noopener" target="<em>blank" title=")</em></p>
<h3 id="heading-time-complexity-and-space-complexity-calculations">Time complexity and space complexity calculations</h3>
<h4 id="heading-time-complexityhttpswwwtechopediacomdefinition22573time-complexity"><a target="_blank" href="https://www.techopedia.com/definition/22573/time-complexity">Time complexity</a></h4>
<p>When we run code or an application in our machine it takes time — CPU cycles. But it’s not the same for every computer. For example, the processing time for a core i7 and a dual core are not the same. To solve this problem there is a concept used in computer science called <strong>time complexity</strong>.</p>
<blockquote>
<p>Time complexity is a concept in computer science that deals with the quantification of the amount of time taken by a set of code or algorithm to process or run as a function of the amount of input.  </p>
<p>In other words, time complexity is essentially efficiency, or how long a program function takes to process a given input. — <a target="_blank" href="https://www.techopedia.com/definition/22573/time-complexity">techopedia</a></p>
</blockquote>
<p>The time complexity of algorithms is most commonly expressed using <strong>big O notation</strong>. It’s an asymptotic notation to represent the time complexity.</p>
<p>Now, the <strong>time</strong> required to move <strong>n</strong> disks is <strong>T(n).</strong> There are two recursive calls for (<strong>n-1</strong>). There is one constant time operation to move a disk from source to the destination, let this be <strong>m1</strong>. Therefore:</p>
<pre><code>T(n) = <span class="hljs-number">2</span>T(n<span class="hljs-number">-1</span>) + m1    ..... eq(<span class="hljs-number">1</span>)
</code></pre><p>And</p>
<pre><code>T(<span class="hljs-number">0</span>) = m2, a constant   ...... eq(<span class="hljs-number">2</span>)
From eq (<span class="hljs-number">1</span>)
T(<span class="hljs-number">1</span>) = <span class="hljs-number">2</span>T(<span class="hljs-number">1</span><span class="hljs-number">-1</span>) + m1
     = <span class="hljs-number">2</span>T(<span class="hljs-number">0</span>)+m1
     = <span class="hljs-number">2</span>m2 + m1 ..... eq(<span class="hljs-number">3</span>) [From eq <span class="hljs-number">2</span>]
T(<span class="hljs-number">2</span>) = <span class="hljs-number">2</span>T(<span class="hljs-number">2</span><span class="hljs-number">-1</span>) + m1
     = <span class="hljs-number">2</span>T(<span class="hljs-number">1</span>) + m1
     = <span class="hljs-number">4</span>m2 + <span class="hljs-number">2</span>m1 + m1 .... eq(<span class="hljs-number">4</span>) [From eq(<span class="hljs-number">3</span>)]
T(<span class="hljs-number">3</span>) = <span class="hljs-number">2</span>T(<span class="hljs-number">3</span><span class="hljs-number">-1</span>) + m1
     = <span class="hljs-number">2</span>T(<span class="hljs-number">2</span>) + m1
     = <span class="hljs-number">8</span>m2 + <span class="hljs-number">4</span>m1 + <span class="hljs-number">2</span>m1 + m1  [From eq(<span class="hljs-number">4</span>)]
</code></pre><p>From these patterns — eq(2) to the last one — we can say that the time complexity of this algorithm is <strong>O(2^n)</strong> or <strong>O(a^n)</strong> where <strong>a</strong> is a constant greater than 1. So it has exponential time complexity. For the single increase in problem size, the time required is double the previous one. This is computationally very expensive. Most of the recursive programs take exponential time, and that is why it is very hard to write them iteratively.</p>
<h4 id="heading-space-complexityhttpswwwcsnorthwesterneduacademicscourses311htmlspace-complexityhtml"><a target="_blank" href="https://www.cs.northwestern.edu/academics/courses/311/html/space-complexity.html">Space complexity</a></h4>
<p>After the explanation of time complexity analysis, I think you can guess now what this is…This is the calculation of space required in ram for running a code or application.</p>
<p>In our case, the space for the parameter for each call is independent of <strong>n</strong>, meaning it is constant. Let it be <strong>J</strong>. When we do the second recursive call, the first one is over. That means that we can reuse the space after finishing the first one. Hence:</p>
<pre><code>T(n) = T(n<span class="hljs-number">-1</span>) + k .... eq(<span class="hljs-number">1</span>)
T(<span class="hljs-number">0</span>) = k, [constant] .... eq(<span class="hljs-number">2</span>)
T(<span class="hljs-number">1</span>) = T(<span class="hljs-number">1</span><span class="hljs-number">-1</span>) + k
     = T(<span class="hljs-number">0</span>) + k
     = <span class="hljs-number">2</span>K
T(<span class="hljs-number">2</span>) = <span class="hljs-number">3</span>k
T(<span class="hljs-number">3</span>) = <span class="hljs-number">4</span>k
</code></pre><p>So the space complexity is <strong>O(n)</strong>.</p>
<p>After these analyses, we can see that time complexity of this algorithm is exponential but space complexity is linear.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>From this article, I hope you can now understand the <strong>Tower of Hanoi</strong> puzzle and how to solve it. Also, I tried to give you some basic understanding about <strong>algorithms, their importance, recursion, pseudocode, time complexity,</strong> and <strong>space complexity.</strong> If you want to learn these topics in detail, here are some well-known online courses links:</p>
<ol>
<li><a target="_blank" href="https://www.coursera.org/course/algs4partI">Algorithms, Part I</a></li>
<li><a target="_blank" href="https://www.coursera.org/course/algs4partII">Algorithms, Part II</a></li>
<li><a target="_blank" href="https://www.udacity.com/course/data-structures-and-algorithms-in-python--ud513">The Google course on Udacity</a></li>
<li><a target="_blank" href="https://learn.freecodecamp.org/">Javascript Algorithms And Data Structures Certification (300 hours)</a></li>
</ol>
<p>You can visit my <a target="_blank" href="https://github.com/dipto0321/datastructures-and-algorithm">data structures and algorithms repo</a> to see my other problems solutions.</p>
<p>I am on <a target="_blank" href="https://github.com/dipto0321/">GitHub</a> | <a target="_blank" href="https://twitter.com/Diptokmk47">Twitter</a> | <a target="_blank" href="https://www.linkedin.com/in/diptokarmakar47/">LinkedIn</a></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
