<?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[ Adalbert Pungu - 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[ Adalbert Pungu - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Fri, 15 May 2026 22:29:29 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/AdalbertPungu/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Use TypeSpec for Documenting and Modeling APIs ]]>
                </title>
                <description>
                    <![CDATA[ If you're curious and passionate about technology like I am, and you’re looking for clarity in your code, you've likely already experienced the limitations of conventional tools for documenting and modeling APIs. Tools such as Swagger, JSON Schema, o... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/use-typespec-for-documenting-and-modeling-apis/</link>
                <guid isPermaLink="false">67f96c998b09f2bdfa144c8b</guid>
                
                    <category>
                        <![CDATA[ TypeSpec ]]>
                    </category>
                
                    <category>
                        <![CDATA[ openai ]]>
                    </category>
                
                    <category>
                        <![CDATA[ APIs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Adalbert Pungu ]]>
                </dc:creator>
                <pubDate>Fri, 11 Apr 2025 19:25:13 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1744399481891/de5db16a-2eea-46d8-820d-50c1e66d5019.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you're curious and passionate about technology like I am, and you’re looking for clarity in your code, you've likely already experienced the limitations of conventional tools for documenting and modeling APIs.</p>
<p>Tools such as Swagger, JSON Schema, or OpenAPI are powerful, but they can be verbose, inflexible, or not conducive to reuse.</p>
<p>Well, I recently discovered TypeSpec. In this guide, I’ll show you how to take advantage of TypeSpec to create modern, maintainable, and well-documented REST APIs.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744242129685/403f9a32-8d06-47e2-b551-2ec1de1f6c0a.png" alt="Screenshot of the TypeSpec website. It features a dark background with &quot;Design APIs&quot; in large text and a description about designing data to generate schemas, specifications, code, and more. It includes &quot;Install&quot; and &quot;Playground&quot; buttons at the top." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>We'll take a look at:</p>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-typespec">What is TypeSpec?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-use-typespec">Why use TypeSpec?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-install-and-configure-typespec">How to Install and Configure TypeSpec</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-typespec-basic-syntax">TypeSpec Basic Syntax</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-a-rest-api-model">How to Create a REST API Model</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-the-api-in-express-and-aspnet-core">How to Build the API in Express and</a> <a target="_blank" href="http://ASP.NET">ASP.NET</a> <a class="post-section-overview" href="#heading-how-to-build-the-api-in-express-and-aspnet-core">Core</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-best-practices-for-structuring-typespec-projects-and-components">Best Practices for Structuring TypeSpec Projects and Components</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>Before we dive into using TypeSpec to document and model APIs, here are a few things you'll need to familiarize yourself with and/or have:</p>
<ul>
<li><p><strong>Node.js</strong> (version 18 or higher)</p>
</li>
<li><p><strong>npm</strong> for dependency management</p>
</li>
<li><p><strong>Visual Studio Code</strong> (recommended to take advantage of the official TypeSpec extension). For an optimal experience, to create your project easily, it provides syntax highlighting, validation, autocompletion, navigation, and more.</p>
</li>
<li><p><strong>TypeSpec Extension</strong> in VS Code (You can install the extension via <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=typespec.typespec-vscode">Visual Studio Marketplace</a>)</p>
</li>
<li><p>An understanding of how to use and create APIs</p>
</li>
</ul>
<h2 id="heading-what-is-typespec">What is TypeSpec?</h2>
<p>TypeSpec is an open-source declarative language, developed by Microsoft, designed to describe APIs in an explicit, reusable, scalable, and standards-based way. It’s designed to model REST, gRPC, GraphQL, and other types of APIs, and offers a modern syntax close to TypeScript.</p>
<p>It can automatically generate:</p>
<ul>
<li><p>OpenAPI, JSON Schema, or Protobuf specifications</p>
</li>
<li><p>server and client code</p>
</li>
<li><p>API documentation</p>
</li>
<li><p>and other interface-related artifacts</p>
</li>
</ul>
<p>TypeSpec isn't just a language – it's an API design platform that favors abstraction, encourages code reuse, and integrates with modern tools like Visual Studio Code via a dedicated extension. You can install the extension via the VS Code <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=typespec.typespec-vscode">Visual Studio Marketplace</a>.</p>
<h2 id="heading-why-use-typespec">Why use TypeSpec?</h2>
<p>Before diving into the code, let's take a minute to understand the TypeSpec philosophy. Microsoft uses TypeSpec internally to deliver high-quality API services to millions of customers, across tens of thousands of endpoints, while ensuring code quality, governance, and scalability.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744242196525/a1947dfb-e46d-4083-95c5-218615ab75e6.png" alt="Screenshot with the text on a dark background reads: &quot;Why TypeSpec - API-First for developers. With TypeSpec, remove the handwritten files that slow you down, and generate standards-compliant API schemas in seconds.&quot;" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Unlike generators such as Swagger, Codegen, or Postman, which start from an OpenAPI file to generate code, TypeSpec does the opposite: you first write your API design in a DSL (Domain Specific Language), then generate everything you need.</p>
<p>TypeSpec has been designed to meet the major challenges of large-scale API design and governance:</p>
<ul>
<li><p><strong>Simplification</strong>: clear, concise syntax to focus on business logic.</p>
</li>
<li><p><strong>Reusability</strong>: encapsulates types, request/response models, and directives in modular components.</p>
</li>
<li><p><strong>Productivity</strong>: automatically generates the necessary resources from a single source definition.</p>
</li>
<li><p><strong>Consistency</strong>: maintains compliance with internal standards thanks to shared libraries.</p>
</li>
<li><p><strong>Interoperability</strong>: integrates with the OpenAPI ecosystem and supports multi-format generation.</p>
</li>
<li><p><strong>Scalability</strong>: designed to handle thousands of endpoints like those used by Microsoft Azure.</p>
</li>
</ul>
<p>Let's take a look at how to install and configure the development environment</p>
<h2 id="heading-how-to-install-and-configure-typespec">How to Install and Configure TypeSpec</h2>
<p>Before you can start writing your first API with TypeSpec, you need to set up your development environment. Here's how to install TypeSpec on your machine.</p>
<h4 id="heading-requirements">Requirements:</h4>
<ul>
<li><p><strong>Node.js</strong> (version 18 or higher)</p>
</li>
<li><p><strong>npm</strong> for dependency management</p>
</li>
<li><p><strong>Visual Studio Code</strong> (recommended to take advantage of the official TypeSpec extension). For an optimal experience, it provides syntax highlighting, validation, autocompletion, navigation, and more.</p>
</li>
</ul>
<p>TypeSpec CLI global installation:</p>
<pre><code class="lang-bash">npm install -g @typespec/compiler
</code></pre>
<h3 id="heading-how-to-create-a-typespec-project">How to Create a TypeSpec Project</h3>
<p>The easiest way to create a project is to use Visual Studio Code via the TypeSpec extension you've installed (if you're not comfortable with the command line (CMD)).</p>
<p>Create a folder containing the project and open it with Visual Studio Code. Then click on the <code>View</code> tab, and next on <code>Comment Palette</code> .</p>
<p>In the search bar that appears, enter <code>TypeSpec: Create TypeSpec Project</code>.</p>
<p>Follow the quick selections to select the root folder of the project you've just created. Then choose the Template – for our case this will be <code>Generic REST API</code> – and enter the project name. Leave the emitter <code>OpenAPI 3.1 document</code> (3.1 is the current version at the time of writing) selected by default. This will put us <code>@typespec/http@typespec/openapi3</code>. Finally, wait for the project configuration to finish.</p>
<p>You should have a basic TypeSpec project configuration with a structure that looks like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744242632713/69485276-b885-450c-870a-56af5e6d8122.png" alt="A screenshot of a file explorer showing a folder named &quot;node_modules&quot; and files: .gitignore, main.tsp, package-lock.json, package.json, and tspconfig.yaml." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<ul>
<li><p><strong>node_modules/</strong>: Directory where npm installs project dependencies.</p>
</li>
<li><p><strong>main.tsp</strong>: the entry point for your TypeSpec build. This file generally contains the main definitions of your models, services, and operations.</p>
</li>
<li><p><strong>package.json</strong>: Contains project metadata, including dependencies, scripts, and other project-related information.</p>
</li>
<li><p><strong>tspconfig.yaml</strong>: TypeSpec compiler configuration file, specifying options and parameters for the generation process.</p>
</li>
</ul>
<p>You can also run <code>tsp compile .</code> to compile the project, but it's better to run <code>tsp compile . --watch</code> to automatically compile changes during development each time you save.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744242865089/dea4c75e-80e3-454d-a1ab-af4186423271.png" alt="A command-line interface showing the successful compilation of a project using TypeSpec compiler v1.0.0-rc.0, with output to &quot;tsp-output/schema/&quot;." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Once the project has been compiled, you'll see the <code>tsp-output</code> and <code>schema</code> folders generated and a file added <code>openai.yaml</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744242771607/ad948a7c-ea56-44df-861d-7fa04cad1a6d.png" alt="File directory structure with folders &quot;node_modules&quot; and &quot;tsp-output&quot;, containing files like &quot;openapi.yaml&quot;, &quot;.gitignore&quot;, &quot;main.tsp&quot;, &quot;package-lock.json&quot;, &quot;package.json&quot;, and &quot;tsconfig.yaml&quot;." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<ul>
<li><p><strong>tsp-output/</strong>: Directory where the TypeSpec compiler generates files.</p>
</li>
<li><p><strong>openapi.yaml</strong>: OpenAPI specification file generated for your API, detailing API endpoints, templates, and operations. Output may vary depending on the target format specified in the <code>tspconfig.yaml</code> file.</p>
</li>
</ul>
<pre><code class="lang-yaml"><span class="hljs-attr">emit:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">"@typespec/openapi3"</span>
<span class="hljs-attr">options:</span>
  <span class="hljs-string">"@typespec/openapi3"</span><span class="hljs-string">:</span>
    <span class="hljs-attr">emitter-output-dir:</span> <span class="hljs-string">"{output-dir}/schema"</span>
    <span class="hljs-attr">openapi-versions:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-number">3.1</span><span class="hljs-number">.0</span>
</code></pre>
<p>Thanks to this configuration of the <code>tspconfig.yaml</code> file, one of TypeSpec's major assets is its ability to automatically generate OpenAPI specifications from clear, typed, and modular source code. This means you can write your API as you would in TypeScript (or a well-structured DSL), and get output in <code>.yaml</code> files compatible with the whole OpenAPI ecosystem: Swagger UI, Postman, Redoc, and so on.</p>
<p>In the next section, we'll look at the basic syntax of TypeSpec.</p>
<h2 id="heading-typespec-basic-syntax">TypeSpec Basic Syntax</h2>
<p>Now that you've got a clear idea of what TypeSpec is and what its benefits are in the world of API design, it's time to get to the heart of the matter: the basic syntax.</p>
<p>TypeSpec is a declarative language, inspired by TypeScript, that lets you model the resources, routes, data structures, and behaviors of an API in an explicit, readable, and modular way. Its syntax is based on simple keywords and clear file organization, making it easy to learn yet powerful.</p>
<h3 id="heading-language-basics">Language Basics</h3>
<p>Here's a very simple example of defining a model with TypeSpec:</p>
<pre><code class="lang-typescript">model Book {
  id: <span class="hljs-built_in">string</span>;
  title: <span class="hljs-built_in">string</span>;
  author: <span class="hljs-built_in">string</span>;
}
</code></pre>
<p>This block defines a <code>Book</code> resource with three typed fields. The <code>model</code> keyword is used to describe the JSON objects manipulated by the API. It is equivalent to schemas in JSON Schema or type definitions in OpenAPI.</p>
<h4 id="heading-defining-an-http-operation">Defining an HTTP operation</h4>
<p>TypeSpec lets you bind operations to models using the <code>@route</code> keyword. Here's a minimal example of an endpoint:</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@route</span>(<span class="hljs-string">"/books"</span>)
op listBooks(): Book[];
</code></pre>
<p>This syntax declares a REST operation that returns a list of books. <code>@route</code> indicates the URL path, <code>op</code> introduces an operation, and <code>Book[]</code> is the return type.</p>
<p>You can also define path, query, or body parameters very easily.</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@route</span>(<span class="hljs-string">"/books/{id}"</span>)
op getBook(<span class="hljs-meta">@path</span> id: <span class="hljs-built_in">string</span>): Book;
</code></pre>
<p>In this example, we declare that <code>id</code> is a URL parameter (path parameter).</p>
<h3 id="heading-fundamental-concepts"><strong>Fundamental Concepts</strong></h3>
<h4 id="heading-model-defining-data-structures"><code>model</code> Defining data structures</h4>
<p>A <code>model</code> represents an API entity, like a JSON object. Models are the basis of your information exchanges.</p>
<pre><code class="lang-typescript">model User {
  id: <span class="hljs-built_in">string</span>;
  email: <span class="hljs-built_in">string</span>;
  age?: int32;
}
</code></pre>
<h4 id="heading-interface-group-operations"><code>interface</code> <strong>Group operations</strong></h4>
<p>An <code>interface</code> groups together a set of logically linked operations. This is useful for structuring large API sets.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">interface</span> BookOperations {
  <span class="hljs-meta">@get</span> op listBooks(): Book[];
  <span class="hljs-meta">@get</span> op getBook(<span class="hljs-meta">@path</span> id: <span class="hljs-built_in">string</span>): Book;
}
</code></pre>
<h4 id="heading-service-entry-point-of-the-api"><code>service</code> <strong>Entry point of the API</strong></h4>
<p>A <code>service</code> defines publicly exposed interfaces, their version, and the basic path.</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@service</span>({ title: <span class="hljs-string">"Book API"</span>, version: <span class="hljs-string">"1.0.0"</span> })
<span class="hljs-keyword">namespace</span> BookApi {
  <span class="hljs-keyword">interface</span> BookOperations;
}
</code></pre>
<h3 id="heading-import-and-organize-your-code-with-namespaces"><strong>Import and Organize Your Code with Namespaces</strong></h3>
<p>TypeSpec provides clear organization through namespaces, similar to modules or packages.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">namespace</span> CommonModels {
  model <span class="hljs-built_in">Error</span> {
    message: <span class="hljs-built_in">string</span>;
  }
}
</code></pre>
<p>Then you can import them into another file like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> CommonModels <span class="hljs-keyword">from</span> <span class="hljs-string">"./common.tsp"</span>;
</code></pre>
<h3 id="heading-complete-example-of-a-rest-service"><strong>Complete Example of a REST Service</strong></h3>
<p>Let's take a complete example of a REST service in TypeSpec.</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@service</span>({ title: <span class="hljs-string">"Book Service"</span>, version: <span class="hljs-string">"1.0.0"</span> })

