<?xml version="1.0" ?>
  <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[Web development blog posts by Roy Derks]]></title>
        <link>https://hackteam.io</link>
        <description>
          <![CDATA[Hackteam - Training and consulting for tech companies by Roy Derks]]>
        </description>
        <language>en</language>
        <lastBuildDate>2025-12-01T09:00:00.000Z</lastBuildDate>
        
      <item>
        <title><![CDATA[Tool calling is broken without MCP Server Composition]]></title>
        <link>https://hackteam.io/blog/tool-calling-is-broken-without-mcp-server-composition</link>
        <pubDate>2025-12-01T09:00:00.000Z</pubDate>
        <guid isPermaLink="false">https://hackteam.io/blog/tool-calling-is-broken-without-mcp-server-composition</guid>
        <media:content
          url="/images/tool-calling-is-broken-without-mcp-server-composition/overview.png"
        />
        <description>
        <![CDATA[Most agents fail not at reasoning, but at picking and using the right tools. This post explains how Model Context Protocol (MCP) server composition fixes that with four practical patterns.]]>
        </description>
        <content:encoded>
        <![CDATA[<p>MCP gives agents access to tools, prompts, and resources, but as a developer building AI applications I find tool calling is the part that actually changes how we build AI systems.</p>
<p>While the Model Context Protocol (MCP) provides a solution to exposes these capabilities without hard‑coding functions or rewriting integrations for each agent framework, it doesn’t tell you how agents should decide which tools to call or how those tools should be organized. Especially, when you need to combine tools from different MCP servers in your agents.</p>
<p>Anyone who has built APIs before will immediately feel nostalgic as these aren’t new problems. Just like backend engineers eventually created Backend‑for‑Frontends (BFFs) to cleanly expose functionality, and just like frontend teams adopted GraphQL to unify scattered data sources, developers building MCP servers need similar architectural layers.</p>
<p>This post is about how MCP server composition provides that missing layer using four patterns I keep seeing in real‑world agent systems for structuring, grouping, and orchestrating tools so that tool calling is no longer broken.</p>
<h2>Why does tool calling often fail?</h2>
<p>Tool calling doesn’t usually fail because &quot;LLMs are bad at handling tools.” It fails because we overload the model with too many tools or badly designed tools. In my previous <a href="/blog/stop-converting-openapi-specs-mcp-servers">blog post (“Stop Converting OpenAPI Specs Into MCP Servers”)</a>, I explained why dumping an entire OpenAPI spec into MCP makes tools impossible for a model to handle. Let’s focus on the first problem: how having too many tools can break your agent.</p>
<p><img src="/images/tool-calling-is-broken-without-mcp-server-composition/overview.png" alt="Tool calling fails because of context bloat"></p>
<h3>Tools overload the context window</h3>
<p>Every LLM has a fixed context window of let's say 8k, 32k, 128k, or even 1M tokens. That window must fit:</p>
<ul>
<li>The system prompt</li>
<li>All tool definitions (their schemas, descriptions, examples)</li>
<li>Conversation history (messages, tool calls, etc)</li>
<li>The tokens the model is currently generating while reasoning</li>
</ul>
<p>Every tool definition you add consumes space that the model cannot use for other tasks. In a <a href="https://www.anthropic.com/engineering/advanced-tool-use">recent blog post</a> Anthropic showed how an agent is using ~72K tokens for the tool definitions of 50+ MCP tools, and another 5k tokens for the conversation history and system prompt. Altogether, this agent is consuming ~77K tokens before any reasoning has been done.</p>
<p>When the model starts with a 38.5% filled context window (Claude Opus 4.5's default context window size is 200k tokens), you'll leave your agent very little room to do subsequent tool calling and handle multi-step reasoning.</p>
<h3>Attention dilution makes the model “compete with itself”</h3>
<p>Even when context windows are huge (for example, Gemini 3 has a default context window of 1M tokens), attention mechanisms still struggle with irrelevant or overly verbose tool definitions.</p>
<p>The model has to attend to every token to decide what’s relevant. The more irrelevant or redundant tool definitions you include, the more “distracted” the model becomes.</p>
<p>This leads to:</p>
<ul>
<li>Confusion between similar tools</li>
<li>Misfires (“wrong tool” calls)</li>
<li>“lost in the middle” failures where the system prompt or earlier instructions are ignored</li>
</ul>
<p>All of these are not context limit problems, they are an attention competition problem.</p>
<p>Because of these constraints, developers end up doing “context budgeting” as part of their context engineering. This requires them to manually select what tools to include, stripping down tool definition schemas to the bare minimum or avoiding large tool surfaces entirely. This is exactly why the four patterns that follow matter, especially when you need to combine tools from multiple MCP servers in your agent. MCP server composition gives the structure  needed to group, layer, and orchestrate tools in a way the model can reliably use them.</p>
<h2>Pattern 1: Tool selection inside the MCP client</h2>
<p>By far the easiest way to limit the amount of tools passed to the LLM is to use tool selection within the MCP client, and most chat applications and IDEs already support this pattern directly. Applications like Claude Desktop, ChatGPT, Cursor, and various AI‑powered IDEs let you pick which MCP servers to load, and which tools inside those servers should be active for the current session. This gives you control over what the model can see and prevents the agent, in this case the chat application or IDE, from being overloaded by tools it doesn’t need.</p>
<p><img src="/images/tool-calling-is-broken-without-mcp-server-composition/pattern-one-overview.png" alt="Example of handling tool selection inside the MCP client"></p>
<p>This pattern is simple but effective: LLM performance goes up the moment you limit the amount of available tools. Explicitly enabling or disabling tools avoids the two biggest failure modes in tool calling: hallucinated tool calls and overloaded contexts. When the model sees just a handful of clearly defined tools instead of dozens of overlapping ones it’s far less likely to guess, misfire, or call the wrong tool.</p>
<p>Tool selection inside the client is the first layer of control before you start composing servers or building orchestration layers, but far from perfect. You still have to manage the selection manually, and it’s hard to share these configurations with colleagues or clients. And what to think of situations where the tools you need change during the course of your session?</p>
<h2>Pattern 2: Composing MCP servers into virtual servers</h2>
<p>One step up from using the MCP client to enable or disable tools is creating a new MCP server that exposes only the tools your agent actually needs. Instead of handing the model three or four MCP servers, with dozens of tools it will never use, you compose a virtual MCP server that contains just the relevant ones.</p>
<p>Imagine you're building an agent that needs to scrape a webpage and store the results in a (local) file. You might rely on three different MCP servers to do this (<code>@playwright/mcp</code>, <code>@modelcontextprotocol/server-filesystem</code> and <code>mcp-server-time</code>), but only a subset of their tools matter. By composing a new MCP server with just those tools, you avoid the above discussed problems related to context bloat and tool confusion that increases the chance of wrong tool calls. If not, these three MCP servers alone would have inserted 25+ tool definitions into the context of your agent.</p>
<p><a href="https://ibm.github.io/mcp-composer/"><img src="/images/tool-calling-is-broken-without-mcp-server-composition/pattern-two-overview.png" alt="Example of composing MCP servers into (virtual) servers using "></a></p>
<p>This maps directly to the earlier mentioned Backend‑for‑Frontend (BFF) pattern in the API world. In a BFF, you create a custom API tailored for a single frontend. If a payment app needs to make several calls to process a transaction, the BFF provides a simplified API surface, sometimes even orchestrating multiple backend calls into one endpoint, that reduces business logic in the client.</p>
<p>MCP server composition works the same way, it becomes the layer that only exposes tool that the agent actually needs. There are two ways to compose MCP servers:</p>
<ul>
<li>Build a new server directly using one of the MCP SDKs or a meta‑framework.</li>
<li>Use an MCP gateway to create a virtual, remote server that proxies and aggregates tools.</li>
</ul>
<p>Personally, I prefer using a meta‑framework as it gives you the best of both worlds: you can compose servers easily using abstractions without the operational overhead that comes with a gateway (more on MCP gateways later). At IBM we built <a href="https://ibm.github.io/mcp-composer/"><code>mcp-composer</code></a>, which has a CLI to make composing your MCP servers as virtual endpoints easy. It lets developers combine multiple MCP servers (or specific tools from them) into domain‑specific servers without rewriting anything. You pick the tools, define the scope, and expose a single interface your agent can reliably use.</p>
<h2>Pattern 3: Dynamic Tool Selection</h2>
<p>With dynamic tool selection, you push the responsibility of choosing the right tool down into the server layer. Most tool‑calling mistakes happen because we force the LLM to choose directly from a long list of tool definitions. The model has to read every tool name, description, and schema in its context just to decide which one to call.</p>
<p>Dynamic tool selection lets the MCP server determine which tool should be called from which MCP server. This removes a big amount of overhead from the model and dramatically improves reliability, without giving away control over the available tools.</p>
<p>There are two emerging approaches to handle dynamic tool selection:</p>
<ul>
<li>Layered Tool Design</li>
<li>RAG‑MCP (Retrieval‑Augmented Tool Selection)</li>
</ul>
<p>Let's break down each of these solutions.</p>
<h3>Layered Tool Design</h3>
<p>With the layered tool design you &quot;hide&quot; the tool definitions behind layers. The LLM interacts only with a small set of high‑level tools (discovery, planning &amp; execution), and those tools internally call lower‑level tools, bundle logic, or orchestrate multi‑step flows. This is the pattern that the engineering team at Block <a href="https://engineering.block.xyz/blog/build-mcp-tools-like-ogres-with-layers">implemented for Square's payment MCP server</a>, and since has been implemented in various MCP solutions.</p>
<p><a href="https://ibm.github.io/mcp-composer/"><img src="/images/tool-calling-is-broken-without-mcp-server-composition/pattern-three-layered.png" alt="Example of Layered Tool Design using "></a></p>
<p>The layers are designed like this:</p>
<ul>
<li>Discovery layer: Returns a short, simplified set of high‑level operations the LLM can choose from. Instead of exposing every tool and schema, this layer prevents the context window from being flooded with unnecessary details.</li>
<li>Planning layer: Once the LLM selects a tool, the planning layer determines the exact inputs needed. It derives the correct parameters based on the underlying tool definitions, so the model only has to fill in these values.</li>
<li>Execution layer: Executes the final tool call by routing it to the correct MCP server, along with the validated input parameters.</li>
</ul>
<p>While a layered MCP server doesn’t technically choose the tool for the LLM, it gives the model a much smaller and more structured surface to choose from. It removes irrelevant information, reduces context bloat, and guides the model toward the correct tool without forcing it to understand every schema. This works especially well for MCP servers that were derived form existing APIs or multi-purpose MCP servers that contain lots of tools.</p>
<p>You can <a href="https://ibm.github.io/mcp-composer/guide/layered_mcp_server.html">implement this layered tool design</a> with <code>mcp-composer</code>, and even combine tool selection approaches: you can first compose a narrowed‑down tool set into a virtual MCP server, and then apply layered tool design on top of that server to make tool selection even more reliable and easier for the model to use.</p>
<h3>RAG‑MCP (Retrieval‑Augmented Tool Selection)</h3>
<p><a href="https://youtu.be/xBSMBEowLcY?si=H-NbDR9DcOS_Sp3L&amp;t=78">Retrieval Augmented Generation (or RAG)</a> helps LLMs to find the right context from a knowledge base, without bloating the context window with irrelevant information. Think of a situation where you are looking for the cancellation policy in a 34-page contract. Instread of shoving all these pages into the context, the RAG system will retreive only the relevant chunks of information to reduce the context bloat. With <a href="https://arxiv.org/pdf/2505.03275">RAG-MCP</a>,the knowledge base would be the tool definitions of all your MCP servers, and the MCP server would dynmically select the required tool.</p>
<p><a href="https://writer.com/engineering/rag-mcp/"><img src="/images/tool-calling-is-broken-without-mcp-server-composition/pattern-three-rag-mcp.jpeg" alt="Breakdown of RAG-MCP from a blog post by Writer"></a></p>
<p>Instead of loading all tools into the context, the server:</p>
<ul>
<li>Embeds each tool definition</li>
<li>Ranks them by semantic similarity to the user request</li>
<li>Loads only the most relevant tools into the model’s context</li>
</ul>
<p>This means the model receives only the tools needed based on the prompt, not everything the MCP server(s) supports. According to the RAG-MCP research paper this approach decreases the amount of tokens spent on tool definitions by over 50% and, based on a benchmark across websearch tools, increases tool selection accuracy by 200%. You can find an <a href="https://github.com/adeweaver/RAG-MCP-example/tree/main">example implementation of RAG-MCP on GitHub</a>, based on a <a href="https://writer.com/engineering/rag-mcp/">blog post by Writer</a>.</p>
<p>Next to this example, you can also find a similar approach in <a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool">Anthropic's new Tool Search capability</a>. When you build an agent using the Anthropic API, you can pass all your MCP servers in a single request and include a flag that tells Claude whether to use <code>regex</code> or <code>bm25</code> for tool selection. Instead of loading every tool definition into the prompt, Claude applies either regex matching (executed as Python code) or <code>BM25</code>  (a lightweight retrieval technique) to determine which tools are relevant based on the user’s message.</p>
<h2>Pattern 4: Programmatic Tool Execution</h2>
<p>The final pattern pushes MCP server composition one step further. Instead of asking the LLM or MCP server to select a tool, you let the model generate code that imports and executes the selected tools in a sandboxed environment. So far, this pattern has been implemented by Cloudflare (called <a href="https://blog.cloudflare.com/code-mode/">&quot;Code Mode&quot;</a>) and <a href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/programmatic-tool-calling">Anthropic</a>.</p>
<p><a href="https://www.anthropic.com/engineering/advanced-tool-use"><img src="/images/tool-calling-is-broken-without-mcp-server-composition/pattern-four-overview.png" alt="Flow of Programmatic Tool Execution as described by Anthropic"></a></p>
<p>Programmatic tool execution makes use of a sandbox with a script generated by the model (usually in Python) to chain tool calls, iterate over results, applies filters, etc. The script is then executed in a runtime that:</p>
<ul>
<li>Enforces valid MCP tool schemas</li>
<li>Prevents unsafe operations</li>
<li>Returns only the final output back to the model</li>
</ul>
<p>This pattern significantly decreases the amount of tokens in the context for the LLM as it only needs to call the tool surfacing the sandbox. It could be specially powerful for tasks that involve multiple tool calls that need to chained or require conditional logic, but depending on how you would implement this, there could be additional tokens needed (and added latency) to generate the tool execution script.</p>
<p>Also, the risk with programmatic tool execution is the lack of control developers have over how tools are being called, the possibility of side effects and all sorts of injections. As many developers are trying to tuns probabilistic LLMs into deterministic software, the last thing most them are willing to do is giving up more control.</p>
<h3>What About MCP Gateways?</h3>
<p>Every enterprise considering adopting MCP is looking at MCP gateways to secure, deploy, version, and route MCP servers in a centralized way, including tracking usage, enforcing usage limits, etc. Similar to API gateways, they are used as the single entry point for an enterprise's developers and clients to interact with their services. However, a lot of MCP gateways do more than proxying or aggregating MCP servers, making the line between a &quot;tool layer&quot; (like a BFF) and a gateway very fine.</p>
<p>That said, not every developer needs a gateway in the traditional sense. Most application developers (now called AI engineers) will get far more value by creating a clean tool layer the agent can rely on, very similar to how frontend developers relied on BFFs to simplify and shape complex backend systems. Gateways, on the other hand, solve operational problems, not design problems. If your tools are badly designed, unstructured, or confusing for the model to use, a gateway won’t fix that problem, but the patterns described in this blog post do.</p>
<p>This is why I believe the future “app layer” for agents won’t be a gateway. It will be a tool composition layer (like <a href="https://ibm.github.io/mcp-composer/"><code>mcp-composer</code></a>), built much closer to where application logic lives. Gateways will still play a role for organizations that need centralized control, but the majority of AI developers will be better served by curating and shaping the tools they expose to their agents first.</p>
<p>If you do end up needing an MCP gateway, check out <a href="https://github.com/IBM/mcp-context-forge">Context Forge</a>, an open-source MCP and A2A gateway built by a great team at IBM.</p>
<h3>To conclude</h3>
<p>MCP server composition gives agents the structure and focus they’ve been missing. Tool calling doesn’t break because LLMs can’t use tools, it breaks because we hand them too many tools, expose the wrong ones, or fail to design them properly. The four patterns in this post should give you an idea how to fix your broken agent, and as the MCP specification keeps evolving I'm interested in seeing how some of these patterns are getting incorporated. Not every team needs every pattern, and not everyone needs a gateway. What every team building agents does need is a thoughtful tool layer that mirrors the evolution we saw with APIs, BFFs, and GraphQL.</p>
<p>If you found this blog post helpful, don’t forget to share it with your network. For more content on AI and web development, subscribe to my <a href="https://www.youtube.com/@gethackteam?sub_confirmation=1">YouTube channel</a> and connect with me on <a href="https://linkedin.com/in/gethackteam">LinkedIn</a>, <a href="https://x.com/gethackteam">X</a>, or <a href="https://bsky.app/profile/gethackteam.bsky.social">Bluesky</a>.</p>
]]>
        </content:encoded>
    </item>
      <item>
        <title><![CDATA[Stop Converting OpenAPI Specs Into MCP Servers]]></title>
        <link>https://hackteam.io/blog/stop-converting-openapi-specs-mcp-servers</link>
        <pubDate>2025-09-12T00:00:00.000Z</pubDate>
        <guid isPermaLink="false">https://hackteam.io/blog/stop-converting-openapi-specs-mcp-servers</guid>
        <media:content
          url="https://i.ytimg.com/vi/8m-O_KiHRjk/hqdefault.jpg"
        />
        <description>
        <![CDATA[Converting your existing OpenAPI specification into an MCP Server ]]>
        </description>
        <content:encoded>
        <![CDATA[<p>MCP has quickly become the standard for connecting agents to data, and as a result new MCP servers are popping up everywhere. Looking online, you can find tens of thousands of MCP servers, and most of these are AI-generated or auto-converted straight from existing OpenAPI specs.</p>
<p>And that’s not surprising, as the majority of APIs built by developers are RESTful-ish, and OpenAPI is the dominant way to describe them. So when developers first try out MCP, the obvious move is to point at an OpenAPI spec file and turn every endpoint into a collection of tools.</p>
<p>But when you do that, you miss the whole point of MCP. Instead of creating better tools for agents, you just increase the risk of hallucinations and poor fault tolerance.</p>
<p>In this post, I’ll walk through some of the frustrations I’ve seen firsthand and explain why treating MCP like just another API spec doesn’t work.</p>
<h2>Too many tools fill up the context window quickly</h2>
<p>Most MCP servers today are used for tool calling. But that doesn’t mean they should expose hundreds of low-level API endpoints. An MCP server is a set of tools, prompts, and resources that each should represent something an agent can actually use.</p>
<p>The most common mistake I see is developers auto-converting OpenAPI specs into MCP servers without any curation. That usually produces dozens (or even hundreds) of very low-level tools, one for every single endpoint.</p>
<p><img src="/images/stop-converting-openapi-specs-mcp-servers/tool-context-window.png" alt="Converting OpenAPI specs to a MCP Server"></p>
<p>In theory, this might look powerful. In practice, it causes problems. The LLMs the agent will connect to have a limited context window, and every tool definition takes up space in that window. Too many tools lead to confusion, poor fault tolerance, and a higher risk of hallucinations.</p>
<p>Curation helps. By exposing only the endpoints that matter, you keep your MCP server focused and more reliable. Some clients like Cursor or Claude Desktop let users toggle tools on and off, but not every environment works that way. If someone connects directly from code, they’d have to curate the tools themselves if you haven’t already done it for them.</p>
<h2>Agents are bad at taking multi-step actions</h2>
<p>A good MCP server should feel like a well-designed API. One of the biggest problems with exposing every endpoint as a tool is that you push the complexity of multi-step actions onto the agent.</p>
<p>Take this example: “refund a customer by email.”</p>
<p><img src="/images/stop-converting-openapi-specs-mcp-servers/multi-step-tool-calls.png" alt="Calling multiple tools to take a single action"></p>
<p>With a 1:1 OpenAPI conversion, the agent has to:</p>
<ul>
<li>Call <code>get_customers</code> with an email address to get the customer ID.</li>
<li>Call <code>get_customer_orders</code> to fetch their orders.</li>
<li>Call <code>create_refund</code> with the right order ID.</li>
</ul>
<p>That’s three separate steps, and a lot can go wrong in the middle. The agent might pass the wrong email, pick the wrong order, or start calling tools like <code>get_customer_by_id</code> or <code>get_order_by_id</code> to collect information it doesn't need to get the job done. LLMs aren’t good at following exact step-by-step flows in a reliable, deterministic way.</p>
<p>If you design the MCP server directly, instead of just converting the OpenAPI spec, you can collapse this workflow into a single action. That makes the process deterministic, reduces hallucinations, and improves fault tolerance.</p>
<p>There are two ways to handle multi-step actions in MCP: prompts or better tool design.</p>
<p><img src="/images/stop-converting-openapi-specs-mcp-servers/design-mcp-use-case.png" alt="Design better tools for MCP servers"></p>
<p>MCP servers can return prompts that could help the agent create a plan on which tools to call, and in what order. In this example, a prompt might spell out the steps for refunding a customer by email. That’s better than leaving the agent to figure it out, but still error-prone.</p>
<p>The stronger approach is to design a higher-level tool that handles the entire workflow behind the scenes. The agent just calls <code>refund_customer_by_email</code>, and your server does the rest. That’s the kind of deterministic design that makes MCP servers actually usable.</p>
<h2>Layered Tool Design can help</h2>
<p>Another way to keep MCP servers that need to span a lot of tools usable is to design them in layers.</p>
<p>Block’s engineering team (the company behind Square) introduced this <a href="https://engineering.block.xyz/blog/build-mcp-tools-like-ogres-with-layers">layered pattern</a> with their own Square MCP server, and it’s a good example of how to structure tools so agents don’t get overwhelmed.</p>
<p>The idea is simple:</p>
<ul>
<li><strong>Discovery</strong> tools help the agent understand what’s available.</li>
<li><strong>Planning</strong> tools guide it toward the right action.</li>
<li><strong>Execution</strong> tools perform the actual operation.</li>
</ul>
<p>This layered approach makes servers easier to use and more fault tolerant. Instead of giving the agent a flat list of dozens of low-level tools, you organize them into progressive steps. The agent can start broad, narrow down, and then execute without getting lost in irrelevant options.</p>
<p><img src="/images/stop-converting-openapi-specs-mcp-servers/layered-tool-design.png" alt="Using a layered tool design using 'mcp-composer'"></p>
<p>You don’t have to build this from scratch either. With libraries like <a href="https://pypi.org/project/mcp-composer"><code>mcp-composer</code></a>, you can implement the layered tool pattern on top of existing OpenAPI specs. The <a href="https://ibm.github.io/mcp-composer/guide/layered_mcp_server.html">documentation</a> explains how to set up this pattern in a couple of steps, including how to add other capabilities like authentication to MCP servers (more about that in a later blog post).</p>
<p>The result is an MCP server that agents can reliably work with, one that is deterministic, less prone to hallucinations, and easier for users to understand.</p>
<h2>Other Considerations</h2>
<p>There are a few other points worth keeping in mind when building MCP servers based on your OpenAPI specification.</p>
<p>⚠️ Error messages: OpenAPI responses aren’t written for LLMs. A <em>&quot;404 not found&quot;</em> might make sense to a developer, but for an agent it’s ambiguous. Was the email wrong? The order missing? Or is the whole service unavailable? Consider normalizing errors into responses the agent can reason about.</p>
<p>⚠️ Irrevocable actions: Just because your API has a <code>DELETE /orders</code> endpoint doesn’t mean it should be exposed as an MCP tool. Agents don’t always understand the consequences of destructive actions. Ask yourself: should this action really be available to the agent, and is there a human in the loop to mitigate?</p>
<p>⚠️ Authentication: We didn’t even touch on auth and security in this post, but they’re critical pieces. From bearer tokens to OAuth delegation, authentication and authorization add another layer of complexity you’ll need to design for. I recommend reading the article <a href="https://news.ycombinator.com/item?id=43600192">The “S” in MCP Stands for Security</a> to learn more about this topic.</p>
<p>These aren’t reasons to avoid MCP. They’re reminders that building good MCP servers means designing for agents, not just translating existing APIs.</p>
<p>If you found this tutorial helpful, don’t forget to share it with your network. For more content on AI and web development, subscribe to my <a href="https://www.youtube.com/@gethackteam?sub_confirmation=1">YouTube channel</a> and connect with me on <a href="https://linkedin.com/in/gethackteam">LinkedIn</a>, <a href="https://x.com/gethackteam">X</a>, or <a href="https://bsky.app/profile/gethackteam.bsky.social">Bluesky</a>.</p>
]]>
        </content:encoded>
    </item>
      <item>
        <title><![CDATA[An LLM does not need to understand MCP]]></title>
        <link>https://hackteam.io/blog/your-llm-does-not-care-about-mcp</link>
        <pubDate>2025-08-07T00:00:00.000Z</pubDate>
        <guid isPermaLink="false">https://hackteam.io/blog/your-llm-does-not-care-about-mcp</guid>
        <media:content
          url="/images/your-llm-does-not-care-about-mcp/overview.png"
        />
        <description>
        <![CDATA[Model Context Protocol (MCP) has became the standard for tool calling when building agents, but contrary to popular belief your LLM does not need to understand MCP.]]>
        </description>
        <content:encoded>
        <![CDATA[<p>Model Context Protocol (MCP) has become the standard for tool calling when building agents, but contrary to popular belief, your LLM does not need to understand MCP. You might have heard about the term &quot;context engineering&quot;; where you, as the person interacting with an LLM, are responsible for providing the right context to help it answer your questions. To gather this context, you can use tool calling to give the LLM access to a set of tools it can use to fetch information or take actions.</p>
<p>MCP helps by standardizing how your agent connects to these tools. But to your LLM, there’s no difference between “regular” tool calling and using a standard like MCP. It only sees a list of tool definitions, it doesn’t know or care what’s happening behind the scenes. And that’s a good thing.</p>
<p>By using MCP you get access to thousands of tools, without writing custom integration logic for each one. It heavily simplifies setting up an agentic loop that involves tool calling, often with almost zero development time. You, the developer, are responsible for calling the tools. The LLM only generates a snippet of what tool(s) to call and with which input parameters.</p>
<p>In this blog post, I’ll break down how tool calling works, what MCP actually does, and how both relate to context engineering.</p>
<h2>Tool Calling</h2>
<p>LLMs understand the concept of tool calling, sometimes also called tool use or function calling. You provide a list of tool definitions as part of your prompt. Each tool includes a name, description, and expected input parameters. Based on the question and available tools, the LLM may generate a call.</p>
<p><a href="http://www.youtube.com/watch?v=h8gMhXYAv1k"><img src="https://i.ytimg.com/vi/h8gMhXYAv1k/hqdefault.jpg" alt="VIDEO: What is Tool Calling? Connecting LLMs to Your Data"></a></p>
<p>But here’s the important part: LLMs don’t know how to use tools. They don’t have native tool calling support. They just generate text that represents a function call.
<img src="/images/your-llm-does-not-care-about-mcp/tool-calling.png" alt="Input and output when interacting with a LLM"></p>
<p>In the diagram above, you can see what the LLM actually sees: a prompt made up of instructions, previous user messages, and a list of available tools. Based on that, the LLM generates a text response which might include a tool that your system should call. It doesn’t understand tools in a meaningful way, it’s just making a prediction.</p>
<p>Let's look at a more practical use case. For example, if you provide a tool called <code>get_weather</code> that takes a <code>location</code> as input, and then ask the model: &quot;What’s the weather in San Jose, CA?&quot; it might respond with:</p>
<pre><code class="language-json">{
  &quot;name&quot;: &quot;get_weather&quot;,
  &quot;input&quot;: {
    &quot;location&quot;: &quot;San Jose, CA&quot;
  }
}
</code></pre>
<p>The LLM is able to generate that snippet based on the context it was provided with, as you can see in the diagram below. The LLM doesn’t know how to call the <code>get_weather</code> tool, nor does it need to. Your agentic loop, or agentic application, is responsible for taking this output and making the actual API call or function invocation. It parses the generated tool name and inputs, runs the tool, and passes the result back to the LLM as a new message.</p>
<p><img src="/images/your-llm-does-not-care-about-mcp/tool-calling-flow.png" alt="Tool Calling flow interaction with a LLM"></p>
<p>This separation of concerns is important. The LLM just generates predictions and your system handles the execution. And that brings us to where MCP fits in.</p>
<h2>Model Context Protocol (MCP)</h2>
<p>Model Context Protocol, or MCP, is a way to <a href="https://www.infoworld.com/article/4029634/what-is-model-context-protocol-how-mcp-bridges-ai-and-external-services.html">standardize how your agent connects</a> to data sources like tools, prompts, resources, and samples. Right now, MCP is best known for simplifying the tools side of that equation. Instead of manually writing code for each tool in a custom format, MCP defines a consistent schema and communication pattern. Think of it as a universal adapter (like USB-C) for tooling.</p>
<p><a href="http://www.youtube.com/watch?v=eur8dUO9mvE"><img src="https://i.ytimg.com/vi/eur8dUO9mvE/hqdefault.jpg" alt="VIDEO: What is MCP? Integrate AI Agents with Databases &amp; APIs"></a></p>
<p>MCP usually involves three components: a host application, an MCP client, and one or more MCP servers. The host might be a chat app or IDE (like Cursor) that includes an MCP client capable of connecting to different servers. These servers expose tools, prompts, samples, or resources.</p>
<p>The way you interact with the LLM doesn’t change. What changes is how the tools are surfaced to it. The agentic application talks to the MCP client, which talks to the right server. Tools are described in a format the LLM can use.</p>
<p><img src="/images/your-llm-does-not-care-about-mcp/tool-calling-flow-mcp.png" alt="Tool Calling flow interaction with a LLM and MCP"></p>
<p>For the same question, &quot;What’s the weather in San Jose, CA?&quot;, the LLM will still get the same list of tools. And based on that list it will tell you what tool to call, how that tool is called is up to the developer. When using MCP, that tool will be called using MCP.</p>
<p>The benefit here isn’t for the LLM, it’s for you as the developer. MCP helps manage complexity of working with many different tools as your agent grows. It makes it easier to reuse tools across projects, enforce consistent formats, and plug into new systems without rewriting everything.</p>
<p>But the LLM will never know you are using MCP, unless you are letting it know in the system prompt of tool definitions. You, the developer, is responsible for calling the tools. The LLM only generates a snippet of what tool(s) to call with which input parameters.</p>
<p>Next, let’s look at how this fits into the bigger picture of context engineering, and why abstraction layers like MCP make things easier for humans, not models.</p>
<h2>Context Engineering</h2>
<p>Context engineering is about giving your LLM the right inputs so it can generate useful outputs. That sounds simple, but it’s actually one of the most important parts of building effective AI systems.</p>
<p>When you ask a model a question, you’re really giving it a prompt -- a block of text it uses to predict the next block of text. The quality of that prompt directly affects the quality of the response.</p>
<p>This is where tools come in. Sometimes the model doesn’t have enough context to answer a question well. Maybe it needs real-time data, access to user profiles, or the ability to take action on behalf of the user. Tool calling lets you solve that by giving the model access to external systems, as you learned in this blog post.</p>
<p>But again, the model doesn’t need to know how those tools work. It just needs to know that they exist, what they’re for, and how to call them. That’s where context engineering meets tool design, you’re crafting a set of tool definitions that serve as part of the model’s prompt.</p>
<p><img src="/images/your-llm-does-not-care-about-mcp/overview.png" alt="Tool Calling as seen by a LLM"></p>
<p>MCP makes that process cleaner and more repeatable. Instead of hardcoding tools or writing ad hoc wrappers, you define a structured interface once and expose it through MCP. The LLM still sees the same types of tool definitions, but now they’re easier to maintain and scale.</p>
<p>So in the end, MCP is a tool for us developers, not for the LLM. It helps us build more reliable, modular systems. And it helps us focus on context engineering without reinventing the plumbing every time.</p>
<h2>Where to go from here?</h2>
<ul>
<li><a href="/blog/build-your-first-mcp-server-with-typescript-in-under-10-minutes">Learn how to build a MCP Server in &lt;10 minutes</a></li>
<li><a href="/blog/build-test-mcp-server-typescript-mcp-inspector">Test MCP Servers using MCP Inspector</a></li>
</ul>
<p>If you found this tutorial helpful, don’t forget to share it with your network. For more content on AI and web development, subscribe to my <a href="https://www.youtube.com/@gethackteam?sub_confirmation=1">YouTube channel</a> and connect with me on <a href="https://linkedin.com/in/gethackteam">LinkedIn</a>, <a href="https://x.com/gethackteam">X</a> or <a href="https://bsky.app/profile/gethackteam.bsky.social">Bluesky</a>.</p>
]]>
        </content:encoded>
    </item>
      <item>
        <title><![CDATA[Build & Test a Model Context Protocol (MCP) Server with TypeScript and MCP Inspector]]></title>
        <link>https://hackteam.io/blog/build-test-mcp-server-typescript-mcp-inspector</link>
        <pubDate>2025-06-14T00:00:00.000Z</pubDate>
        <guid isPermaLink="false">https://hackteam.io/blog/build-test-mcp-server-typescript-mcp-inspector</guid>
        <media:content
          url="https://i.ytimg.com/vi/TMmin7oZ84w/hqdefault.jpg"
        />
        <description>
        <![CDATA[In this tutorial, we’ll show you how to build and test a Model Context Protocol (MCP) server using TypeScript, with the help of LLMs and the MCP Inspector.]]>
        </description>
        <content:encoded>
        <![CDATA[<p>Building MCP servers can be stressful and time-consuming. This is why you should use a combination of both LLMs and the MCP Inspector to assist you while building your MCP server. The MCP Inspector is a tool that can help you with this process by letting you test MCP servers in a similar way as you would test APIs. LLMs, on the other hand, can provide you with suggestions and guidance as you build your server, and help you debug issues that may arise during the build process.</p>
<p>We'll walk through the full process of building an MCP server for Open Library, a free and open-source book catalog API. You'll learn how to:</p>
<ul>
<li>Build a TypeScript-based MCP server</li>
<li>Use the MCP Inspector to validate server responses</li>
<li>Leverage LLMs for suggestions and debugging</li>
<li>Integrate Open Library’s public API into your MCP setup</li>
</ul>
<p>Click the image below to watch the <a href="http://www.youtube.com/watch?v=TMmin7oZ84w">YouTube video version</a>:</p>
<p><a href="http://www.youtube.com/watch?v=TMmin7oZ84w"><img src="https://i.ytimg.com/vi/TMmin7oZ84w/hqdefault.jpg" alt="VIDEO: Build &amp; Test a MCP Server with TypeScript and MCP Inspector"></a></p>
<h2>Introduction</h2>
<p><strong><a href="https://hackteam.io/blog/build-your-first-mcp-server-with-typescript-in-under-10-minutes/">Learn more about the Model Context Protocol (MCP)</a></strong></p>
<p>In this tutorial, we'll be building an MCP server for Open Library, an open, editable library catalog with a public API. Using the API, you can search and browse through a vast collection of books, authors, publishers, and more. Open Library is a project from the Internet Archive and can be thought of as the &quot;Wikipedia for books&quot;. Furthermore, we'll use MCP Inspector and Claude Desktop to test the MCP server while building it.</p>
<h2>Building a MCP server</h2>
<p>As we'll be using the Node.js SDK for the MCP server, we'll need to install it first. You can do this by running the following commands in your terminal:</p>
<pre><code class="language-bash">npm init -y
npm i @modelcontextprotocol/sdk zod
npm i --save-dev typescript
</code></pre>
<p>This will set up a new Node.js project with a package.json file. We'll also need to install the Zod library, which is used for defining and validating types in TypeScript -- which is the other dependency we just installed.</p>
<p>In the package.json file, we'll need to add a &quot;type&quot;: &quot;module&quot; property. This tells Node.js that our project is using ES modules instead of CommonJS. Also, we'll add a few scripts to run the project:</p>
<pre><code class="language-json">{
  &quot;name&quot;: &quot;mcp-open-library&quot;,
  &quot;version&quot;: &quot;0.1.0&quot;,
  &quot;description&quot;: &quot;A Model Context Protocol server for Open Library&quot;,
  &quot;private&quot;: true,
  &quot;type&quot;: &quot;module&quot;,
  &quot;bin&quot;: {
    &quot;mcp-open-library&quot;: &quot;./build/index.js&quot;
  },
  &quot;files&quot;: [&quot;build&quot;],
  &quot;scripts&quot;: {
    &quot;build&quot;: &quot;tsc &amp;&amp; node -e \&quot;require('fs').chmodSync('build/index.js', '755')\&quot;&quot;,
    &quot;prepare&quot;: &quot;npm run build&quot;,
    &quot;watch&quot;: &quot;tsc --watch&quot;,
    &quot;inspector&quot;: &quot;npx @modelcontextprotocol/inspector build/index.js&quot;
  }
  //...
}
</code></pre>
<p>As you can see in the above code snippet, I've named the project <code>mcp-open-library</code> and set its version to <code>1.0.0</code>. Also, we have scripts to build the code (both <code>build</code> and <code>watch</code>) and to run the project using the <code>inspector</code> script.</p>
<p>In a new file called <code>src/index.ts</code> you should add the following code:</p>
<pre><code class="language-ts">import { McpServer } from &quot;@modelcontextprotocol/sdk/server/mcp.js&quot;;
import { StdioServerTransport } from &quot;@modelcontextprotocol/sdk/server/stdio.js&quot;;
import { z } from &quot;zod&quot;;

const server = new McpServer({ name: &quot;mcp-open-library&quot;, version: &quot;1.0.0&quot; });

server.tool(
  &quot;search_books&quot;,
  `
  Search for books on the Open Library API.
  `,
  {
    q: z.string(),
  },
  async ({ q }) =&gt; {
    const data = await fetch(
      `https://openlibrary.org/search.json?q=${q}&amp;limit=20`
    );
    const json = await data.json();

    return {
      content: [
        {
          type: &quot;text&quot;,
          text: JSON.stringify(json),
        },
      ],
    };
  }
);

await server.connect(new StdioServerTransport());
</code></pre>
<p>This code is a bit more complex than the previous example, but it's still pretty straightforward. We're creating an instance of the <code>McpServer</code> class and setting its name to &quot;mcp-open-library&quot; and version to &quot;1.0.0&quot;. Then we add a tool called &quot;search_books&quot; that takes a query string as input and returns a list of books from the <a href="https://openlibrary.org/dev/docs/api/search">Open Library Search API</a>. Later on in this tutorial we'll add more information about how to use this tool later on, but the value of <code>q</code> can be either a search term (like <code>rowling</code> for finding results about J.K. Rowling) or a search term prefixed with a category like <code>author</code> or <code>title</code>.</p>
<p>We then connect to a server using the <code>StdioServerTransport</code> class, which allows us to run our server in an interactive shell. Finally, we export the server instance so that it can be used by other scripts.</p>
<h2>Try out a MCP server in MCP Inspector</h2>
<p>To try this MCP server, you need first need to build and compile the code by running the following command in your terminal:</p>
<pre><code class="language-bash">npm run watch
</code></pre>
<p>(You could also run <code>npm run build</code> but it will only run once, means you'll have to run it again after every change in your code).</p>
<p>Once you've built and compiled your code, you can run the server by running the following command in ANOTHER terminal window or tab:</p>
<pre><code class="language-bash">npm run inspector
</code></pre>
<p>This will start MCP Inspector running on a local server, and you can connect to it by opening the following URL in your browser <code>http://127.0.0.1:6274</code>.</p>
<p>Here, you would first need to connect to the MCP server:</p>
<ul>
<li>In the left menu select <code>stdio</code> under &quot;Transport type&quot;</li>
<li>Under &quot;Command&quot; type <code>node</code></li>
<li>Under &quot;Arguments&quot;, type <code>build/index.js</code></li>
<li>Press &quot;Connect&quot; to connect to the MCP server</li>
</ul>
<p>The MCP Inpector will automatically list all the tools available on the MCP server, and you can try them out by selecting one and pressing &quot;Run tool&quot;.</p>
<p>For example, to use the Open Library tool, you would select it from the list of tools, provide a value for <code>q</code> (like <code>author:rowling</code>) and press &quot;Run tool&quot;. This wil call the Open Library tool and display the results in the MCP inspector, as you can see in the screenshot below:</p>
<p><img src="/images/build-test-mcp-server-typescript-mcp-inspector-view1.png" alt="MCP Inspector via stdio overview"></p>
<p>In the MCP inspector you can also find the history of all the tools you've run, and you can also find the response for each tool.</p>
<h2>Iterating on the server</h2>
<p>You can also iterate on the server by modifying the code. For example, we can limit the amount of data returned by the tool and handle pagination to see more than just 20 results.</p>
<p>First, let's add the <code>page</code> and <code>limit</code> arguments to the tool:</p>
<pre><code class="language-ts">  {
    q: z.string(),
    limit: z.number().default(20),
    page: z.number().default(1),
  },
</code></pre>
<p>The values for <code>limit</code> and <code>page</code> are optional, so we can set a default value for both.</p>
<p>And then pass these arguments to the <code>fetch</code> call:</p>
<pre><code class="language-ts">  async ({ q, limit, page }) =&gt; {
    const data = await fetch(
      `https://openlibrary.org/search.json?q=${q}&amp;limit=${limit}&amp;page=${page}`
    );
</code></pre>
<p>If you still have the command <code>npm run watch</code> running in your terminal you can restart the MCP inspector and see you can now add values for <code>page</code> and <code>limit</code> to see more results.</p>
<p>We also need to clean up the response of the tool, as it includes many fields we don't need. Remember, every character returned by the tool will be shared with the LLM you connect it to. This means that more characters increase your token count and thereby costs.</p>
<p>In the callback function we can add the following:</p>
<pre><code class="language-ts">const json = await data.json();
let books = [];

if (json?.docs?.length &gt; 0) {
  books = json.docs.map((book: any) =&gt; {
    const title = book.title;
    const author_name = book.author_name.join(&quot;, &quot;);
    const first_publish_year = book.first_publish_year;
    const id = book.lending_edition_s;

    return { id, title, author_name, first_publish_year };
  });
}

return {
  content: [
    {
      type: &quot;text&quot;,
      text: JSON.stringify(books),
    },
  ],
};
</code></pre>
<p>From the MCP inspector you can now see way less data is returned from the tool compared to before. This is because we are now only returning a subset of the data.</p>
<p>Finally, let's add some extra informaiton for the LLM before we use the tool in a MCP client like Claude Desktop. Add the following to the tool description:</p>
<pre><code class="language-md">Use the following format:

  q=title:flammable will find any books with &quot;flammable&quot; in the title field
  q=author:solnit will find authors with &quot;solnit&quot; in their name
  q=subject:tennis rules will find any books about &quot;tennis&quot; AND &quot;rules&quot;
  q=place:lisbon will find books about Lisbon
  q=person:rosa parks will look for people with rosa AND parks in their name
  q=language:spa will find any books with at least one edition in Spanish (most other language codes use the first three letters of the language except for Japanese which uses jpn There is also mul for multiple languages and und for undetermined)
  q=publisher:harper will looks for any books published by a publisher with &quot;harper&quot; in their name. (Publisher has never been a controlled field in the library world, so you can see we have a ton of variants of this famous publisher in the search facets.)
  q=publish_year:[* TO 1800] will find anything published before and up to the year 1800.

  You can also blend them together:

  q=subject:travel place:istanbul will look for books about travel in Istanbul.
  q=subject:dogs subject:(&quot;Juvenile fiction&quot; OR &quot;Juvenile literature&quot;) will look for children's books about dogs.
</code></pre>
<p>This description is a bit long, but it gives the LLM all the options on how to use the book search tool. You can try out these combinations in MCP Inspector yourself and remove any that you ecpect not to use.</p>
<h2>Connect to a MCP Client</h2>
<p>Now we have our server ready for use, let's connect to it from an MCP client. We'll start with the simplest possible example:</p>
<p>To use with Claude Desktop, open the server config:</p>
<ul>
<li>On MacOS: <code>/Users/USER_NAME/Library/Application Support/Claude/claude_desktop_config.json</code></li>
<li>On Windows: <code>%APPDATA%/Claude/claude_desktop_config.json</code></li>
</ul>
<p>And add the following config:</p>
<pre><code class="language-json">{
  &quot;mcpServers&quot;: {
    &quot;mcp-open-libary&quot;: {
      &quot;command&quot;: &quot;node&quot;,
      &quot;args&quot;: [&quot;/path/to/mcp-open-library/build/index.js&quot;]
    }
  }
}
</code></pre>
<p>You can now open Claude Desktop and you would see the new MCP server list. If you had Claude Desktop open before editing the config, you'll need to restart it for the changes to take effect.</p>
<p>Let's start with a simple query: &quot;Retrieve all books written by JK Rowling&quot;. Claude should see the server we just set up and return the results.</p>
<p>We can also use Claude Desktop to run more complex queries against our MCP server. For example, let's try asking this question: &quot;Show me books about wizards that take place in the United Kingdom&quot;.</p>
<p>Interacting with Claude Desktop will require you to approve the suggested tool call to the MCP server, this looks something like the following:</p>
<p><img src="/images/build-your-first-mcp-server-with-typescript-in-under-10-minutes-claude-desktop04.png" alt="MCP server tool details in Claude Deskop"></p>
<p>The tool calls that Claude now generates are more complex than a simple query and will be able to generate multiple queries for you. For example, it can generate a list of all books about wizards written by JK Rowling, or a list of all books about wizards that take place in the United Kingdom.</p>
<p>The search queries it generated are:</p>
<pre><code class="language-bash">`q`: `subject:wizards place:\&quot;united kingdom\&quot;`
</code></pre>
<p>And</p>
<pre><code class="language-bash">`q`: `subject:(wizards OR magic) place:(britain OR england OR \&quot;united kingdom\&quot; OR scotland)`
</code></pre>
<p>This will return a list of books that include the Harry Potter series but also the &quot;The Chronicles of Narnia&quot; series by C.S. Lewis (1950) and &quot;Northern Lights&quot; (part of &quot;His Dark Materials&quot;) by Philip Pullman (1995).</p>
<h2>What's next?</h2>
<p>Building MCP servers becomes significantly easier when leveraging both LLMs and the MCP Inspector. They provide guidance and testing capabilities, helping you build efficient and reliable MCP servers faster.</p>
<p>If you found this tutorial helpful, don’t forget to share it with your network. For more content on AI and web development, subscribe to my <a href="https://www.youtube.com/@gethackteam?sub_confirmation=1">YouTube channel</a> and connect with me on <a href="https://linkedin.com/in/gethackteam">LinkedIn</a>, <a href="https://x.com/gethackteam">X</a> or <a href="https://bsky.app/profile/gethackteam.bsky.social">Bluesky</a>.</p>
]]>
        </content:encoded>
    </item>
      <item>
        <title><![CDATA[Build Your First MCP Server with TypeScript]]></title>
        <link>https://hackteam.io/blog/build-your-first-mcp-server-with-typescript-in-under-10-minutes</link>
        <pubDate>2024-12-12T00:00:00.000Z</pubDate>
        <guid isPermaLink="false">https://hackteam.io/blog/build-your-first-mcp-server-with-typescript-in-under-10-minutes</guid>
        <media:content
          url="https://i.ytimg.com/vi/8m-O_KiHRjk/hqdefault.jpg"
        />
        <description>
        <![CDATA[Learn how to set up your first MCP server with TypeScript. This step-by-step guide walks you through the basics of the Model Context Protocol and how to connect AI agents to your tools and data.]]>
        </description>
        <content:encoded>
        <![CDATA[<p>If you're building AI agents, you've probably heard of MCP (short for &quot;Model Context Protocol&quot;), a new open-source protocol for connecting agents to your data. MCP was created by Anthropic as an open specification, now being adopted by many tech companies. This tutorial will guide you through setting up your first MCP server using TypeScript. By the end, you'll be ready to build and connect tools to an MCP host like Claude Desktop.</p>
<h3>What You'll Learn:</h3>
<ul>
<li>Install and set up an MCP server with TypeScript</li>
<li>Define custom tools for your MCP server</li>
<li>Execute tools using the MCP protocol</li>
<li>Integrate your MCP server with a host such as Claude Desktop</li>
</ul>
<p>Click the image below to watch the <a href="http://www.youtube.com/watch?v=8m-O_KiHRjk">YouTube video version</a>:</p>
<p><a href="http://www.youtube.com/watch?v=8m-O_KiHRjk"><img src="https://i.ytimg.com/vi/8m-O_KiHRjk/hqdefault.jpg" alt="VIDEO: Build Your First MCP Server in TypeScript"></a></p>
<h2>What is MCP?</h2>
<p>The <a href="https://modelcontextprotocol.io/introduction">Model Context Protocol (MCP)</a> simplifies the process of enabling AI agents to interact with various tools. MCP consists of three main components:</p>
<ul>
<li><strong>MCP Servers</strong>: These act as bridges to connect APIs, databases, or code. They expose data sources as tools to the host and can be built using Python or TypeScript SDKs.</li>
<li><strong>MCP Clients</strong>: These clients use the protocol to interact with MCP servers. Like servers, they can be developed using SDKs in Python or TypeScript.</li>
<li><strong>MCP Hosts</strong>: These systems manage communication between servers and clients, ensuring smooth data exchange. Popular hosts include <a href="https://claude.ai/download">Claude Desktop</a>, <a href="https://zed.dev/">Zed</a>, and <a href="https://sourcegraph.com/cody">Sourcegraph Cody</a>.</li>
</ul>
<p><img src="/images/build-your-first-mcp-server-with-typescript-in-under-10-minutes-diagram.png" alt="MCP server diagram"></p>
<p>The tools provided by an MCP server can be accessed via any MCP host, allowing developers to connect AI agents to new tools without the need for custom integration code.</p>
<h2>Setting Up an MCP Server</h2>
<p>In this tutorial, we'll focus on building an MCP server using the TypeScript SDK. We’ll use Claude Desktop as our host for testing.</p>
<h3>Step 1: Install Dependencies</h3>
<p>Begin by creating a new project and initializing an npm package. Add the necessary dependencies for the MCP server and TypeScript. Ensure your project includes configuration files like <code>package.json</code> and <code>tsconfig.json</code>:</p>
<pre><code class="language-bash">mkdir mcp-server
cd mcp-server
</code></pre>
<p>Create a <code>package.json</code> file:</p>
<pre><code class="language-json">{
  &quot;name&quot;: &quot;mcp-server&quot;,
  &quot;version&quot;: &quot;0.1.0&quot;,
  &quot;description&quot;: &quot;A Model Context Protocol server example&quot;,
  &quot;private&quot;: true,
  &quot;type&quot;: &quot;module&quot;,
  &quot;bin&quot;: {
    &quot;mcp-server&quot;: &quot;./build/index.js&quot;
  },
  &quot;files&quot;: [
    &quot;build&quot;
  ],
  &quot;scripts&quot;: {
    &quot;build&quot;: &quot;tsc &amp;&amp; node -e \&quot;require('fs').chmodSync('build/index.js', '755')\&quot;&quot;,
    &quot;prepare&quot;: &quot;npm run build&quot;,
    &quot;watch&quot;: &quot;tsc --watch&quot;,
    &quot;inspector&quot;: &quot;npx @modelcontextprotocol/inspector build/index.js&quot;
  },
  &quot;dependencies&quot;: {
    &quot;@modelcontextprotocol/sdk&quot;: &quot;0.6.0&quot;
  },
  &quot;devDependencies&quot;: {
    &quot;@types/node&quot;: &quot;^20.11.24&quot;,
    &quot;typescript&quot;: &quot;^5.3.3&quot;
  }
}
</code></pre>
<p>Create a <code>tsconfig.json</code> file:</p>
<pre><code class="language-json">{
  &quot;compilerOptions&quot;: {
    &quot;target&quot;: &quot;ES2022&quot;,
    &quot;module&quot;: &quot;Node16&quot;,
    &quot;moduleResolution&quot;: &quot;Node16&quot;,
    &quot;outDir&quot;: &quot;./build&quot;,
    &quot;rootDir&quot;: &quot;./src&quot;,
    &quot;strict&quot;: true,
    &quot;esModuleInterop&quot;: true,
    &quot;skipLibCheck&quot;: true,
    &quot;forceConsistentCasingInFileNames&quot;: true
  },
  &quot;include&quot;: [&quot;src/**/*&quot;],
  &quot;exclude&quot;: [&quot;node_modules&quot;]
}
</code></pre>
<p>Run the following command to install dependencies:</p>
<pre><code class="language-bash">npm install
</code></pre>
<h3>Step 2: Write Boilerplate Code</h3>
<p>Create a file <code>src/index.ts</code> and add the following boilerplate code:</p>
<pre><code class="language-typescript">import { Server } from &quot;@modelcontextprotocol/sdk/server/index.js&quot;;
import { StdioServerTransport } from &quot;@modelcontextprotocol/sdk/server/stdio.js&quot;;
import {
  CallToolRequestSchema,
  ErrorCode,
  ListToolsRequestSchema,
  McpError,
} from &quot;@modelcontextprotocol/sdk/types.js&quot;;

const server = new Server({
  name: &quot;mcp-server&quot;,
  version: &quot;1.0.0&quot;,
}, {
  capabilities: {
    tools: {}
  }
});

server.setRequestHandler(ListToolsRequestSchema, async () =&gt; {
  return { tools: [] };
});

server.setRequestHandler(CallToolRequestSchema, async (request) =&gt; {
  if (request.params.name === &quot;name_of_tool&quot;) {
    return {};
  }
  throw new McpError(ErrorCode.ToolNotFound, &quot;Tool not found&quot;);
});

const transport = new StdioServerTransport();
await server.connect(transport);
</code></pre>
<h3>Step 3: Define and Add Tools</h3>
<p>Define a tool schema and its execution logic. For example, to add a tool that calculates the sum of two numbers:</p>
<pre><code class="language-typescript">server.setRequestHandler(ListToolsRequestSchema, async () =&gt; {
  return {
    tools: [{
      name: &quot;calculate_sum&quot;,
      description: &quot;Add two numbers together&quot;,
      inputSchema: {
        type: &quot;object&quot;,
        properties: {
          a: { type: &quot;number&quot; },
          b: { type: &quot;number&quot; }
        },
        required: [&quot;a&quot;, &quot;b&quot;]
      }
    }]
  };
});

server.setRequestHandler(CallToolRequestSchema, async (request) =&gt; {
  if (request.params.name === &quot;calculate_sum&quot;) {
    const { a, b } = request.params.arguments;
    return { toolResult: a + b };
  }
  throw new McpError(ErrorCode.ToolNotFound, &quot;Tool not found&quot;);
});
</code></pre>
<h3>Step 4: Integrate with Claude Desktop</h3>
<p>Register the MCP server in <code>claude_desktop_config.json</code>:</p>
<pre><code class="language-json">{
  &quot;mcpServers&quot;: {
    &quot;mcp-server&quot;: {
      &quot;command&quot;: &quot;node&quot;,
      &quot;args&quot;: [
        &quot;/Users/YOUR_USER/mcp-server/build/index.js&quot;
      ]
    }
  }
}
</code></pre>
<p>Restart Claude Desktop to see the tools listed.</p>
<p><img src="/images/build-your-first-mcp-server-with-typescript-in-under-10-minutes-claude-desktop01.png" alt="MCP server tools in Claude Desktop"></p>
<p>You can click on the &quot;tools&quot; button to see the name and description of the available tools, including the MCP server that provided the tool:</p>
<p><img src="/images/build-your-first-mcp-server-with-typescript-in-under-10-minutes-claude-desktop02.png" alt="MCP server tool details in Claude Deskop"></p>
<p>After verifying the MCP server and the tool are available, you can start asking a question that would trigger a call to the <code>calculate_sum</code> tool, such as:</p>
<pre><code class="language-bash">What is the sum of 9999 + 1?
</code></pre>
<p>When you press &quot;enter,&quot; it should start generating your answer. If a tool is found that matches your question, you will be asked to grant Claude access to call that tool. This process is called &quot;human in the loop&quot; and will prevent malicious tool calls:</p>
<p><img src="/images/build-your-first-mcp-server-with-typescript-in-under-10-minutes-claude-desktop03.png" alt="Tool use in Claude Desktop"></p>
<p>If granted access, Claude will use the tool &quot;calculate_sum&quot; to add up the two numbers and print the result (which is <em>10000</em>) in the chat.</p>
<h3>4. Calling a REST API as a tool</h3>
<p>Besides executing code in the MCP server, you can also retrieve remote data from a source such as an API. Let's use a mock REST API from <a href="https://httpbin.org/#/Response_formats/get_json">httpbin.org</a> that returns JSON data about a mock slideshow.</p>
<p>In the file <code>src/index.ts</code> you need to add the following code to define the tool:</p>
<pre><code class="language-ts">// Define available tools
server.setRequestHandler(ListToolsRequestSchema, async () =&gt; {
  return {
    tools: [
      { 
        // calculate_sum tool definition
      },
      {
        name: &quot;httpbin_json&quot;,
        description: &quot;Returns data about slide show&quot;,
        inputSchema: {
          type: &quot;object&quot;,
          properties: {
            id: { type: &quot;number&quot; }
          },
          required: []
        }
      }
    ]
  };
});
</code></pre>
<p>As you can see in the <a href="http://www.youtube.com/watch?v=8m-O_KiHRjk">video recording</a> of this tutorial, I used Claude Desktop to generate the code to execute this REST API request. You need to add this code to <code>src/index.ts</code> too:</p>
<pre><code class="language-ts">// Handle tool execution
server.setRequestHandler(CallToolRequestSchema, async (request) =&gt; {
  if (request.params.name === &quot;calculate_sum&quot;) {
   // ...
  }
  if (request.params.name === &quot;httpbin_json&quot;) {
    try {
      const response = await fetch('https://httpbin.org/json', {
        method: 'GET',
        headers: {
          'accept': 'application/json'
        }
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const data = await response.json();

      return ({
        toolResult: data
      })
    } catch (e) {
      throw new Error(&quot;Something went wrong&quot;);
    }

    throw new Error(&quot;Tool not found&quot;);
});
</code></pre>
<p>Once you've added both pieces of code, make sure to build the MCP server code again by running:</p>
<pre><code class="language-bash">npm run build
</code></pre>
<p>You don't need to make any changes to the Claude Desktop configuration this time, as we did not update the MCP server but only the tools for this server. You do have to <strong>close and restart</strong> Claude Desktop, as otherwise it doesn't pick up the newly built code.</p>
<p>After restarting Claude Desktop, you should see that there are two tools available now, and you can ask a question like:</p>
<pre><code class="language-bash">Give me more details about the latest slideshow
</code></pre>
<p>After pressing &quot;enter&quot; you'll be asked to give Claude access to the new <code>httpbin_json</code> tool:</p>
<p><img src="/images/build-your-first-mcp-server-with-typescript-in-under-10-minutes-claude-desktop04.png" alt="REST API as a tool in Claude Desktop"></p>
<p>Once granted access, the MCP host will initiate a tool call to the MCP server. The MCP server will call the <code>httpbin.org</code> mock REST API and return the result back to the MCP host.</p>
<h2>What's next?</h2>
<p>he Model Context Protocol represents more than just a technical specification—it's a model for connecting your data sources to AI agents across different applications. While MCP simplifies integration, there are still areas where developers need to provide additional support, such as caching, authentication, and scalability.</p>
<p>One of the key next steps is to explore advanced integrations. For instance, combining MCP with a tool library or platform like <a href="https://ibm.biz/wxflows">IBM watsonx.ai Flows Engine</a> can provide an even better tool development experience. This platform allows you to transform any data source into a tool and deploy it to a GraphQL endpoint. From there, tools can easily connect to AI agents or be integrated into MCP hosts.</p>
<p>If you found this tutorial helpful, don’t forget to share it with your network. For more content on AI and web development, subscribe to my <a href="https://www.youtube.com/@gethackteam?sub_confirmation=1">YouTube channel</a> and connect with me on <a href="https://linkedin.com/in/gethackteam">LinkedIn</a>, <a href="https://x.com/gethackteam">X</a> or <a href="https://bsky.app/profile/gethackteam.bsky.social">Bluesky</a>.</p>
]]>
        </content:encoded>
    </item>
      <item>
        <title><![CDATA[Build AI Applications With LangChain, JavaScript, and React]]></title>
        <link>https://hackteam.io/blog/build-ai-applications-langchain-javascript-react</link>
        <pubDate>2024-02-19T00:00:00.000Z</pubDate>
        <guid isPermaLink="false">https://hackteam.io/blog/build-ai-applications-langchain-javascript-react</guid>
        <media:content
          url="https://i.ytimg.com/vi/_jIXRkGVQOo/hqdefault.jpg"
        />
        <description>
        <![CDATA[Coding tutorial showing how to use LangChainJS to build AI applications with JavaScript and React. We code a ChatGPT clone from scratch with Vite and OpenAI models.]]>
        </description>
        <content:encoded>
        <![CDATA[<p>As a software developer seeking to accelerate development and incorporate AI into products, integrating tools like LangChain into your workflow is an exciting prospect. This post will provide a guide for developers on leveraging LangChain to execute prompting with OpenAI models.</p>
<p>We will walk through:</p>
<ul>
<li>Setting up a React app with Vite</li>
<li>Installing and configuring LangChain</li>
<li>Connecting to the OpenAI API</li>
<li>Building a query function with LangChain</li>
<li>Handling form submission to interface with the AI</li>
</ul>
<p>Click the image below to watch the <a href="http://www.youtube.com/watch?v=_jIXRkGVQOo">YouTube video version</a> of this blog post:</p>
<p><a href="http://www.youtube.com/watch?v=_jIXRkGVQOo"><img src="https://i.ytimg.com/vi/_jIXRkGVQOo/hqdefault.jpg" alt="VIDEO: Build AI Applications With LangChain, JavaScript, and React"></a></p>
<h2>Setting up a React app with Vite</h2>
<p><a href="/blog/vite-better-create-react-app-alternative">Vite</a> is a rapid frontend build tool for modern web development. For this tutorial, we use a basic Vite app styled similarly to ChatGPT - with a query box against an empty background ready to display questions and answers.</p>
<p>I've already created a boilerplate for this tutorial, which you can find <a href="https://github.com/royderks/ai-frontend-workshop/tree/main/my-gpt">here</a>.</p>
<p>You can check out the repository by running the following command in your terminal:</p>
<pre><code class="language-bash">git clone https://github.com/royderks/ai-frontend-workshop.git
</code></pre>
<p>After cloning the repository, you'll need to move into the new directory and install the dependencies.</p>
<pre><code class="language-bash">cd ai-frontend-workshop/my-gpt
npm install
</code></pre>
<p>Once you've got everything installed, open your project in whatever IDE you use – we're gonna go with Visual Studio Code here. The project folder is gonna look pretty familiar if you've ever dabbled with Create React App. You'll find static assets such as images in <code>public</code> and your React code in <code>src</code>. Plus, all the must-haves like <code>package.json</code> and <code>vite.config.js</code> are there. Oh, and TypeScript users, you haven’t been forgotten – there’s a <code>tsconfig.json</code> in there for you.</p>
<p>Ready to see your project live? Start your local development server with:</p>
<pre><code class="language-bash">npm run dev
</code></pre>
<p>And just like that, your Vite app is up and running in your browser. Which will look something like the screenshot you can see below.</p>
<p><img src="/images/langchain-vite-initial-chat-app.png" alt="Initial chat app with Vite"></p>
<p>You get hot-reloading and all the modern features that make coding less of a chore.</p>
<h2>Installing and configuring LangChain</h2>
<p>LangChainJS is a JavaScript library designed to integrate language AI capabilities into web and Node.js applications. LangChain began as a Python SDK but now has JavaScript and TypeScript support. By offering developers an easy-to-use interface to leverage Large Language Models (LLMs) like GPT-4, <a href="https://js.langchain.com/docs/get_started/introduction">LangChainJS</a> simplifies the process of incorporating advanced natural language understanding and generation into projects.</p>
<p>Popular use cases for LangChainJS are chatbots, automating content creation, enhancing search functionalities, or crafting personalized user experiences. You can do all of this with a limited amount of knowledge about LLMs as LangChain offers a set of abstractions on top of popular LLM providers such as OpenAI and IBM Watson.</p>
<p>Before installing LangChain, let's stop the dev server and run:</p>
<pre><code class="language-bash">npm install langchain @langchain/openai
</code></pre>
<p>This will install both the general LangChain library and the library needed to connect to OpenAI. In the next section, we'll be connecting to OpenAI for which we need to generate an API Key first.</p>
<h2>Connecting to OpenAI API</h2>
<p>OpenAI isn't only the creator of ChatGPT; it also has a platform where you can access the models used by ChatGPT. Developers can sign up for free, and often, will get a small credit of $5 to try out their APIs. On</p>
<p>the <a href="https://platform.openai.com/">OpenAI dashboard</a>, we will generate a new secret key to authenticate our app.</p>
<p>With our key secured, we create an environment file called <code>.env</code> to store it:</p>
<pre><code>VITE_OPENAI_API_KEY=&lt;your_key&gt;
</code></pre>
<p><em>We're using <code>VITE_</code> as a prefix so the environment variable gets picked up by Vite.</em></p>
<p>Now we can initialize the connection in a new file called <code>langchain.ts</code>:</p>
<pre><code class="language-ts">import { OpenAI } from &quot;@langchain/openai&quot;;

const llm = new OpenAI({
    openAIApiKey: import.meta.env.VITE_OPENAI_API_KEY,
});
</code></pre>
<p>After creating the connection to OpenAI, we can create a function to call the LLM and pass our question to retrieve the answer.</p>
<h2>Building a query function with LangChain</h2>
<p>There are multiple methods to query an LLM using LangChain, each of these methods will behave slightly differently. For this tutorial, we'll use the <code>invoke</code> method, one of the simplest and quickest available in LangChainJS.</p>
<p>With our connection configured, we can build out the query function in the same <code>langchain.ts</code> file:</p>
<pre><code class="language-js">import { OpenAI } from &quot;@langchain/openai&quot;;

const llm = new OpenAI({
    openAIApiKey: import.meta.env.VITE_OPENAI_API_KEY,
});

export async function getAnswer(question: string) {
    let answer = ''

    try {
        answer = await llm.invoke(question);
    } catch (e) {
        console.error(e);
    }

    return answer;
}
</code></pre>
<p>This async function takes the question, queries the API using LangChain's <code>invoke</code> method, and returns the answer. There's a try/catch block around the function so we can catch errors, for example, when we run out of tokens.</p>
<h2>Handling form submission to interface with the AI</h2>
<p>The final step to completing this tutorial is to use the <code>getAnswer</code> function in the user interface that we built in the first section. As we're using client-side React, we need to create a few state variables in <code>src/App.tsx</code> and import the <code>getAnswer</code> function from <code>langchain.ts</code>. Also, the <code>getAnswer</code> function needs to be wrapped in a function that we can connect to the <code>onSubmit</code> function of the text input for typing the question:</p>
<pre><code class="language-ts">import { useState } from &quot;react&quot;;
import { getAnswer } from &quot;./langchain&quot;;

export default function App() {
  const [question, setQuestion] = useState(&quot;&quot;);

  async function handleSubmit(e: React.FormEvent&lt;HTMLFormElement&gt;) {
    e.preventDefault();
    const result = await getAnswer(question);
    console.log(result);
  }

  // ...
</code></pre>
<p>We can now handle the submission of the question by adding this function to the <code>onSubmit</code> in the <code>form</code> element:</p>
<pre><code class="language-html">&lt;form
    className=&quot;stretch mx-2 flex flex-row gap-3 last:mb-2 md:mx-4 md:last:mb-6 lg:mx-auto lg:max-w-2xl xl:max-w-3xl&quot;
    onSubmit={handleSubmit}
&gt;
</code></pre>
<p>With that, our app can now interface with the AI! We can ask questions and see it return answers that are logged to the console. If you want to display the result in the user interface, you can create another state variable for the answer:</p>
<pre><code class="language-ts">import { useState } from &quot;react&quot;;
import { getAnswer } from &quot;./langchain&quot;;

export default function App() {
  const [question, setQuestion] = useState(&quot;&quot;);
  const [answer, setAnswer] = useState(&quot;&quot;);

  async function handleSubmit(e: React.FormEvent&lt;HTMLFormElement&gt;) {
    e.preventDefault();
    const result = await getAnswer(question);

    setAnswer(result);
  }
  
  // ...
</code></pre>
<p>The value for <code>answer</code> can be rendered anywhere in the user interface, for example, in a text balloon.</p>
<h2>What's next?</h2>
<p>Integrating LangChain opens up lots of possibilities for automating workflows, analyzing data, providing search functionality, and more. The contents of this tutorial should give you a good start in building your own AI integrations. Feel free to leave any questions below!</p>
<p>If you found this article useful, let me know on <a href="https://linkedin.com/in/gethackteam">LinkedIn</a>, <a href="https://x.com/gethackteam">X</a> or <a href="https://bsky.app/profile/gethackteam.bsky.social">Bluesky</a>. Please share it around the web or subscribe to my <a href="https://www.youtube.com/@gethackteam?sub_confirmation=1">YouTube channel</a> for more exciting content on web technologies.</p>
]]>
        </content:encoded>
    </item>
      <item>
        <title><![CDATA[Building a Project Management Board with React, TypeScript and Tailwind CSS]]></title>
        <link>https://hackteam.io/blog/building-project-management-board-trello-react-vitejs-typescript-tailwind</link>
        <pubDate>2023-12-14T00:00:00.000Z</pubDate>
        <guid isPermaLink="false">https://hackteam.io/blog/building-project-management-board-trello-react-vitejs-typescript-tailwind</guid>
        <media:content
          url="https://i.ytimg.com/vi/YmhPU9SR5hQ/hqdefault.jpg"
        />
        <description>
        <![CDATA[In this detailed live coding session, we walk through building a Trello-style project management board from scratch using React, TypeScript, and Tailwind CSS. The end result is an interactive drag and drop board for organizing tasks into different workflow stages.']]>
        </description>
        <content:encoded>
        <![CDATA[<p>Last year I released the second edition of my book <a href="https://www.amazon.com/React-Projects-cross-platform-professional-developer/dp/1801070636">React Projects</a>, and to celebrate this I'm sharing one of the projects from the book with you. In this detailed live coding session, we walk through building a Trello-style project management board from scratch using React, TypeScript, and Tailwind CSS. The end result is an interactive drag and drop board for organizing tasks into different workflow stages.</p>
<p>Click the image below to watch the <a href="https://www.youtube.com/watch?v=YmhPU9SR5hQ">YouTube video version</a> of this blog post:</p>
<p><a href="https://www.youtube.com/watch?v=YmhPU9SR5hQ"><img src="https://i.ytimg.com/vi/YmhPU9SR5hQ/hqdefault.jpg" alt="VIDEO: Build a Project Management Board like Trello | React Projects Chapter 3"></a></p>
<h2>Getting started</h2>
<p>Here's a high-level overview of what we'll cover:</p>
<ul>
<li>Setting up a new React project with Vite instead of Create React App</li>
<li>Creating React components for the header, board, lanes, and tasks</li>
<li>Passing data and functions between components</li>
<li>Implementing drag and drop using browser Web APIs</li>
<li>Replacing CSS with Tailwind classes</li>
</ul>
<p>You will need to have Node and npm installed on your machine.</p>
<h2>Setting up a new React project with Vite</h2>
<p><a href="https://vitejs.dev/guide/">Starting a new project</a> with Vite is as easy as running a single command:</p>
<pre><code class="language-bash">npx create-vite@latest
</code></pre>
<p>Upon running this command, you'll be prompted to answer a few questions, including the name for your new project. For this example, let's go with <code>project-board</code>. One of Vite's standout features is its compatibility with a range of JavaScript flavors and frameworks—not just React, but also Preact, Lit, Svelte, and even vanilla JavaScript. We select React as the framework, and opt to use TypeScript as well. Vite handles all the configuration for us and scaffolds the initial project files.</p>
<p>With the project generated, we need to move into the project directory and install the dependencies:</p>
<pre><code class="language-bash">cd project-board
npm install
</code></pre>
<p>After the installation is complete, we can start the development server:</p>
<pre><code class="language-bash">npm run dev
</code></pre>
<p>The starter Vite React app loads up in the browser, on the endpoint displayed in your terminal.</p>
<p><img src="/images/project-board-vite-starter-app.png" alt="The starter Vite React app"></p>
<p>Next step is to delete the boilerplate content, leaving just an &lt;h1&gt; with &quot;Project Board&quot; for our starting point. We also remove the <code>.svg</code> files and the import statement for it in <code>src/App.tsx</code>.</p>
<h2>Creating React components</h2>
<p>With a blank slate, we can begin creating React components for the major pieces of the project board:</p>
<ul>
<li><code>Header</code> - simple component that renders the title</li>
<li><code>Board</code> - main area that will contain the lanes</li>
<li><code>Lane</code> - vertical column for a stage in the workflow</li>
<li><code>Task</code> - draggable ticket/card that lives inside a lane</li>
</ul>
<p>Each component goes in its own file like <code>src/components/Header/Header.tsx</code>:</p>
<pre><code class="language-tsx">// src/components/Header/Header.tsx
export default function Header() {
    return (
        &lt;div className=&quot;Header&quot;&gt;
            &lt;h1&gt;Project Board&lt;/h1&gt;
        &lt;/div&gt;
    )
}
</code></pre>
<p>We can then import and render the <code>Header</code> component in <code>src/App.tsx</code>:</p>
<pre><code class="language-tsx">// src/App.tsx
import Header from './components/Header/Header'

export default function App() {
  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;Header /&gt;
    &lt;/div&gt;
  )
}
</code></pre>
<p>The <code>Board</code> component is next. It will contain the lanes, so we can start by creating a <code>Lane</code> component in a new file called <code>src/components/Lane/Lane.tsx</code>:</p>
<pre><code class="language-tsx">// src/components/Lane/Lane.tsx
export default function Lane() {
    return (
        &lt;div className=&quot;Lane&quot;&gt;
            &lt;h2&gt;Lane&lt;/h2&gt;
        &lt;/div&gt;
    )
}
</code></pre>
<p>And importing it into <code>Board</code>, which you can create a new file for at <code>src/components/Board/Board.tsx</code>:</p>
<pre><code class="language-tsx">// src/components/Board/Board.tsx
import Lane from '../Lane/Lane';

export default function Board() {
  return (
    &lt;div className=&quot;Board&quot;&gt;
      &lt;Lane /&gt;
      &lt;Lane /&gt;
      &lt;Lane /&gt;
      &lt;Lane /&gt;
    &lt;/div&gt;
  )
}
</code></pre>
<p>Next, we'll create the <code>Task</code> component in <code>src/components/Task/Task.tsx</code>:</p>
<pre><code class="language-tsx">// src/components/Task/Task.tsx
export default function Task() {
    return (
        &lt;div className=&quot;Task&quot;&gt;
            &lt;h3&gt;Task&lt;/h3&gt;
        &lt;/div&gt;
    )
}
</code></pre>
<p>And finally, we can import and render the <code>Board</code> component in <code>App.tsx</code>:</p>
<pre><code class="language-tsx">// src/App.tsx
import Header from './components/Header/Header';
import Board from './components/Board/Board';

function App() {
  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;Header /&gt;
      &lt;Board /&gt;
    &lt;/div&gt;
  )
}
</code></pre>
<p>From this point, we can start adding some basic styling to the components. We'll use &quot;plain old&quot; CSS for this first, and get to Tailwind CSS later:</p>
<ul>
<li>
<p><code>Board</code> - first create the styling file <code>src/components/Board/Board.css</code> and add the following:</p>
<pre><code class="language-css">/* src/components/Board/Board.css */
.Board {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  padding: 1rem;
  margin: 0 auto;
  max-width: 1200px;
}
</code></pre>
<p>And import it into <code>Board.tsx</code> at the top:</p>
<pre><code class="language-tsx">// src/components/Board/Board.tsx
import './Board.css';

// Everything else...
</code></pre>
</li>
<li>
<p><code>Lane</code> - create the styling file <code>src/components/Lane/Lane.css</code> and add the following:</p>
<pre><code class="language-css">/* src/components/Lane/Lane.css */
.Lane {
  background-color: #DBEAFE;
  border-radius: 0.5rem;
  flex: 1;
  margin: 0 0.5rem;
  padding: 1rem;
}
</code></pre>
<p>And import it into <code>Lane.tsx</code> at the top:</p>
<pre><code class="language-tsx">// src/components/Lane/Lane.tsx
import './Lane.css';

// Everything else...
</code></pre>
</li>
<li>
<p><code>Task</code> - create the styling file <code>src/components/Task/Task.css</code> and add the following:</p>
<pre><code class="language-css">/* src/components/Task/Task.css */
.Task {
  background-color: #fff;
  border-radius: 0.5rem;
  box-shadow: 0 0 0.5rem rgba(0, 0, 0, 0.1);
  margin: 0.5rem 0;
  padding: 1rem;
}
</code></pre>
<p>And import it into <code>Task.tsx</code> at the top:</p>
<pre><code class="language-tsx">// src/components/Task/Task.tsx
import './Task.css';

// Everything else...
</code></pre>
</li>
<li>
<p><code>Header</code> - create the styling file <code>src/components/Header/Header.css</code> and add the following:</p>
<pre><code class="language-css">/* src/components/Header/Header.css */
.Header {
  background-color: #e5e7eb;
  box-shadow: 0 0 0.5rem rgba(0, 0, 0, 0.1);
  padding: 1rem;
  text-align: center;
}
</code></pre>
<p>And import it into <code>Header.tsx</code> at the top:</p>
<pre><code class="language-tsx">// src/components/Header/Header.tsx
import './Header.css';

// Everything else...
</code></pre>
</li>
</ul>
<p>Make sure to import the CSS files into the components, otherwise the styles won't be applied, the application will look like this:</p>
<p><img src="/images/project-board-basic-styling.png" alt="Project Board with basic styling"></p>
<p>With the basic styling in place, we can start adding some content to the components to make them look more like a project management board.</p>
<h2>Passing data and functions between components</h2>
<p>To pass data and functions between components, we'll use props. In React, props are used to pass data from a parent component to a child component. Props are passed to components via HTML attributes, and are accessed in the component via the <code>props</code> object.</p>
<p>Let's start by adding some props to the <code>Lane</code> component. We'll add a <code>title</code> prop to the <code>Lane</code> component, and pass it in from the <code>Board</code> component. As we're using TypeScript, we'll also add a type for the <code>title</code> prop:</p>
<pre><code class="language-tsx">// src/components/Lane/Lane.tsx
import './Lane.css';

type LaneProps = {
    title: string;
}

export default function Lane({ title }: LaneProps) {
    return (
        &lt;div className=&quot;Lane&quot;&gt;
            &lt;h2&gt;{title}&lt;/h2&gt;
        &lt;/div&gt;
    )
}
</code></pre>
<p>And in the <code>Board</code> component, we'll pass in the <code>title</code> prop to each <code>Lane</code> component. We'll create an object for each lane, with an <code>id</code> and <code>title</code> property:</p>
<pre><code class="language-tsx">// src/components/Board/Board.tsx
import Lane from &quot;../Lane/Lane&quot;;

const lanes = [
    {
        id: 1,
        title: &quot;To Do&quot;,
    },
    {
        id: 2,
        title: &quot;In Progress&quot;,
    },
    {
        id: 3,
        title: &quot;Review&quot;,
    },
    {
        id: 4,
        title: &quot;Done&quot;,
    }
]

export default function Board() {
  return (
    &lt;div className=&quot;Board&quot;&gt;
      {lanes.map(lane =&gt; (
        &lt;Lane 
          key={lane.id} 
          id={lane.id}
          title={lane.title} 
        /&gt;
      ))}
    &lt;/div&gt;
  )
}
</code></pre>
<p>We're also passing the prop <code>id</code> to the <code>Lane</code> component, which we'll use later to identify the lane when we implement drag and drop. In the <code>Lane</code> component, we'll already create a type for the <code>id</code> prop:</p>
<pre><code class="language-tsx">// src/components/Lane/Lane.tsx
import './Lane.css';

type LaneProps = {
    id: number;
    title: string;
}

export default function Lane({ id, title }: LaneProps) {
    return (
        &lt;div className=&quot;Lane&quot;&gt;
            &lt;h2&gt;{title}&lt;/h2&gt;
        &lt;/div&gt;
    )
}
</code></pre>
<p>We can now see the lane titles in the browser, but first we'll add some task to fill our page a bit more. We'll use a basic state hook to store the tasks in the <code>Board</code> component:</p>
<pre><code class="language-tsx">// src/components/Board/Board.tsx
import { useState } from &quot;react&quot;;

// ...

export default function Board() {
    const [tasks, setTasks] = useState([
        {
            &quot;id&quot;: 1,
            &quot;title&quot;: &quot;Fix navigation bug&quot;,
            &quot;body&quot;: &quot;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque egestas dictum libero, vel tristique odio pulvinar vitae.&quot;,
            &quot;laneId&quot;: 1
        },
        {
            &quot;id&quot;: 2,
            &quot;title&quot;: &quot;Release new website&quot;,
            &quot;body&quot;: &quot;hasellus eleifend lacus vitae est ultrices placerat. Nunc at risus id risus venenatis laoreet sit amet cursus neque.&quot;,
            &quot;laneId&quot;: 2
        },
        {
            &quot;id&quot;: 3,
            &quot;title&quot;: &quot;Change button color&quot;,
            &quot;body&quot;: &quot;Suspendisse ac lorem a neque tempus luctus non aliquam sapien. Cras ut lacus bibendum, placerat nibh eu, tempus neque.&quot;,
            &quot;laneId&quot;: 3
        },
        {
            &quot;id&quot;: 4,
            &quot;title&quot;: &quot;Deploy server on acceptance environment&quot;,
            &quot;body&quot;: &quot;Pellentesque pharetra fermentum sapien, aliquet ultrices ligula mattis porttitor.&quot;,
            &quot;laneId&quot;: 3
        },
        {
            &quot;id&quot;: 5,
            &quot;title&quot;: &quot;Change layout for the content page&quot;,
            &quot;body&quot;: &quot;Cras tellus ligula, mattis at facilisis eu, ultricies vel elit. Ut aliquam volutpat lacus, a rutrum sem vulputate non.&quot;,
            &quot;laneId&quot;: 3
        },
        {
            &quot;id&quot;: 6,
            &quot;title&quot;: &quot;Complete the registration flow&quot;,
            &quot;body&quot;: &quot;In vel commodo ipsum. Duis id ipsum semper, condimentum ipsum sit amet, maximus massa.&quot;,
            &quot;laneId&quot;: 4
        },
        {
            &quot;id&quot;: 7,
            &quot;title&quot;: &quot;Create new database instance&quot;,
            &quot;body&quot;: &quot; Curabitur nec sem lorem. Donec venenatis, arcu vitae malesuada consequat, dolor ante placerat mi, in fermentum diam ipsum id libero.&quot;,
            &quot;laneId&quot;: 4
        }
    ])

    // Everything else...

}
</code></pre>
<p>The values in the <code>laneId</code> property correspond to the <code>id</code> of the lane. We'll use this to filter the tasks and render them in the correct lane. We'll pass the <code>tasks</code> state to the <code>Lane</code> component as a prop, and filter the tasks based on the <code>laneId</code>:</p>
<pre><code class="language-tsx">// src/components/Board/Board.tsx

// ...

export default function Board() {
    // ...

    return (
        &lt;div className=&quot;Board&quot;&gt;
            {lanes.map(lane =&gt; (
                &lt;Lane
                    key={lane.id}
                    id={lane.id}
                    title={lane.title}
                    tasks={tasks.filter(task =&gt; task.laneId === lane.id)}
                /&gt;
            ))}
        &lt;/div&gt;
    )
}
</code></pre>
<p>In the <code>Lane</code> component, we'll add a type for the <code>tasks</code> prop, and import the component we need to render the tasks in the lane:</p>
<pre><code class="language-tsx">// src/components/Lane/Lane.tsx
import './Lane.css';
import Task from &quot;../Task/Task&quot;;

type LaneProps = {
    id: number;
    title: string;
    tasks: {
        id: number;
        title: string;
        body: string;
        laneId: number;
    }[];
}

export default function Lane({ id, title, tasks }: LaneProps) {

  // ...

}
</code></pre>
<p>And render the tasks in the <code>Lane</code> component by mapping over the <code>tasks</code> prop and rendering a <code>Task</code> component for each task:</p>
<pre><code class="language-tsx">// src/components/Lane/Lane.tsx
// ...

export default function Lane({ id, title, tasks }: LaneProps) {
    return (
        &lt;div className=&quot;Lane&quot;&gt;
            &lt;h2&gt;{title}&lt;/h2&gt;
            &lt;div&gt;
                {
                    tasks.map((task) =&gt; {
                        return (
                            &lt;Task
                                key={task.id}
                                id={task.id}
                                title={task.title}
                                body={task.body}
                                laneId={task.laneId}
                            /&gt;
                        )
                    })
                }
            &lt;/div&gt;
        &lt;/div&gt;
    )
}
</code></pre>
<p>Finally, we need to update the <code>Task</code> component to accept the new props:</p>
<pre><code class="language-tsx">// src/components/Task/Task.tsx
import './Task.css';

type TaskProps = {
    id: number;
    title: string;
    body: string;
    laneId: number;
}

export default function  Task({ id, title, body, laneId }: TaskProps) {
    return (
        &lt;div className=&quot;Task&quot;&gt;
            &lt;h3&gt;{title}&lt;/h3&gt;
            &lt;p&gt;{body}&lt;/p&gt;
        &lt;/div&gt;
    )
}
</code></pre>
<p>In the browser, we can now see the tasks in the correct lanes:</p>
<p><img src="/images/project-board-with-tasks.png" alt="Project Board with tasks"></p>
<p>Fantastic! We now have a basic project board with lanes and tasks. Next, we'll implement drag and drop to make the tasks draggable between lanes.</p>
<h2>Implementing drag and drop using browser Web APIs</h2>
<p>To make the tasks draggable, we utilize the <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API">browser's native drag and drop API</a>. The drag and drop API consists of a set of events that are fired when a draggable element is dragged, dropped, or dragged over another element. We'll use the following events:</p>
<ul>
<li><code>dragstart</code> - fired when the user starts dragging an element</li>
<li><code>dragover</code> - fired when the user drags an element over another element</li>
<li><code>drop</code> - fired when the user drags an element over another element</li>
</ul>
<p>First, we'll create two functions that handle the <code>dragstart</code> and <code>dragover</code> events. This function will be called when the user starts dragging a task. We'll add the function to the <code>Board</code> component:</p>
<pre><code class="language-tsx">// src/components/Board/Board.tsx
// ...

function handleOnDragStart(event: React.DragEvent, id: number) {
    console.log('Drag event started', { id })
    event.dataTransfer.setData(&quot;id&quot;, id.toString());
}

function handleOnDragOver(event: React.DragEvent) {
    event.preventDefault();
}

export default function Board() {
    // ...

        return (
        &lt;div className=&quot;Board&quot;&gt;
            {lanes.map(lane =&gt; (
                &lt;Lane
                    key={lane.id}
                    id={lane.id}
                    title={lane.title}
                    tasks={tasks.filter(task =&gt; task.laneId === lane.id)}
                    handleOnDragStart={handleOnDragStart}
                    handleOnDragOver={handleOnDragOver}
                    handleOnDrop={handleOnDrop}
                /&gt;
            ))}
        &lt;/div&gt;
    )
}
</code></pre>
<p>The <code>handleOnDragStart</code> function takes two arguments: the <code>event</code> object and the <code>id</code> of the task. We'll use the <code>id</code> to identify the task when we drop it in another lane. The <code>handleOnDragOver</code> function takes only the <code>event</code> object as an argument. We'll use this function to prevent the default behavior of the <code>dragover</code> event, which is to not allow dropping on an element.</p>
<p>We'll need to add the <code>onDragStart</code> and <code>onDragOver</code> event handlers to the <code>Lane</code> and <code>Task</code> components, and pass in the functions we just created:</p>
<ul>
<li><code>Lane</code>:</li>
</ul>
<p>First, add the functions to the types and props for the component:</p>
<pre><code class="language-tsx">// src/components/Lane/Lane.tsx

// ...

type LaneProps = {
    id: number;
    title: string;
    tasks: {
        id: number;
        title: string;
        body: string;
        laneId: number;
    }[];
    handleOnDragStart: (event: React.DragEvent, id: number) =&gt; void;
    handleOnDragOver: (event: React.DragEvent) =&gt; void;
}

export default function Lane({ id, title, tasks, handleOnDragStart, handleOnDragOver }: LaneProps) {
  // ...

}
</code></pre>
<p>Then, pass the functions to the <code>onDragStart</code> and <code>onDragOver</code> event handlers or the component:</p>
<pre><code class="language-tsx">// src/components/Lane/Lane.tsx
// ...

    return (
        &lt;div 
          className=&quot;Lane&quot;
          onDragOver={handleOnDragOver}
        &gt;
            &lt;h2&gt;{title}&lt;/h2&gt;
            &lt;div&gt;
                {
                    tasks.map((task) =&gt; {
                        return (
                            &lt;Task
                                key={task.id}
                                id={task.id}
                                title={task.title}
                                body={task.body}
                                laneId={task.laneId}
                                handleOnDragStart={handleOnDragStart}
                            /&gt;
                        )
                    })
                }
            &lt;/div&gt;
        &lt;/div&gt;
    )
}
</code></pre>
<ul>
<li><code>Task</code>:</li>
</ul>
<p>We passed the function <code>handleOnDragStart</code> to the <code>Task</code> component as a prop, and now add it to the types and props for the component. Also, we add the <code>onDragStart</code> event handler and the <code>draggable</code> attribute to the <code>Task</code> component:</p>
<pre><code class="language-tsx">// src/components/Task/Task.tsx
// ...

export default function  Task({ id, title, body, laneId }: TaskProps) {
    return (
        &lt;div 
          className=&quot;Task&quot;
          draggable
        &gt;
            &lt;h3&gt;{title}&lt;/h3&gt;
            &lt;p&gt;{body}&lt;/p&gt;
        &lt;/div&gt;
    )
}
</code></pre>
<p>You can now drag the tasks around, but they don't do anything yet. We'll create a function to handle the <code>drop</code> event, and add it to the <code>Board</code> component:</p>
<pre><code class="language-tsx">// src/components/Board/Board.tsx
// ...

export default function Board() {
    // ...

    function handleOnDrop(event: React.DragEvent, laneId: number) {
        const id = event.dataTransfer.getData(&quot;id&quot;);

        const task = tasks.find((task) =&gt; task.id === parseInt(id));

        if (task) {
            const newTasks = tasks.filter((task) =&gt; task.id !== parseInt(id));
            setTasks(newTasks.concat({ ...task, laneId }));
        }
    }

    return (
      // ...
    )
}
</code></pre>
<p>The <code>handleOnDrop</code> function takes two arguments: the <code>event</code> object and the <code>laneId</code> of the lane where the task is dropped. We'll use the <code>laneId</code> to update the <code>laneId</code> of the task. We'll also use the <code>event</code> object to get the <code>id</code> of the task that is being dropped. We'll use this <code>id</code> to identify the task in the <code>tasks</code> array, and update the <code>laneId</code> of the task.</p>
<p>We'll need to pass the <code>handleOnDrop</code> function to the <code>Lane</code> component:</p>
<pre><code class="language-tsx">// src/components/Board/Board.tsx
// ...

    return (
        &lt;div className=&quot;Board&quot;&gt;
            {lanes.map(lane =&gt; (
                &lt;Lane
                    key={lane.id}
                    id={lane.id}
                    title={lane.title}
                    tasks={tasks.filter(task =&gt; task.laneId === lane.id)}
                    handleOnDrop={handleOnDrop}
                /&gt;
            ))}
        &lt;/div&gt;
    )
}
</code></pre>
<p>And add it to the types and props for the <code>Lane</code> component, where the <code>onDrop</code> event handler is also added to the <code>div</code> element. The function is called with the <code>event</code> object and the <code>id</code> of the lane:</p>
<pre><code class="language-tsx">// src/components/Lane/Lane.tsx
// ...

type LaneProps = {
    // ...
    handleOnDragStart: (event: React.DragEvent, id: number) =&gt; void;
    handleOnDragOver: (event: React.DragEvent) =&gt; void;
    handleOnDrop: (event: React.DragEvent, laneId: number) =&gt; void;
}

export default function Lane({ id, title, tasks, handleOnDragStart, handleOnDragOver, handleOnDrop }: LaneProps) {
    return (
        &lt;div 
            className=&quot;Lane&quot;          
            onDragOver={handleOnDragOver}
            onDrop={(event) =&gt; handleOnDrop(event, id)}
        &gt;
            // ...
    )
}
</code></pre>
<p>Et voilà! You can now drag the tasks between lanes!</p>
<h2>Replacing CSS with Tailwind classes</h2>
<p>Now that we have the drag and drop functionality in place, we can start replacing the CSS with Tailwind classes. Tailwind makes it easy to style your components without having to write any CSS. In some ways it's comparable to Bootstrap, which is <a href="/blog/bootstrap-easiest-way-to-style-react-apps-2023">one of the easiest was</a> to style React applications. We'll start by installing Tailwind and its dependencies, and then configure it to work with Vite:</p>
<pre><code class="language-bash">npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
</code></pre>
<blockquote>
<p>You can find the most recent installation guide for Vite and Tailwind <a href="https://tailwindcss.com/docs/guides/vite">here</a>.</p>
</blockquote>
<p>Once the installation is complete, we'll need to configure Tailwind to work with Vite. We'll do this by adding the following to the <code>tailwind.config.ts</code> file, which is created by the <code>npx tailwindcss init -p</code> command:</p>
<pre><code class="language-ts">// tailwind.config.ts
/** @type {import('tailwindcss').Config} */
export default {
  content: [
    &quot;./index.html&quot;,
    &quot;./src/**/*.{js,ts,jsx,tsx}&quot;,
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
</code></pre>
<p>Tailwind is now configured to work with Vite. We'll need to import the Tailwind CSS files with base styling into the <code>src/index.css</code> file:</p>
<pre><code class="language-css">@tailwind base;
@tailwind components;
@tailwind utilities;
</code></pre>
<p>Make sure to check if the <code>index.css</code> file is imported in the <code>src/main.tsx</code> file. If not, add the following line to the top of the file:</p>
<pre><code class="language-ts">// src/main.tsx
import './index.css'

// Everything else...
</code></pre>
<p>Restart the development server, and you should see the Tailwind styles applied to the application.</p>
<p><img src="/images/project-board-tailwind-css.png" alt="Project Board with Tailwind CSS"></p>
<p>We can now start replacing the CSS with Tailwind classes. We'll start with the <code>Board</code> component, and replace the CSS with Tailwind classes. Also, the import statement for the <code>Board.css</code> CSS file can be removed:</p>
<pre><code class="language-tsx">// src/components/Board/Board.tsx
// ...

    return (
        &lt;div className=&quot;grid grid-cols-4 gap-4&quot;&gt;
            {lanes.map(lane =&gt; (
                &lt;Lane
                    key={lane.id}
                    id={lane.id}
                    title={lane.title}
                    tasks={tasks.filter(task =&gt; task.laneId === lane.id)}
                    handleOnDragStart={handleOnDragStart}
                    handleOnDragOver={handleOnDragOver}
                    handleOnDrop={handleOnDrop}
                /&gt;
            ))}
        &lt;/div&gt;
    )
}
</code></pre>
<p>Next, we'll replace the CSS in the <code>Lane</code> component with Tailwind classes. We'll also remove the import statement for the <code>Lane.css</code> CSS file:</p>
<pre><code class="language-tsx">// src/components/Lane/Lane.tsx
// ...

  return (
    &lt;div 
      className=&quot;bg-blue-100 p-4&quot;
      onDragOver={handleOnDragOver}
      onDrop={(event) =&gt; handleOnDrop(event, id)}
    &gt;
      &lt;h2 className=&quot;text-center text-xl font-bold mb-4&quot;&gt;{title}&lt;/h2&gt;
      &lt;div&gt;
        // ...  

  )
}
</code></pre>
<p>Also, we'll replace the CSS in the <code>Task</code> component with Tailwind classes. We'll also remove the import statement for the <code>Task.css</code> CSS file:</p>
<pre><code class="language-tsx">// src/components/Task/Task.tsx
// ...

  return (
    &lt;div 
      className=&quot;bg-white border border-gray-400 p-4 rounded-lg mb-4&quot;
      draggable
      onDragStart={(event) =&gt; handleOnDragStart(event, id)}
    &gt;
      &lt;h3&gt;{title}&lt;/h3&gt;
      &lt;p&gt;{body}&lt;/p&gt;
    &lt;/div&gt;
  )
}
</code></pre>
<p>And finally, we'll replace the CSS in the <code>Header</code> component with Tailwind classes. We'll also remove the import statement for the <code>Header.css</code> CSS file:</p>
<pre><code class="language-tsx">// src/components/Header/Header.tsx
export default function Header() {
    return (
        &lt;div className=&quot;bg-blue-600 white p-6 mb-4&quot;&gt;
            &lt;h1 className=&quot;text-center text-white text-6xl&quot;&gt;Project Board&lt;/h1&gt;
        &lt;/div&gt;
    )
}
</code></pre>
<p>And that's it! We now have a fully functional project management board built with React, TypeScript, and Tailwind CSS.</p>
<p><img src="/images/project-board-tailwind-css-completed.png" alt="Project Board with Tailwind CSS completed"></p>
<h2>Learn more</h2>
<p>You can find the full source code for this project on <a href="https://github.com/royderks/project-management-board">GitHub</a> or watch the recording on my <a href="https://www.youtube.com/watch?v=YmhPU9SR5hQ">YouTube channel</a>. If you found this article useful, let me know on <a href="https://linkedin.com/in/gethackteam">LinkedIn</a>, <a href="https://x.com/gethackteam">X</a> or <a href="https://bsky.app/profile/gethackteam.bsky.social">Bluesky</a>. Please share it around the web or subscribe to my <a href="https://www.youtube.com/@gethackteam?sub_confirmation=1">YouTube channel</a> for more exciting content on web technologies.</p>
]]>
        </content:encoded>
    </item>
      <item>
        <title><![CDATA[Do I Need GraphQL Now that We Have React Server Components?]]></title>
        <link>https://hackteam.io/blog/do-need-graphql-now-react-server-components</link>
        <pubDate>2023-11-01T00:00:00.000Z</pubDate>
        <guid isPermaLink="false">https://hackteam.io/blog/do-need-graphql-now-react-server-components</guid>
        <media:content
          url="https://i.ytimg.com/vi/Tm_0BaTKBZs/hqdefault.jpg"
        />
        <description>
        <![CDATA[GraphQL and React Server Components have been hot topics in the React community, especially in recent months. With the release of Next.js for the theme, the debate around the need for GraphQL has resurfaced. Developers can now query databases directly from their React components, which raises the question: do we still need GraphQL?]]>
        </description>
        <content:encoded>
        <![CDATA[<p>React Server Components have been a hot topic in the React community, especially in recent months. With the release of Next.js 14 last week, developers can finally try them out in &quot;production&quot;. Server Components introduce a new pattern for data fetching in React, and with this, the debate around the need for GraphQL has resurfaced. Developers can now query databases directly from their React components, which raises the question: do we still need GraphQL?</p>
<p>Click the image below to watch the <a href="https://www.youtube.com/watch?v=Tm_0BaTKBZs">YouTube video version</a> of this blog post:</p>
<p><a href="https://www.youtube.com/watch?v=Tm_0BaTKBZs"><img src="https://i.ytimg.com/vi/Tm_0BaTKBZs/hqdefault.jpg" alt="VIDEO: Do I Need GraphQL Now that We Have React Server Components?"></a></p>
<h2>Short vs. Long Answer</h2>
<p>The short answer (as is the answer to any hard problem in software engineering) is &quot;It depends&quot;. However, the long answer is more nuanced and depends on various factors. As a solo developer or a small startup team, you may not necessarily need GraphQL. However, if you are a growing organization or an enterprise, it is essential to consider the benefits of GraphQL. Let's dive into this topic and explore the long-form answer.</p>
<h2>What are React Server Components?</h2>
<p>The introduction of React Server Components in Next.js 14 is something many developers have been eagerly awaiting. By writing React components server-side and subsequently requesting the data displayed in that component server-side as well, you can reduce the bundle size of your application. The diagram below shows how React Server Components work:</p>
<p><img src="/images/nextjs-14-react-server-components-chart.jpg" alt="React Server Components">
<em>Overview of how React Server Components work. Source: <a href="https://nextjs.org/">Next.js</a></em></p>
<p>React Server Components bring us back to the MVC (Model, View, Controller) days that some of you might remember from PHP. Data fetching was coupled with the view, which is something that we moved away from when we started building single-page applications with JavaScript frameworks React. When we ditched MVC, we lost server-side rendering and embraced client-side rendering. But for all sorts of reasons, in recent years we returned to server-side rendering.</p>
<p>Why are developers debating server components? Well, it means that you (for example) can now query databases directly from your React components, which means that (in theory) you no longer need to use GraphQL or other data-fetching libraries like React Query. Instead, you can use React Server Components to fetch data from your database and render it directly in your React components:</p>
<p><img src="/images/nextjs-14-react-server-components-database.jpg" alt="Querying a database from a React components">
<em>Still from a talk at Next.js Conf 2023</em></p>
<p>In the example above, we are querying a database directly from a React component. This is something that was not possible before React Server Components. The React team has been working on this feature for a while now, and it's finally available in Next.js 14. However, it's important to note that this feature is still experimental and not recommended for production use. Furthermore, I would argue that it's not a good idea to query a database directly from your React components.</p>
<h2>When Should You Use GraphQL?</h2>
<p>So when should you use GraphQL? GraphQL shines when you need to maintain relationships between multiple backends and applications.</p>
<blockquote>
<p>Don't know what GraphQL is? Check out my <a href="/blog/why-developers-love-graphql">Why Developers Love GraphQL</a> blog post.</p>
</blockquote>
<p>It excels in scenarios where you have a one-to-many or many-to-many setup. By using GraphQL Federation or <a href="https://chillicream.com/blog/2023/08/15/graphql-fusion">GraphQL Fusion</a> (a newer federation spec from the GraphQL Foundation), you can bring together multiple GraphQL backends and have a single source of truth for different backends. This empowers developers integrating with your GraphQL API to have control over the data they load into their applications.</p>
<p><img src="/images/nextjs-14-react-server-components-database-graphql.png" alt="When to use GraphQL"></p>
<p>In the above 1:1 relations React Server Components offer convenience and rapid prototyping for solo developers or teams that are moving fast. Having to maintain a GraphQL API on top of your database can be a lot of work, especially if you are a small team. There are solutions out there that can help you with this, such as <a href="https://stepzen.com/">StepZen</a>, which I highly recommend checking out (I was working at StepZen, before joining IBM after our acquisition). With just a few lines of code, you can generate a GraphQL API on top of your database. This is a great solution for small teams that want to move fast and don't want to maintain a GraphQL API on top of their database.</p>
<p>However, it's important to consider the size of your product and the capacity of your team. GraphQL may introduce complexity that isn't necessary for small-scale applications or teams still relying on a one-to-one connection between their backend data source and front-end application. In such cases, the added complexity might outweigh the benefits provided by GraphQL. Alternatively, you could try <a href="/blog/compare-graphql-and-trpc">tRPC</a>, which is a great alternative to GraphQL when you're building your entire stack with TypeScript. A good talk I recommend watching is <a href="https://www.youtube.com/watch?v=_zNKTWcigyY">The Right Size for GraphQL</a> by The Browne at the last GraphQL Conf in San Francisco last September.</p>
<h2>Conclusion</h2>
<p>In conclusion, the question of whether we still need GraphQL in a world of React Server Components is subjective. Server components have the potential to speed up web experiences and offer more flexibility in scaling applications. However, I have reservations about how well they will scale in the long run, especially when serving numerous users. For example, querying a database directly from a React component, as shown in the Next.js Conf example, is not recommended. Growing teams would likely benefit more from using other solutions like tRPC or GraphQL.</p>
<p>If you decide to adopt GraphQL for your startup, product, or team, I recommend exploring other resources, such as my <a href="https://www.youtube.com/@gethackteam?sub_confirmation=1">YouTube videos</a>, where I discuss GraphQL extensively. Feel free to reach out to me on <a href="https://linkedin.com/in/gethackteam">LinkedIn</a>, <a href="https://x.com/gethackteam">X</a> or <a href="https://bsky.app/profile/gethackteam.bsky.social">Bluesky</a> too.</p>
]]>
        </content:encoded>
    </item>
      <item>
        <title><![CDATA[Vite is the better Create React App alternative]]></title>
        <link>https://hackteam.io/blog/vite-better-create-react-app-alternative</link>
        <pubDate>2023-08-31T00:00:00.000Z</pubDate>
        <guid isPermaLink="false">https://hackteam.io/blog/vite-better-create-react-app-alternative</guid>
        <media:content
          url="https://i.ytimg.com/vi/XH69M0qIAis/hqdefault.jpg"
        />
        <description>
        <![CDATA[The React documentation has undergone a major update. As part of this update, there's no more mention of Create React App. Instead, you should use a framework like Next.js or Remix. But what if you don't want to use a framework? What if you want to use React with a simple build tool? In this article, I will explain why Vite is the better Create React App alternative.']]>
        </description>
        <content:encoded>
        <![CDATA[<p>The landscape of frontend development is always shifting, and React is no exception to this trend. Recent <a href="https://react.dev/blog/2023/03/16/introducing-react-dev">updates to the React documentation</a> show a significant shift away from Create React App (CRA) as the go-to method for bootstrapping new React applications. The change has led developers toward frameworks like Next.js and Remix, but what if you're looking for something a bit leaner—a library, perhaps? Enter <a href="https://vitejs.dev/">Vite</a>, a next-generation frontend tooling library that could just be the answer to many of your development concerns.</p>
<p>Click the image below to watch the <a href="https://www.youtube.com/watch?v=XH69M0qIAis">YouTube video version</a> of this blog post:</p>
<p><a href="https://www.youtube.com/watch?v=XH69M0qIAis"><img src="https://i.ytimg.com/vi/XH69M0qIAis/hqdefault.jpg" alt="Vite is the better Create React App alternative"></a></p>
<h2>What's wrong with Create React App?</h2>
<p>While Create React App (CRA) has been a popular choice for bootstrapping React applications, it's important to note that it's not inherently &quot;wrong&quot; or &quot;bad.&quot; Rather, there are limitations and scenarios where other tools may be a better fit. Below are some common critiques developers have about Create React App:</p>
<ul>
<li>
<p>Lack of maintainability: Create React App is a large project with a lot of moving parts. As such, it can be difficult to maintain and update. This is especially true when you consider that Create React App isn't maintained by the React core team or any other official organization.</p>
</li>
<li>
<p>Limited to Webpack: CRA is tightly coupled with webpack. While webpack is powerful, it can be complex to configure, and it's not the only module bundler out there. Alternatives like Vite use the native ES modules feature in modern browsers for faster development and smaller builds, without relying on webpack.</p>
</li>
<li>
<p>Bad tree shaking: Although webpack supports tree shaking, CRA does not make it as straightforward as some developers would like. In other tools like Vite or Rollup, tree shaking is often more efficient, which helps in reducing the final bundle size.</p>
</li>
</ul>
<p>And much more can be said about why React developers started to dislike using Create React App.</p>
<h2>Why Vite Over Create React App?</h2>
<p>While Create React App has been an industry standard for bootstrapping React applications, it's not without its limitations—namely, its lack of build optimizations for production-grade applications. On the other hand, Vite offers various features and optimizations aimed at improving both your build size and development speed. Here are some of the key benefits of using Vite over Create React App:</p>
<ul>
<li>
<p>Faster development: Vite offers a lightning-fast development server that leverages native ES modules in modern browsers. This means that your code is compiled on the fly, which results in faster development times.</p>
</li>
<li>
<p>Proper maintenance: Vite is maintained by the Vue core team, which means that it's more likely to receive updates and bug fixes than Create React App.</p>
</li>
<li>
<p>Smaller bundle size: Vite uses Rollup under the hood, which is a module bundler that's known for its tree-shaking capabilities. This means that Vite can produce smaller bundles than Create React App.</p>
</li>
</ul>
<p>As you can see from the list above it's an excellent choice for those who have found Create React App's capabilities limiting.</p>
<h2>Setting Up a New Project with Vite</h2>
<p><a href="https://vitejs.dev/guide/">Starting a new project</a> with Vite is as easy as running a single command:</p>
<pre><code class="language-bash">npx create-vite
</code></pre>
<p>Upon running this command, you'll be prompted to answer a few questions, including the name for your new project. For this example, let's go with &quot;vite-project&quot;. One of Vite's standout features is its compatibility with a range of JavaScript flavors and frameworks—not just React, but also Preact, Lit, Svelte, and even vanilla JavaScript.</p>
<p>After setup, your project directory will look quite familiar if you've ever used Create React App before. You'll see directories like public and src containing your static assets and React components, respectively. Additionally, you'll find crucial configuration files like <code>package.json</code> and <code>vite.config.js</code>. If you're into TypeScript, it's good to know that a <code>tsconfig.json</code> will also be present.</p>
<p>To install all dependencies, execute:</p>
<pre><code class="language-bash">npm install
</code></pre>
<p>Open your project in your IDE of choice — let's use Visual Studio Code for this example. Vite's primary configuration can be found in <code>vite.config.ts</code>. Unlike Create React App, which relies heavily on webpack, Vite allows you to place all your plugins and configurations within this single file.</p>
<p>To fire up your local development server, run:</p>
<pre><code class="language-bash">npm run dev
</code></pre>
<p>Doing this will launch your Vite application, which you can then view in your browser. The development server offers hot-reloading and other features that make development a breeze.</p>
<h2>Building Your React App</h2>
<p>Once the development server is running, building out your React application using Vite is fundamentally the same as it would be with Create React App. You're free to create new components, apply styles using CSS, or even employ other styling libraries like Tailwind CSS. Additional configurations for certain libraries can be made in the <code>vite.config.ts</code> file, but Vite is generally designed to be compatible with most existing libraries.</p>
<p>If you've been following the latest advice from the React core team, you might find Vite to be a recommended alternative to Create React App for future projects. It's a promising choice for those looking to stay ahead of the curve in the rapidly evolving frontend development landscape.</p>
<h2>Conclusion</h2>
<p>Vite is positioning itself as the modern solution for building efficient and fast React applications. With features designed to optimize both build size and development speed, it stands as a compelling alternative to Create React App. So why not give Vite a try? It could be the game-changer you've been waiting for in your React development.</p>
<p>If you found this article useful, let me know on <a href="https://linkedin.com/in/gethackteam">LinkedIn</a>, <a href="https://x.com/gethackteam">X</a> or <a href="https://bsky.app/profile/gethackteam.bsky.social">Bluesky</a>. Please share it around the web or subscribe to my <a href="https://www.youtube.com/@gethackteam?sub_confirmation=1">YouTube channel</a> for more exciting content on web technologies.</p>
]]>
        </content:encoded>
    </item>
      <item>
        <title><![CDATA[GraphQL IDEs: GraphiQL vs Altair]]></title>
        <link>https://hackteam.io/blog/graphql-ide-graphiql-vs-altair</link>
        <pubDate>2023-05-25T00:00:00.000Z</pubDate>
        <guid isPermaLink="false">https://hackteam.io/blog/graphql-ide-graphiql-vs-altair</guid>
        <media:content
          url="https://hackteam.io/images/graphiql-ide-graphql-vs-altair.png"
        />
        <description>
        <![CDATA[The simplest way to set up a React TypeScript project from scratch is by using Next.js. In this blog post we will explore how to use Next.js for your next project and how you have to write zero configuration to use it with TypeScript.]]>
        </description>
        <content:encoded>
        <![CDATA[<p>In the world of web development, GraphQL has revolutionized how we think about APIs. GraphQL enables developers to query data in a much more flexible and efficient way compared to traditional RESTful APIs. However, as with any technology, you need the right tools to make the most of it. Today, we will compare two GraphQL Integrated Development Environments (IDEs): GraphiQL and Altair.</p>
<p>Click the image below to watch the <a href="https://www.youtube.com/watch?v=q3lDfKECGbU">YouTube video version</a> of this blog post:</p>
<p><a href="https://www.youtube.com/watch?v=q3lDfKECGbU"><img src="https://i.ytimg.com/vi/q3lDfKECGbU/hqdefault.jpg" alt="VIDEO: GraphiQL vs. Altair - What's the best GraphQL IDE?"></a></p>
<h2>Introduction to GraphQL IDEs</h2>
<p>Before diving into our comparison, let's quickly understand what a GraphQL IDE is. A GraphQL IDE is a tool that helps developers interact with GraphQL APIs, very similar to how your text-editor (like VSCode or IntelliJ) helps you write code.</p>
<p>These IDEs provide several functionalities, such as auto-completion, error highlighting, and interactive documentation. They help developers to construct and test GraphQL queries and mutations, visualize the returned data, and understand the structure of the GraphQL schema.</p>
<p>Two popular GraphQL IDEs are GraphiQL and Altair. Let's take a closer look at each.</p>
<h2>GraphiQL</h2>
<p><img src="/images/graphiql-graphql-ide.png" alt="GraphiQL GraphQL IDE"></p>
<p><a href="https://github.com/graphql/graphiql">GraphiQL</a> is one of the most well-known GraphQL IDEs. Originally developed by Facebook, it is an in-browser tool that enables developers to write, validate, and test GraphQL queries. It is open-source and can be integrated into any project that uses GraphQL. Recently, GraphiQL has been revamped with a new UI and several new features as you can read in ths <a href="/blog/exploring-graphiql-2-updates-and-new-features.md">blog post</a> I wrote earlier.</p>
<p>The most important features of GraphiQL are:</p>
<ul>
<li>
<p><strong>Schema introspection:</strong> GraphiQL offers a robust view of the schema, letting you examine types, fields, and overall structure.</p>
</li>
<li>
<p><strong>Autocompletion:</strong> Based on the schema, GraphiQL provides autocompletion, making it easier to construct complex queries.</p>
</li>
<li>
<p><strong>Syntax highlighting:</strong> This feature makes it easier to understand and navigate through the GraphQL queries and mutations. This includes errors. If you make a syntax mistake, GraphiQL will underline it immediately.</p>
</li>
<li>
<p><strong>Interactive Documentation:</strong> GraphiQL builds an interactive GraphQL API documentation on-the-fly, making it easy to understand the API.</p>
</li>
<li>
<p><strong>Query history:</strong> This feature lets you access your previous queries, so you don't have to rewrite them.</p>
</li>
</ul>
<p>As mentioned, if you want to learn more about GraphiQL then check out this <a href="/blog/exploring-graphiql-2-updates-and-new-features.md">blog post</a> I wrote earlier.</p>
<h2>Altair</h2>
<p><img src="/images/altair-graphql-ide.png" alt="Altair GraphQL IDE"></p>
<p><a href="https://altairgraphql.dev/">Altair GraphQL Client</a> is another impressive GraphQL IDE. It is open-source and available as a desktop app for all major operating systems, as well as a web extension for Chrome and Firefox.</p>
<p>There's a lot of features that Altair offers that you can also find in GraphiQL, but here are some of the most important ones:</p>
<ul>
<li>
<p><strong>Multiple Windows:</strong> Altair allows you to open multiple windows at the same time, enabling you to work with different queries (and GraphQL APIs) simultaneously.</p>
</li>
<li>
<p><strong>Autocompletion &amp; Error Highlighting:</strong> Like GraphiQL, Altair also offers autocompletion and error highlighting.</p>
</li>
<li>
<p><strong>Subscriptions:</strong> Altair supports GraphQL subscriptions, enabling real-time updates.</p>
</li>
<li>
<p><strong>File Uploads:</strong> Altair supports GraphQL multipart request specification (Multipart request), allowing you to test file uploads.</p>
</li>
<li>
<p><strong>Pre-request scripting:</strong> You can write scripts that run before the request is sent. This is useful for handling complex authentication flows.</p>
</li>
<li>
<p><strong>Collections:</strong>: Perhaps the most powerful feature of Altair is the ability to create collections of queries and mutations. This allows you to organize your queries and mutations across multiple GraphQL APIs in a logical way.</p>
</li>
</ul>
<p>Of course, there are many more features that Altair offers. If you want to learn more about Altair, then check out the <a href="https://altair.sirmuel.design/docs/">official documentation</a>.</p>
<p>So how do GraphiQL and Altair compare? Let's find out.</p>
<h2>Comparing GraphiQL and Altair</h2>
<p>GraphiQL and Altair share a common set of features like schema introspection, syntax highlighting, error highlighting, and auto-completion. However, they have some distinctive attributes as well.</p>
<p>While GraphiQL's interactive documentation and query history make API exploration and reiteration of queries more comfortable, it lacks some advanced features like pre-request scripting, file uploads, and subscriptions, which are provided by Altair.</p>
<p>On the other hand, Altair shines with its extensive feature set, providing advanced functionalities that make it more versatile for complex use-cases. The ability to handle file uploads and work with multiple GraphQL APIs simultaneously is a huge plus.</p>
<p>To see a side-by-side comparison of GraphiQL and Altair, check out <a href="https://www.youtube.com/watch?v=q3lDfKECGbU">the video</a> on my <a href="https://www.youtube.com/@gethackteam?sub_confirmation=1">YouTube channel</a>.</p>
<p>Or find me on <a href="https://linkedin.com/in/gethackteam">LinkedIn</a>, <a href="https://x.com/gethackteam">X</a> or <a href="https://bsky.app/profile/gethackteam.bsky.social">Bluesky</a>. I'd love to hear from you!</p>
]]>
        </content:encoded>
    </item>
      <item>
        <title><![CDATA[React Router 6 Basics]]></title>
        <link>https://hackteam.io/blog/react-router-6-basics</link>
        <pubDate>2023-02-18T00:00:00.000Z</pubDate>
        <guid isPermaLink="false">https://hackteam.io/blog/react-router-6-basics</guid>
        <media:content
          url="https://i.ytimg.com/vi/m2kGnitUpIs/hqdefault.jpg"
        />
        <description>
        <![CDATA[React Router is still the most popular routing library for React. In this blog post, we will explore the basics of React Router 6, including how to bootstrap React Router 6, create layouts and pass arguments to routes.]]>
        </description>
        <content:encoded>
        <![CDATA[<p>React Router is still the most popular routing library for React. This blog post will explore React Router 6, including how to bootstrap React Router 6, create layouts using the new <code>&lt;Outlet&gt;</code> component, and pass arguments to routes.</p>
<p>Click the image below to watch the <a href="https://www.youtube.com/watch?v=m2kGnitUpIs">YouTube video version</a> of this blog post:</p>
<p><a href="https://www.youtube.com/watch?v=m2kGnitUpIs"><img src="https://i.ytimg.com/vi/m2kGnitUpIs/hqdefault.jpg" alt="VIDEO: React Router 6 Basics"></a></p>
<h2>React Router history</h2>
<p>React Router has become a popular choice for managing routing in React applications and is widely used in both small and large applications. It is also highly customizable, allowing developers to create custom routing logic and integrate it into their applications. Currently, the library is maintained by the team behind <a href="https://remix.run/">Remix</a>, a React-based framework for building web applications.</p>
<p>With React Router, you can define routes and their corresponding components using a declarative syntax. When the user navigates to a particular URL, React Router will render the corresponding component for that URL. React Router also provides features such as nested routes, route parameters, and query parameters. One of the biggest advantages of React Router is that it works with any Reaac application, regardless of the framework or library that is used.</p>
<h2>Setting up React Router</h2>
<p>React Router is a JavaScript library, so you can use a package manager such as npm or Yarn. Assuming you already have a React project set up, you can follow these steps to install React Router using npm:</p>
<p>Open your terminal and navigate to your React project directory. Run the following command to install React Router:</p>
<pre><code>npm install react-router-dom
</code></pre>
<p>This will install React Router and its dependencies.</p>
<p>Once the installation is complete, you can use React Router in your application. To get started, you can import the necessary methods and components from React Router as you'll learn in the next step.</p>
<h2>Creating routes</h2>
<p>To create routes in React Router, you can use the <code>createBrowserRouter</code> method with the <code>RouterProvider</code> component. With <code>createBrowserRouter</code> you define the available routes and their corresponding component. You can use the <code>path</code> prop to define the URL path for the route, and the <code>element</code> prop to define the component that should be rendered when the user navigates to the route.</p>
<p>The following example shows how to create a route for the <code>/about</code> URL path:</p>
<pre><code class="language-jsx">import { createBrowserRouter, RouterProvider } from 'react-router-dom';

function About() {
  return &lt;h1&gt;About&lt;/h1&gt;;
}

const router = createBrowserRouter([
  {
    path: '/about',
    element: &lt;About /&gt;,
  },
]);

function App() {
  return (
    &lt;RouterProvider value={router}&gt;
      {/* Your components */}
    &lt;/RouterProvider&gt;
  );
}
</code></pre>
<p>When the user navigates to the <code>/about</code> URL path, React Router will render the <code>About</code> component. But how would you handle nested routes? For example, what if you want to share the same layout for multiple routes? In the next section, you'll learn how to create nested routes and layouts using the <code>&lt;Outlet /&gt;</code> component.</p>
<h2>Use <code>&lt;Outlet /&gt;</code> to create children routes</h2>
<p>With React Router 6, you can define nested routes using the <code>children</code> field in the route object. This allows you to create layouts that can be shared across multiple routes.</p>
<p>Let's say you want to create a layout that contains a header and a footer. You can use the <code>element</code> prop to define the layout component and the <code>children</code> field to define the nested routes. The following example shows how to create a layout that contains a header and a footer:</p>
<pre><code class="language-jsx">import { createBrowserRouter, RouterProvider, Outlet } from 'react-router-dom';

function About() {
  return &lt;h1&gt;About&lt;/h1&gt;;
}

function Layout() {
  return (
    &lt;div&gt;
      &lt;header&gt;
        &lt;h1&gt;Layout&lt;/h1&gt;
      &lt;/header&gt;
      &lt;Outlet /&gt;
      &lt;footer&gt;Copyright 2023&lt;/footer&gt;
    &lt;/div&gt;
  );
}

const router = createBrowserRouter([
  {
    path: '/',
    element: &lt;Layout /&gt;,
    children: [
      {
        path: 'about',
        element: &lt;About /&gt;,
      },
    ],
  },
]);
</code></pre>
<p>You can use the <code>&lt;Outlet /&gt;</code> component to render nested routes. This allows you to create layouts that can be shared across multiple routes, reducing the amount of duplicated code in your application.</p>
<h2>React Router 6 parameters</h2>
<p>React Router 6 allows you to pass parameters to routes. This will enable you to create dynamic routes that can be used to render different components based on the parameters that are passed to the route.</p>
<p>To pass parameters to a route, you can add the params to the <code>path</code> field in the route object. The following example shows how to pass a <code>userId</code> parameter to the <code>/user/:userId</code> route:</p>
<pre><code class="language-jsx">const router = createBrowserRouter([
  {
    path: '/',
    element: &lt;Layout /&gt;,
    children: [
      {
        path: 'about',
        element: &lt;About /&gt;,
      },
      {
        path: 'user/:userId',
        element: &lt;User /&gt;,
      },
    ],
  },
]);
</code></pre>
<p>And the following example shows how to retrieve the <code>userId</code> parameter with the <code>useParams</code> hook in the <code>User</code> component:</p>
<pre><code class="language-jsx">import { useParams } from 'react-router-dom';

function User() {
  const { userId } = useParams();

  return &lt;h1&gt;User {userId}&lt;/h1&gt;;
}
</code></pre>
<p>You can use the <code>useParams</code> hook to retrieve the parameters that are passed to the route. The <code>useParams</code> hook returns an object with the parameters that are passed to the route.</p>
<h2>Keep learning</h2>
<p>In this blog post, you learned how to bootstrap React Router 6, create layouts using the new <code>&lt;Outlet&gt;</code> component, and pass parameters to routes. If you want to learn more about React Router 6, you can check out the <a href="https://reactrouter.com/">official documentation</a>. Also, keep an eye out for my <a href="https://www.youtube.com/@gethackteam?sub_confirmation=1">YouTube channel</a>, where I'll post more videos about React and React Router 6.</p>
<p><a href="https://www.youtube.com/@gethackteam?sub_confirmation=1">&gt; Subscribe to my YouTube channel</a></p>
<p>Or find me on <a href="https://linkedin.com/in/gethackteam">LinkedIn</a>, <a href="https://x.com/gethackteam">X</a> or <a href="https://bsky.app/profile/gethackteam.bsky.social">Bluesky</a>. I'd love to hear from you!</p>
]]>
        </content:encoded>
    </item>
      <item>
        <title><![CDATA[Learn React in 5 minutes]]></title>
        <link>https://hackteam.io/blog/learn-react-in-five-minutes</link>
        <pubDate>2023-01-21T00:00:00.000Z</pubDate>
        <guid isPermaLink="false">https://hackteam.io/blog/learn-react-in-five-minutes</guid>
        <media:content
          url="https://i.ytimg.com/vi/JKtLRDfTYTU/hqdefault.jpg"
        />
        <description>
        <![CDATA[The simplest way to set up a React TypeScript project from scratch is by using Next.js. In this blog post we will explore how to use Next.js for your next project and how you have to write zero configuration to use it with TypeScript.]]>
        </description>
        <content:encoded>
        <![CDATA[<p>Can you learn React in five minutes? Well, it depends on what you mean by &quot;learn React&quot;. In this blog post you will &quot;learn the basics of React&quot; in five minutes, by going over a few of the core concepts of React.</p>
<p>Click the image below to watch the <a href="https://www.youtube.com/watch?v=JKtLRDfTYTU">YouTube video version</a> of this blog post:</p>
<p><a href="https://www.youtube.com/watch?v=JKtLRDfTYTU"><img src="https://i.ytimg.com/vi/JKtLRDfTYTU/hqdefault.jpg" alt="VIDEO: Learn React in 5 minutes"></a></p>
<h2>What is React?</h2>
<p>React is a JavaScript library that is widely used for building user interfaces, particularly for single-page applications. It allows you to create reusable components that can be rendered on the web, mobile, or desktop. Today, it is one of the most popular tools for front-end web development.</p>
<p>So, if you're interested in learning React, where do you start?</p>
<h2>JavaScript</h2>
<p>First, it's important to have a solid understanding of JavaScript. React is built with JavaScript, so you'll need to be comfortable with the basics of the language before you dive into React.</p>
<p>Once you've got a handle on JavaScript, the next step is to familiarize yourself with the React syntax and concepts.</p>
<h2>Components</h2>
<p>One of the core principles of React is that a component should be a self-contained piece of code that is easy to understand and maintain.</p>
<p>This is what a component looks like:</p>
<pre><code class="language-jsx">function MyComponent() {
  return (
    &lt;div&gt;
      &lt;h1&gt;My Component&lt;/h1&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<p>A component is a JavaScript function that returns a React element. It can be a simple function that returns a single element, or it can be a more complex component that returns multiple elements or has state.</p>
<h2>Data flows</h2>
<p>In React, data flows in a single direction from the parent component to the child component, following the unidirectional data flow principle. This helps make applications easier to reason about and debug.</p>
<p>Parent components can pass data to child components using props, below is an example of a child compoinent that receives data from a parent component:</p>
<pre><code class="language-jsx">function MyComponent() {
  return (
    &lt;div&gt;
      &lt;Title title='My Component' /&gt;
    &lt;/div&gt;
  );
}

function Title({ title }) {
  return &lt;h1&gt;{title}&lt;/h1&gt;;
}
</code></pre>
<p>Props are used to keep track of data that is passed from a parent component to a child component. They are immutable, which means that they cannot be changed once they are passed to a child component.</p>
<h2>State</h2>
<p>State is a special type of data that is managed by a component. It is used to store data that is specific to a component and it can be passed on to other components lower in the tree. State is often used to store data that is used to render the UI, such as a list of items or a user's name.</p>
<p>State can be managed using the useState hook, which is a function that returns an array with two values: the current state and a function that can be used to update the state:</p>
<pre><code class="language-jsx">import React, { useState } from 'react';

function MyComponent() {
  const [count, setCount] = useState(0);

  return (
    &lt;div&gt;
      &lt;Counter count={count} setCount={setCount} /&gt;
    &lt;/div&gt;
  );
}

function Counter({ count, setCount }) {
  return (
    &lt;div&gt;
      &lt;p&gt;{count}&lt;/p&gt;
      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;Increment&lt;/button&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<h2>Virtual DOM</h2>
<p>React uses a virtual DOM (Document Object Model) to optimize updates and minimize the number of DOM mutations. This makes applications built with React faster and more efficient.</p>
<p>The <a href="https://reactjs.org/docs/faq-internals.html">Virtual DOM</a> is a virtual representation of a user interface, which is kept in memory and synchronized with the &quot;real&quot; DOM by for example ReactDOM.</p>
<h2>Ecosystem</h2>
<p>React also has a large ecosystem of tools and libraries that can be leveraged to build amazing applications. Some popular ones include <a href="https://tanstack.com/query/latest/docs/react/examples/react/basic">Tanstack Query</a> for data fetching, Tailwind for styling and <a href="https://nextjs.org/">Next.js</a> or <a href="https://remix.run/">Remix</a> for server-rendered React applications.</p>
<h2>Building Projects</h2>
<p>It's also a good idea to start building some small projects with React to get a feel for how it works in practice. There are plenty of resources available online that can help you get started with your first React project, including templates and starter kits.</p>
<p>Need inspiration for a project?</p>
<p>you might want to have a look at my book React Projects. Which walks you through all the React concepts in 10 chapters. You'll build 10 unique projects. These are a &quot;movie list&quot; (like IMDB), a developer portfolio website using Github, a mobile game application and much more.</p>
<h2>Keep learning</h2>
<p>Finally, keep in mind that learning React is an ongoing process. As you build more complex projects and encounter new challenges, you'll continue to learn and improve your skills.</p>
<p>The comings months I'll livestreams on building these projects - and the first ones are already uploaded. So if you're interested in learning React, make sure to subscribe to my YouTube channel.</p>
<p><a href="https://www.youtube.com/@gethackteam?sub_confirmation=1">&gt; Subscribe to my YouTube channel</a></p>
<p>Or find me on <a href="https://linkedin.com/in/gethackteam">LinkedIn</a>, <a href="https://x.com/gethackteam">X</a> or <a href="https://bsky.app/profile/gethackteam.bsky.social">Bluesky</a>. I'd love to hear from you!</p>
]]>
        </content:encoded>
    </item>
      <item>
        <title><![CDATA[Bootstrap Is The Easiest Way To Style React Apps in 2023]]></title>
        <link>https://hackteam.io/blog/bootstrap-easiest-way-to-style-react-apps-2023</link>
        <pubDate>2023-01-13T00:00:00.000Z</pubDate>
        <guid isPermaLink="false">https://hackteam.io/blog/bootstrap-easiest-way-to-style-react-apps-2023</guid>
        <media:content
          url="https://i.ytimg.com/vi/huqR946Y5is/hqdefault.jpg"
        />
        <description>
        <![CDATA[Let's learn how to use Bootstrap 5 to style a React application. With Bootstrap you don't have to write any stying rules yourself. Instead you can use classnames to apply styles to HTML elements.]]>
        </description>
        <content:encoded>
        <![CDATA[<p>This blog post will teach you how to use Bootstrap 5 to style a React application. With Bootstrap, you don't have to write any stying rules yourself; instead, you can use class names to apply styles to HTML elements.</p>
<p>Click the image below to watch the <a href="http://www.youtube.com/watch?v=I-DzvL6yvGI">YouTube video version</a> of this blog post:</p>
<p><a href="http://www.youtube.com/watch?v=I-DzvL6yvGI"><img src="https://i.ytimg.com/vi/I-DzvL6yvGI/hqdefault.jpg" alt="VIDEO: Create a React Project From Scratch Without any Framework"></a></p>
<blockquote>
<p>This blog post is extracted from my book React Projects, available on <a href="https://packt.link/ReactProjects">Packt</a> and <a href="https://amzn.to/3vq4FQP">Amazon</a>.</p>
</blockquote>
<h2>Why use Bootstrap?</h2>
<p>IMO, Bootstrap is still the easiest way to style a React application. Bootstrap has been around for a long time and is widely used across web applications of all sorts and sizes. And build with different frameworks or tools, ranging from WordPress to React. There are a few reasons why you might want to use Bootstrap to style a React app:</p>
<ul>
<li>Ease of use: Bootstrap is a well-documented and widely-used CSS framework, making it easy to start and learn.</li>
<li>Responsive design: Bootstrap includes a responsive grid system and predefined styles for common UI elements, which makes it easier to build a responsive app that looks good on multiple devices.</li>
<li>Time savings: Using a CSS framework like Bootstrap can save you time by providing a set of pre-styled UI components that you can use out-of-the-box, rather than style everything from scratch.</li>
<li>Consistency: By using a common CSS framework, you can ensure that your app has a consistent look and feel, which can improve the user experience.</li>
</ul>
<p>Overall, Bootstrap (or any other CSS framework) can be useful for building a well-designed and responsive React app more efficiently.</p>
<h2>Installing Bootstrap</h2>
<p>You can install Bootstrap using npm or yarn. For this blog post, we will use npm:</p>
<pre><code>npm install --save-dev bootstrap
</code></pre>
<p>This will install Bootstrap as a <code>devDependency</code> in your project, and it will only be used during development and will not be included in the production build. By installing Bootstrap you can now include the CSS in your project by importing it in the root of your React project, for example, your <code>index.js</code> file that contains the root component of your app:</p>
<pre><code class="language-js">import ReactDOM from 'react-dom/client';
import List from './containers/List';

import 'bootstrap/dist/css/bootstrap.min.css';

function App() {
  // ...
}

const container = document.getElementById('app');
const root = ReactDOM.createRoot(container);

root.render(&lt;App /&gt;);
</code></pre>
<p>The important part in the code block above is the line <code>import 'bootstrap/dist/css/bootstrap.min.css'</code>, which will import the Bootstrap CSS file from the <code>node_modules</code> directory. This will make the Bootstrap styles available to your app.</p>
<h2>Using Bootstrap components</h2>
<p>Bootstrap includes several pre-styled components that you can use in your React app. For example, you can use the <a href="https://getbootstrap.com/docs/5.3/components/navbar/"><code>NavBar</code> component</a> to add a header element to your application.</p>
<p>To use this component, you can copy-paste the following code block and use it in your app:</p>
<pre><code class="language-js">import React from 'react';
import 'bootstrap/dist/css/bootstrap.css';

export default function Header() {
  return (
    &lt;nav class=&quot;navbar bg-body-tertiary&quot;&gt;
      &lt;div class=&quot;container-fluid&quot;&gt;
        &lt;a class=&quot;navbar-brand&quot; href=&quot;#&quot;&gt;
          &lt;img src=&quot;https://getbootstrap.com/docs/5.3/assets/brand/bootstrap-logo.svg&quot; alt=&quot;Logo&quot; width=&quot;30&quot; height=&quot;24&quot; class=&quot;d-inline-block align-text-top&quot;&gt;
          Bootstrap
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/nav&gt;
  )
}
</code></pre>
<p>Which will render the following header:</p>
<p><img src="/images/bootstrap-react-styling-navbar.png" alt="Bootstrap NavBar component"></p>
<p>By adding the correct class names to HTML elements, you will get a modern-looking header that you don't need to style.</p>
<p>Of course, there are much more Bootstrap components that you can use in your React app. For example, you can use the <a href="https://getbootstrap.com/docs/5.3/components/card/"><code>Card</code> component</a> to render a card with a title, image, and text:</p>
<pre><code class="language-js">import React from 'react';
import 'bootstrap/dist/css/bootstrap.css';

export default function Card() {
  return (
    &lt;div class='card' style='width: 18rem;'&gt;
      &lt;img src='...' class='card-img-top' alt='...' /&gt;
      &lt;div class='card-body'&gt;
        &lt;h5 class='card-title'&gt;Card title&lt;/h5&gt;
        &lt;p class='card-text'&gt;
          Some quick example text to build on the card title and make up the
          bulk of the card's content.
        &lt;/p&gt;
        &lt;a href='#' class='btn btn-primary'&gt;
          Go somewhere
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<p>Which will render the following card:</p>
<p><img src="/images/bootstrap-react-styling-card.png" alt="Bootstrap Card component"></p>
<p>With just a few lines of HTML you can render a card with a title, image, and text. And you can extend this further by using Bootstrap utilities or custom CSS to style the card even more.</p>
<h2>Bootstrap utilities</h2>
<p>Bootstrap includes a set of utility classes that can be used to apply common styles quickly and easily. These utility classes are designed to be used in conjunction with other Bootstrap styles and can be used to override or extend the default styles of certain elements.</p>
<p>Some of the Bootstrap utilities include:</p>
<ul>
<li><code>.text-*:</code> These classes can be used to apply different colors to text, depending on the context (e.g. .text-primary, .text-secondary, etc.).</li>
<li><code>.bg-*:</code> These classes can be used to apply different background colors to elements (e.g. .bg-primary, .bg-secondary, etc.).</li>
</ul>
<p>Let's look at an example:</p>
<pre><code class="language-js">import React from 'react';
import 'bootstrap/dist/css/bootstrap.css';

function App() {
  return (
    &lt;div className=&quot;container mt-5&quot;&gt;
      &lt;div className=&quot;row&quot;&gt;
        &lt;div className=&quot;col-md-6&quot;&gt;
          &lt;div className=&quot;card bg-primary text-white&quot;&gt;
            &lt;div className=&quot;card-body&quot;&gt;
              &lt;h5 className=&quot;card-title&quot;&gt;Primary Card&lt;/h5&gt;
              &lt;p className=&quot;card-text&quot;&gt;Some quick example text to build on the card title and make up the bulk of the card's content.&lt;/p&gt;
            &lt;/div&gt;
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;div className=&quot;col-md-6&quot;&gt;
          &lt;div className=&quot;card bg-secondary text-white&quot;&gt;
            &lt;div className=&quot;card-body&quot;&gt;
              &lt;h5 className=&quot;card-title&quot;&gt;Secondary Card&lt;/h5&gt;
              &lt;p className=&quot;card-text&quot;&gt;Some quick example text to build on the card title and make up the bulk of the card's content.&lt;/p&gt;
            &lt;/div&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  );
}

export default App;
</code></pre>
<p>In this example, we use Bootstrap's grid system to create a layout with two equal-width columns, and we use the <code>.bg-primary</code> and <code>.bg-secondary</code> classes to give the cards different background colors. We are also using the <code>.text-white</code> class to make the text white to be visible against the colored backgrounds.</p>
<p>These are just a few examples of Bootstrap utilities. Many others are available, and you can find more information in the <a href="https://getbootstrap.com/docs/5.3/utilities/">Bootstrap documentation</a>.</p>
<h2>Conclusion</h2>
<p>This blog post has shown how to use Bootstrap 5 to style a React application. With Bootstrap you don't have to write any stying rules yourself. Instead, you can use class names to apply styles to HTML elements. Of course, you can also use Bootstrap utilities to apply common styles quickly and easily.</p>
<blockquote>
<p>This blog post is extracted from my book React Projects, available on <a href="https://packt.link/ReactProjects">Packt</a> and <a href="https://amzn.to/3vq4FQP">Amazon</a>.</p>
</blockquote>
<p>I hope you learned some new things about styling in React! Any feedback? Let me know by connecting to me on <a href="https://linkedin.com/in/gethackteam">LinkedIn</a>, <a href="https://x.com/gethackteam">X</a> or <a href="https://bsky.app/profile/gethackteam.bsky.social">Bluesky</a>. Or leave a comment on my <a href="https://www.youtube.com/@gethackteam?sub_confirmation=1">YouTube channel</a>.</p>
]]>
        </content:encoded>
    </item>
      <item>
        <title><![CDATA[Create a React Project From Scratch Without any Framework]]></title>
        <link>https://hackteam.io/blog/create-react-project-from-scratch-without-framework</link>
        <pubDate>2023-01-06T00:00:00.000Z</pubDate>
        <guid isPermaLink="false">https://hackteam.io/blog/create-react-project-from-scratch-without-framework</guid>
        <media:content
          url="https://i.ytimg.com/vi/huqR946Y5is/hqdefault.jpg"
        />
        <description>
        <![CDATA[This blog post will show you how to create a new single-page React application from scratch with Webpack and Babel, giving you a strong foundation for any project you may undertake before using a framework like Next.js or Remix.]]>
        </description>
        <content:encoded>
        <![CDATA[<p>This blog post will guide you through the process of creating a new single-page React application from the ground up. We will begin by setting up a new project using Webpack and Babel. Building a React project from scratch will give you a strong foundation and understanding of the fundamental requirements of a project, which is essential for any project you may undertake before jumping into a framework like Next.js or Remix.</p>
<p>Click the image below to watch the <a href="http://www.youtube.com/watch?v=X48Kt8rSByQ">YouTube video version</a> of this blog post:</p>
<p><a href="http://www.youtube.com/watch?v=X48Kt8rSByQ"><img src="https://i.ytimg.com/vi/X48Kt8rSByQ/hqdefault.jpg" alt="VIDEO: Create a React Project From Scratch Without any Framework"></a></p>
<blockquote>
<p>This blog post is extracted from my book React Projects, available on <a href="https://packt.link/ReactProjects">Packt</a> and <a href="https://amzn.to/3vq4FQP">Amazon</a>.</p>
</blockquote>
<h2>Setting up a new project</h2>
<p>Before you can start building your new React project, you will need to create a new directory on your local machine. For this blog (which is based upon the book React Projects), you can name this directory 'chapter-1'.</p>
<p>To initiate the project, navigate to the directory you just created and enter the following command in the terminal:</p>
<pre><code>npm init -y
</code></pre>
<p>This will create a <code>package.json</code> file with the minimum information required to run a JavaScript/React project. The <code>-y</code> flag allows you to bypass the prompts for setting project details such as the name, version, and description.</p>
<p>After running this command, you should see a <code>package.json</code> file created for your project similar to the following:</p>
<pre><code class="language-json">{
  &quot;name&quot;: &quot;chapter-1&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;&quot;,
  &quot;main&quot;: &quot;index.js&quot;,
  &quot;scripts&quot;: {
    &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;
  },
  &quot;keywords&quot;: [],
  &quot;author&quot;: &quot;&quot;,
  &quot;license&quot;: &quot;ISC&quot;
}
</code></pre>
<p>Now that you have created the <code>package.json</code> file, the next step is to add Webpack to the project. This will be covered in the following section.</p>
<h2>Adding Webpack to the project</h2>
<p>In order to run the React application, we need to install Webpack 5 (the current stable version at the time of writing) and the Webpack CLI as <code>devDependencies</code>. Webpack is a tool that allows us to create a bundle of JavaScript/React code that can be used in a browser. Follow these steps to set up Webpack:</p>
<ol>
<li>Install the necessary packages from npm using the following command:</li>
</ol>
<pre><code>npm install --save-dev webpack webpack-cli
</code></pre>
<ol start="2">
<li>After installation, these packages will be listed in the package.json file and can be run in our start and build scripts. But first, we need to add some files to the project:</li>
</ol>
<pre><code>chapter-1
|- node_modules
|- package.json
   |- src
      |- index.js
</code></pre>
<p>This will add an <code>index.js</code> file to a new directory called <code>src</code>. Later, we will configure Webpack so that this file is the starting point for our application.</p>
<ol start="3">
<li>Add the following code block to this file:</li>
</ol>
<pre><code class="language-js">console.log('Rick and Morty');
</code></pre>
<ol start="4">
<li>To run the code above, we will add start and build scripts to our application using Webpack. The test script is not needed in this case, so it can be removed. Also, the main field can be changed to private with the value of true, as the code we are building is a local project:</li>
</ol>
<pre><code class="language-json">{
  &quot;name&quot;: &quot;chapter-1&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;&quot;,
  &quot;main&quot;: &quot;index.js&quot;,
  &quot;scripts&quot;: {
    &quot;start&quot;: &quot;webpack --mode=development&quot;,
    &quot;build&quot;: &quot;webpack --mode=production&quot;
  },
  &quot;keywords&quot;: [],
  &quot;author&quot;: &quot;&quot;,
  &quot;license&quot;: &quot;ISC&quot;
}
</code></pre>
<p>The npm start command will run Webpack in development mode, while npm run build will create a production bundle using Webpack. The main difference is that running Webpack in production mode will minimize our code and reduce the size of the project bundle.</p>
<ol start="5">
<li>Run the <code>start</code> or <code>build</code> command from the command line; Webpack will start up and create a new directory called <code>dist</code>.</li>
</ol>
<pre><code>chapter-1
|- node_modules
|- package.json
   |- dist
      |- main.js
   |- src
      |- index.js
</code></pre>
<ol start="6">
<li>Inside this directory, there will be a file called <code>main.js</code> that includes our project code and is also known as our bundle. If successful, you should see the following output:</li>
</ol>
<pre><code>asset main.js 794 bytes [compared for emit] (name: main)
./src/index.js 31 bytes [built] [code generated]
webpack compiled successfully in 67 ms
</code></pre>
<p>The code in this file will be minimized if you run Webpack in production mode.</p>
<ol start="7">
<li>To test if your code is working, run the main.js file in your bundle from the command line:</li>
</ol>
<pre><code>node dist/main.js
</code></pre>
<p>This command runs the bundled version of our application and should return the following output:</p>
<pre><code>&gt; node dist/main.js
Rick and Morty
</code></pre>
<p>Now, we're able to run JavaScript code from the command line. In the next part of this blog post, we will learn how to configure Webpack so that it works with React.</p>
<h2>Configuring Webpack for React</h2>
<p>Now that we have set up a basic development environment with Webpack for a JavaScript application, we can begin installing the packages necessary to run a React application. These packages are <code>react</code> and <code>react-dom</code>, where the former is the core package for React and the latter provides access to the browser's DOM and allows for rendering of React. To install these packages, enter the following command in the terminal:</p>
<pre><code>npm install react react-dom
</code></pre>
<p>However, simply installing the dependencies for React is not enough to run it, since by default, not all browsers can understand the format (such as ES2015+ or React) in which your JavaScript code is written. Therefore, we need to compile the JavaScript code into a format that can be read by all browsers.</p>
<p>To do this, we will use Babel and its related packages to create a toolchain that allows us to use React in the browser with Webpack. These packages can be installed as <code>devDependencies</code> by running the following command:</p>
<p>In addition to the Babel core package, we will also install <code>babel-loader</code>, which is a helper that allows Babel to run with Webpack, and two preset packages. These preset packages help determine which plugins will be used to compile our JavaScript code into a readable format for the browser (<code>@babel/preset-env</code>) and to compile React-specific code (<code>@babel/preset-react</code>).</p>
<p>Now that we have the packages for React and the necessary compilers installed, the next step is to configure them to work with Webpack so that they are used when we run our application.</p>
<pre><code>npm install --save-dev @babel/core babel-loader @babel/preset-env @babel/preset-react
</code></pre>
<p>To do this, configuration files for both Webpack and Babel need to be created in the src directory of the project: <code>webpack.config.js</code> and <code>babel.config.json</code>, respectively. The <code>webpack.config.js</code> file is a JavaScript file that exports an object with the configuration for Webpack. The <code>babel.config.json</code> file is a JSON file that contains the configuration for Babel.</p>
<p>The configuration for Webpack is added to the <code>webpack.config.js</code> file to use <code>babel-loader</code>:</p>
<pre><code class="language-js">module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
        },
      },
    ],
  },
};
</code></pre>
<p>This configuration file tells Webpack to use <code>babel-loader</code> for every file with the <code>.js</code> extension and excludes files in the <code>node_modules</code> directory from the Babel compiler.</p>
<p>To utilize the Babel presets, the following configuration must be added to <code>babel.config.json</code>:</p>
<pre><code class="language-json">{
  &quot;presets&quot;: [
    [
      &quot;@babel/preset-env&quot;,
      {
        &quot;targets&quot;: {
          &quot;esmodules&quot;: true
        }
      }
    ],
    [
      &quot;@babel/preset-react&quot;,
      {
        &quot;runtime&quot;: &quot;automatic&quot;
      }
    ]
  ]
}
</code></pre>
<p>In the above <code>@babel/preset-env</code> must be set to target <code>esmodules</code> in order to use the latest Node modules. Additionally, defining the JSX runtime to automatic is necessary since React 18 has adopted the <a href="https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html">new JSX Transform functionality</a>.</p>
<p>Now that we have set up Webpack and Babel, we can run JavaScript and React from the command line. In the next section, we will write our first React code and run it in the browser.</p>
<h2>Rendering React components</h2>
<p>Now that we have installed and configured the packages necessary to set up Babel and Webpack in the previous sections, we need to create a real React component that can be compiled and run. This process involves adding some new files to the project and making changes to the Webpack configuration:</p>
<ol>
<li>Let's edit the <code>index.js</code> file that already exists in our <code>src</code> directory so that we can use <code>react</code> and <code>react-dom</code>. Replace the contents of this file with the following:</li>
</ol>
<pre><code class="language-js">import ReactDOM from 'react-dom/client';

function App() {
  return &lt;h1&gt;Rick and Morty&lt;/h1&gt;;
}

const container = document.getElementById('root');
const root = ReactDOM.createRoot(container);
root.render(&lt;App /&gt;);
</code></pre>
<p>As you can see, this file imports the <code>react</code> and <code>react-dom</code> packages, defines a simple component that returns an <code>h1</code> element containing the name of your application, and has this component rendered in the browser with <code>react-dom</code>. The last line of code mounts the <code>App</code> component to an element with the <code>root</code> ID selector in your document, which is the entry point of the application.</p>
<ol start="2">
<li>We can create a file that has this element in a new directory called <code>public</code> and name that file <code>index.html</code>. The document structure of this project should look like the following:</li>
</ol>
<pre><code>chapter-1
  |- node_modules
  |- package.json
  |- babel.config.json
  |- webpack.config.js
  |- dist
    |- main.js
  |- public
    |- index.html
  |- src
    |- index.js
</code></pre>
<ol start="3">
<li>After adding a new file called <code>index.html</code> to the new <code>public</code> directory, we add the following code inside it:</li>
</ol>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta
      name=&quot;viewport&quot;
      content=&quot;width=device-width,
initial-scale=1.0&quot;
    /&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;ie=edge&quot; /&gt;
    &lt;title&gt;Rick and Morty&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;section id=&quot;root&quot;&gt;&lt;/section&gt;
  &lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>This adds an HTML heading and body. Within the <code>head</code> tag is the title of our application, and inside the <code>body</code> tag is a section with the &quot;root&quot; ID selector. This matches the element we have mounted the <code>App</code> component to in the <code>src/index.js</code> file.</p>
<ol start="4">
<li>The final step in rendering our React component is extending Webpack so that it adds the minified bundle code to the body tags as scripts when running. To do this, we should install the <code>html-webpack-plugin</code> package as a <code>devDependency</code>:</li>
</ol>
<pre><code>npm install --save-dev html-webpack-plugin
</code></pre>
<p>To use this new package to render our files with React, the Webpack configuration in the <code>webpack.config.js</code> file must be updated:</p>
<pre><code class="language-js">const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html',
      filename: './index.html',
    }),
  ],
};
</code></pre>
<p>Now, if we run <code>npm start</code> again, Webpack will start in development mode and add the <code>index.html</code> file to the <code>dist</code> directory. Inside this file, we'll see that a new <code>scripts</code> tag has been inserted inside the body tag that points to our application bundle – that is, the <code>dist/main.js</code> file.</p>
<p>If we open this file in the browser or run <code>open dist/index.html</code> from the command line, it will display the result directly in the browser. The same is true when running the npm run build command to start Webpack in production mode; the only difference is that our code will be minified:.</p>
<p>This process can be sped up by setting up a development server with Webpack. We'll do this in the final part of this blog post.</p>
<h2>Setting up a Webpack development server</h2>
<p>While working in development mode, every time we make changes to the files in our application, we need to rerun the <code>npm start</code> command. This can be tedious, so we will install another package called <code>webpack-dev-server</code>. This package allows us to force Webpack to restart every time we make changes to our project files and manages our application files in memory instead of building the <code>dist</code> directory.</p>
<p>The <code>webpack-dev-server</code> package can be installed with npm:</p>
<pre><code>npm install --save-dev webpack-dev-server
</code></pre>
<p>Also, we need to edit the dev script in the <code>package.json</code> file so that it uses <code>webpack- dev-server</code> instead of Webpack. This way, you don't have to recompile and reopen the bundle in the browser after every code change:</p>
<pre><code class="language-json">{
  &quot;name&quot;: &quot;chapter-1&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;&quot;,
  &quot;main&quot;: &quot;index.js&quot;,
  &quot;scripts&quot;: {
    &quot;start&quot;: &quot;webpack serve --mode=development&quot;,
    &quot;build&quot;: &quot;webpack --mode=production&quot;
  },
  &quot;keywords&quot;: [],
  &quot;author&quot;: &quot;&quot;,
  &quot;license&quot;: &quot;ISC&quot;
}
</code></pre>
<p>The preceding configuration replaces Webpack in the start scripts with <code>webpack-dev-server</code>, which runs Webpack in development mode. This will create a local development server that runs the application and ensures that Webpack is restarted every time an update is made to any of your project files.</p>
<p>To start the local development server, just enter the following command in the terminal:</p>
<pre><code>npm start
</code></pre>
<p>This will cause the local development server to be active at <code>http://localhost:8080/</code> and refresh every time we make an update to any file in our project.</p>
<p>Now, we have created the basic development environment for our React application, which you can further develop and structure when you start building your application.</p>
<h2>Conclusion</h2>
<p>In this blog post, we learned how to set up a React project with Webpack and Babel. We also learned how to render a React component in the browser. I always like to learn a technology by building something with it from scratch before jumping into a framework like Next.js or Remix. This helps me understand the fundamentals of the technology and how it works.</p>
<blockquote>
<p>This blog post is extracted from my book React Projects, available on <a href="https://packt.link/ReactProjects">Packt</a> and <a href="https://amzn.to/3vq4FQP">Amazon</a>.</p>
</blockquote>
<p>I hope you learned some new things about React! Any feedback? Let me know by connecting to me on <a href="https://linkedin.com/in/gethackteam">LinkedIn</a>, <a href="https://x.com/gethackteam">X</a> or <a href="https://bsky.app/profile/gethackteam.bsky.social">Bluesky</a>. Or leave a comment on my <a href="https://www.youtube.com/@gethackteam?sub_confirmation=1">YouTube channel</a>.</p>
]]>
        </content:encoded>
    </item>
      <item>
        <title><![CDATA[Why Do Developers Love GraphQL?]]></title>
        <link>https://hackteam.io/blog/why-developers-love-graphql</link>
        <pubDate>2022-12-17T00:00:00.000Z</pubDate>
        <guid isPermaLink="false">https://hackteam.io/blog/why-developers-love-graphql</guid>
        <media:content
          url="https://i.ytimg.com/vi/huqR946Y5is/hqdefault.jpg"
        />
        <description>
        <![CDATA[GraphQL has changed how developers interact with data in their applications and has often been called the successor to REST. But why do developers love GraphQL so much? In this blog post, I will give you three reasons why!]]>
        </description>
        <content:encoded>
        <![CDATA[<p>GraphQL has changed how developers interact with data in their applications and has often been called the successor to REST. REST APIs have been the standard for a long time but lack certain features to make consuming them easy. GraphQL on the other is hand was created to make the lifes of developers easy. So why do developers love GraphQL so much? In this blog post, I'll give you three reasons why!</p>
<p>Click the image below to watch the <a href="http://www.youtube.com/watch?v=huqR946Y5is">YouTube video version</a> of this blog post:</p>
<p><a href="http://www.youtube.com/watch?v=huqR946Y5is"><img src="https://i.ytimg.com/vi/huqR946Y5is/hqdefault.jpg" alt="VIDEO: Can you compare GraphQL and tRPC?"></a></p>
<h2>What is GraphQL?</h2>
<p>If you haven't heard of GraphQL, it's a query language for APIs. It was created by Facebook in 2012 and open-sourced in 2015. GraphQL allows you to query data from an API in a structured way. It's a great alternative to REST, the most popular way to create APIs today.</p>
<p>I started using GraphQL in 2016 during a hackathon in Berlin and have been using it ever since. I'm using GraphQL in all my projects where I need access to an API, and I have been creating content about GraphQL for years. I've created a GraphQL book, <a href="https://www.newline.co/books/fullstack-graphql/welcome">Fullstack GraphQL</a>, and multiple GraphQL tutorials on my <a href="https://www.youtube.com/@gethackteam?sub_confirmation=1">YouTube channel</a>.</p>
<h2>Why do developers love GraphQL?</h2>
<h2>One single endpoint for all your data</h2>
<p>One of the biggest advantages of GraphQL is that you only need one single endpoint to query all your data. In REST, you need multiple endpoints to query different data. Generally speaking, every data entity (like a database table) in REST API will have its own endpoint. For example, if you want to get a list of posts and a specific from a CMS API, you need to send requests to two endpoints:</p>
<ul>
<li><a href="https://jsonplaceholder.typicode.com/posts">GET /posts</a> (list of posts)</li>
<li><a href="https://jsonplaceholder.typicode.com/posts/1">GET /posts/1</a> (specific post)</li>
</ul>
<p>In GraphQL, you can request both the list of posts and the specific post in one single query:</p>
<pre><code class="language-graphql">query {
  posts {
    id
    title
  }
  post(id: 1) {
    id
    title
  }
}
</code></pre>
<p>GraphQL would execute this query against a single endpoint, which is much easier to manage. You don't need to worry about creating multiple endpoints, and you don't need to worry about versioning them.</p>
<h2>No more over- and under-fetching</h2>
<p>In REST, you sometimes fetch more than the data you actually need, and this is called over-fetching. In the example from the previous section, you're fetching the list of posts from a REST API, and let's say we want to display them on an overview page. Therefore we need the <code>id</code> and <code>title</code> of each post, but this REST API is returning a lot more data than you need. Not only is it returning the <code>id</code> and <code>title</code> of the post, but also the <code>body</code> and <code>userId</code>. Getting more data than you need wastes bandwidth and processing power.</p>
<pre><code class="language-json">[
  {
    &quot;id&quot;: 1,
    &quot;userId&quot;: 1,
    &quot;title&quot;: &quot;sunt aut facere repellat provident occaecati excepturi optio reprehenderit&quot;,
    &quot;body&quot;: &quot;quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto&quot;
  },
  {
    &quot;id&quot;: 2,
    &quot;userId&quot;: 1,
    &quot;title&quot;: &quot;qui est esse&quot;,
    &quot;body&quot;: &quot;est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla&quot;
  }
  // Other posts...
]
</code></pre>
<p>In GraphQL, you can request exactly the data you need by specifying the fields you want to get in your query:</p>
<pre><code class="language-graphql">query {
  posts {
    id
    title
  }
}
</code></pre>
<p>Opposite to over-fetching, there's also under-fetching. Sometimes need to make multiple requests to REST API endpoints to get all the data you need. This is called under-fetching because you're not getting all the data you need at once. Let's have another look at the example from the previous section. Instead of just getting a specific post on a detail page, we also want the comments for this post. In REST, you need to make two requests as a different endpoint than the post returns the comments:</p>
<ul>
<li><a href="https://jsonplaceholder.typicode.com/posts/1">GET /posts/1</a> (specific post)</li>
<li><a href="https://jsonplaceholder.typicode.com/posts/1/comments">GET /posts/1/comments</a> (comments for specific post)</li>
</ul>
<p>In GraphQL, you can request exactly the data you need even when the data is spread across multiple entities. You can request the post and the comments in one single query:</p>
<pre><code class="language-graphql">{
  post(id: 1) {
    id
    title
    comments {
      id
      name
    }
  }
}

</code></pre>
<p>This query would return the post and comments in one single response, which is much easier to manage in your application and takes fewer data to transfer. Especially as you prevent over-fetching in this example and only receive the data you're using on your detail page.</p>
<h2>GraphQL is self-documenting</h2>
<p>Well, at least partially...</p>
<p>In REST, you need to document your API. This is a lot of work, and it's easy to forget to update the documentation when you make changes to your API. In GraphQL, you don't need to document your API, as the documentation is generated automatically. You can use the GraphiQL tool to explore your GraphQL API and see all the available queries and mutations. You can also see the fields you can request for each query and mutation. This is much easier to manage than documenting your API manually.</p>
<p><img src="/images/exploring-graphiql-2-changes.png" alt="Using GraphiQL"></p>
<p>GraphQL APIs have built-in documentation, which can be generated from its GraphQL schema. Every GraphQL API has a schema for defining all the operations and data types. The schema is used to validate the queries and mutations you send to the API. You can use the GraphiQL tool (read more in this <a href="/blog/exploring-graphiql-2-updates-and-new-features">blog post</a>) to explore your GraphQL API and see all the available queries and mutations. You can also see the fields you can request for each query and mutation. But also to generate the documentation, making using a GraphQL API a lot easier to manage than having to document your REST API manually.</p>
<h2>Conclusion</h2>
<p>There are many reasons developers love GraphQL, especially frontend developers. GraphQL is easier to manage than REST and is much easier to use in your application. You can use GraphQL in your frontend application to fetch all the data you need in one single request. It prevents over- and under-fetching, plus it's self-documenting.</p>
<p>I'd love to hear your thoughts on this topic. Do you love GraphQL? Why? Let me know by connecting to me on <a href="https://linkedin.com/in/gethackteam">LinkedIn</a>, <a href="https://x.com/gethackteam">X</a> or <a href="https://bsky.app/profile/gethackteam.bsky.social">Bluesky</a>. Or leave a comment on my <a href="https://www.youtube.com/@gethackteam?sub_confirmation=1">YouTube channel</a>.</p>
]]>
        </content:encoded>
    </item>
      <item>
        <title><![CDATA[Exploring GraphiQL 2 Updates and New Features]]></title>
        <link>https://hackteam.io/blog/exploring-graphiql-2-updates-and-new-features</link>
        <pubDate>2022-12-12T00:00:00.000Z</pubDate>
        <guid isPermaLink="false">https://hackteam.io/blog/exploring-graphiql-2-updates-and-new-features</guid>
        <media:content
          url="https://i.ytimg.com/vi/IFoMMoXezJg/hqdefault.jpg"
        />
        <description>
        <![CDATA[GraphiQL is a popular tool for GraphQL developers. But for many years, GraphiQL has not had a UI update. Since a few months, GraphiQL 2 is here and in this video I will explore the new features of GraphiQL 2 and show you how to use them.]]>
        </description>
        <content:encoded>
        <![CDATA[<p>GraphiQL is a popular tool for GraphQL developers. It is a web-based IDE for GraphQL that lets you explore a GraphQL API. It's a great tool for developers to test their GraphQL queries and mutations, and find out what the schema of a GraphQL API looks like. For many developers it's the first tool they use to learn GraphQL.</p>
<p>But for many years, GraphiQL hasn't had a UI update. And it's been a while since it's been updated. But now since few months, GraphiQL 2 is here. It's a complete new version of GraphiQL with a new UI and a lot of new features. In this blog post, I'll explore the new features of GraphiQL 2 and show you how to use them.</p>
<p>Click the image below to watch the <a href="http://www.youtube.com/watch?v=IFoMMoXezJg">YouTube video version</a> of this blog post:</p>
<p><a href="http://www.youtube.com/watch?v=IFoMMoXezJg"><img src="https://i.ytimg.com/vi/IFoMMoXezJg/hqdefault.jpg" alt="VIDEO: Can you compare GraphQL and tRPC?"></a></p>
<h2>Little bit of history</h2>
<p>GraphiQL is a tool that was created to help developers explore GraphQL APIs, maintained by the GraphQL Foundation. But when GraphiQL became more and more popular, developers started to create additional GraphQL IDEs. A good example of this was <a href="https://github.com/graphql/graphql-playground">GraphQL Playground</a>, which quickly became the most popular GraphQL IDE. It was loosely based on GraphiQL, but had more features and a better UI.</p>
<p>After GraphQL Playground became part of the GraphQL Foundation, the need for having just one GraphQL IDE became more important. So the GraphQL Foundation decided to merge GraphiQL and GraphQL Playground into one tool. GraphiQL 1 relied on major tech debt and multiple dependencies that were outdated and hard to maintain. With the merge of GraphiQL and GraphQL Playground, the GraphQL Foundation decided to create a new version of GraphiQL, which is now called GraphiQL 2. The design and creation of GraphiQL 2 was <a href="https://github.com/graphql/graphiql/discussions/2216">all documented in Github</a>.</p>
<h2>First look at GraphiQL 2</h2>
<p>For me personally, this is one of the biggest releases in GraphQL world this year. As for too many years we had to work with GraphiQL 1, which is looking like it's coming from the Stone Age. With GraphiQL 2, the theme behind GraphiQL has really outdone themselves as they've created a better version of GraphiQL that looks like it's actually from modern day.</p>
<p><img src="/images/exploring-graphiql-2-changes.png" alt="Exploring GraphiQL 2 updates"></p>
<p>As you can see in the above screenshot of GraphiQL 2, it looks way more modern than GraphiQL 1. It has a dark mode, a light mode, and a system mode. It has a new UI, and a lot of new features. Compared to GraphiQL 1, it's looks like a complete new version of GraphiQL with the same feel.</p>
<p>Let's look at the same page in GraphiQL 1:</p>
<p><img src="/images/exploring-graphiql-2-comparison.png" alt="Comparison with GraphiQL 1"></p>
<p>This screenshot is from GraphiQL 1 and as you can see it just feels outdated, from the color scheme to the used font. As oppposed to GraphiQL 2 there's no way to change the theme from the UI itself.</p>
<p>Most features from GraphiQL 1 are also available in GraphiQL 2, such as the docs page, history, and the ability to pass variables and headers. But GraphiQL 2 has a lot of new features as well, which I'll explore in the next section.</p>
<h2>New features in GraphiQL 2</h2>
<p>I already mentioned GraphiQL 2 has a dark mode, which is a great addition and something most modern developer tools have today. OFcourse, you cna also switch to system mode, which will use the system theme so it changes to dark when sun sets.</p>
<p><img src="/images/exploring-graphiql-2-dark-mode.png" alt="Dark mode in GraphiQL 2"></p>
<p>But next to dark mode the biggest feature update is the tabs to switch between multiple queries. This is a great addition as it allows you to have multiple queries open at the same time. This is something I've been missing in GraphiQL 1 for a long time.</p>
<p><img src="/images/exploring-graphiql-2-tabs.png" alt="Tabs GraphiQL 2"></p>
<p>Having tabs is especially useful when you have a query to get a list of results and a query to get a specific item. You can now have both open at the same time and switch between them.</p>
<h2>Conclusion</h2>
<p>GraphiQL 2 is a great update to GraphiQL 1. It has a new UI, a lot of new features, and a dark mode. It's still the easiest tool to use for GraphQL developers to explore a GraphQL API. I'm really excited to see what the future of GraphiQL 2 will bring, especially as GraphiQL 2 is now maintained more activley than GraphiQL 1 used to be.</p>
<p>P.S. Follow Roy Derks on <a href="https://linkedin.com/in/gethackteam">LinkedIn</a>, <a href="https://x.com/gethackteam">X</a> or <a href="https://bsky.app/profile/gethackteam.bsky.social">Bluesky</a> for more React, GraphQL and TypeScript tips &amp; tricks. And subscribe to my <a href="ttps://www.youtube.com/@gethackteam?sub_confirmation=1">YouTube channel</a> for React, GraphQL and TypeScript tutorials.</p>
]]>
        </content:encoded>
    </item>
      <item>
        <title><![CDATA[Zero Config TypeScript Applications with Next.js]]></title>
        <link>https://hackteam.io/blog/zero-config-typescript-applications-nextjs</link>
        <pubDate>2022-12-06T00:00:00.000Z</pubDate>
        <guid isPermaLink="false">https://hackteam.io/blog/zero-config-typescript-applications-nextjs</guid>
        <media:content
          url="https://i.ytimg.com/vi/ntG90Mf9ySE/hqdefault.jpg"
        />
        <description>
        <![CDATA[The simplest way to set up a React TypeScript project from scratch is by using Next.js. In this blog post we will explore how to use Next.js for your next project and how you have to write zero configuration to use it with TypeScript.]]>
        </description>
        <content:encoded>
        <![CDATA[<p>Do you want to get up and running quickly with modern web applications but don't have the time or knowledge to navigate complex configurations? With Next.js, you can set up zero config TypeScript applications to build modern and performant web apps using this open-source JavaScript framework. With this blog post, you'll get up to speed quickly on how to use these two technologies together to build applications without worrying about complex configurations. You'll get into the core concepts of Next.js, understand how to use TypeScript within your projects, and learn how to set up a development environment so that you can start building quickly and easily.</p>
<p>Click the image below to watch the <a href="https://www.youtube.com/watch?v=ntG90Mf9ySE">YouTube video version</a> of this blog post:</p>
<p><a href="https://www.youtube.com/watch?v=ntG90Mf9ySE"><img src="https://i.ytimg.com/vi/ntG90Mf9ySE/hqdefault.jpg" alt="VIDEO: Zero Config TypeScript Applications with Next.js"></a></p>
<p>By the end of this blog post, you will:</p>
<ul>
<li>Know how to set up a fresh application with Next.js</li>
<li>Understand the core concepts of Next.js and TypeScript</li>
<li>Be able to use TypeScript in your Next.js Project</li>
</ul>
<h2>Why combine Next.js and TypeScript?</h2>
<p>Building robust, modern web applications can be easy. With Next.js, you'll leverage two of today's most popular technologies - Next.js and TypeScript - together without needing any complex configuration.</p>
<p>Next.js is a framework that allows you to build React applications quickly. It's a great choice for developers who want to get up and running soon with modern web applications without worrying about complex configurations. It's also an excellent choice for developers who wish to build performant and scalable applications, as Next.js has many features that help you make fast and efficient applications. For example, Next.js supports Server-side Rendering (SSR) and Static Site Generation (SSG), two of the most efficient ways to load data in a web application.</p>
<p>TypeScript, on the other hand, is a typed language that adds type safety and improved performance to your codebase.</p>
<p>Together, they form a powerful combination for building modern and performant web apps.</p>
<h2>Getting Started with Next.js</h2>
<p>Setting up a development environment with Next.js is straightforward.</p>
<p>You can create a new Next.js project from your terminal using the following command:</p>
<pre><code class="language-bash">npx create-next-app my-app
</code></pre>
<p>Where <code>my-app</code> is the name of your project, Next.js will prompt you to choose a template, creating a new project for you. For the sake of this blog post, we will select the default template, a simple Next.js application with a single page. And NOT set up a TypeScript project.</p>
<p>Once the project is created, you can run the following command to start the development server:</p>
<pre><code class="language-bash">npm run dev
</code></pre>
<p>And you should be seeing a small application that's available at <code>http://localhost:3000</code>.</p>
<h2>Fix the &quot;parsing error for using import&quot;</h2>
<p>When writing this blog post, I'm using Next.js version 13.0.5. And when I hover over any of the <code>import</code> statements at the top of a file, I get the following error:</p>
<pre><code class="language-bash">Parsing error: Cannot find module 'next/babel'
</code></pre>
<p>This error shows because Next.js is using Babel to transpile the code, which somehow interferes with the Prettier plugin that my VSCode uses. To fix this, I need to change my <code>.eslintrc.json</code> file from:</p>
<pre><code class="language-json">{
  &quot;extends&quot;: &quot;next/core-web-vitals&quot;
}
</code></pre>
<p>To this:</p>
<pre><code class="language-json">{
  &quot;extends&quot;: [&quot;next/core-web-vitals&quot;, &quot;prettier&quot;]
}
</code></pre>
<p>When you're done, you should be able to hover over the <code>import</code> statements without getting any errors.</p>
<h2>Using TypeScript in your Next.js Project</h2>
<p>Now that we have a basic Next.js application, we can start adding TypeScript to it. To do this, you don't have to install any additional packages, as Next.js has built-in support for TypeScript.</p>
<p>Convert all the files in your project from <code>.js</code> to <code>.tsx</code>, and you're good to go. For example, if you have a file called <code>pages/index.js</code>, you can rename it to <code>pages/index.tsx</code>.</p>
<p>And restart your development server. Next.js will install the dependencies needed to use TypeScript for your project and generate a <code>tsconfig.json</code>. This file includes all the required configurations to use Next.js together with TypeScript. You should now be able to use TypeScript features in your codebase.</p>
<p>Once you've done this, you can use TypeScript features in your codebase. For example, you can add types to your function parameters and use interfaces to define the shape of your data.</p>
<h2>Conclusion</h2>
<p>In this blog post, you learned how to set up a new application with Next.js, understand the core concepts of Next.js and TypeScript, and be able to use TypeScript in your Next.js Project.</p>
<p>If you're ready to take your web development skills to the next level and learn how to build powerful applications using Next.js and TypeScript, join me for my upcoming videos by subscribing to my YouTube channel.</p>
<p><a href="https://www.youtube.com/@gethackteam?sub_confirmation=1">&gt; Subscribe to my YouTube channel</a></p>
<p>Or find me on <a href="https://linkedin.com/in/gethackteam">LinkedIn</a>, <a href="https://x.com/gethackteam">X</a> or <a href="https://bsky.app/profile/gethackteam.bsky.social">Bluesky</a>. I'd love to hear from you!</p>
]]>
        </content:encoded>
    </item>
      <item>
        <title><![CDATA[Apollo Server v4 Breaking Changes. Time to move away?]]></title>
        <link>https://hackteam.io/blog/apollo-server-v4-breaking-changes</link>
        <pubDate>2022-12-02T00:00:00.000Z</pubDate>
        <guid isPermaLink="false">https://hackteam.io/blog/apollo-server-v4-breaking-changes</guid>
        <media:content
          url="https://i.ytimg.com/vi/BzYxqXCpEmI/hqdefault.jpg"
        />
        <description>
        <![CDATA[Apollo Server has been the go-to JavaScript library for building GraphQL servers. Many breaking changes were announced for the latest Apollo Server v4, along with an EOL for Apollo Server v2 and v3 as early as October 2023. In this article, I will explain the breaking changes and why it might be time to move away from Apollo Server.]]>
        </description>
        <content:encoded>
        <![CDATA[<p>Apollo Server has been the go-to JavaScript library for building GraphQL servers for the last half-decade. But almost every year, there are breaking changes, and the latest version 4 is no exception. Not only did they announce breaking changes, they also announced that Apollo will drop support for Apollo Server v2 and v3 as early as October 2023. In this article, I will explain the breaking changes and why it might be time to move away from Apollo Server.</p>
<p>Click the image below to watch the <a href="http://www.youtube.com/watch?v=BzYxqXCpEmI">YouTube video version</a> of this blog post:</p>
<p><a href="http://www.youtube.com/watch?v=BzYxqXCpEmI"><img src="https://i.ytimg.com/vi/BzYxqXCpEmI/hqdefault.jpg" alt="VIDEO: Apollo Server v4 Breaking Changes. Time to move away?"></a></p>
<h2>Biggest Breaking Changes</h2>
<p>Let's look at the most significant breaking changes in Apollo Server v4. Together with these breaking changes, a migration path from earlier versions of Apollo Server was also published in the documentation.</p>
<blockquote>
<p>&quot;We recommend that all users of Apollo Server upgrade to Apollo Server 4 as soon as possible. Apollo Server 2 and Apollo Server 3 are deprecated, with an end-of-life date of October 22nd, 2023.&quot; - <a href="https://www.apollographql.com/docs/apollo-server/migration/">Apollo Server v4 Migration Guide</a></p>
</blockquote>
<h3>New project structure</h3>
<p>Apollo Server v4 is the latest version of Apollo Server and is replacing Apollo Server v2 and v3. As part of this update, they've bundled some packages in <code>@apollo/server</code> to replace the <code>apollo-server</code> package. Part of this is the <code>apollo-server-express</code> package, the most popular package for building GraphQL servers in Node.js, which is now integrated into the <code>@apollo/server</code> package.</p>
<p>Thus, if you want to use Apollo Server v4, you must follow the migration guide and update your code to use the new packages. As shown in the migration guide flowchart below:</p>
<p><img src="/images/apollo-server-v4-breaking-changes-migration.png" alt="Apollo Server v4 Migration Path"></p>
<p>This seems like a minor deal unless you're not using Express as your web framework. And an important note here is that Express GraphQL is <a href="https://github.com/graphql/express-graphql">being deprecated</a> by the GraphQL Foundation. So if you're using Express for a GraphQL API, you should move away from it anyway.</p>
<h3>Dropped support for other web frameworks</h3>
<p>Now that Express is the default framework for running the GraphQL server, Apollo decided to remove support for all other web frameworks. This means Apollo is forcing developers to use Express to run their GraphQL servers. This is a big change as Apollo Server v2, and v3 allowed you to build on top of the <code>apollo-server-*</code> packages, such as <code>apollo-server-fastify</code> or <code>apollo-server-koa</code>. This is a huge change as it means you can no longer use Koa or Fastify to run your GraphQL servers unless someone builds a <strong>new package</strong> for it.</p>
<p><img src="/images/apollo-server-v4-breaking-changes-support.png" alt="Apollo Server v4 Breaking Changes"></p>
<p>Until someone decides to build a new package for the web framework you use, you're stuck with Apollo Server v3, which is deprecated and will be end-of-life in October 2023.</p>
<h3>Updated concept of <code>dataSources</code></h3>
<p>Apollo Server v4 has a new concept of <code>dataSources</code>. In Apollo Server v2 and v3 you could use the <code>dataSources</code> property to pass in an object with all of your data sources. This is no longer the case in Apollo Server v4. Instead, you will need to create a class that extends the <code>DataSource</code> class and then pass in an array of instances of this class to the <code>dataSources</code> property.</p>
<p><img src="/images/apollo-server-v4-breaking-changes-datasources.png" alt="Deprecated data sources in Apollo Server v4"></p>
<p>As a &quot;side effect&quot; of this change, Apollo deprecated the data source implementations created for SQL, MongoDB, and Firestore. Similar to the web framework plugins, you will need to make your own data source implementation for these data sources.</p>
<h3>What else has changed?</h3>
<p>Besides no longer supporting any other web framework than Express, there are a <a href="https://github.com/apollographql/apollo-server/blob/main/packages/server/CHANGELOG.md#400">a lot of other breaking changes</a>. Not all of them are bad, and the new Apollo Server v4 seems to be fixing a lot of tech debt the team has been building up over the years. For example, Apollo Server v4 has better TypeScript support than previous versions. And the deprecation of <code>ApolloError</code> in favor of <code>GraphQLError</code> from the <code>graphql</code> package is a good step forward to keep Apollo Server more in line with other libraries to build your GraphQL API.</p>
<h2>Should I move away from Apollo Server?</h2>
<p>It's entirely up to you. But from a <a href="https://www.reddit.com/r/graphql/comments/z2d5uo/comment/iy94y43/">Reddit post of the Apollo team</a> it seems the next &quot;backwards incompatible&quot; release of Apollo Server will be Apollo Server v5, in spring 2023(!). To me, that just shows that Apollo Server is not a stable library to build your GraphQL API. And if you're building a GraphQL API for a company, you don't want to be stuck with a library that is not stable and will be deprecated every few years.</p>
<p>That said, if you are using Express you can easily upgrade to Apollo Server v4. Keeping in mind that <code>express-graphql</code> has been deprecated as well. If you're using Koa or Fastify, you can still use Apollo Server v3 until October 2023. You're out of luck if you're using any other web framework. You will either need to switch to Express, stay on Apollo Server v3 or wait for community support for the web framework you're using. In that case, consider moving away from Apollo Server.</p>
<p>When moving away from Apollo Server, and you're looking for a replacement built with JavaScript or TypeScript, let me give you some options. If you want to keep building your GraphQL API schema first, you might want to consider <a href="https://mercurius.dev/">Mercurius</a> (which relies on Fastify) or <a href="https://the-guild.dev/graphql/yoga-server">GraphQL Yoga</a>. If you're going to build your GraphQL API code or resolver first, have a look at <a href="https://typegraphql.com/">TypeGraphQL</a> or <a href="https://nexusjs.org/">Nexus</a>. Alternatively, there are great GraphQL-as-a-Service solutions such as <a href="https://stepzen.com/">StepZen</a> in case you no longer want to build, maintain and host your own GraphQL API.</p>
<blockquote>
<p>You can learn more about the differences between schema-first, code/resolver-first, or using a GraphQL-as-a-Service in this <a href="https://www.youtube.com/watch?v=SIq8g9vMVHc">recording of my talk at GraphQL Galaxy 2021</a>.</p>
</blockquote>
<p>Are you using Apollo Server? What are your thoughts on the breaking changes? Let me know on <a href="https://linkedin.com/in/gethackteam">LinkedIn</a>, <a href="https://x.com/gethackteam">X</a> or <a href="https://bsky.app/profile/gethackteam.bsky.social">Bluesky</a>.</p>
]]>
        </content:encoded>
    </item>
      <item>
        <title><![CDATA[Can you compare GraphQL and tRPC?]]></title>
        <link>https://hackteam.io/blog/compare-graphql-and-trpc</link>
        <pubDate>2022-11-28T00:00:00.000Z</pubDate>
        <guid isPermaLink="false">https://hackteam.io/blog/compare-graphql-and-trpc</guid>
        <media:content
          url="Can you compare GraphQL and tRPC?"
        />
        <description>
        <![CDATA[There have been many discussions on Twitter around "GraphQL versus tRPC" for building a modern backend for your application. As a developer working with GraphQL in the past years, this triggered me to compare the two and see what they are both excellent at (and what they are not).]]>
        </description>
        <content:encoded>
        <![CDATA[<p>There have been many discussions on Twitter around &quot;GraphQL versus tRPC&quot; for building a modern backend for your application. GraphQL has become popular in recent years as the defacto successor to REST, while tRPC solves the problem of end-to-end safety in fullstack applications. It's like <a href="https://x.com/alexdotjs/status/1597182082941595648?s=20&amp;t=hisusYuNOJ46q08HF8Is8w">comparing apples to oranges</a>.</p>
<p>TLDR; GraphQL is a query language, and tRPC is a library.</p>
<p>As a developer working with GraphQL in the past years, this triggered me to compare the two and see what they are both excellent at (and what they are not).</p>
<p>Click the image below to watch the <a href="http://www.youtube.com/watch?v=_Tc7YVR-0LU">YouTube video version</a> of this blog post:</p>
<p><a href="http://www.youtube.com/watch?v=_Tc7YVR-0LU"><img src="https://i.ytimg.com/vi/_Tc7YVR-0LU/hqdefault.jpg" alt="VIDEO: Can you compare GraphQL and tRPC?"></a></p>
<h2>But first; You might have been using GraphQL wrong</h2>
<p>GraphQL is a query language for your API, and it's not a one-to-one replacement for REST. It's a way to query your API in a way that is more flexible than REST, giving you control over the response of the requests. In many of the Twitter conversations, I found that people were comparing GraphQL to REST, and that's different from what GraphQL is. Also, the GraphQL type system is not meant to be used for end-to-end type safety, at least not in a first way. But instead, as a way to document your API and ensure the runtime types of your API are correct.</p>
<h2>Can we compare GraphQL to tRPC?</h2>
<p>GraphQL is a query language for your API, while tRPC is a set of libraries for building end-to-end typesafe APIs. As mentioned earlier, this is like comparing apples to oranges. But let's break down both of them and learn about their characteristics.</p>
<h3>GraphQL is a query language</h3>
<p>GraphQL APIs typically use HTTP as a transport layer, and the GraphQL query is sent as a POST request to the API. The API then processes the query and returns the result as a JSON response. This is the same way that REST APIs work, but GraphQL is a query language, not a protocol. This means that you can use GraphQL over any transport layer and any protocol you want. This is also why you can use GraphQL in your frontend application because it's just a query language.</p>
<p><img src="/images/graphql-versus-trpc-graphql-overview.png" alt="GraphQL overview"></p>
<p>GraphQL itself is nothing more than a query language, and it's up to the GraphQL implementation libraries and frameworks to implement this query language according to its specification. This means that there are many different ways to implement GraphQL, and there are many different ways to use GraphQL. This is also why there are many different ways to use GraphQL in your front end application.</p>
<h3>tRPC is a library</h3>
<p><a href="https://trpc.io/">tRPC</a> is a set of libraries that uses TypeScript to ensure type safety throughout the entire application. Its primary purpose is to make it easy to build end-to-end typesafe applications in a single codebase. The basis is a tRPC server in which you define the endpoints (or routes), the type definition for these endpoints, and handle any connection to a data source - like a database.</p>
<p><img src="/images/graphql-versus-trpc-trpc-overview.png" alt="tRPC overview"></p>
<p>You can consume a tRPC API in your frontend application, using the tRPC client library. You're not directly sending an HTTP request to get your data, but let the tRPC client handle this for you, almost like an ORM for APIs. This client can make strongly typed API calls without relying on code generation. You can import TypeScript types from the server directly into your frontend application without generating any code.</p>
<h2>What differentiates GraphQL and tRPC?</h2>
<p>This is a very subjective question, but I think it's important to know what differentiates GraphQL and tRPC. This way, you can decide for yourself what you want to use in your application.</p>
<h3>GraphQL is great for querying multiple data sources</h3>
<p>GraphQL excels in combining multiple data sources into a single query. GraphQL is often used for data modeling and architecture, and it's great for this. For example, if you want to query data from one service (like a Headless CMS) and data from another (let's say a database), you can do this in a single query with GraphQL. You can even combine this data on field or type level. It is one of the major reasons companies like Facebook and GitHub are using GraphQL.</p>
<p><img src="/images/graphql-versus-trpc-tweets.png" alt="GraphQL versus tRPC on X">
<em>Tweets from <a href="https://x.com/notrab">Jamie Barton</a> and <a href="https://x.com/tazsingh">Taz Singh</a>.</em></p>
<p>Whereas tRPC is not really meant for this. It's meant for building end-to-end typesafe APIs, and it's not really meant for combining multiple data sources. You can do this, but it's not the purpose of tRPC.</p>
<h3>tRPC is great for end-to-end type safety</h3>
<p>tRPC is great for end-to-end type safety, and it allows you to use the same types in your frontend application as you use in your backend application. GraphQL has no built-in way to share type definitions between a frontend and backend, but you can use the GraphQL schema to generate TypeScript type definitions. But this is different from end-to-end type safety. Every time you update your GraphQL schema, you have to regenerate the types.</p>
<p>When using tRPC, you're building everything using TypeScript. This means that you can import the types from the server directly into your frontend application. The tRPC client can access the TypeScript types from your tRPC server directly. You don't need external libraries when querying tRPC in your frontend application because it's all built-in the tRPC libraries.</p>
<h3>GraphQL allows for decoupled services; tRPC for a single codebase</h3>
<p>GraphQL is great for decoupled services as it's programming language and transport layer agnostic. This means that you can use any programming language and any transport layer you want. Services that expose a GraphQL API can be implemented in any programming language, for example TypeScript and Go, and still be able to communicate with each other. For teams and companies that are technologicallyy diverse this is a great way to scale and limit the amount of dependencies between teams.</p>
<p>tRPC is not really meant for this. It's meant for building end-to-end typesafe APIs in a single codebase, in TypeScript! It brings your frontend and backend closely together, for example in a monorepo. You can use the same types in your frontend and backend application, which allows you to rapidly iterate on your application. What's not to love if you're building a fullstack TypeScript project?</p>
<h3>tRPC is easier to use than GraphQL</h3>
<p>&quot;tRPC is easier to use than GraphQL&quot; is a recurring statement people make when comparing GraphQL and tRPC. But as tRPC is a library and GraphQL is a query language, it's impossible to compare. For GraphQL, it's up to the developer to build a GraphQL using one of the many available implementations, while tRPC is a set of libraries you can use out of the box. This makes it not a fair comparison, but let's break it down anyway.</p>
<p>For example, you could build a GraphQL API using a schema-first GraphQL server library. You have to define a GraphQL schema, write the resolvers to collect the data from a data source, and then generate the types from the schema. Going this path is a lot of work and comes with many choices you need to make as a developer.</p>
<p>But you can also build a GraphQL API using a code-first GraphQL server library. This means you can write the resolvers and then generate the schema from the resolvers. Code-first libraries are much closer to tRPC in terms of Developer Experience but still more challenging than using a GraphQL-as-a-service like <a href="https://stepzen.com">StepZen</a>.</p>
<p>Then you also have a wide choice of various GraphQL client libraries. You can use GraphQL client library like <a href="https://www.apollographql.com/docs/react/">Apollo Client</a> or <a href="https://formidable.com/open-source/urql/">urql</a> that helps you with caching and state management, or use a library that only handles the HTTP requests. There are many choices, which could be unclear when you're new to GraphQL.</p>
<h2>Conclusion</h2>
<p>In this blog post, I explained the differences between GraphQL and tRPC. I hope this blog post helped you understand the differences between the two and that you can now make a better decision on which one to use for your next project. The main questions to ask yourself when choosing between GraphQL and tRPC are:</p>
<ul>
<li>Do you want to query multiple data sources in a single query and keep your services decoupled? If so, GraphQL is a perfect choice. If you want end-to-end type safety and don't care about decoupling your frontend and backend, tRPC is a better fit.</li>
<li>Are you planning to work with multiple programming languages? Go for GraphQL, as it's programming language agnostic. If you want to use TypeScript throughout your entire application, tRPC might be a better fit.</li>
</ul>
<p>There are many other things to consider when choosing between GraphQL and tRPC, but these are the main ones in my opinion. I'd love to hear your thoughts on this, so please let me know via <a href="https://linkedin.com/in/gethackteam">LinkedIn</a>, <a href="https://x.com/gethackteam">X</a> or <a href="https://bsky.app/profile/gethackteam.bsky.social">Bluesky</a>.</p>
]]>
        </content:encoded>
    </item>
      <item>
        <title><![CDATA[Setting up Your First React TypeScript Project From Scratch]]></title>
        <link>https://hackteam.io/blog/setting-up-first-react-typescript-project-from-scratch</link>
        <pubDate>2022-11-26T00:00:00.000Z</pubDate>
        <guid isPermaLink="false">https://hackteam.io/blog/setting-up-first-react-typescript-project-from-scratch</guid>
        <media:content
          url="https://i.ytimg.com/vi/ek6rGKXk4e4/hqdefault.jpg"
        />
        <description>
        <![CDATA[This post is a complete overview of how to start a React TypeScript project from scratch. It discusses the necessary libraries and considerations for setting up the environment, creating a basic project structure and running the application. ]]>
        </description>
        <content:encoded>
        <![CDATA[<p>Are you looking to create your own React TypeScript project, but don't know where to start? With this blog post, you'll get a comprehensive guide to setting up a React TypeScript project from scratch. We'll discuss the necessary components and considerations for environment setup, creating a basic project structure and running the application. With this comprehensive guide in hand, you'll have all the information you need to get started on your React TypeScript journey and create something truly amazing. So, let's dive in and get started on your React TypeScript project!</p>
<p>Click the image below to watch the YouTube video version of this blog post:</p>
<p><a href="http://www.youtube.com/watch?v=ek6rGKXk4e4"><img src="https://i.ytimg.com/vi/ek6rGKXk4e4/hqdefault.jpg" alt="VIDEO: Setting up Your First React TypeScript Project From Scratch"></a></p>
<h2>Installing Create React App</h2>
<p>Today, Create React App is the most popular way to create a React project. It's a tool that allows you to create a React project without having to worry about the configuration. It's a great way to get started with React and TypeScript. You can create a new project with Create React App using <code>npx</code> with the following command:</p>
<pre><code class="language-bash">npx create-react-app my-app

</code></pre>
<p>This will create a new React project in the <code>my-app</code> directory. Now that your React project is set up, it's time to run the application. You can then run the project with the following command:</p>
<pre><code class="language-bash">cd my-app
npm start
</code></pre>
<p>This will start the development server and open the application in your browser in <code>http://localhost:3000</code>. You can now start developing your React TypeScript project!</p>
<blockquote>
<p>Note: <code>npx</code> is installed on your machine when you install Node.js.</p>
</blockquote>
<h2>Installing TypeScript</h2>
<p>To use TypeScript in your Create React App project, you need to add a <code>tsconfig.json</code> file that holds the TypeScrupt configuration. You can do this by running the following command:</p>
<pre><code class="language-bash">touch tsconfig.json
</code></pre>
<p>And add this configuration to the <code>tsconfig.json</code> file:</p>
<pre><code class="language-json">{
  &quot;compilerOptions&quot;: {
    &quot;outDir&quot;: &quot;dist&quot;,
    &quot;rootDir&quot;: &quot;src&quot;,
    &quot;sourceMap&quot;: true,
    &quot;noImplicitAny&quot;: true,
    &quot;allowJs&quot;: true,
    &quot;moduleResolution&quot;: &quot;node&quot;,
    &quot;module&quot;: &quot;commonJS&quot;,
    &quot;lib&quot;: [&quot;es6&quot;, &quot;dom&quot;],
    &quot;target&quot;: &quot;ES5&quot;,
    &quot;jsx&quot;: &quot;react&quot;
  },
  &quot;exclude&quot;: [&quot;node_modules&quot;, &quot;dist&quot;]
}
</code></pre>
<p>To use TypeScript in your project, you only need to restart the development server by running <code>npm start</code> again. This will now compile your TypeScript code to JavaScript and run the application.</p>
<p>Every file in your application can be renamed from <code>js</code> to <code>tsx</code> to use TypeScript. You can also add the <code>ts</code> extension to your files, but it's needed to use <code>tsx</code> for React components as these files contain JSX.</p>
<p>You can now start developing your React TypeScript project!</p>
<h2>Allowing synthetic default imports</h2>
<p>In your IDE you might see some errors highlighted about synthetic default imports. This is because TypeScript doesn't know how to import the default export from a module. By default, imports in TypeScript have the following syntax:</p>
<pre><code class="language-typescript">import * as React from 'React';
</code></pre>
<p>If we want to keep importing our modules as we did with Babel, we need to change some settings in our <code>tsconfig.json</code> file:</p>
<pre><code class="language-json">{
  &quot;compilerOptions&quot;: {
    &quot;allowSyntheticDefaultImports&quot;: true,
    &quot;esModuleInterop&quot;: true,
    ...
  }
}
</code></pre>
<p>After this, we can deconstruct our imports again and avoid the obligatory asterisk <code>*</code>:</p>
<pre><code class="language-typescript">import React, { FC } from 'react';
</code></pre>
<p>This will allow us to import our modules as we did before. But there are more things we should do to make our TypeScript project more robust.</p>
<h2>Adding global type definitions</h2>
<p>Another highlighted error in your IDE (I'm using VS code) is that it cannot find the type definitions for the SVG files we're importing.</p>
<p><code>Cannot find module './logo.svg' or its corresponding type declarations.</code></p>
<p>To fix this, we need to add this type definition to our project. We can do this by creating a <code>global.d.ts</code> file in the <code>src</code> directory and adding the following code:</p>
<pre><code class="language-typescript">declare module '*.svg' {
  const content: string;
  export default content;
}
</code></pre>
<p>This will allow us to import SVG files in our project without any errors.</p>
<h2>Creating a TypeScript React component</h2>
<p>Now that we've set up our project, it's time to create our first TypeScript React component. We can do this by creating a <code>components/Link.tsx</code> file in the <code>src</code> directory and adding the following code:</p>
<pre><code class="language-typescript">import * as React from 'react';

type LinkProps = {
  href: string;
  targetBlank: boolean;
  children: React.ReactNode | string;
};

export default function Link({
  href,
  targetBlank = false,
  children,
}: LinkProps) {
  return (
    &lt;a
      className='App-link'
      href={href}
      target={targetBlank ? '_blank' : ''}
      rel={targetBlank ? 'noopener noreferrer' : ''}
    &gt;
      {children}
    &lt;/a&gt;
  );
}
</code></pre>
<p>This will create a simple <code>Link</code> component that we can use in our application. We can now import this component in our <code>App.tsx</code> file and use it in our application.</p>
<p>For example, we can replace the <code>a</code> tag in the <code>App.tsx</code> file with our <code>Link</code> component:</p>
<pre><code class="language-typescript">import * as React from 'react';
import logo from './logo.svg';
import './App.css';
import Link from './components/Link';

function App() {
  return (
    &lt;div className='App'&gt;
      &lt;header className='App-header'&gt;
        &lt;img src={logo} className='App-logo' alt='logo' /&gt;
        &lt;p&gt;
          Edit &lt;code&gt;src/App.js&lt;/code&gt; and save to reload.
        &lt;/p&gt;
        &lt;Link href='https://reactjs.org' targetBlank&gt;
          Learn React
        &lt;/Link&gt;
      &lt;/header&gt;
    &lt;/div&gt;
  );
}

export default App;
</code></pre>
<p>This will now render the <code>Link</code> component in our application. You can now start developing your React TypeScript project by adding more components!</p>
<h2>Conclusion</h2>
<p>By the end of this blog post, you should have all the information you need to get started on React TypeScript development. We've discussed how to set up an environment, create a project structure and run the application. And that’s it! With this comprehensive guide in hand, you now have all the information you need to set up and run your React TypeScript project from scratch. I hope this guide was helpful and wish you luck on your React TypeScript journey!</p>
<p>Good luck and happy coding!</p>
<p>P.S. Follow Roy Derks on <a href="https://linkedin.com/in/gethackteam">LinkedIn</a>, <a href="https://x.com/gethackteam">X</a> or <a href="https://bsky.app/profile/gethackteam.bsky.social">Bluesky</a> for more React, GraphQL and TypeScript tips &amp; tricks. And subscribe to my <a href="https://www.youtube.com/@gethackteam">YouTube channel</a> for more React, GraphQL and TypeScript tutorials.</p>
]]>
        </content:encoded>
    </item>
    </channel>
  </rss>