<span class="hljs-meta">@route</span>(<span class="hljs-string">"/books"</span>)

<span class="hljs-keyword">namespace</span> BookService {

  model Book {
    id: <span class="hljs-built_in">string</span>;
    title: <span class="hljs-built_in">string</span>;
    author: <span class="hljs-built_in">string</span>;
    publishedYear?: int32;
  }

  <span class="hljs-meta">@get</span>()
  op listBooks(): Book[];

  <span class="hljs-meta">@post</span>()
  op createBook(<span class="hljs-meta">@body</span> book: Book): Book;

  <span class="hljs-meta">@get</span>(<span class="hljs-string">"/{id}"</span>)
  op getBook(<span class="hljs-meta">@path</span> id: <span class="hljs-built_in">string</span>): Book;

  <span class="hljs-meta">@put</span>(<span class="hljs-string">"/{id}"</span>)
  op updateBook(<span class="hljs-meta">@path</span> id: <span class="hljs-built_in">string</span>, <span class="hljs-meta">@body</span> book: Book): Book;

  <span class="hljs-meta">@delete</span>(<span class="hljs-string">"/{id}"</span>)
  op deleteBook(<span class="hljs-meta">@path</span> id: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">void</span>;
}
</code></pre>
<p><strong>Here’s what’s going on</strong>:</p>
<ul>
<li><p><code>@service({ title, version })</code>: Defines service metadata (name, version), useful for generated documentation (for example, Swagger UI).</p>
</li>
<li><p><code>@route("/books")</code>: Defines the basic path for all operations of this API.</p>
</li>
<li><p><code>namespace BookService { ... }</code>: Encapsulates all models and operations linked to this service under a single logical name.</p>
</li>
</ul>
<p><strong>Next come the operations</strong>:</p>
<ul>
<li><p><code>@get() op listBooks()</code>: Endpoint <code>GET /books</code> qui retourne un tableau de livres.</p>
</li>
<li><p><code>@post() op createBook()</code>: Endpoint <code>POST /books</code> which accepts a <code>Book</code> object in the request body (<code>@body</code>) and returns the created book.</p>
</li>
<li><p><code>@get("/{id}")</code>: Endpoint <code>GET /books/{id}</code> which retrieves a book via its identifier (<code>@path</code>).</p>
</li>
<li><p><code>@put("/{id}")</code>: Endpoint <code>PUT /books/{id}</code> which updates a book's data.</p>
</li>
<li><p><code>@delete("/{id}")</code>: Deletes a book via its <code>id</code>. The <code>void</code> type means that no data is returned.</p>
</li>
</ul>
<p>With just a few lines, you get a complete, well-organized, easily readable REST service, ready to be automatically converted into OpenAPI documentation, a client SDK, or backend code.</p>
<h3 id="heading-add-validation-annotations"><strong>Add Validation Annotations</strong></h3>
<p>TypeSpec makes it easy to add validation annotations to your models using:</p>
<pre><code class="lang-typescript">model Book {
  id: <span class="hljs-built_in">string</span>;
  title: <span class="hljs-built_in">string</span> <span class="hljs-meta">@minLength</span>(<span class="hljs-number">3</span>);
  author: <span class="hljs-built_in">string</span> <span class="hljs-meta">@minLength</span>(<span class="hljs-number">3</span>);
  publishedYear?: int32 <span class="hljs-meta">@minValue</span>(<span class="hljs-number">1800</span>);
}
</code></pre>
<p>This adds validation rules directly to the schema, which will be taken into account during OpenAPI generation.</p>
<h3 id="heading-comparison-with-other-tools-openapi-swagger">Comparison with Other Tools (OpenAPI / Swagger)</h3>
<p>So you might wonder – why should you use TypeSpec rather than writing directly in OpenAPI?</p>
<p>Let's take the example of OpenAPI 3 (YAML):</p>
<pre><code class="lang-yaml"><span class="hljs-attr">paths:</span>
  <span class="hljs-string">/books:</span>
    <span class="hljs-attr">get:</span>
      <span class="hljs-attr">summary:</span> <span class="hljs-string">Get</span> <span class="hljs-string">list</span> <span class="hljs-string">of</span> <span class="hljs-string">books</span>
      <span class="hljs-attr">responses:</span>
        <span class="hljs-attr">'200':</span>
          <span class="hljs-attr">description:</span> <span class="hljs-string">OK</span>
          <span class="hljs-attr">content:</span>
            <span class="hljs-attr">application/json:</span>
              <span class="hljs-attr">schema:</span>
                <span class="hljs-attr">type:</span> <span class="hljs-string">array</span>
                <span class="hljs-attr">items:</span>
                  <span class="hljs-string">$ref:</span> <span class="hljs-string">'#/components/schemas/Book'</span>
    <span class="hljs-attr">post:</span>
      <span class="hljs-attr">summary:</span> <span class="hljs-string">Create</span> <span class="hljs-string">a</span> <span class="hljs-string">new</span> <span class="hljs-string">book</span>
      <span class="hljs-attr">requestBody:</span>
        <span class="hljs-attr">content:</span>
          <span class="hljs-attr">application/json:</span>
            <span class="hljs-attr">schema:</span>
              <span class="hljs-string">$ref:</span> <span class="hljs-string">'#/components/schemas/Book'</span>
      <span class="hljs-attr">responses:</span>
        <span class="hljs-attr">'201':</span>
          <span class="hljs-attr">description:</span> <span class="hljs-string">Created</span>
  <span class="hljs-string">/books/{id}:</span>
    <span class="hljs-attr">get:</span>
      <span class="hljs-attr">parameters:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">id</span>
          <span class="hljs-attr">in:</span> <span class="hljs-string">path</span>
          <span class="hljs-attr">required:</span> <span class="hljs-literal">true</span>
          <span class="hljs-attr">schema:</span>
            <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
      <span class="hljs-attr">responses:</span>
        <span class="hljs-attr">'200':</span>
          <span class="hljs-attr">description:</span> <span class="hljs-string">OK</span>
    <span class="hljs-attr">put:</span>
      <span class="hljs-attr">parameters:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">id</span>
          <span class="hljs-attr">in:</span> <span class="hljs-string">path</span>
          <span class="hljs-attr">required:</span> <span class="hljs-literal">true</span>
          <span class="hljs-attr">schema:</span>
            <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
      <span class="hljs-attr">requestBody:</span>
        <span class="hljs-attr">content:</span>
          <span class="hljs-attr">application/json:</span>
            <span class="hljs-attr">schema:</span>
              <span class="hljs-string">$ref:</span> <span class="hljs-string">'#/components/schemas/Book'</span>
    <span class="hljs-attr">delete:</span>
      <span class="hljs-attr">parameters:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">id</span>
          <span class="hljs-attr">in:</span> <span class="hljs-string">path</span>
          <span class="hljs-attr">required:</span> <span class="hljs-literal">true</span>
          <span class="hljs-attr">schema:</span>
            <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
<span class="hljs-attr">components:</span>
  <span class="hljs-attr">schemas:</span>
    <span class="hljs-attr">Book:</span>
      <span class="hljs-attr">type:</span> <span class="hljs-string">object</span>
      <span class="hljs-attr">properties:</span>
        <span class="hljs-attr">id:</span>
          <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
        <span class="hljs-attr">title:</span>
          <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
        <span class="hljs-attr">author:</span>
          <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
        <span class="hljs-attr">publishedYear:</span>
          <span class="hljs-attr">type:</span> <span class="hljs-string">integer</span>
</code></pre>
<p>As you can see, the OpenAPI definition is much more verbose. Relationships between paths, methods, schemas, and parameters are scattered, which complicates reading and maintenance. Also, it's less typed, given that OpenAPI remains YAML (or JSON), without the typing security or modularity of a real language.</p>
<h4 id="heading-why-typespec-is-useful-here">Why TypeSpec is useful here</h4>
<p>With TypeSpec, everything is centralized in a declarative, modular, typed, and intuitive format.</p>
<ul>
<li><p><strong>Greater legibility</strong>: less noise, more intent.</p>
</li>
<li><p><strong>Reusability</strong>: you can create modular components and share them between projects.</p>
</li>
<li><p><strong>Productivity</strong>: you write less code and generate more (OpenAPI, client, server, doc).</p>
</li>
<li><p><strong>Consistency</strong>: errors are detected early thanks to strong typing.</p>
</li>
</ul>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Criteria</strong></td><td><strong>OpenAPI / Swagger</strong></td><td><strong>TypeSpec</strong></td></tr>
</thead>
<tbody>
<tr>
<td></td><td></td><td></td></tr>
<tr>
<td><strong>Syntax</strong></td><td>Verbose (YAML/JSON)</td><td>Declarative, typed, concise</td></tr>
<tr>
<td><strong>Organization</strong></td><td>Fragmented</td><td>Modular (namespace, import)</td></tr>
<tr>
<td><strong>Modular</strong></td><td>Limited</td><td>High (models, services)</td></tr>
<tr>
<td><strong>Built-in validation</strong></td><td>Separate or manual</td><td>Decorators (@minLength, and so on)</td></tr>
<tr>
<td><strong>Automatic generation</strong></td><td>Manual</td><td>Integrated (OpenAPI, SDK, and so on)</td></tr>
</tbody>
</table>
</div><p>Note: TypeSpec doesn't replace OpenAPI, but complements it: you write to TypeSpec, then automatically generate OpenAPI files, SDKs, specs and so on. It gives you a source language for accurately describing your API.</p>
<p>In the next section, we'll look at how to create a REST API template.</p>
<h2 id="heading-how-to-create-a-rest-api-model">How to Create a REST API Model</h2>
<p>To deepen our understanding of REST API creation with TypeSpec, let's continue with the example of managing books. In this example, we'll create a <code>Book</code> model, define a service to manage the books, and add validations to ensure that the data respects the right constraints.</p>
<h3 id="heading-define-a-data-model-for-book">Define a Data Model for <code>Book</code></h3>
<p>First, we'll define a data model for the Book resource. A book can have the following properties:</p>
<ul>
<li><p><code>id</code>: A unique identifier for the book.</p>
</li>
<li><p><code>title</code>: The title of the book.</p>
</li>
<li><p><code>author</code>: The author of the book.</p>
</li>
<li><p><code>publicationYear</code>: The book's year of publication.</p>
</li>
<li><p><code>isbn</code>: The book's ISBN number.</p>
</li>
</ul>
<p><code>Book</code> <strong>model in TypeSpec</strong></p>
<pre><code class="lang-typescript">model Book {
  id: integer;
  <span class="hljs-meta">@minLength</span>(<span class="hljs-number">1</span>)
  title: <span class="hljs-built_in">string</span>;
  <span class="hljs-meta">@minLength</span>(<span class="hljs-number">1</span>)
  author: <span class="hljs-built_in">string</span>;
  publicationYear: integer;
  <span class="hljs-meta">@pattern</span>(<span class="hljs-string">"^\\d{3}-\\d{1,5}-\\d{1,7}-\\d{1,7}-\\d{1}$"</span>)
  isbn: <span class="hljs-built_in">string</span>;
}
</code></pre>
<ul>
<li><p><code>id</code>: Unique book identifier (<code>integer</code> type).</p>
</li>
<li><p><code>title</code> and <code>author</code>: Character strings representing the book's title and author, validated by <code>@minLength(1)</code> to ensure they are not empty.</p>
</li>
<li><p><code>publicationYear</code>: The book's year of publication (<code>integer</code> type).</p>
</li>
<li><p><code>isbn</code>: The book's ISBN number, validated with a regular expression that matches the standard format of an ISBN.</p>
</li>
</ul>
<h3 id="heading-define-a-rest-service-to-manage-books">Define a REST Service to Manage Books</h3>
<p>Now that we have a <code>Book</code> model, we'll create a service to manage CRUD operations on this resource. This service will contain methods for retrieving a book by its identifier, creating a new book, updating an existing book, and deleting a book.</p>
<p><code>BooksService</code> <strong>service in TypeSpec</strong></p>
<pre><code class="lang-typescript">service BooksService {

  <span class="hljs-meta">@get</span>(<span class="hljs-string">"/books/{id}"</span>)
  getBook(id: integer): Book;

  <span class="hljs-meta">@post</span>(<span class="hljs-string">"/books"</span>)
  createBook(book: Book): Book;

  <span class="hljs-meta">@put</span>(<span class="hljs-string">"/books/{id}"</span>)
  updateBook(id: integer, book: Book): Book;

  <span class="hljs-meta">@delete</span>(<span class="hljs-string">"/books/{id}"</span>)
  deleteBook(id: integer): <span class="hljs-built_in">void</span>;
}
</code></pre>
<p>The <code>BooksService</code> contains four methods for performing actions on books:</p>
<ul>
<li><p><code>@get("/books/{id}")</code>: Method for retrieving a book by its <code>id</code>.</p>
</li>
<li><p><code>@post("/books")</code>: Method for creating a new book.</p>
</li>
<li><p><code>@put("/books/{id}")</code>: Method for updating an existing book by its <code>id</code>.</p>
</li>
<li><p><code>@delete("/books/{id}")</code>: Method for deleting a book based on its <code>id</code>.</p>
</li>
</ul>
<p>These methods use HTTP annotations to indicate the type of operation they perform (GET, POST, PUT, DELETE).</p>
<h3 id="heading-add-additional-validations-for-the-book-model"><strong>Add Additional Validations for the</strong> <code>Book</code> <strong>Model</strong></h3>
<p>As in the previous example for users, we can add additional validations on <strong>Book</strong> template properties.</p>
<p><strong>Example of validation on</strong> <code>publicationYear</code> <strong>and</strong> <code>isbn</code></p>
<pre><code class="lang-typescript">model Book {
  id: integer;
  <span class="hljs-meta">@minLength</span>(<span class="hljs-number">1</span>)
  title: <span class="hljs-built_in">string</span>;
  <span class="hljs-meta">@minLength</span>(<span class="hljs-number">1</span>)
  author: <span class="hljs-built_in">string</span>;
  <span class="hljs-meta">@minValue</span>(<span class="hljs-number">1000</span>)
  publicationYear: integer;
  <span class="hljs-meta">@pattern</span>(<span class="hljs-string">"^\\d{3}-\\d{1,5}-\\d{1,7}-\\d{1,7}-\\d{1}$"</span>)
  isbn: <span class="hljs-built_in">string</span>;
}
</code></pre>
<ul>
<li><p><code>@minValue(1000)</code> guarantees that the year of publication is greater than or equal to 1000.</p>
</li>
<li><p>Validation of the <code>isbn</code> remains the same, using a regular expression to validate a standard ISBN format.</p>
</li>
</ul>
<h3 id="heading-a-complete-service-for-managing-books"><strong>A Complete Service for Managing Books</strong></h3>
<p>Now that we have the <code>Book</code> model and the necessary validations, here's a complete service for managing books, with all the essential operations.</p>
<p><strong>Complete</strong> <code>BooksService</code> <strong>in TypeSpec</strong></p>
<pre><code class="lang-typescript">model Book {
  id: integer;
  <span class="hljs-meta">@minLength</span>(<span class="hljs-number">1</span>)
  title: <span class="hljs-built_in">string</span>;
  <span class="hljs-meta">@minLength</span>(<span class="hljs-number">1</span>)
  author: <span class="hljs-built_in">string</span>;
  <span class="hljs-meta">@minValue</span>(<span class="hljs-number">1000</span>)
  publicationYear: integer;
  <span class="hljs-meta">@pattern</span>(<span class="hljs-string">"^\\d{3}-\\d{1,5}-\\d{1,7}-\\d{1,7}-\\d{1}$"</span>)
  isbn: <span class="hljs-built_in">string</span>;
}

service BooksService {
  <span class="hljs-meta">@get</span>(<span class="hljs-string">"/books/{id}"</span>)
  getBook(id: integer): Book;

  <span class="hljs-meta">@post</span>(<span class="hljs-string">"/books"</span>)
  createBook(book: Book): Book;

  <span class="hljs-meta">@put</span>(<span class="hljs-string">"/books/{id}"</span>)
  updateBook(id: integer, book: Book): Book;

  <span class="hljs-meta">@delete</span>(<span class="hljs-string">"/books/{id}"</span>)
  deleteBook(id: integer): <span class="hljs-built_in">void</span>;
}
</code></pre>
<ul>
<li><p>The <code>Book</code> model defines properties and validations for a book.</p>
</li>
<li><p>The <code>BooksService</code> provides endpoints for retrieving, creating, updating, and deleting a book.</p>
</li>
<li><p>Each service method is correctly annotated with the corresponding HTTP verbs (<code>GET</code>, <code>POST</code>, <code>PUT</code>, <code>DELETE</code>).</p>
</li>
</ul>
<p>And here’s a summary of everything we’ve done:</p>
<ul>
<li><p>We created a <code>Book</code> model with properties such as title, author, year of publication, and ISBN number.</p>
</li>
<li><p>We defined a <code>BooksService</code> to provide CRUD operations on books.</p>
</li>
<li><p>We added validations to ensure that the data respected specified constraints (for example, ISBN and year of publication).</p>
</li>
<li><p>We designed a complete REST API to manage books with TypeSpec, using a minimum amount of code and staying true to standards.</p>
</li>
</ul>
<p>This example shows just how quickly and efficiently TypeSpec can be used to model a REST API, while ensuring a clear structure and robust validations.</p>
<h2 id="heading-how-to-build-the-api-in-express-and-aspnet-core">How to Build the API in Express and ASP.NET Core</h2>
<p>Now that we've defined a book management REST service with TypeSpec, let's see how we'd implement this same API using two popular frameworks:</p>
<ul>
<li><p><strong>ExpressJS (Node.js / TypeScript)</strong></p>
</li>
<li><p><strong>ASP.NET Core (C#)</strong></p>
</li>
</ul>
<p>This will allow us to better compare TypeSpec's conciseness and readability with traditional implementations.</p>
<p><strong>Manual implementation with ExpressJS (Node.js / TypeScript):</strong></p>
<pre><code class="lang-typescript"><span class="hljs-comment">//server.ts</span>
<span class="hljs-keyword">import</span> express <span class="hljs-keyword">from</span> <span class="hljs-string">'express'</span>;

<span class="hljs-keyword">const</span> app = express();
app.use(express.json());

<span class="hljs-keyword">interface</span> Book {
  id: <span class="hljs-built_in">number</span>;
  title: <span class="hljs-built_in">string</span>;
  author: <span class="hljs-built_in">string</span>;
  publicationYear: <span class="hljs-built_in">number</span>;
  isbn: <span class="hljs-built_in">string</span>;
}

<span class="hljs-keyword">const</span> books: Book[] = [];

<span class="hljs-comment">// GET /books/:id</span>
app.get(<span class="hljs-string">'/books/:id'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> id = <span class="hljs-built_in">parseInt</span>(req.params.id);
  <span class="hljs-keyword">const</span> book = books.find(<span class="hljs-function"><span class="hljs-params">b</span> =&gt;</span> b.id === id);
  <span class="hljs-keyword">if</span> (!book) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">404</span>).send({ message: <span class="hljs-string">'Book not found'</span> });
  res.send(book);
});

<span class="hljs-comment">// POST /books</span>
app.post(<span class="hljs-string">'/books'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> newBook: Book = req.body;
  books.push(newBook);
  res.status(<span class="hljs-number">201</span>).send(newBook);
});

<span class="hljs-comment">// PUT /books/:id</span>
app.put(<span class="hljs-string">'/books/:id'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> id = <span class="hljs-built_in">parseInt</span>(req.params.id);
  <span class="hljs-keyword">const</span> index = books.findIndex(<span class="hljs-function"><span class="hljs-params">b</span> =&gt;</span> b.id === id);
  <span class="hljs-keyword">if</span> (index === <span class="hljs-number">-1</span>) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">404</span>).send({ message: <span class="hljs-string">'Book not found'</span> });

  books[index] = req.body;
  res.send(books[index]);
});

<span class="hljs-comment">// DELETE /books/:id</span>
app.delete(<span class="hljs-string">'/books/:id'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> id = <span class="hljs-built_in">parseInt</span>(req.params.id);
  <span class="hljs-keyword">const</span> index = books.findIndex(<span class="hljs-function"><span class="hljs-params">b</span> =&gt;</span> b.id === id);
  <span class="hljs-keyword">if</span> (index === <span class="hljs-number">-1</span>) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">404</span>).send({ message: <span class="hljs-string">'Book not found'</span> });

  books.splice(index, <span class="hljs-number">1</span>);
  res.status(<span class="hljs-number">204</span>).send();
});

app.listen(<span class="hljs-number">3000</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Server is running on port 3000'</span>);
});
</code></pre>
<p><strong>Observations:</strong></p>
<ul>
<li><p>A lot of repetitive logic.</p>
</li>
<li><p>No automatic validation.</p>
</li>
<li><p>Routes must be maintained manually.</p>
</li>
<li><p>No automatically generated API documentation.</p>
</li>
</ul>
<p><strong>Manual implementation with</strong> <a target="_blank" href="http://ASP.NET"><strong>ASP.NET</strong></a> <strong>Core (C#):</strong></p>
<pre><code class="lang-csharp"><span class="hljs-comment">// Book.cs</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Book</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> Id { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    [<span class="hljs-meta">Required</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Title { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; } = <span class="hljs-keyword">string</span>.Empty;

    [<span class="hljs-meta">Required</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Author { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; } = <span class="hljs-keyword">string</span>.Empty;

    [<span class="hljs-meta">Range(1000, int.MaxValue)</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> PublicationYear { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    [<span class="hljs-meta">RegularExpression(@<span class="hljs-meta-string">"^\d{3}-\d{1,5}-\d{1,7}-\d{1,7}-\d{1}$"</span>)</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Isbn { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; } = <span class="hljs-keyword">string</span>.Empty;
}
</code></pre>
<pre><code class="lang-csharp"><span class="hljs-comment">// BooksController.cs</span>
[<span class="hljs-meta">ApiController</span>]
[<span class="hljs-meta">Route(<span class="hljs-meta-string">"books"</span>)</span>]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">BooksController</span> : <span class="hljs-title">ControllerBase</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> List&lt;Book&gt; books = <span class="hljs-keyword">new</span>();

    [<span class="hljs-meta">HttpGet(<span class="hljs-meta-string">"{id}"</span>)</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> IActionResult <span class="hljs-title">GetBook</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> id</span>)</span>
    {
        <span class="hljs-keyword">var</span> book = books.FirstOrDefault(b =&gt; b.Id == id);
        <span class="hljs-keyword">if</span> (book == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> NotFound(<span class="hljs-string">"Book not found"</span>);
        <span class="hljs-keyword">return</span> Ok(book);
    }

    [<span class="hljs-meta">HttpPost</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> IActionResult <span class="hljs-title">CreateBook</span>(<span class="hljs-params">[FromBody] Book book</span>)</span>
    {
        books.Add(book);
        <span class="hljs-keyword">return</span> CreatedAtAction(<span class="hljs-keyword">nameof</span>(GetBook), <span class="hljs-keyword">new</span> { id = book.Id }, book);
    }

    [<span class="hljs-meta">HttpPut(<span class="hljs-meta-string">"{id}"</span>)</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> IActionResult <span class="hljs-title">UpdateBook</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> id, [FromBody] Book updatedBook</span>)</span>
    {
        <span class="hljs-keyword">var</span> index = books.FindIndex(b =&gt; b.Id == id);
        <span class="hljs-keyword">if</span> (index == <span class="hljs-number">-1</span>) <span class="hljs-keyword">return</span> NotFound(<span class="hljs-string">"Book not found"</span>);

        books[index] = updatedBook;
        <span class="hljs-keyword">return</span> Ok(updatedBook);
    }

    [<span class="hljs-meta">HttpDelete(<span class="hljs-meta-string">"{id}"</span>)</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> IActionResult <span class="hljs-title">DeleteBook</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> id</span>)</span>
    {
        <span class="hljs-keyword">var</span> book = books.FirstOrDefault(b =&gt; b.Id == id);
        <span class="hljs-keyword">if</span> (book == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> NotFound(<span class="hljs-string">"Book not found"</span>);

        books.Remove(book);
        <span class="hljs-keyword">return</span> NoContent();
    }
}
</code></pre>
<p><strong>Observations:</strong></p>
<ul>
<li><p>More formal and structured than Express, thanks to C# annotations (<code>[HttpPost]</code>, <code>[Required]</code>, and so on).</p>
</li>
<li><p>Validation is handled automatically via Data Annotations.</p>
</li>
<li><p>Once again, no automatic OpenAPI generation or SDK client without additional configuration.</p>
</li>
</ul>
<p><strong>Comparison with TypeSpec:</strong></p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Aspect</strong></td><td><strong>TypeSpec</strong></td><td><strong>ExpressJS</strong></td><td><a target="_blank" href="http://ASP.NET"><strong>ASP.NET</strong></a> <strong>Core</strong></td></tr>
</thead>
<tbody>
<tr>
<td></td><td></td><td></td><td></td></tr>
<tr>
<td><strong>Syntax</strong></td><td>Declarative</td><td>Imperative</td><td>Structured</td></tr>
<tr>
<td><strong>Validation</strong></td><td>Automatic</td><td>Manual</td><td>Data Annotations</td></tr>
<tr>
<td><strong>Documentation</strong></td><td>Automatic</td><td>Manual</td><td>Generated(Swashbuckle)</td></tr>
<tr>
<td><strong>Reusability</strong></td><td>High</td><td>Low</td><td>Medium</td></tr>
<tr>
<td><strong>Generation</strong></td><td>OpenAPI/SDK</td><td>Non-native</td><td>Possible</td></tr>
</tbody>
</table>
</div><h2 id="heading-best-practices-for-structuring-typespec-projects-and-components">Best Practices for Structuring TypeSpec Projects and Components</h2>
<p>When you start writing API definitions in TypeSpec, it's easy to put everything in a single file. But as with any software project, as the application grows, a good structure becomes essential to guarantee the readability, reusability and maintainability of the code.</p>
<p>Here's a set of best practices I strongly recommend:</p>
<h3 id="heading-organize-by-functional-area"><strong>Organize by Functional Area</strong></h3>
<p>Use namespaces to group models, interfaces, and operations by business domain: <strong>book</strong>, <strong>user</strong>, <strong>auth</strong>, <strong>payment</strong>, and so on.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">namespace</span> MyApi.Books;
</code></pre>
<p>Create a <code>/books</code> folder with the following files:</p>
<pre><code class="lang-yaml"><span class="hljs-string">src/</span>
<span class="hljs-string">├──</span> <span class="hljs-string">books/</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">models.tsp</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">routes.tsp</span>
<span class="hljs-string">│</span>   <span class="hljs-string">└──</span> <span class="hljs-string">service.tsp</span>
</code></pre>
<p>This ensures a clear separation of responsibilities, just like in a well-structured Node.js project.</p>
<h3 id="heading-a-single-maintsp-entry-point"><strong>A Single</strong> <code>main.tsp</code> <strong>Entry Point</strong></h3>
<p>This is the main file that orchestrates:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// main.tsp</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"./books/service.tsp"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./users/service.tsp"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./auth/service.tsp"</span>;
</code></pre>
<p>This allows you to compile the entire project from a single point.</p>
<h3 id="heading-create-reusable-components">Create Reusable Components</h3>
<p>Define common models and types in a shared file. Example:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// common/models.tsp</span>
model ErrorResponse {
  code: <span class="hljs-built_in">string</span>;
  message: <span class="hljs-built_in">string</span>;
}

<span class="hljs-meta">@defaultResponse</span>
op <span class="hljs-built_in">Error</span>(): ErrorResponse;
</code></pre>
<p>Then import them into your other files:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> <span class="hljs-string">"../common/models.tsp"</span>;
</code></pre>
<p>This is handy for centralizing errors, standard answers, pagination types, and so on.</p>
<h3 id="heading-use-decorators-to-enrich-your-components">Use Decorators to Enrich Your Components</h3>
<p>Decorators such as <code>@doc</code>, <code>@minLength</code>, <code>@server</code>, <code>@route</code> or <code>@tag</code> can be used to generate valid, documented APIs without any extra effort:</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@route</span>(<span class="hljs-string">"/books"</span>)
<span class="hljs-meta">@doc</span>(<span class="hljs-string">"Get all books"</span>)
op listBooks(): Book[];
</code></pre>
<p>A well-annotated API is one that is ready for automatic generation of documentation or clients.</p>
<h3 id="heading-define-servers-in-the-right-place">Define Servers in the Right Place</h3>
<p>Add your @server directive to a <code>service.tsp</code> or global <code>api.tsp</code> file:</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@server</span>(<span class="hljs-string">"Production"</span>, <span class="hljs-string">"https://api.mysite.com"</span>)
<span class="hljs-meta">@server</span>(<span class="hljs-string">"Staging"</span>, <span class="hljs-string">"https://staging.mysite.com"</span>)
</code></pre>
<p>This allows you to target different environments without duplicating definitions.</p>
<h3 id="heading-validate-regularly">Validate Regularly</h3>
<p>Integrate <code>tsp compile</code> into your CI/CD to ensure that your definitions are always valid. Example with an npm script:</p>
<pre><code class="lang-bash">npm run tsp compile src/main.tsp --emit=./dist
</code></pre>
<p>This avoids last-minute errors and guarantees the consistency of your API over time.</p>
<p><strong>Example of a recommended complete structure:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-string">project-root/</span>
<span class="hljs-string">├──</span> <span class="hljs-string">src/</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">books/</span>
<span class="hljs-string">│</span>   <span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">models.tsp</span>
<span class="hljs-string">│</span>   <span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">routes.tsp</span>
<span class="hljs-string">│</span>   <span class="hljs-string">│</span>   <span class="hljs-string">└──</span> <span class="hljs-string">service.tsp</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">users/</span>
<span class="hljs-string">│</span>   <span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">models.tsp</span>
<span class="hljs-string">│</span>   <span class="hljs-string">│</span>   <span class="hljs-string">└──</span> <span class="hljs-string">service.tsp</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">common/</span>
<span class="hljs-string">│</span>   <span class="hljs-string">│</span>   <span class="hljs-string">└──</span> <span class="hljs-string">models.tsp</span>
<span class="hljs-string">│</span>   <span class="hljs-string">└──</span> <span class="hljs-string">main.tsp</span>
<span class="hljs-string">├──</span> <span class="hljs-string">tspconfig.yaml</span>
<span class="hljs-string">├──</span> <span class="hljs-string">package.json</span>
<span class="hljs-string">└──</span> <span class="hljs-string">README.md</span>
</code></pre>
<p>In summary:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Good practice</strong></td><td><strong>Why it's important</strong></td></tr>
</thead>
<tbody>
<tr>
<td></td><td></td></tr>
<tr>
<td>Use <code>namespaces</code></td><td>Clear organization, readability</td></tr>
<tr>
<td>Dividing files by domain</td><td>Reusability, modularity</td></tr>
<tr>
<td>Centralize shared components</td><td>DRY (Don't Repeat Yourself)</td></tr>
<tr>
<td>Use decorators</td><td>Enrich documentation and validation</td></tr>
<tr>
<td>Integrate with CI/CD</td><td>Continuous quality, no surprises</td></tr>
<tr>
<td>Have a clear input file (<code>main.tsp</code>)</td><td>Simple, centralized compilation</td></tr>
</tbody>
</table>
</div><h2 id="heading-conclusion">Conclusion</h2>
<p>TypeSpec represents a real evolution in the way we design, document and maintain APIs. By adopting a declarative, modular, and typed approach, it simplifies the definition of APIs while enhancing their quality, readability, and consistency on a large scale.</p>
<p>Whether you're a front-end developer consuming APIs, a software architect looking to standardize your team's practices, or a technical documentation enthusiast, TypeSpec offers you a robust, modern, and extensible solution.</p>
<p>The TypeSpec ecosystem is still young but very promising, supported by Microsoft and used internally on a large scale. So now's the time to start exploring and adopting it for your projects.</p>
<h4 id="heading-ressources">Ressources</h4>
<ol>
<li><p><strong>TypeSpec official website</strong><br> <a target="_blank" href="https://typespec.io/">https://typespec.io</a><br> Full documentation, guides, syntax references and APIs.</p>
</li>
<li><p><strong>TypeSpec GitHub repository (Microsoft)</strong><br> <a target="_blank" href="https://github.com/microsoft/typespec/">https://github.com/microsoft/typespec</a><br> Source code, examples and community discussions.</p>
</li>
<li><p><strong>Playground TypeSpec (essayer dans le navigateur)</strong><br> <a target="_blank" href="https://typespec.io/playground/">https://typespec.io/playground</a><br> Quickly test your models without installing anything.</p>
</li>
<li><p><strong>TypeSpec documentation — Microsoft Learn</strong><br> <a target="_blank" href="https://learn.microsoft.com/en-us/azure/developer/typespec/overview/">https://learn.microsoft.com/en-us/azure/developer/typespec/overview</a><br> Learn how to use TypeSpec to create consistent, high-quality APIs efficiently and integrate them seamlessly with existing toolchains.</p>
</li>
<li><p><strong>OpenAPI Specification</strong><br> <a target="_blank" href="https://swagger.io/specification/">https://swagger.io/specification</a><br> To compare with current API description standards.</p>
</li>
<li><p><strong>TypeSpec 101 by Mario Guerra Product Manager for TypeSpec at Microsoft</strong><br> <a target="_blank" href="https://www.youtube.com/playlist?list=PLYWCCsom5Txglkl_I1XvwzrzM5G3SuVsR/">https://www.youtube.com/playlist?list=PLYWCCsom5Txglkl_I1XvwzrzM5G3SuVsR</a><br> A tutorial series, hosted by Mario Guerra, TypeSpec product manager at Microsoft, will guide you through the process of building a REST API using TypeSpec, and generating an OpenAPI specification from our code.</p>
</li>
<li><p><strong>APIs at Scale with TypeSpec</strong><br> <a target="_blank" href="https://youtu.be/yfCYrKaojDo/">https://youtu.be/yfCYrKaojDo</a><br> A talk given by Mandy Whaley from Microsoft at the 2024 Austin API Summit in Austin, Texas.</p>
</li>
</ol>
<p>Thanks for reading. You can find me on <a target="_blank" href="https://www.linkedin.com/in/AdalbertPungu/">LinkedIn</a>, and follow me on all socials @AdalbertPungu.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How TypeScript Can Improve Your Web Development Projects ]]>
                </title>
                <description>
                    <![CDATA[ Hi, everyone! In this article I'm going to talk about how TypeScript can help enhance and improve your web development projects. If you're not familiar with TypeScript, you can read through this comprehensive beginner's guide to get started. If you d... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-typescript-can-improve-web-development-projects/</link>
                <guid isPermaLink="false">66d84c8eda89a73e2ddf574d</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Adalbert Pungu ]]>
                </dc:creator>
                <pubDate>Fri, 25 Aug 2023 16:30:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/08/pexels-ian-beckley-2440024.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Hi, everyone! In this article I'm going to talk about how TypeScript can help enhance and improve your web development projects.</p>
<p>If you're not familiar with TypeScript, you can <a target="_blank" href="https://www.freecodecamp.org/news/learn-typescript-beginners-guide/">read through this comprehensive beginner's guide</a> to get started. If you do know some TS, that's great – I'll discuss why it's recommended in most projects that use JavaScript.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/ts-lettermark-blue.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>TypeScript Logo</em></p>
<h2 id="heading-what-is-typescript">What is TypeScript?</h2>
<p>TypeScript is a superset of JavaScript. This means you can use all the useful JavaScript features you already know and love, along with some others that TypeScript adds that didn't exist before.</p>
<p>In other words, TypeScript offers all the JavaScript functionality plus an extra layer, which is the TypeScript type system.</p>
<p>TypeScript addresses many of JavaScript's limitations that other languages have tackled to help produce complex applications.</p>
<p>With TypeScript, you can run your code anywhere and on any platform, browser or hosted. This is because these tools are multi-platform, which means you can develop TypeScript applications using Windows, Mac, or Linux.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/windows-4nSKsoYyuPQ-unsplash.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Windows - unsplash</em></p>
<p>Microsoft developed TypeScript to meet the challenges of modern web development. It provides static type checking along with many productivity-enhancing features. It also aligns with the rapid evolution of ECMAScript.</p>
<p>Some of TypeScript's most useful features are its types, annotations, interfaces, classes, encapsulation of your logic, and data with access modifiers. You can also take advantage of productivity enhancements such as variable and property renaming. All this helps you more easily find errors in your code before executing it.</p>
<h2 id="heading-what-makes-typescript-so-successful">What Makes TypeScript So Successful?</h2>
<p>TypeScript fills a gap in the world of web development, offering a versatile, high-performance solution to help you build scalable, high-quality web applications.</p>
<p>TypeScript was first announced in October 2012. Since then it has grown rapidly and steadily, becoming a popular solution for web development and application development in general.</p>
<p>TS adds a variety of useful tools and syntax to an already mature language, bringing the power and productivity of open source object-oriented development to a fully compatible core of JavaScript.</p>
<p>Here are some of the advantages that have made TypeScript so successful and a better choice for web development:</p>
<ul>
<li><p>TypeScript is a superset of JavaScript, meaning that all existing JavaScript code is valid in TypeScript. Developers can gradually migrate their JavaScript code to TypeScript without disrupting their workflow.</p>
</li>
<li><p>TypeScript offers static type checking, which means that developers can detect typing errors early in the development phase. This significantly reduces type-related bugs and improves code stability and reliability.</p>
</li>
<li><p>Thanks to its static typing system, TypeScript provides editor assistance, an autocomplete feature, and better documentation. This makes development easier and accelerates developer productivity.</p>
</li>
<li><p>Thanks to static type checking, many errors that would normally occur at runtime in JavaScript are detected at the development stage, reducing debugging time and effort.</p>
</li>
<li><p>TypeScript benefits from an active and constantly growing community of developers, as well as regular support and frequent updates from Microsoft, which continues to perfect this technology.</p>
</li>
</ul>
<p>Thanks to these benefits, TypeScript has gained in popularity and is a solid choice for modern web development. Its ability to improve code quality, facilitate smooth development, and deliver a better overall experience has contributed to its success in the web development ecosystem.</p>
<h2 id="heading-using-typescript-with-other-technologies">Using TypeScript with Other Technologies</h2>
<p>TypeScript integrates seamlessly with other popular technologies and frameworks such as React, Angular, Vue.js and Node.js. This compatibility makes it a natural choice for developers working in these ecosystems.</p>
<p>TypeScript also encourages better code organization through the use of interfaces, classes, and modules. This facilitates code maintenance and readability, especially when managing complex projects.</p>
<h3 id="heading-typescript-and-angular">TypeScript and Angular</h3>
<p>Google's Angular caught everyone's attention when it decided to use TypeScript as its primary programming language from the start of its development in September 2014.</p>
<p>The Angular development team announced this change at ng-conf in October 2014, where they presented <strong>Angular 2</strong> (the major version of AngularJS) based on TypeScript.</p>
<p>Let's look at an example of some Angular code before the introduction of TypeScript:</p>
<pre><code class="lang-bash">// Angular Component <span class="hljs-keyword">in</span> JavaScript (ES5)
angular.module(<span class="hljs-string">'app'</span>).component(<span class="hljs-string">'appRoot'</span>, {
    templateUrl: <span class="hljs-string">'./app.component.html'</span>,
    controller: <span class="hljs-function"><span class="hljs-title">function</span></span> () {
        this.message = <span class="hljs-string">"Hello, JavaScript and Angular!"</span>;
    }
});

Here<span class="hljs-string">'s what'</span>s going on and what to note:

* **AngularJS Syntax**: Before the arrival of Angular 2, Angular used JavaScript (ES5) syntax. In the above example, we<span class="hljs-string">'re using `angular.module` to define a module, and `component` to define a component.
* **Controller**: In AngularJS, a controller is used to manage the logic of a component. In the example above, the controller function defines the property `this.message`.
* **TemplateUrl**: The HTML template is defined via the `templateUrl` property in the component configuration. In this example, it'</span>s supposed to be <span class="hljs-keyword">in</span> the file `<span class="hljs-string">'./app.component.html'</span>`.

And here<span class="hljs-string">'s what the same Angular component would look like after the introduction of TypeScript:

```code
// Angular Component in TypeScript
import { Component } from '</span>@angular/core<span class="hljs-string">';

@Component({
    selector: '</span>app-root<span class="hljs-string">',
    templateUrl: '</span>./app.component.html<span class="hljs-string">',
    styleUrls: ['</span>./app.component.css<span class="hljs-string">']
})
export class AppComponent {
    message: string = "Hello, TypeScript and Angular!";
}</span>
</code></pre>
<p>It's important to note that the switch from JavaScript to TypeScript in Angular has brought several benefits, including:</p>
<ul>
<li><p><strong>Strong typing</strong>: TypeScript lets you specify variable types, making code safer and less error-prone.</p>
</li>
<li><p><strong>Better Intellisense</strong>: The code editor can provide suggestions and type information in real time, improving developer productivity.</p>
</li>
<li><p><strong>Early error detection</strong>: TypeScript can detect compiler errors before runtime, making debugging easier and reducing runtime errors.</p>
</li>
<li><p><strong>Better maintainability</strong>: Type annotations and code structure make code easier to read and maintain.</p>
</li>
</ul>
<p>Angular switched to TypeScript because of several factors, including TypeScript's static type checking, which solved many of the typing problems encountered in AngularJS (the previous version of Angular).</p>
<p>TS also offered advantages in terms of complex project management, productivity, compatibility with JavaScript and active support from Microsoft.</p>
<p>TypeScript also offered developers greater productivity thanks to its advanced development support features, such as autocompletion, code navigation, and early error detection. This has enabled Angular to establish itself as a robust web development framework appreciated by many developers and companies.</p>
<p>Angular has continued to evolve using TypeScript as its core language, and the combination of Angular and TypeScript has become a common choice for the development of modern web applications.</p>
<p>This has also helped to strengthen TypeScript's adoption among the developer community, making it one of the most popular languages for web development.</p>
<h2 id="heading-how-to-configure-typescript-for-use-in-existing-javascript-projects">How to Configure TypeScript for Use in Existing JavaScript Projects</h2>
<p>Angular is already based on TypeScript, so there's no need to convert JavaScript to TypeScript in your modern Angular projects.</p>
<p>But if you use JavaScript in your TypeScript files, it will be less strict in its type checks. So, when integrating TypeScript into your existing JavaScript-based projects, it's important to make a gradual transition, set up <code>tsconfig.json</code>, manage types carefully, and test regularly.</p>
<h3 id="heading-how-to-use-typescript-with-nodejs">How to Use TypeScript with Node.js:</h3>
<p>As your development needs grow with your team, you may need more powerful tools and syntax when working with Node.js.</p>
<p>This is where using TypeScript with Node.js can be a good approach – and it lets you take adtvantage of TS's static type checking, as well as support for the latest JavaScript features.</p>
<p>The first thing to do is install or add TypeScript to the project like this:</p>
<pre><code class="lang-bash">npm install --save-dev typescript
</code></pre>
<p>Create a TypeScript configuration file (tsconfig.json) manually at the root of the project or by running the command below, which will generate it automatically.</p>
<pre><code class="lang-bash">npx tsc --init
</code></pre>
<p>Modify the <code>tsconfig.json</code> file to specify the necessary compilation parameters and configure the paths to existing JavaScript files.</p>
<p>This is an example of the TypeScript configuration file (tsconfig.json):</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"compilerOptions"</span>: {
    <span class="hljs-attr">"target"</span>: <span class="hljs-string">"ES2020"</span>,              <span class="hljs-comment">// Target JavaScript version</span>
    <span class="hljs-attr">"module"</span>: <span class="hljs-string">"CommonJS"</span>,            <span class="hljs-comment">// Module system to use</span>
    <span class="hljs-attr">"outDir"</span>: <span class="hljs-string">"./dist"</span>,              <span class="hljs-comment">// Output directory for compiled files</span>
    <span class="hljs-attr">"rootDir"</span>: <span class="hljs-string">"./src"</span>,              <span class="hljs-comment">// Source directory for TypeScript files</span>
    <span class="hljs-attr">"strict"</span>: <span class="hljs-literal">true</span>,                  <span class="hljs-comment">// Enable strict type checking</span>
    <span class="hljs-attr">"esModuleInterop"</span>: <span class="hljs-literal">true</span>,         <span class="hljs-comment">// Enable ES6 module interop</span>
    <span class="hljs-attr">"forceConsistentCasingInFileNames"</span>: <span class="hljs-literal">true</span>, <span class="hljs-comment">// Check consistent file casing</span>
    <span class="hljs-attr">"declaration"</span>: <span class="hljs-literal">true</span>,            <span class="hljs-comment">// Generate declaration files (.d.ts)</span>
    <span class="hljs-attr">"sourceMap"</span>: <span class="hljs-literal">true</span>               <span class="hljs-comment">// Generate source map files (.js.map)</span>
  },
  <span class="hljs-attr">"include"</span>: [<span class="hljs-string">"src/**/*.ts"</span>],       <span class="hljs-comment">// Files to include in compilation</span>
  <span class="hljs-attr">"exclude"</span>: [<span class="hljs-string">"node_modules"</span>]       <span class="hljs-comment">// Files to exclude from compilation</span>
}
</code></pre>
<p>Don't forget to place the <code>tsconfig.json</code> file at the root of your project if you've done this manually. Then be sure to adjust the values of the options according to your project's needs, such as source directory (rootDir), output directory (outDir), "target", "module" options, etc.</p>
<p>After doing this you'll be ready to use TypeScript in your Node projects.</p>
<h3 id="heading-how-to-use-typescript-with-react">How to Use TypeScript with React:</h3>
<p>TypeScript offers developers a more structured approach to JavaScript application development, and is a natural fit for the processes that most React developers already use.</p>
<p>Combining React's component-based approach with TypeScript's discipline allows you to create clean web applications that will be easier to maintain over time.</p>
<p>React has various tools at its disposal, such as accessory types and flow, but if you want a more mature option, that's where TypeScript comes in. It enables better management of component states, properties, events, and so on.</p>
<p>TS also implements many best coding practices and built-in type checking to approve the syntax and coding styles of your code.</p>
<p>For a new React.JS project, there are many ways to configure TypeScript. There are tools that allow you to run React and TypeScript online, which can be useful for debugging or making shareable reproductions. Examples of these tools include <a target="_blank" href="https://stackblitz.com/fork/react-ts">StackBlitz</a> and <a target="_blank" href="https://ts.react.new/">CodeSandbox</a>, or you can use this <a target="_blank" href="https://react-typescript-cheatsheet.netlify.app/">React TypeScript Cheatsheets</a> checklist as a reference.</p>
<p>You can also simply use Create React App and set it up via your terminal with this command:</p>
<pre><code class="lang-bash">npx create-react-app my-app --template typescript
</code></pre>
<p>For an existing React project, create-react-app uses Babel to compile the JavaScript code. So for TypeScript you'll just need to install a few TypeScript-related packages like <strong>@types/react</strong> and <strong>@types/react-dom</strong> in your project.</p>
<p>Don't forget the various compilation options that you'll need to define in the <code>tsconfig.json</code> file. <code>dom</code> must be included in <code>lib</code> (Note: if no <code>liboption</code> is specified, <code>dom</code> is included by default) and JSX must be set to one of the valid options. Preserved should be sufficient for most applications.</p>
<p>All that's left is to rename the files to TypeScript and convert the code to TypeScript (component, and so on). JavaScript files in the React application can be renamed using the extension .tsx for files containing JSX (React) code and .ts for files containing standard TypeScript code.</p>
<p>For example, if you have a <strong>src/App.js</strong> file, you can rename it to <strong>src/App.tsx</strong>. Don't forget to do the same for the other files.</p>
<p>Now open the .tsx files you've renamed and start adding types to declarations, React components, and any other appropriate places.</p>
<pre><code class="lang-bash">npm install @types/react @types/react-dom
</code></pre>
<p>or if you miss certain dependencies you can run this:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> mon-app
npm install typescript @types/node @types/react @types/react-dom @types/react-scripts --save
</code></pre>
<p>Now you're all set to use TS in your React projects.</p>
<h3 id="heading-how-to-use-typescript-with-nextjs">How to Use TypeScript with Next.js:</h3>
<p>TypeScript can help improve the performance of server-side rendering (SSR) and client-side rendering (CSR) applications by detecting errors early and facilitating type sharing between server and client.</p>
<p>It also enables better integration with Next.js, such as interfaces for SSR data and type annotations for routing functions.</p>
<p>Next.js provides a TypeScript-first development experience for building your React applications. It comes with built-in TypeScript support for automatically installing the necessary packages and configuring the proper settings.</p>
<p>For new projects just use <code>create-next-app</code> which now comes with TypeScript by default.</p>
<pre><code class="lang-bash">npx create-next-app@latest
</code></pre>
<p>In your existing projects, the first thing to do is install or add TypeScript to your project by renaming a file to <code>.ts</code> / <code>.tsx</code>. Run <code>next dev</code> and <code>next build</code> to automatically install the necessary dependencies and add a <code>tsconfig.json</code> file with the recommended config options.</p>
<p>If you already had a <code>jsconfig.json</code> file, copy the <code>paths</code> compiler option from the old <code>jsconfig.json</code> into the new <code>tsconfig.json</code> file, and delete the old <code>jsconfig.json</code> file.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>TypeScript has been steadily growing in popularity in the web development ecosystem, thanks to its performance, type safety, and productivity advantages.</p>
<p>As the preferred choice for technologies such as ReactJS, Next.js, Angular and others, TypeScript improves code quality, facilitates collaboration between development teams, and enables the creation of high-performance, scalable web applications.</p>
<p>For more information on TypeScript, here are some helpful resources:</p>
<ul>
<li><p><a target="_blank" href="https://www.typescriptlang.org/docs/">TypeScript - Official documentation</a></p>
</li>
<li><p><a target="_blank" href="https://learn.microsoft.com/fr-fr/training/paths/build-javascript-applications-typescript/">Microsoft Learn - TypeScript</a></p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/learn-typescript-with-this-crash-course/">TypeScript course on freeCodeCamp</a></p>
</li>
</ul>
<p>Thanks for reading. You can find me on <a target="_blank" href="https://www.linkedin.com/in/AdalbertPungu/">LinkedIn here</a>, and follow me on all socials @AdalbertPungu.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Sass with CSS ]]>
                </title>
                <description>
                    <![CDATA[ Hi there! If you are reading this article, you're probably trying to understand what Sass is and how it works. Sass is a CSS preprocessor that helps you manage tasks in large projects where the style sheets get larger, you have a number of lines of C... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-sass-with-css/</link>
                <guid isPermaLink="false">66d84c8cf6f7ca5a6046249d</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Sass ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Adalbert Pungu ]]>
                </dc:creator>
                <pubDate>Mon, 25 Apr 2022 22:32:38 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/04/sass-image.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Hi there! If you are reading this article, you're probably trying to understand what Sass is and how it works.</p>
<p>Sass is a CSS preprocessor that helps you manage tasks in large projects where the style sheets get larger, you have a number of lines of CSS code, and it becomes difficult to maintain your CSS codes.</p>
<p>This is where Sass becomes useful, as it has features that don't yet exist in CSS like nesting, creating functions with mixins, inheritance, and more. These features will help you write maintainable CSS code.</p>
<p>Sass lets you reuse your code, split it into files, and it also helps you create functions, variables, nest your CSS selectors, and other shortcuts.</p>
<h2 id="heading-how-sass-works">How Sass Works</h2>
<p>The web browser does not understand Sass code, though – it only understands CSS code. This means that you have to transform the Sass code into CSS code.</p>
<p>To do this, the compiler will generate a file with the CSS code. This transformation is called compilation. When you write Sass code in a .scss file, it is compiled into a regular CSS file that the browser will use to display it on the web page.</p>
<h2 id="heading-why-use-sass">Why Use Sass?</h2>
<p>There are many advantages to using Sass, so let's look at some of them now:</p>
<p>First, Sass is easy to understand if you know CSS. Since it's a CSS preprocessor its syntax is similar.</p>
<p>Also, if you use Sass, your CSS code will be compatible with all versions of browsers.</p>
<p>Sass also makes it possible to reuse your code by creating variables and functions with mixins (cutting up pieces of code) that can be reused over and over again. This helps you save time and allows you to code faster.</p>
<p>Speaking of saving time, Sass reduces the repetition of writing CSS code. This is thanks to its features like functions, variables, inheritance, and so on.</p>
<p>Finally, Sass is compiled to CSS and adds all the necessary vendor prefixes so you don't have to worry about writing them manually.</p>
<h2 id="heading-how-to-install-and-configure-sass">How to Install and Configure Sass</h2>
<p>In this article, I'll show you two ways to install Sass.</p>
<h3 id="heading-how-to-install-sass-with-nodejs">How to Install Sass with Node.js</h3>
<p>First, we'll download and install Node. Then we'll use the JavaScript package manager npm to install Sass and configure it in your project.</p>
<p>We are going to do a global installation, because this will save you from installing it every time you plan to work in your projects with Sass.</p>
<p>Here are the steps to follow to install and set up Sass in a project:</p>
<p>First, open your terminal and type:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">npm</span> <span class="hljs-selector-tag">install</span> <span class="hljs-selector-tag">-g</span> <span class="hljs-selector-tag">scss</span>
</code></pre>
<p>Again, this is global installation. If you do this, you avoid installing it every time you plan to work with Sass in your projects.</p>
<p>Then, in the project folder, create a Sass file in the one you are going to work on:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">style</span><span class="hljs-selector-class">.scss</span>
</code></pre>
<p><code>style</code> is the file name and <code>.scss</code> is the Sass extension name.</p>
<p>Then you will use the following command to generate a style.css file from the SASS file:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">sass</span> <span class="hljs-selector-tag">--watch</span> <span class="hljs-selector-tag">style</span><span class="hljs-selector-class">.scss</span> <span class="hljs-selector-tag">style</span><span class="hljs-selector-class">.css</span>
</code></pre>
<p><code>style.scss</code> is the source file and <code>style.css</code> is the destination file where Sass generates the CSS code.</p>
<p>Now installation and configuration are complete! You can use Sass in your projects.</p>
<p>But before we get into how to use Sass, I want to show you a second way of doing it. I recommend this way, as it is the simplest and easiest way to install and configure Sass.</p>
<h3 id="heading-how-to-install-sass-using-vs-code">How to Install Sass Using VS Code</h3>
<p>First, download and install Microsoft's VS Code editor if you haven't already. Then launch the editor so you can download the Live Sass Compiler extension.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-37.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And that's all you have to do. Once the installation is done, you'll be able to use Sass in your projects. Easy, right?</p>
<h2 id="heading-how-to-use-sass-in-a-project">How to Use Sass in a Project</h2>
<p>To understand how to use Sass, we will work on an example project where we will create two grids. The idea here is not to learn everything about Sass but what you see is mostly what you need to know to start using Sass.</p>
<p>Here is an overview of what we will create to understand Sass.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/Screenshot--12--1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You might be wondering why I took the grid example? Well, because we often use grids in web pages and they're simple to understand.</p>
<p>First of all, you should know that we'll do all the coding in the Sass file (style.scss) and not in the style.css file. It is Sass that will generate a CSS file for us with the same code.</p>
<p>To start, create a folder with two folders inside, <strong>CSS</strong> and <strong>images</strong>. Then inside the CSS folder create a file with the Sass extension – in my case it's <strong>style.scss</strong>.</p>
<p>Then open it and the file will be detected right away. Below the editor a button will appear named <strong>Watch Sass</strong>. Just click on it to tell Sass to watch this file and start generating (compiling) code in the CSS file.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/capt.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-38.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Once SASS finishes compiling it will create three files in the project's CSS folder: <strong>style.css</strong>, <strong>style.scss</strong>, and <strong>style.css.map</strong>. It tracks all the changes and it is ready to generate CSS code.</p>
<p>If you come back soon to continue working, all you have to do is open the file which has the extension .scss. Then click on Watch Sass for Sass to start generating the modifications in the CSS file (otherwise nothing will be generated in the CSS file).</p>
<p>I hope it's going ok so far. You have just seen how to install, configure, and start using Sass in your project. So now let's continue with our example of the grids to understand the different functionalities Sass brings.</p>
<h2 id="heading-how-to-use-variables-in-sass">How to Use Variables in Sass</h2>
<p>Before seeing how to create Sass variables, create an <strong>index.html</strong> file copy and paste the code below in the file:</p>
<pre><code class="lang-html">
<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">http-equiv</span>=<span class="hljs-string">"X-UA-Compatible"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"IE=edge"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>card with sass<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://images.unsplash.com/photo-1524749292158-7540c2494485?ixlib=rb-1.2.1&amp;ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTd8fGRldmVsb3BlcnN8ZW58MHx8MHx8&amp;auto=format&amp;fit=crop&amp;w=500&amp;q=60"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card_content"</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card_title"</span>&gt;</span>Lorem<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card_description"</span>&gt;</span>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Rerum porro dolores sapiente.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card card_dark"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://media.istockphoto.com/photos/put-more-in-get-more-out-picture-id1291318636?b=1&amp;k=20&amp;m=1291318636&amp;s=170667a&amp;w=0&amp;h=UvVIk7wwkN3X9OFm8gBlWWviV5vAjfrq2ejYP30JmnA="</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card_content"</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card_title"</span>&gt;</span>Lorem<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card_description"</span>&gt;</span>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Atque amet obcaecati nihil.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

      <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Run the file in your browser to see the result.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/Screenshot--14--1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Sass lets you create variables, but I want to show you a difference between Sass and CSS.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
    <span class="hljs-attribute">font-family</span>: <span class="hljs-string">'Poppins'</span>, Helvertica, sans-serif;
    <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#ab99ca</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">2rem</span>;
    <span class="hljs-attribute">min-height</span>: <span class="hljs-number">100vh</span>;
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">align-items</span>: center;
    <span class="hljs-attribute">justify-content</span>: center;
}
</code></pre>
<p>If you look at this example, it's CSS. But if in the project I want to reuse any color, padding, or font, I have to rewrite the same code (in CSS).</p>
<p>But with Sass I can create variables so I can reuse these features. To create a variable in Sass, we use the dollar sign <strong>$</strong> followed by the variable name and a colon for the value. Keep in mind that it's best to create a name that reflects the object you're going to use.</p>
<pre><code class="lang-css"><span class="hljs-comment">/* Creating and Using Variables */</span>

$<span class="hljs-selector-tag">fonts</span>: '<span class="hljs-selector-tag">Poppins</span>', <span class="hljs-selector-tag">Helvertica</span>, <span class="hljs-selector-tag">sans-serif</span>;
$<span class="hljs-selector-tag">primary-color</span>: <span class="hljs-selector-id">#ab99ca</span>;
$<span class="hljs-selector-tag">spacing</span>: 2<span class="hljs-selector-tag">rem</span>;

<span class="hljs-selector-tag">body</span> {
    <span class="hljs-attribute">font-family</span>: $fonts;
    <span class="hljs-attribute">background-color</span>: $primary-color;
    <span class="hljs-attribute">padding</span>: $spacing;
    <span class="hljs-attribute">min-height</span>: <span class="hljs-number">100vh</span>;
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">align-items</span>: center;
    <span class="hljs-attribute">justify-content</span>: center;
}
</code></pre>
<p>Add the above code in the style.scss file. Since we are working with a Sass file and HTML does not recognize Sass, to see the results we'll specify the CSS file that has been generated in our file <strong>index.html</strong>.</p>
<h2 id="heading-how-to-link-the-css-file">How to Link the CSS File</h2>
<p>It's really important to link the CSS file to index.html, to allow the CSS file to apply the CSS styles to the HTML. Otherwise there will be no styling applied and you will only see the code produced by the HTML.</p>
<p>So we will link our CSS file in the index.html file. In my case:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"css/style.css"</span>&gt;</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/Screenshot--13--1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Run the file in your browser to see the result.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/Screenshot--15--1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We will now see how to organize the code thanks to IMPORTS. The code will be cut into files while we keep using our example.</p>
<p>When creating a file, the file name will be followed by an underscore(_) at the beginning to prevent it from being compiled by Sass.</p>
<p>Create three files:</p>
<ul>
<li><p><code>_variables.scss</code>: to add the variables</p>
</li>
<li><p><code>_mixins.scss</code>: to add the functions that we will reuse</p>
</li>
<li><p><code>_card.scss</code>: to add the styles of our cards</p>
</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-40.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Copy and paste the variables you created in the <strong>style.scss</strong> file and put them in the <code>_variables.scss</code> file:</p>
<pre><code class="lang-css">    $<span class="hljs-selector-tag">fonts</span>: '<span class="hljs-selector-tag">Poppins</span>', <span class="hljs-selector-tag">Helvetica</span>, <span class="hljs-selector-tag">sans-serif</span>;
    $<span class="hljs-selector-tag">primary-color</span>: <span class="hljs-selector-id">#ab99ca</span>;
    $<span class="hljs-selector-tag">spacing</span>: 2<span class="hljs-selector-tag">rem</span>;
    $<span class="hljs-selector-tag">dark-grey</span>: <span class="hljs-selector-id">#999</span>;
</code></pre>
<p>For the <code>_mixins.scss</code> file, this is where we'll create the reusable functions with mixins.</p>
<p>Mixins allow you to create reusable functions. To declare a function you must enter <code>@mixin name_fonction { content }</code> or if your function has a parameter, you must enter <code>@mixin name_fonction($name_variable) { content }</code>.</p>
<p>To use mixins, you have to import it by typing <code>@include namefunction();</code> which saves time in a large project.</p>
<p>Add this code to the <code>_mixins.scss</code> file:</p>
<pre><code class="lang-css">
<span class="hljs-keyword">@mixin</span> flex-center {
    <span class="hljs-selector-tag">display</span>: <span class="hljs-selector-tag">flex</span>;
    <span class="hljs-selector-tag">align-items</span>: <span class="hljs-selector-tag">center</span>;
    <span class="hljs-selector-tag">justify-content</span>: <span class="hljs-selector-tag">center</span>;
}

<span class="hljs-comment">/* $radius is the parameter of the function */</span>

<span class="hljs-keyword">@mixin</span> border-radius($radius) {
    <span class="hljs-selector-tag">-webkit-border-radius</span>: $<span class="hljs-selector-tag">radius</span>;
    <span class="hljs-selector-tag">-moz-border-radius</span>: $<span class="hljs-selector-tag">radius</span>;
    <span class="hljs-selector-tag">border-radius</span>: $<span class="hljs-selector-tag">radius</span>;
}
</code></pre>
<p>For the <code>_card.scss</code> file, add this code to it:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.card</span> {
    <span class="hljs-attribute">background-color</span>: white;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">20rem</span>;
    <span class="hljs-attribute">overflow</span>: hidden;
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">2rem</span>;
    <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">5px</span> <span class="hljs-number">5px</span> <span class="hljs-number">5px</span> <span class="hljs-number">5px</span> <span class="hljs-number">#000</span>;
    @include border-radius(0.5rem); <span class="hljs-comment">/* using the mixins function */</span>

    img {
        <span class="hljs-attribute">height</span>: <span class="hljs-number">15rem</span>;
        <span class="hljs-attribute">background-size</span>: cover;
        <span class="hljs-attribute">background-position</span>: center center;
    }

    <span class="hljs-selector-class">.card_content</span> {
        <span class="hljs-attribute">padding</span>: $spacing;
    }

    <span class="hljs-selector-class">.card_title</span> {
        <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
        <span class="hljs-attribute">color</span>: black;
    }

    <span class="hljs-selector-class">.card_description</span> {
        <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
        <span class="hljs-attribute">color</span>: $dark-grey;
    }

    &amp;_<span class="hljs-selector-tag">dark</span> {

        <span class="hljs-attribute">background-color</span>: black;

        .card_title {
            <span class="hljs-attribute">color</span>: white;
        }
    }

}
</code></pre>
<p>In the code above we're using <strong>nesting</strong> and <strong>aliases</strong>. Nesting helps us simplify the way we write our CSS styles and allows us to nest CSS selectors.</p>
<p>For aliases you can use (<strong>&amp;</strong>) or (<strong>and</strong>) followed by the class name that will resume the parent selector's code.</p>
<p>To use an alias, you must import it by typing the alias followed by the name of the variable (&amp;_dark).</p>
<p>If you try to run the index.html file, nothing will change. It does not change because we have created files that are not related to index.html and our style.sass file only generates the code it has.</p>
<p>To fix this, we'll import all the files we've created into the style.sass file so that when SASS does the monitoring, it'll generate the code of those files.</p>
<pre><code class="lang-css"><span class="hljs-comment">/* file import */</span>
<span class="hljs-keyword">@import</span> <span class="hljs-string">'variables'</span>;
<span class="hljs-keyword">@import</span> <span class="hljs-string">'mixins'</span>;
<span class="hljs-keyword">@import</span> <span class="hljs-string">'card'</span>;
</code></pre>
<p>For the style.scss file, add the above code. The style.scss file should be like this:</p>
<pre><code class="lang-css">
<span class="hljs-comment">/* file import */</span>

<span class="hljs-keyword">@import</span> <span class="hljs-string">'variables'</span>;
<span class="hljs-keyword">@import</span> <span class="hljs-string">'mixins'</span>;
<span class="hljs-keyword">@import</span> <span class="hljs-string">'card'</span>;

<span class="hljs-selector-tag">body</span> {
    <span class="hljs-attribute">font-family</span>: $fonts; <span class="hljs-comment">/* variable usage */</span>
    <span class="hljs-attribute">background-color</span>: $primary-color;
    <span class="hljs-attribute">padding</span>: $spacing;
    <span class="hljs-attribute">min-height</span>: <span class="hljs-number">100vh</span>;
    @include flex-center(); <span class="hljs-comment">/* using the mixins function */</span>
}
</code></pre>
<p>In the previous code, I imported the files (<strong>SASS import</strong>) into style.css so that they can be tracked and generate code when there are changes.</p>
<p>Run the index.html file in your browser to see the result.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/Screenshot--12--1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If you get the same result as in the capture above, congratulations, you now understand how Sass works.</p>
<p>Here is the preview link for the project we built: <a target="_blank" href="https://adalbertpungu.github.io/card_with_sass/">https://adalbertpungu.github.io/card_with_sass/</a></p>
<p>And here's the GitHub repository link:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/AdalbertPungu/card_with_sass">https://github.com/AdalbertPungu/card_with_sass</a></div>
<p> </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you learned how Sass works by building a simple photo grid. In this small project, we've covered many core Sass features, but not all of them. So I hope you will start using it in your projects to learn more.</p>
<p>You can check the documentation if you want to dive deeper: <a target="_blank" href="https://sass-lang.com/documentation">https://sass-lang.com/documentation</a>.</p>
<p>That’s all for this article. Thank you for reading! I think you’re ready to try using Sass.</p>
<p>Happy coding.</p>
<p>Follow me on Twitter: <a target="_blank" href="https://twitter.com/adalbertpungu">twitter.com/AdalbertPungu</a></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
