<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Scott Molinari</title>
    <description>The latest articles on DEV Community by Scott Molinari (@smolinari).</description>
    <link>https://dev.to/smolinari</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F121141%2F9917d639-20c8-489e-9602-aac666338e89.png</url>
      <title>DEV Community: Scott Molinari</title>
      <link>https://dev.to/smolinari</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/smolinari"/>
    <language>en</language>
    <item>
      <title>The Ball and Chain: Why Git is an Anti-Pattern for AI-Native Engineering</title>
      <dc:creator>Scott Molinari</dc:creator>
      <pubDate>Sat, 07 Feb 2026 11:10:40 +0000</pubDate>
      <link>https://dev.to/m8a-io/the-ball-and-chain-why-git-is-an-anti-pattern-for-ai-native-engineering-1i47</link>
      <guid>https://dev.to/m8a-io/the-ball-and-chain-why-git-is-an-anti-pattern-for-ai-native-engineering-1i47</guid>
      <description>&lt;p&gt;In our previous discussions on &lt;a href="https://dev.to/m8a-io/the-human-centric-ai-native-distributed-systems-manifesto-1jlh"&gt;The Human-Centric AI-Native Distributed Systems Manifesto&lt;/a&gt; and &lt;a href="https://dev.to/smolinari/intent-driven-development-idd-is-our-current-future-5fh4"&gt;Intent Driven Development (IDD)&lt;/a&gt;, we established a clear vision: the future of software belongs to &lt;strong&gt;Architects of Intent&lt;/strong&gt;, not laborers of syntax.&lt;/p&gt;

&lt;p&gt;But there is a problem. A massive, silent friction point is dragging us backward.&lt;/p&gt;

&lt;p&gt;We are attempting to build fluid, intent-driven, AI-generated systems, but we are storing them in a rigid, line-based history tool designed in 2005 for the Linux Kernel. We are trying to fly a starship with a steering wheel made of stone.&lt;/p&gt;

&lt;p&gt;It is time to say the quiet part out loud: &lt;strong&gt;Git is becoming the bottleneck of the AI Era.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To fully realize the promise of Intent Driven Development, we cannot continue treating Git as the engine of our engineering. We must recognize it for what it truly is: a legacy file system that doesn't understand logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "Text-Blind" Problem
&lt;/h2&gt;

&lt;p&gt;Git is a marvel of engineering, but it is fundamentally "dumb." It sees the world in lines of text.&lt;/p&gt;

&lt;p&gt;If you rename a function in &lt;code&gt;auth.ts&lt;/code&gt; from &lt;code&gt;loginUser&lt;/code&gt; to &lt;code&gt;authenticateUser&lt;/code&gt;, Git sees this as:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;- loginUser(creds)&lt;/code&gt;&lt;br&gt;
&lt;code&gt;+ authenticateUser(creds)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Git does not know you refactored a symbol. It only knows you deleted a line and added a line. It sees text; it does not see &lt;strong&gt;Logic&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For human-to-human collaboration, this was acceptable. We could read the diff and infer the intent. But in an AI-native world, this "text-blindness" creates a critical disconnect.&lt;/p&gt;

&lt;p&gt;In a true AI-Native development environment, the AI shouldn't just look at a flat directory of files. It needs to operate on a &lt;strong&gt;System Graph&lt;/strong&gt;. It must understand the &lt;em&gt;relationships&lt;/em&gt; between things—not just their proximity in a file. It needs to know that the &lt;code&gt;User&lt;/code&gt; object is semantically connected to the &lt;code&gt;Billing&lt;/code&gt; service.&lt;/p&gt;

&lt;p&gt;If the AI modifies the &lt;code&gt;User&lt;/code&gt; object, it isn't just editing text; it is propagating a ripple effect of logical changes across the entire graph. When we force that rich, multi-dimensional logic into a flat, line-based diff, we are &lt;strong&gt;downsampling&lt;/strong&gt; the intelligence of our system. We are taking a 3D model and smashing it into a 2D drawing. We lose the "Why" (The Intent) and keep only the "What" (The Text).&lt;/p&gt;

&lt;p&gt;In other words, we continue to use Git, we suffer from a &lt;strong&gt;Cognitive Impedance Mismatch&lt;/strong&gt;. We take a high-fidelity concept (The Intent) and force it through a low-fidelity medium (The Text File). Then, every time a human or an AI needs to reason about the system, they must burn energy trying to reconstruct the original architectural picture from thousands of lines of syntax. This is a massive waste of computational power and human intellect. We are throwing away the map, shredding it into strips of paper, and then trying to tape it back together every single day.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Merge Conflict is a Syntax Error, Not a Logic Error
&lt;/h2&gt;

&lt;p&gt;The ultimate symptom of this mismatch is the Merge Conflict.&lt;/p&gt;

&lt;p&gt;In a distributed system where multiple agents (human or AI) are working on different Intents simultaneously— say, &lt;strong&gt;"Integrate Stripe Payments"&lt;/strong&gt; and &lt;strong&gt;"Enforce Age Verification"&lt;/strong&gt;— Git often fails to merge them simply because they touched adjacent lines of code.&lt;/p&gt;

&lt;p&gt;These conflicts are artificial. Logically, the two changes might be perfectly compatible. But because Git manages &lt;strong&gt;Files&lt;/strong&gt; instead of &lt;strong&gt;Functions&lt;/strong&gt;, it throws a conflict.&lt;/p&gt;

&lt;p&gt;We spend hours of our lives resolving these text-based collisions. In an IDD world, this is wasted life. We should be resolving &lt;strong&gt;Logical Conflicts&lt;/strong&gt;, not text conflicts.&lt;/p&gt;

&lt;p&gt;A logical conflict looks like this: &lt;em&gt;"You cannot remove the 'Email Address' field from the User object because the 'Send Receipt' intent explicitly relies on it."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That is a valuable conflict. That protects the business. Git cannot see that conflict; it can only see that two people edited line 45.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Database Must Become the Repo
&lt;/h2&gt;

&lt;p&gt;If Git is the "Assembly Language" of version control, what is the high-level language?&lt;/p&gt;

&lt;p&gt;The logical evolution is &lt;strong&gt;Database-as-Code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In an AI-Native future, the "Source Code" cannot remain a folder of text files on a hard drive. It must become structured, versioned data in a &lt;strong&gt;Temporal Database&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you aren't familiar with the term, a "Temporal Database" is simply a database that has a built-in concept of &lt;em&gt;Time&lt;/em&gt;. It doesn't just store the &lt;em&gt;current&lt;/em&gt; value of a record; it stores the &lt;em&gt;entire history&lt;/em&gt; of how that record changed. It is like a Time Machine for your data.&lt;/p&gt;

&lt;p&gt;Imagine a world where:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Granularity is Logical:&lt;/strong&gt; You don't version a "File." You version a &lt;strong&gt;Node&lt;/strong&gt;, a &lt;strong&gt;Function&lt;/strong&gt;, or a &lt;strong&gt;Policy&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;History is Queryable:&lt;/strong&gt; You don't ask "What changed in this file?" You query: &lt;em&gt;"Show me the exact state of the 'Billing Logic' as it existed last Tuesday."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Refactoring is Instant:&lt;/strong&gt; If you rename a verified business concept, the system updates the pointer in the database. There is no "Search and Replace." There is no diff. The entity simply evolves.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the architectural reality we need to support &lt;strong&gt;Intent Driven Development&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If the AI generates the implementation, why do we need to store the implementation in a text file? We don't. We need to store the &lt;strong&gt;Intent&lt;/strong&gt; (The Horizon Node) and the &lt;strong&gt;Verification Policy&lt;/strong&gt; (The Test). The implementation code is just a compiled artifact—a transient output that serves the intent.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "Ball and Chain" of Transparency
&lt;/h2&gt;

&lt;p&gt;So, do we kill Git?&lt;/p&gt;

&lt;p&gt;Not yet. And this is the paradox.&lt;/p&gt;

&lt;p&gt;We cannot abandon Git today because it is the &lt;strong&gt;Universal Protocol of Trust&lt;/strong&gt;. It is our audit log, our backup, and our "break glass in case of emergency" tool. Developers (rightfully) fear vendor lock-in. If the code lives in a proprietary database, they feel trapped.&lt;/p&gt;

&lt;p&gt;But we must change our relationship with it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git must become the Display, not the Engine.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this new architectural vision, the Database is the Source of Truth. It holds the rich, structured, intent-based graph of your application. Git becomes a &lt;strong&gt;Projection&lt;/strong&gt;—a mirror. The system automatically syncs the state of the database to a Git repository so you have a human-readable backup.&lt;/p&gt;

&lt;p&gt;But the work—the actual engineering—happens in the Graph, in the Intent, and in the Policy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Moving from "Commits" to "Intents"
&lt;/h2&gt;

&lt;p&gt;This shift allows us to finally clean up the history of our software.&lt;/p&gt;

&lt;p&gt;We have all seen a Git log that looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;fix typo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;update styling&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;trying to fix build again&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wip&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is noise. It is the frantic scribbling of a human trying to make a machine work.&lt;/p&gt;

&lt;p&gt;In an Intent-Based future, we stop caring about the scribbles. We care about the &lt;strong&gt;Completed Horizon&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Intent:&lt;/strong&gt; "Implement GDPR Compliance."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Status:&lt;/strong&gt; Verified &amp;amp; Sealed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The "Commit" is too small a unit of measure for a business. The &lt;strong&gt;Intent&lt;/strong&gt; is the atomic unit of value. By moving the "Source of Truth" to a database backed system that understands these high-level concepts, we can finally have a history log that reads like a story of business evolution, not a transcript of syntax errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: Let Go of the Files
&lt;/h2&gt;

&lt;p&gt;The transition to IDD requires us to let go of our security blankets. For decades, the text file was our safety. If we had the file, we had the power.&lt;/p&gt;

&lt;p&gt;But in the age of AI, the power is no longer in the &lt;em&gt;text of the code&lt;/em&gt;. The power is in the &lt;strong&gt;Context&lt;/strong&gt;, the &lt;strong&gt;Constraint&lt;/strong&gt;, and the &lt;strong&gt;Intent&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Yes, these are still written in text — of course, language is how we define meaning — but that text represents high-level &lt;strong&gt;Abstractions&lt;/strong&gt;, not low-level machine instructions.&lt;/p&gt;

&lt;p&gt;Git served us well in the era of manual coding. It was the perfect tool for the "Human Compiler." But as we ascend to become Architects, we need tools that understand the architecture, not just the bricks.&lt;/p&gt;

&lt;p&gt;It is time to stop managing lines, and start managing logic.&lt;/p&gt;

</description>
      <category>git</category>
      <category>ai</category>
      <category>programming</category>
      <category>devops</category>
    </item>
    <item>
      <title>Intent Driven Development (IDD) is our Current Future</title>
      <dc:creator>Scott Molinari</dc:creator>
      <pubDate>Thu, 29 Jan 2026 08:36:54 +0000</pubDate>
      <link>https://dev.to/m8a-io/intent-driven-development-idd-is-our-current-future-5fh4</link>
      <guid>https://dev.to/m8a-io/intent-driven-development-idd-is-our-current-future-5fh4</guid>
      <description>&lt;p&gt;For decades, the measure of a software engineer was their command of syntax. We spent our careers acting as human compilers, translating business requirements into machine code, line by painstaking line. But as we transition into the AI-native era, that metric is shifting. We are moving away from a world where we focus on how to implement a feature, and into a world where we focus entirely on what that feature is intended to accomplish.&lt;/p&gt;

&lt;p&gt;In our &lt;a href="https://dev.to/m8a-io/the-human-centric-ai-native-distributed-systems-manifesto-1jlh"&gt;Human-centric AI-Native Distributed Systems Manifesto&lt;/a&gt; (if you haven't read it yet, please do), we outlined a future where we prioritize "Verifiable Intent over Syntactic Correctness." To ground this philosophy in reality, we need a new operating model. We need to move beyond the traditional boundaries of Domain Driven Design and Test Driven Development.&lt;/p&gt;

&lt;p&gt;We need &lt;strong&gt;Intent Driven Development (IDD)&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Inescapable Reality of Distributed Systems
&lt;/h2&gt;

&lt;p&gt;To understand why IDD is necessary, we must first accept the current state of the global economy. It is no longer possible to conduct significant business today without applications that are, in some manner, distributed. The era of the "isolated application" is dead.&lt;/p&gt;

&lt;p&gt;Whether you are a logistics giant or a local fintech startup, your digital footprint is inherently fragmented. You are consuming APIs from payment providers, syncing data to mobile devices, replicating databases across regions for latency, and relying on third-party authentication services. "No application is an island," as our manifesto states. Every piece of logic exists within a complex, fragile web of dependencies, network latency, and eventual consistency.&lt;/p&gt;

&lt;p&gt;This complexity creates a dangerous trap. As systems become more distributed, the cognitive load required to maintain them explodes. If we rely solely on manual coding, we move too slowly to compete. But if we recklessly hand the keys to an AI, we invite chaos. An AI can write a function that works perfectly in isolation on a developer’s laptop but fails catastrophically when introduced to the latency of a real-world network.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;IDD becomes the critical bridge&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Engine of Intent
&lt;/h2&gt;

&lt;p&gt;Intent Driven Development is the natural evolution of software engineering, accelerated by the "engine" of Artificial Intelligence. In an IDD workflow, the engineer’s primary responsibility shifts from being the manual laborer laying every brick to becoming the Architect defining the destination.&lt;/p&gt;

&lt;p&gt;In the past, methodologies like Domain Driven Design (DDD) gave us the vocabulary—the maps of our system—but still required us to manually write the glue code to make those words interact. Test Driven Development (TDD) gave us verification, but required us to write "intent" buried inside unit tests that were often as complex as the code they were testing.&lt;/p&gt;

&lt;p&gt;IDD elevates these concepts. DDD becomes the strict Schema that prevents the AI from hallucinating business concepts. TDD becomes Policy Verification, where we define high-level behavioral contracts, and the AI navigates the route to satisfy them.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, What is IDD?
&lt;/h2&gt;

&lt;p&gt;We have established the philosophy, but how does Intent Driven Development manifest in a daily engineering workflow?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IDD is an "Implementation-Last" methodology.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In traditional software development, we spend 80% of our time writing the implementation and 20% verifying it. IDD flips this ratio. We spend 80% of our time defining the Constraints and the Verification, and we let the AI handle the implementation in the seconds remaining. Specifically, IDD is a three-stage lifecycle:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The Definition Phase (The Human Context)&lt;/strong&gt;&lt;br&gt;
This is where the "Intent" is crystallized. Before a single line of executable code is written, the human engineer constructs the "Immutable Skeleton." This is not a vague prompt like "Make a user system." It is a rigorous set of artifacts:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Contract (Schema):&lt;/strong&gt; You define the exact input and output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Environmental Constraints:&lt;/strong&gt; You explicitly select the technology (e.g., Vue, NestJS and MongoDB, or Angular, Spring Boot, and MySQL, etc. etc.). We call these "Foundries" in m8a. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Behavioral Policy:&lt;/strong&gt; Instead of writing code, you write the criteria for success (e.g., "Must retry 3 times with exponential backoff").&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The Generation Phase (The AI Engine)&lt;/strong&gt;&lt;br&gt;
Once the Skeleton and Policy are locked, the AI is engaged. It is tasked with filling the void between the Input Contract and the Output Contract. Because the AI is constrained by your pre-selected stack and pre-defined business rules, it generates the boilerplate and logic required to satisfy your intent without "guessing."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The Verification Phase (The Automated Judge)&lt;/strong&gt;&lt;br&gt;
This is where "Verifiable Intent" supersedes "Syntactic Correctness." As soon as the AI generates the code, the system runs the Policy Tests. If the output fails the Schema or the Behavior check, it is rejected and regenerated. The human only reviews the solution that has already proven it meets the intent.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "Intent File"
&lt;/h2&gt;

&lt;p&gt;To make this concrete, IDD relies on a tangible "Intent File."&lt;/p&gt;

&lt;p&gt;We are already seeing primitive shadows of this in the developer community today. Many developers are now adding files like CLAUDE.md or GEMINI.md to their repositories to "prep" the AI with context. While this is a step in the right direction, these local files are severely limited. They are static snapshots that only understand the code sitting next to them in the folder; they lack the global awareness of the living system. They are passive suggestions, not active architectural drivers.&lt;/p&gt;

&lt;p&gt;In true IDD, the "Intent File" is not limited to a rigid format like YAML, JSON, or a static markdown file. The "Intent" can be anything made of text. It can be a structured design document, a technical spec, or—in advanced platforms like m8a—it can be context injected dynamically via Retrieval-Augmented Generation (RAG). By pulling context from your existing documentation, knowledge bases, or previous system states, the "Intent File" becomes a living entity.&lt;/p&gt;

&lt;p&gt;Regardless of the source, the concept remains the same: The Intent is the Source Code; the actual Python or TypeScript files that get generated are merely the compiled artifacts of that intent.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Non-Negotiable Human Layer
&lt;/h2&gt;

&lt;p&gt;However, a critical distinction must be made to separate IDD from the chaotic "AI-generated" workflows often hyped today. In a true IDD architecture, AI drives the car, but the Human builds the road.&lt;br&gt;
We do not ask the AI to "imagine" an architecture. We do not ask it to pick a database, choose a framework, or decide on a logging strategy. These are the "Rigid Structures" of our system, and they must remain under strict human ownership.&lt;/p&gt;

&lt;p&gt;This is not a matter of preference; it is a matter of accountability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The "3 AM" Rule&lt;/strong&gt;&lt;br&gt;
The primary reason humans must define the stack is simple: Accountability cannot be automated. When a production database locks up at 3:00 AM, the AI is not the one answering the pager. The engineer is. Therefore, the engineer must possess total agency over the tools they are required to debug. If we allow an AI to whimsically choose an obscure library because it "fit the prompt," we burden the human team with technical debt they did not consent to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Guardrails Against Entropy&lt;/strong&gt;&lt;br&gt;
AI is inherently probabilistic; it craves novelty. If you ask an AI to "build a service" ten times without constraints, it might give you ten slightly different architectural variations. In a distributed system, this inconsistency is fatal. By locking the architecture into "Immutable Skeletons"—human-defined templates—we force the AI to adhere to organizational standards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Strategic Homogeneity&lt;/strong&gt;&lt;br&gt;
Finally, architecture is rarely just technical; it is strategic. An AI cannot know that we use a specific cloud provider because of a corporate discount, or that we avoid a certain language because it conflicts with our hiring strategy. AI lacks the global context of the business.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architects of "Done"
&lt;/h2&gt;

&lt;p&gt;This brings us to the ultimate role of the human in IDD: we are the Architects of "Done."&lt;/p&gt;

&lt;p&gt;The AI can iterate indefinitely, generating code that is syntactically perfect but semantically void. It is the human engineer who must review the outcome, not for style, but for meaning. We provide the "Why" and the "Where." We set the hard guardrails, the frameworks, and the templates. The AI simply provides the "How."&lt;/p&gt;

&lt;p&gt;By embracing Intent Driven Development, we stop being the manual laborers of syntax and finally become what we were always meant to be: the Architects of Intent.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>distributedsystems</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Human-centric AI-Native Distributed Systems Manifesto</title>
      <dc:creator>Scott Molinari</dc:creator>
      <pubDate>Thu, 29 Jan 2026 06:10:11 +0000</pubDate>
      <link>https://dev.to/m8a-io/the-human-centric-ai-native-distributed-systems-manifesto-1jlh</link>
      <guid>https://dev.to/m8a-io/the-human-centric-ai-native-distributed-systems-manifesto-1jlh</guid>
      <description>&lt;h2&gt;
  
  
  Preamble
&lt;/h2&gt;

&lt;p&gt;We are uncovering better ways of building software with AI at breakneck speed, but at the same time, we must acknowledge that in the modern enterprise, &lt;strong&gt;no application is an island&lt;/strong&gt;. Every piece of logic exists within a complex web of dependencies, latency, and state. We also recognize that AI is not a replacement for engineering, but a powerful engine for realizing intent.&lt;/p&gt;

&lt;p&gt;Through this work with AI, we have come to:&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Values
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Verifiable Intent over Syntactic Correctness:&lt;/strong&gt; We value code that provably matches the system's objective via automated policy and testing, not just code that compiles without error.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;System Resilience over Local Optimization:&lt;/strong&gt; We value the stability and survival of the entire network over the raw execution speed of a single node or function.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deterministic Execution over Probabilistic Agents:&lt;/strong&gt; We value AI as a builder of rigid, predictable automation scripts, rather than as a real-time, probabilistic decision-maker for critical processes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Architectural Guardrails over Manual Review:&lt;/strong&gt; We value automated, platform-level constraints that physically prevent anti-patterns over relying on human vigilance to catch them during code review.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Managed Metadata over Generative Novelty:&lt;/strong&gt; We value strict, pre-defined structures and contracts (schemas/templates) over loosely coupled or "reimagined" AI-generated logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Human Augmentation over Human Replacement:&lt;/strong&gt; We value AI as a tool to increase the capacity, velocity, and insight of the engineer, not as a means to reduce the engineering workforce.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;That is, while there is value in the items on the right, we value the items on the left more.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Principles of AI-Native Engineering
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. The Logic is Ephemeral; The State is Permanent&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We treat AI-generated components as stateless workers. The AI writes the logic, but the Platform manages the persistence. This ensures that when the logic fails or scales, no data is lost in the wreckage of a hallucinatory variable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The Transition to Determinism&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI is a tool for discovery and construction, not permanent execution. Once a process is fully understood and automated, the AI steps aside, leaving behind rigid, deterministic code to perform the task. We do not ask AI to "think" about a solved problem twice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Contracts are King&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The "Handshake" between services (APIs, Data Models, Event Schemas, etc.) must be defined by humans before generation begins. The AI may write the code that fulfills the contract, but it is never permitted to alter the contract alone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Context is Global&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We reject the illusion of the "local environment." AI must be prompted and constrained to generate code that assumes the network will fail, the database will be locked, and the service will be unavailable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Human Responsibility
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;We are the Context Bearers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI cannot see the world outside the prompt. We are responsible for identifying and injecting the external conditions - legal, ethical, physical, and business - that the code must survive in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We are the Governors of Semantics&lt;/strong&gt;&lt;br&gt;
Code is math, but Systems are meaning. The AI can ensure a string is 10 characters long, but only a Human can decide if that string should be a Customer ID or a Product Code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We are the Architects of "Done"&lt;/strong&gt;&lt;br&gt;
An AI can iterate indefinitely. Only a human can declare that a system satisfies the business need and is safe for deployment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What do you think of this manifesto?&lt;/strong&gt;&lt;br&gt;
It is the first document (of hopefully many), which I'll make public while building the m8a platform (working on alpha). I've made this manifesto public, because it is the rules and the perspective I'm working with and I'd love to hear thoughts about this from others.&lt;/p&gt;

&lt;p&gt;Next article in our m8a series: &lt;a href="https://dev.to/smolinari/intent-driven-development-idd-is-our-current-future-5fh4"&gt;https://dev.to/smolinari/intent-driven-development-idd-is-our-current-future-5fh4&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>vibecoding</category>
      <category>distributedsystems</category>
      <category>aiidd</category>
    </item>
    <item>
      <title>NestJS - Circular Dependency Hell and How to Avoid it</title>
      <dc:creator>Scott Molinari</dc:creator>
      <pubDate>Thu, 25 Sep 2025 05:58:40 +0000</pubDate>
      <link>https://dev.to/smolinari/nestjs-circular-dependency-hell-and-how-to-avoid-it-4lfp</link>
      <guid>https://dev.to/smolinari/nestjs-circular-dependency-hell-and-how-to-avoid-it-4lfp</guid>
      <description>&lt;p&gt;Before you begin, if you haven't &lt;a href="https://dev.to/smolinari/nestjs-and-project-structure-what-to-do-1223"&gt;read my other article about project structure&lt;/a&gt;, please do. It is important in your journey to learning Nest.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Conundrum
&lt;/h3&gt;

&lt;p&gt;Many development teams, especially those building CRUD apps, frequently run into the dreaded circular dependency error. That cryptic message signals a deeper issue in your application’s architecture. A circular dependency is a &lt;strong&gt;code smell&lt;/strong&gt; because it makes your modules tightly coupled, difficult to test and reuse, and hard to refactor.&lt;/p&gt;

&lt;p&gt;So, why does this happen to so many of us? The most common reason is a simple, yet fundamental, mental model error.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Mental Model Mistake: Confusing the Data in the Database with a Module's "Work"
&lt;/h3&gt;

&lt;p&gt;This is the central flaw that leads to most circular dependencies in NestJS. Developers building applications often try to &lt;strong&gt;model their database relationships directly in their modules&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Database relationships can be bi-directional:&lt;/strong&gt; An  &lt;code&gt;Author&lt;/code&gt; can have many &lt;code&gt;Books&lt;/code&gt;, and a &lt;code&gt;Book&lt;/code&gt; can have one &lt;code&gt;Author&lt;/code&gt;. This is a two-way relationship that a database and ORMs are designed to handle with ease.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Module dependencies must be uni-directional:&lt;/strong&gt; An &lt;code&gt;AuthorModule&lt;/code&gt; can expose an &lt;code&gt;AuthorService&lt;/code&gt; that's consumed by the &lt;code&gt;BookModule&lt;/code&gt;. But if the &lt;code&gt;BookModule&lt;/code&gt; then tries to import something from the &lt;code&gt;AuthorModule&lt;/code&gt;— and the &lt;code&gt;AuthorModule&lt;/code&gt; already depends on the &lt;code&gt;BookModule&lt;/code&gt;— you've created a cycle. I'm absolutely certain everyone has faced this. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your application's modules are not a mirror of your database. Their purpose is to encapsulate functionality, and their dependencies should reflect the &lt;strong&gt;flow of application logic&lt;/strong&gt;, &lt;em&gt;&lt;strong&gt;not the structure of your data&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Right Mental Model: Modules as a City with One-Way Streets
&lt;/h2&gt;

&lt;p&gt;Let's use your application as an analogy of a city. But, instead of thinking about your city with two-way streets, picture them as a city with &lt;strong&gt;strictly one-way streets&lt;/strong&gt;. Each module is a neighborhood in the city (e.g., &lt;code&gt;UserModule&lt;/code&gt;, &lt;code&gt;AuthModule&lt;/code&gt;, &lt;code&gt;AuthorModule&lt;/code&gt;, &lt;code&gt;BookModule&lt;/code&gt;, etc.), and the dependencies are the roads. A car can travel from the &lt;code&gt;BookModule&lt;/code&gt; neighborhood to the &lt;code&gt;AuthorModule&lt;/code&gt; to get author information, yet that same car cannot travel from &lt;code&gt;AuthorModule&lt;/code&gt; back to the &lt;code&gt;BookModule&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What you are visualizing with your module dependencies in this city of one-way roads is a &lt;strong&gt;directed acyclic graph (DAG)&lt;/strong&gt;: .&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Directed:&lt;/strong&gt; The relationships flow in a single direction. &lt;code&gt;A&lt;/code&gt; depends on &lt;code&gt;B&lt;/code&gt;, not the other way around.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Acyclic:&lt;/strong&gt; There are no cycles. You cannot start at &lt;code&gt;A&lt;/code&gt;, follow the dependencies, and end up back at &lt;code&gt;A&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Package Carrier Analogy: Your Delivery Route in the City
&lt;/h3&gt;

&lt;p&gt;This is where your NestJS application becomes a &lt;strong&gt;delivery service&lt;/strong&gt;. Think of a request coming into your application as a &lt;strong&gt;package carrier&lt;/strong&gt; starting a delivery route. The carrier enters the city and proceeds down the one-way streets, visiting each module to perform a task. The key rule is that the carrier never turns around and goes back to a house they've already visited.&lt;/p&gt;

&lt;p&gt;The entire "delivery route" forms the &lt;strong&gt;directed acyclic graph&lt;/strong&gt;. The carrier starts at the beginning (AppModule), proceeds through the dependencies, and at the end of the route, the last module sends a result back, confirming the "delivery is complete." This model reminds us that the flow of execution should always be forward and purposeful, never circling back on itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  Practical Rules to Avoid the Cycle
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Define a Clear Hierarchy:&lt;/strong&gt; Arrange your modules in layers. &lt;strong&gt;Core modules&lt;/strong&gt; should be at the bottom, &lt;strong&gt;feature-specific modules&lt;/strong&gt; in the middle, and &lt;strong&gt;entry-point modules&lt;/strong&gt; at the top. Dependencies should only flow &lt;em&gt;down&lt;/em&gt; the hierarchy. This principle is a cornerstone of architectural patterns like &lt;strong&gt;Clean Architecture&lt;/strong&gt;, popularized by Robert C. Martin ("Uncle Bob").&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Separate Shared Logic:&lt;/strong&gt; If two modules both need the same shared utility, create a &lt;strong&gt;third, separate &lt;code&gt;UtilModule&lt;/code&gt;&lt;/strong&gt; that both can import. This is the &lt;strong&gt;"extract common concerns"&lt;/strong&gt; rule. These things go into a "common" or "shared" module. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use a Higher-Level Module to Orchestrate:&lt;/strong&gt; Rather than having two modules directly depend on each other, create a higher-level module that depends on both. This module acts as the "middleman," orchestrating the flow of data without creating a circular dependency. This kind of module should be "doing things" and not representing a specific data(base) model. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  A Concrete Example: Counting an Author's Books
&lt;/h3&gt;

&lt;p&gt;Let's use the &lt;code&gt;Author&lt;/code&gt; and &lt;code&gt;Book&lt;/code&gt; example. We need to get the number of books an author has written.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;AuthorsModule&lt;/code&gt;&lt;/strong&gt;: Responsible for all things authors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;BooksModule&lt;/code&gt;&lt;/strong&gt;: Responsible for all things books.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of having &lt;code&gt;AuthorsModule&lt;/code&gt; import &lt;code&gt;BooksModule&lt;/code&gt; (to get the book count) and &lt;code&gt;BooksModule&lt;/code&gt; import &lt;code&gt;AuthorsModule&lt;/code&gt; (to find author info), we introduce a new, higher-level module: &lt;strong&gt;&lt;code&gt;PublishingModule&lt;/code&gt;&lt;/strong&gt;. This module acts as our "package carrier," orchestrating the request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/authors/authors.module.ts&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AuthorsService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./authors.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AuthorsService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AuthorsService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthorsModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/books/books.module.ts&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BooksService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./books.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;BooksService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;BooksService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BooksModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/publishing/publishing.module.ts&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AuthorsModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../authors/authors.module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BooksModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../books/books.module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PublishingService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./publishing.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PublishingResolver&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./publishing.resolver&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;AuthorsModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;BooksModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;PublishingService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PublishingResolver&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PublishingModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;PublishingModule&lt;/code&gt; correctly models the package carrier's route. It orchestrates the process by visiting the &lt;code&gt;AuthorsModule&lt;/code&gt; to get the author and then the &lt;code&gt;BooksModule&lt;/code&gt; to get the books, all while maintaining a unidirectional dependency flow. The &lt;code&gt;AuthorsModule&lt;/code&gt; and &lt;code&gt;BooksModule&lt;/code&gt; know nothing about the &lt;code&gt;PublishingModule&lt;/code&gt; and remain decoupled and reusable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Taking it a Step Further: Abstraction with an Interface
&lt;/h2&gt;

&lt;p&gt;The concrete example above is a great starting point, but what if our application grows? What if we add new content types like &lt;code&gt;Blogs&lt;/code&gt; or &lt;code&gt;Articles&lt;/code&gt;? We would have to update our &lt;code&gt;PublishingModule&lt;/code&gt; to import &lt;code&gt;BlogsModule&lt;/code&gt;, &lt;code&gt;ArticlesModule&lt;/code&gt;, and so on, making the module cluttered and difficult to manage.&lt;/p&gt;

&lt;p&gt;This is where the power of abstraction comes in. Instead of depending on concrete implementations, we can rely on a shared contract, or &lt;strong&gt;interface&lt;/strong&gt;. This makes our code more flexible and scalable.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Define the Interface and a Shared Token
&lt;/h3&gt;

&lt;p&gt;First, you need a shared &lt;strong&gt;interface&lt;/strong&gt; to establish a common contract for all your services. This provides type safety. Additionally, define a unique &lt;strong&gt;token&lt;/strong&gt; using a &lt;code&gt;Symbol&lt;/code&gt; to avoid naming conflicts and serve as the key for your injection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/publishing/interfaces/publishable.interface.ts&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IPublishable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;getPublishableType&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;getContentCountByAuthorId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authorId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/publishing/interfaces/publishable-service-token.ts&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PUBLISHABLE_SERVICE_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PUBLISHABLE_SERVICE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2. Implement the Interface in Each Service
&lt;/h3&gt;

&lt;p&gt;Each of your services, like &lt;code&gt;BooksService&lt;/code&gt; and a new &lt;code&gt;BlogsService&lt;/code&gt;, will implement the &lt;code&gt;IPublishable&lt;/code&gt; interface. They will each have a &lt;code&gt;getPublishableType()&lt;/code&gt; method to uniquely identify themselves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/books/books.service.ts&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IPublishable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../publishing/interfaces/publishable.interface&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BooksService&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;IPublishable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;getPublishableType&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;book&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;getContentCountByAuthorId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authorId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Logic to get book count&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/blogs/blogs.service.ts&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IPublishable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../content/interfaces/publishable.interface&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlogsService&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;IPublishable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;getPublishableType&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;getContentCountByAuthorId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authorId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Logic to get blog count&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  3. Create a Multi-Provider Factory in the Central Module
&lt;/h3&gt;

&lt;p&gt;This is the most crucial step. Instead of each module exporting a provider with the same token, you'll create a single, central module that gathers all the individual services and provides them as an &lt;strong&gt;array&lt;/strong&gt; under the shared token. This prevents the previous providers from being overwritten.&lt;/p&gt;

&lt;p&gt;In this pattern, the central module &lt;strong&gt;knows about all the concrete implementations&lt;/strong&gt; and orchestrates their provision. Other modules, like &lt;code&gt;BooksModule&lt;/code&gt; and &lt;code&gt;BlogsModule&lt;/code&gt;, can be simple and focused on their specific business logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/publishing/publishing.module.ts&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PUBLISHABLE_SERVICE_TOKEN&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./interfaces/publishable-service-token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BooksService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../books/books.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BlogsService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../blogs/blogs.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PublishingService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./publishing.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; 
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;BooksService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;BlogsService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;provide&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PUBLISHABLE_SERVICE_TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;useFactory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;booksService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BooksService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;blogsService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BlogsService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;booksService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;blogsService&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;BooksService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BlogsService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;PublishingService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;PUBLISHABLE_SERVICE_TOKEN&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PublishingModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  4. Inject and Use the Array in the Service
&lt;/h3&gt;

&lt;p&gt;Now, your &lt;code&gt;PublishingService&lt;/code&gt; can correctly inject the array of &lt;code&gt;IPublishable&lt;/code&gt; services. NestJS's container will use the factory we defined to provide a single array containing all the services. This allows you to iterate over them and perform actions polymorphically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/publishing/publishing.service.ts&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Inject&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IPublishable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../content/interfaces/publishable.interface&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PUBLISHABLE_SERVICE_TOKEN&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PublishingService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PUBLISHABLE_SERVICE_TOKEN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;publishableServices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IPublishable&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getAuthorTotalContentCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authorId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publishableServices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContentCountByAuthorId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authorId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;counts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getAuthorCountByPublishableType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authorId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publishableServices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPublishableType&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`No service found for publishable type: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContentCountByAuthorId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authorId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the real power of the one-way street analogy. Our &lt;code&gt;PublishingService&lt;/code&gt; doesn't care if the content is a book, a blog, or a new content type we create next week. It only cares that it can talk to a service that fulfills the &lt;code&gt;IPublishable&lt;/code&gt; contract, maintaining a clean, decoupled architecture. This new method shows how the carrier can use a key (&lt;code&gt;'book'&lt;/code&gt;) to bypass all other modules and go straight to the one it needs, all while following the one-way streets.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;The next time you're building a new module, pause for a moment. Instead of thinking about &lt;strong&gt;data retrieval&lt;/strong&gt; ("I need to get posts for this user"), think about the &lt;strong&gt;process&lt;/strong&gt; being accomplished ("I need to get all content published by this author"). This subtle but powerful shift in perspective, combined with the one-way street mind-frame, will guide you toward a clean, maintainable, and scalable architecture. And you'll finally avoid the hair pulling issue of circular dependency hell. &lt;/p&gt;

&lt;p&gt;How do you avoid circular dependencies? Or how do you work to make your modules even less dependent? Let me know in the comments below. &lt;/p&gt;

</description>
      <category>nestjs</category>
      <category>architecture</category>
      <category>dependencyinversion</category>
      <category>backend</category>
    </item>
    <item>
      <title>NestJS and Project Structure - What to Do?</title>
      <dc:creator>Scott Molinari</dc:creator>
      <pubDate>Sun, 03 Sep 2023 12:42:21 +0000</pubDate>
      <link>https://dev.to/smolinari/nestjs-and-project-structure-what-to-do-1223</link>
      <guid>https://dev.to/smolinari/nestjs-and-project-structure-what-to-do-1223</guid>
      <description>&lt;p&gt;So, you're just getting going with Nest, ey? You might not yet completely understand why you want to use Nest or why it is one of the most popular NodeJS frameworks on the planet. But, you are saying for sure, "if this many people are using it, it must be good", right?&lt;/p&gt;

&lt;p&gt;Well, this article will get you a few steps closer to that better understanding of why you've chosen Nest. &lt;/p&gt;

&lt;h3&gt;
  
  
  The Onion/ Clean -&amp;gt; Nest Architecture
&lt;/h3&gt;

&lt;p&gt;You hopefully know about &lt;a href="https://jeffreypalermo.com/2008/07/the-onion-architecture-part-1/" rel="noopener noreferrer"&gt;Onion Architecture&lt;/a&gt;, or &lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="noopener noreferrer"&gt;Clean Architecture&lt;/a&gt; or you have a basic understanding of what &lt;a href="https://en.wikipedia.org/wiki/Separation_of_concerns" rel="noopener noreferrer"&gt;Separation of Concerns&lt;/a&gt; is all about. &lt;/p&gt;

&lt;p&gt;And, some other knowledge you should have is a rough idea of what &lt;a href="https://en.wikipedia.org/wiki/Domain-driven_design" rel="noopener noreferrer"&gt;Domain Driven Design&lt;/a&gt; is. Especially what a "domain" is (and it's not about the names of websites).&lt;/p&gt;

&lt;p&gt;Check out this image.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dq6ay0n4wles2jz7q3s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dq6ay0n4wles2jz7q3s.png" alt="Puh! Overwhelming, right? Borrowed from https://herbertograca.com/2017/11/16/explicit-architecture-01-ddd-hexagonal-onion-clean-cqrs-how-i-put-it-all-together/" width="800" height="547"&gt;&lt;/a&gt;Puh! Overwhelming, right? Image borrowed from &lt;a href="https://herbertograca.com/2017/11/16/explicit-architecture-01-ddd-hexagonal-onion-clean-cqrs-how-i-put-it-all-together/" rel="noopener noreferrer"&gt;herbertograca.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don't get too caught up in this image, but yeah, this is practically everything you have to juggle to make sure a full stack application will work (in any language, with any framework). &lt;/p&gt;

&lt;p&gt;And, Nest is only a part of it. The "core" part to be exact. &lt;/p&gt;

&lt;p&gt;Since Nest is the core part of your system, it also covers some of the "layers" of the architecture for your stack, namely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the communication layer via controllers for REST/ resolvers for GraphQL or Gateways for Websockets (and a lot more for microservices)&lt;/li&gt;
&lt;li&gt;the database abstraction layer with ORM repositories or ODM models or Prisma clients&lt;/li&gt;
&lt;li&gt;the business logic layer with services&lt;/li&gt;
&lt;li&gt;the access control layer with guards&lt;/li&gt;
&lt;li&gt;the data validation and transformation layer with pipes&lt;/li&gt;
&lt;li&gt;a CQRS/ Bus system&lt;/li&gt;
&lt;li&gt;presentation layer too, if you go for MVC architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;..and a good bit more.&lt;/p&gt;

&lt;p&gt;The point being, your Nest application can do a whole lot of things, and wondering how to put all of those things in their right places AND also somehow model the overall business domain problems the application needs to help solve, is a daunting task. At the very beginning, very often the question arises - How do I structure my Nest application?&lt;/p&gt;

&lt;p&gt;This question arises usually because you are just learning Nest. And yet, for sure, you have a fairly clear idea about what your app should do. &lt;/p&gt;

&lt;p&gt;..and that is a really good thing, because we can take advantage of that to build the Nest application!&lt;/p&gt;

&lt;p&gt;But for now, just keep in mind that Nest will build the final "onion" or "clean" architecture for you. It's one of the reasons why Nest has its module system (and why you need to add all this new verbosity to your app) and also why Nest is so popular. It's kind of a paradox, in a way.&lt;/p&gt;
&lt;h3&gt;
  
  
  Two Domains
&lt;/h3&gt;

&lt;p&gt;As just mentioned, you have two main Domains to juggle as an app developer. Those two domains are the &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Developer Domain" - knowledge about how to make an app work in the framework and language in use, in our case Nest and TypeScript/JavaScript&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and the &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Business Domain" - knowledge about what the app should do to solve your business problems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you write code with Nest, you have to fit these two domains together, when in fact, they really don't fit together in any way at all. Again, the paradox.... &lt;/p&gt;

&lt;p&gt;So, it's at this point the questions arise...&lt;/p&gt;

&lt;p&gt;Do I organize my code to the domain of creating the code and the framework and somewhere inside, I'll be able to put in the business logic? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;or - &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do I try to model my business domain and figure out how to fit in the development domain into that? &lt;/p&gt;

&lt;p&gt;The latter should be the one you choose and Nest's module system simplifies it for you. &lt;/p&gt;
&lt;h3&gt;
  
  
  Domains, Features and Modules
&lt;/h3&gt;

&lt;p&gt;As we noted earlier, as a beginner with Nest, you probably know your business domain much better than you know the development domain. So, in that sense, why not start with what you know best? &lt;/p&gt;

&lt;p&gt;Let's move forward with a new Nest app. &lt;/p&gt;

&lt;p&gt;If you haven't already, &lt;a href="https://docs.nestjs.com/#installation" rel="noopener noreferrer"&gt;install the Nest global CLI&lt;/a&gt; and create a new project too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frtyflfs12j5mwgtu7801.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frtyflfs12j5mwgtu7801.png" alt="New Nest app folder structure" width="465" height="653"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;app.controller.ts&lt;/code&gt; and &lt;code&gt;app.service.ts&lt;/code&gt; are just examples to give you a running app. You can delete them. Keep &lt;code&gt;app.module.ts&lt;/code&gt; though. That is your "root" module. &lt;/p&gt;

&lt;p&gt;Now, let's take your business domain and work with it right now. Let's say you want to build a blog application like Wordpress, but it will be the next best thing. It will be even bigger and better than Wordpress! Haha! We all want world domination, right! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkv5rpxm52teo7ckfmkf5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkv5rpxm52teo7ckfmkf5.png" alt=" " width="460" height="349"&gt;&lt;/a&gt;&lt;br&gt;
IMAGE CREDIT: &lt;a href="http://www.doomsteaddiner.org/" rel="noopener noreferrer"&gt;DOOMSTEADDINER.ORG&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ok. Ok. Maybe not. But for sure, you do want your business domain problems solved. So, either way, you definitely know what you want. For our example, it's a blog application. &lt;/p&gt;

&lt;p&gt;Ask yourself, what are the overall "features" you might want to give your blog application? We'll start relatively simple of course. How about..&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Blog management:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Draft a blog&lt;/li&gt;
&lt;li&gt;Publish a blog&lt;/li&gt;
&lt;li&gt;Comment on a blog&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And, what about user management?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User Management:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a User&lt;/li&gt;
&lt;li&gt;Remove a User&lt;/li&gt;
&lt;li&gt;Edit a User&lt;/li&gt;
&lt;li&gt;Show users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And lastly, what about getting the users into the app with the right permissions? &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Auth Management:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Login a User&lt;/li&gt;
&lt;li&gt;Logout a User&lt;/li&gt;
&lt;li&gt;Register a User&lt;/li&gt;
&lt;li&gt;Set permissions for a user&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is simple enough, right? &lt;/p&gt;
&lt;h3&gt;
  
  
  Creating the Onion's Layers
&lt;/h3&gt;

&lt;p&gt;Now you can use the Nest CLI's commands to build your app. &lt;/p&gt;

&lt;p&gt;Let's create the high level "management" domains. Inside your project folder, run these commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nest generate module blog
nest generate module user
nest generate module auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice three things have happened. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have folders with the names of these domains&lt;/li&gt;
&lt;li&gt;You have modules TS files with those names&lt;/li&gt;
&lt;li&gt;(the kicker) the modules are already imported into your &lt;code&gt;app.modules.ts&lt;/code&gt;. How cool is that?&lt;/li&gt;
&lt;/ul&gt;

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

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

&lt;p&gt;Now could be a good time to think even farther into the future. You could continue with the module creation process for the management features, but it might be overkill depending on what must actually be done in terms of code to make the features a reality. &lt;/p&gt;

&lt;p&gt;You think the &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;auth&lt;/code&gt; modules will be fairly straight forward, so you don't continue with adding modules there. But with with &lt;code&gt;blog&lt;/code&gt;, hmmm.... you aren't so certain. It could get hairy and more complex, especially the commenting part. So, you carry on inside the &lt;code&gt;blog&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;Change into the &lt;code&gt;blog&lt;/code&gt; folder and run the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nest generate module drafting
nest generate module publishing
nest generate module commenting
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You end up with the below image and again, the modules are automatically registered in &lt;code&gt;blog.module.ts&lt;/code&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F62zxl5qs2nlms3ld462i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F62zxl5qs2nlms3ld462i.png" alt=" " width="472" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's move on to the &lt;code&gt;auth&lt;/code&gt; module.. ehem...domain, um...management. (See how this DDD stuff is getting in here?)&lt;/p&gt;

&lt;p&gt;Ok. We only need the three processes. Login, Logout and Register. Theoretically, we only see these being three methods, but the methods might get somewhat large. So, we decide to make singular classes for each process. Change into the &lt;code&gt;auth&lt;/code&gt; directory and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nest generate service login
nest generate service logout
nest generate service register
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You now have this: &lt;/p&gt;

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

&lt;p&gt;And again, the services are auto-registered into the &lt;code&gt;auth&lt;/code&gt; module. Nice!&lt;/p&gt;

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

&lt;p&gt;Hopefully by now, you are catching on. &lt;/p&gt;

&lt;p&gt;But, we need more things to make the &lt;code&gt;auth&lt;/code&gt; feature work. How about a controller to get the calls routed to the service? Controllers should be small, so you know you can fit them all in one class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nest generate controller auth --flat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the &lt;code&gt;--flat&lt;/code&gt; argument. It tells Nest not to create a folder named &lt;code&gt;auth&lt;/code&gt; with the controller in it. It puts the controller file in the current directory. And once more, the controller is automatically registered in &lt;code&gt;auth.module.ts&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Ok. We have our controller, what now?&lt;/p&gt;

&lt;p&gt;We've learned about &lt;a href="https://docs.nestjs.com/guards" rel="noopener noreferrer"&gt;guards&lt;/a&gt;, and thus know we'll also need a guard of some sort to protect certain other paths in our future API. Let's create that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nest generate guard auth --flat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And our guard is created. Note though, guards aren't automatically registered in your module. &lt;/p&gt;

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

&lt;p&gt;We can continue on with even more creation of Nest providers, like adding the ORM files (repositories, entities), creating classes for DTOs, pipes for validation and a whole bunch of other stuff, but you are more than likely getting the idea by now. &lt;/p&gt;

&lt;p&gt;The important part to note with this exercise is, we are putting all the layers of the architecture in a module (a mini-onion). When compiling, Nest aggregates all of the modules to create the finished application (the big final kick-ass onion). &lt;/p&gt;

&lt;p&gt;There are some very nice advantages to this module system:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You can basically take any module and reuse it somewhere else (with some modification). Code reuse for the win!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You get a powerful dependency injection system. We didn't even start on that subject, but such a system is hugely important for enterprise grade code bases and at some point for your sanity. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When you have an issue with a feature, you can quickly find the code you need to work on. For instance, let's say you have a problem with validation of a blog input. You go to the &lt;code&gt;/blog/draft&lt;/code&gt; folder and there you'll have either the DTO you need defining the validation rules or the pipe that works the validation. All together. No searching through tons of files to find the right pieces of the puzzle.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lastly, Nest's modularization pushes you more into the direction of a Service Oriented kind of thinking. That, in turn, will help you make the jump to microservices easier. Remember, we wanted world domination! Right? Haha! &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Joking aside. Basically, you could say, Nest tries to get out of your way as a dev, by making you follow a process of modularization, where Nest is sort of secondary. It is a means to an end, but your domain problem is the first class citizen (or rather it should be). Your business problems at hand should determine how you build the app. Nest just adds the neat tools to make it happen. &lt;/p&gt;

&lt;h3&gt;
  
  
  Hmm....Something is Missing!
&lt;/h3&gt;

&lt;p&gt;You might be saying, "wait a sec! What about those things in an application, which don't belong to any business domain, but only to the developer domain? Things like connecting to a database -or- generating the API via Swagger -or- configuration?" &lt;/p&gt;

&lt;p&gt;Great question! &lt;/p&gt;

&lt;p&gt;How about a &lt;code&gt;core&lt;/code&gt; domain... uh...ehem...module?&lt;/p&gt;

&lt;p&gt;Change directory up to the root and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nest generate module core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's also create some services for the things mentioned above. Change back down to the &lt;code&gt;core&lt;/code&gt; folder and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nest generate module database
nest generate module swagger
nest generate module config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There you go! (Note: image shows common, as I originally used common, but this module should be named "core". Common should be for things commonly shared like utilities. &lt;/p&gt;

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

&lt;p&gt;Now you can tackle your problems logically. &lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;I hope this got you to a better understanding of why Nest's module system is so potent for your work as a developer. There are a good number of other features in Nest that make it a pleasure to work with. Yes, it seems verbose at the beginning. But, now you know why. And once you use Nest more and more, you'll wonder how you did your backend applications without it before.&lt;/p&gt;

&lt;p&gt;Enjoy Nest and have fun! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Additional Note:&lt;/strong&gt; After helping someone in the Nest Discord server once more about project structure, I realized one more advantage to Nest's modules. In our blog example, we had higher level &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;auth&lt;/code&gt; modules. In effect though, they could be considered "things I would always need in any app". I mentioned code reuse, and if you know these modules would always be added to any app together, you might want to end up with a "core" module holding such other modules like "auth", "authz" and "user". The cool things being (and the advantage) you can refactor this fairly easily. Create a "Core" module and move the folders and register them in the module as imports and if need be, break it out into its own library for use in any other of your apps.Awesome, right? 🙂&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Additional Note 2:&lt;/strong&gt; One of the things I see people often attempt, is to try and fit "DDD" into the file structure of a Nest project. Nest is flexible enough to allow for this, however, you end up with two problems.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Actually fixing a problem requires sifting through those different layers of the file system you've determined to be "proper" for fitting your app to "DDD". Whereas, if you just keep the DDD within each module, as Nest prescribes, you just need to go to that one module to fix the problem. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The bigger issue, you've broken up Nest's module system and thus the ability to reuse code/ modules as libraries. Maybe not a big deal for those just starting, but it will be when you realize you could take a lot of code and reuse it in new or other Nest projects. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To me, and this is my personal opinion, DDD should be a guide to how you think about your application, not necessarily how you design your file system/ project structure. When you come across a problem in the real world, either it being to enhance or to fix the application, nobody should need to rethink about the locality of code according to DDD to fix it. That is just going to waste a ton of time. Use Nest's "way of modularization". That is the standard you should work with. Keep DDD in your mind, when dealing with the overall problem and keep it away from the code structure. It just isn't necessary. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Additional Note 3:&lt;/strong&gt; I just ran into this article today. I think it helps make my points above. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/@stevebishop_89684/clean-architecture-is-not-a-project-structure-b158c9c4163f" rel="noopener noreferrer"&gt;https://medium.com/@stevebishop_89684/clean-architecture-is-not-a-project-structure-b158c9c4163f&lt;/a&gt;      &lt;/p&gt;

</description>
      <category>nestjs</category>
      <category>javascript</category>
      <category>node</category>
      <category>typescript</category>
    </item>
    <item>
      <title>m8a scenario #1 - Using Coder to Develop Keycloak Templates Live (almost)...</title>
      <dc:creator>Scott Molinari</dc:creator>
      <pubDate>Thu, 09 Feb 2023 10:32:34 +0000</pubDate>
      <link>https://dev.to/m8a-io/m8a-scenario-1-using-coder-to-develop-keycloak-templates-live-almost-26e2</link>
      <guid>https://dev.to/m8a-io/m8a-scenario-1-using-coder-to-develop-keycloak-templates-live-almost-26e2</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fas9kqjmrj3wi92rfviwz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fas9kqjmrj3wi92rfviwz.png" alt="Keycloak Custom Theming" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This article will be one of many posts about the trials and tribulations, the learnings and sharings of information as we build out the m8a.io platform (in POC). &lt;/p&gt;

&lt;p&gt;The goal of these scenario articles will be to highlight one or more technologies and explain what we did with them.&lt;/p&gt;

&lt;p&gt;We want to share these learnings and experiences, because we do believe we are making some cutting edge decisions for our new platform and/ or are coming up with alternative ways to do things that haven't yet been discovered before. And the publication of this knowledge is all in the name of giving back to those technologies that are helping us with our very lofty endeavour. It's a start. &lt;/p&gt;

&lt;p&gt;In this article, two of the technologies being highlighting are: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://coder.com/" rel="noopener noreferrer"&gt;Coder&lt;/a&gt; and &lt;a href="https://www.keycloak.org/" rel="noopener noreferrer"&gt;Keycloak&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From their websites:&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;Coder offloads development from local workstations to your on-prem and public cloud infrastructure. Boost developer productivity with instant onboarding and powerful server resources. Keep code and data under control within your network.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnpop0s8s0ycl30lsanku.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnpop0s8s0ycl30lsanku.png" alt="spacer" width="305" height="8"&gt;&lt;/a&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhn0ca50928owbduxetif.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhn0ca50928owbduxetif.png" alt="Keycloak" width="285" height="59"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Add authentication to applications and secure services with minimum effort. No need to deal with storing users or authenticating users.&lt;br&gt;
Keycloak provides user federation, strong authentication, user management, fine-grained authorization, and more.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As you can imagine, these are two pretty powerful sounding applications, right? &lt;/p&gt;

&lt;h2&gt;
  
  
  Scenario Description
&lt;/h2&gt;

&lt;p&gt;Above and beyond these two great applications, we are also using &lt;a href="https://kubernetes.io/" rel="noopener noreferrer"&gt;Kubernetes&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This article will assume you have some fairly good knowledge of Kubernetes and Helm and how they both work together. You should also be familiar with Terraform. &lt;/p&gt;

&lt;p&gt;As you hopefully know, Kubernetes (k8s) is a very powerful platform for orchestrating container workloads. If you are still reading this and you don't know about k8s, I highly recommend learning about. &lt;/p&gt;

&lt;p&gt;Getting back to our two main technologies....we have implemented Keycloak as our &lt;a href="https://www.techtarget.com/searchsecurity/definition/identity-access-management-IAM-system" rel="noopener noreferrer"&gt;Identification and Authorization Management system&lt;/a&gt; (IAM). However, as these things go, Keycloak has its own tech stack. One of the technologies, of course, is the language they used, which is Java. And being it is Java, they chose to use a templating engine called &lt;a href="https://freemarker.apache.org/" rel="noopener noreferrer"&gt;Freemarker&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To keep this article as short as possible and because it isn't the intention of this article, we won't go into the deeper details of Keycloak's templating system and how to use it. Instead, I'll refer you to two good articles that explain it all well:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.baeldung.com/spring-keycloak-custom-themes" rel="noopener noreferrer"&gt;Customizing Themes for Keycloak&lt;/a&gt;&lt;br&gt;
&lt;a href="https://trigodev.com/blog/how-to-customize-keycloak-themes" rel="noopener noreferrer"&gt;How to Customize Keycloak Themes&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;That being said, if you are familiar with any other templating system for the backend, you'll understand Freemarker fairly quickly too. &lt;/p&gt;

&lt;p&gt;And, because Keycloak uses this template system, setting up your Corporate Identity within Keycloak is very much possible and not entirely difficult. &lt;/p&gt;

&lt;p&gt;However, despite knowing about templating and Keycloak you'll quickly understand the first hurdle of having Keycloak in k8s. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Above and beyond designing the templates, how can we even get those new templates into the Keycloak pods for use by the application?&lt;/em&gt;&lt;/strong&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are two suggested ways to get customized templates into the Keycloak pod or pods.  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;using an init container to "load" the new templates over a shared volume.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;using a secret to load in a tarballed archive of the files. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Why won't this work?
&lt;/h3&gt;

&lt;p&gt;Both require a number of steps to make the template contents usable by Keycloak and as you can imagine, are miles away from any kind of live development.  &lt;/p&gt;

&lt;p&gt;With either of these two steps, you'd need to have a local version of Keycloak to design on, then create a container with the files or create a tarball and load it into a secret and then restart Keycloak. Restarting Keycloak alone takes about a minute until it is ready to go. And if you happen to see a mistake, as it always happen, it's wash, rinse and repeat (pulling out hair or getting grey from the process). &lt;/p&gt;
&lt;h2&gt;
  
  
  Coder to the Rescue!
&lt;/h2&gt;

&lt;p&gt;Coder is going to be an integral part of the m8a platform. And as it may be, we can also use it for the purpose of (almost) live development of custom templates in a running Keycloak pod. &lt;/p&gt;

&lt;p&gt;Point #1 above of getting a template set into Keycloak via a shared volume gave us the initial idea. Why not just use another pod, a Coder agent/ workspace pod in parallel and share the volume between them? That way you can develop on the files in the volume and Keycloak would use them directly. Yes!&lt;/p&gt;

&lt;p&gt;So, off we went looking to resolve this challenge.  &lt;/p&gt;
&lt;h3&gt;
  
  
  Installing and Setting up Coder
&lt;/h3&gt;

&lt;p&gt;To get going with Coder, you'll need to &lt;a href="https://coder.com/docs/v2/latest/install/kubernetes" rel="noopener noreferrer"&gt;install Coder into your k8s cluster via Helm&lt;/a&gt;. Follow the instructions carefully and you should have Coder up and  running in cluster in no time. &lt;/p&gt;

&lt;p&gt;Next, you'll need a workspace template to be able to create a workspace. Again, the &lt;a href="https://coder.com/docs/v2/latest/templates" rel="noopener noreferrer"&gt;Coder's docs explain how to do this well&lt;/a&gt; and there is an example &lt;a href="https://github.com/coder/coder/tree/main/examples/templates/kubernetes" rel="noopener noreferrer"&gt;k8s template you can start from&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;You'll also need to install the Coder CLI onto your local machine for working on the templates.&lt;/p&gt;

&lt;p&gt;Coder's templates are basically Terraform modules. So, you'll need knowledge of how Terraform works and the config language itself, to develop them. If you know k8s though, it's fairly easy to pick up. &lt;/p&gt;
&lt;h2&gt;
  
  
  Getting Everything Set Up
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Coder's service account permissions
&lt;/h3&gt;

&lt;p&gt;In order to have Coder work with k8s objects outside its own workspace, we have to give the Coder service account (which should have been installed while installing Coder's Helm chart) enough permissions to work across namespaces. We did this by creating an admin cluster role and binding it to the service account via &lt;code&gt;kubectl&lt;/code&gt;.  &lt;/p&gt;
&lt;h3&gt;
  
  
  Keycloak setup
&lt;/h3&gt;

&lt;p&gt;This was the trickier part. And of course, this will require a development environment, and not your production Keycloak. Setting up a complete development environment in k8s is way beyond the scope of this article, but if you are a good with k8s, you'll know what to do, if you haven't done it already (i.e. you really should!). &lt;/p&gt;

&lt;p&gt;Ok. So, with Keycloak in a dev environment, you'll need to have only one Keycloak pod running, to not run into caching issues. And, you'll be setting this up in the Helm chart (we are using the Bitnami chart):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="na"&gt;extraStartupArgs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;-&lt;/span&gt;
  &lt;span class="s"&gt;--spi-theme-static-max-age=-1 --spi-theme-cache-themes=false --spi-theme-cache-templates=false&lt;/span&gt;

&lt;span class="s"&gt;...&lt;/span&gt;

&lt;span class="na"&gt;replicaCount&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These startup args will turn off the Keycloak caching process for templates.&lt;/p&gt;

&lt;p&gt;Or, you can also do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="na"&gt;extraEnvVars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;KEYCLOAK_PRODUCTION&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;false'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will start the pod in dev-mode, which should also mean template caching is turned off. &lt;/p&gt;

&lt;h3&gt;
  
  
  Set up the volume
&lt;/h3&gt;

&lt;p&gt;We are using &lt;a href="https://longhorn.io/" rel="noopener noreferrer"&gt;Longhorn&lt;/a&gt; as a more capable storage system inside our k8s clusters. To set up the volume with Longhorn, you can go into the UI and create a new Persistent Volume Claim (pvc)/ Volume. &lt;/p&gt;

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

&lt;p&gt;You can also do this via &lt;code&gt;kubectl&lt;/code&gt;, and with any other storage system in k8s. &lt;/p&gt;

&lt;p&gt;Once you have the pvc created (making sure it is in the &lt;code&gt;keycloak&lt;/code&gt; namespace) you are halfway there.&lt;/p&gt;

&lt;p&gt;As a next step, you'll need to bind the pvc to the Keycloak pod via a Persistent Volume (pv). To do this, add the following to the Helm chart and upgrade it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;extraVolumeMounts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;mountPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/opt/bitnami/keycloak/themes/m8a-theme&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;theme&lt;/span&gt;
&lt;span class="na"&gt;extraVolumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;theme&lt;/span&gt;
    &lt;span class="na"&gt;persistentVolumeClaim&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;claimName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pvc-keycloak-theme&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;mountPath&lt;/code&gt; is dependent on where Keycloak is installed in the pod. The path above it where the Bitnami chart puts it. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;claimName&lt;/code&gt; is the name of your pvc. Ours is &lt;code&gt;pvc-keycloak-theme&lt;/code&gt;. Keep that in mind.  &lt;/p&gt;

&lt;p&gt;Now you have the Keycloak instance working with a volume that can be attached to other pods. Let's do that now with a Coder workspace.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up the Coder workspace (the pod)
&lt;/h3&gt;

&lt;p&gt;As mentioned above, you can use the example Coder template to create the workspace. The only difference is now, you'll need to have the volume also bind to the workspace pod. To make that happen, you'll need to add this to the template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"kubernetes_pod"&lt;/span&gt; &lt;span class="s2"&gt;"main"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coder_workspace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;me&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start_count&lt;/span&gt;

   &lt;span class="p"&gt;...&lt;/span&gt;


      &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;name&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"CODER_AGENT_TOKEN"&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;coder_agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;volume_mount&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;mount_path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/home/template-dev/my-theme"&lt;/span&gt;
        &lt;span class="nx"&gt;name&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"theme"&lt;/span&gt;
        &lt;span class="nx"&gt;read_only&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;volume&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"theme"&lt;/span&gt;
      &lt;span class="nx"&gt;persistent_volume_claim&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;claim_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"pvc-keycloak-theme"&lt;/span&gt;
        &lt;span class="nx"&gt;read_only&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;volume_mount&lt;/code&gt; and &lt;code&gt;volume&lt;/code&gt; entries are the important additions. &lt;code&gt;volume_mount&lt;/code&gt; is the location of the files you'll be working on. &lt;code&gt;volume&lt;/code&gt; is the binding of the pvc to the pod. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://coder.com/docs/v2/latest/templates#edit-templates" rel="noopener noreferrer"&gt;Push up&lt;/a&gt; or &lt;a href="https://coder.com/docs/v2/latest/templates#add-a-template" rel="noopener noreferrer"&gt;add your template&lt;/a&gt; to your Coder instance via the Coder CLI and you are almost ready for development. &lt;/p&gt;

&lt;h3&gt;
  
  
  The new development workflow
&lt;/h3&gt;

&lt;p&gt;Ok. Now that we have pretty much everything set up. Go into your Coder installation (either via port forward or if you set everything up properly, via the URL), go to the Templates tab and fire up a new workspace. &lt;/p&gt;

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

&lt;p&gt;I like to use my local VSCode, so I press on the button, which will open the workspace in VSCode. &lt;/p&gt;

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

&lt;p&gt;Coder will also let you work directly in the browser too, if that is what you want. We removed that feature from our template and why you don't see the option above. &lt;/p&gt;

&lt;p&gt;Remember, this is a pod working inside a k8s cluster. It's true remote development in a just-like-production dev environment. &lt;/p&gt;

&lt;p&gt;Once you've clicked on the button shown above, you'll be greeted with this a few seconds later:&lt;/p&gt;

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

&lt;p&gt;With the workspace running, you can add your files as necessary and start developing directly on your Keycloak templates. &lt;/p&gt;

&lt;p&gt;Note1: In the image above, the &lt;code&gt;login&lt;/code&gt; folder is the one I was working in. You'll need to add the different folders yourself for the different areas you want to customize Keycloak's templates. &lt;/p&gt;

&lt;p&gt;Note2: In the future, you'll be able to determine which folder the Workspace should open up in. The suggestion wasn't yet implemented in Coder at the time of writing. &lt;/p&gt;

&lt;p&gt;Note3: Don't make the same mistake as I did and have browser caching turned on (and have forgotten about it). If you aren't seeing changes made directly after refreshing the Keycloak page you are customizing, see if it works with Ctrl + F5. Or turn off your browser's cache. &lt;/p&gt;

&lt;p&gt;So, that is it. I searched very hard to find something like this and couldn't find anything remotely similar. I hope this will help others, at least those wanting to customize their Keycloak instance more efficiently inside k8s. &lt;/p&gt;

&lt;p&gt;Happy Coding!!!! 😁&lt;/p&gt;

</description>
      <category>keycloak</category>
      <category>kubernetes</category>
      <category>coder</category>
      <category>backend</category>
    </item>
    <item>
      <title>QuasarConf 2022 - Speakers and Schedule</title>
      <dc:creator>Scott Molinari</dc:creator>
      <pubDate>Tue, 28 Jun 2022 19:26:29 +0000</pubDate>
      <link>https://dev.to/quasar/quasarconf-2022-speakers-and-schedule-dp3</link>
      <guid>https://dev.to/quasar/quasarconf-2022-speakers-and-schedule-dp3</guid>
      <description>&lt;p&gt;&lt;em&gt;Get out your calendar, and save the date!&lt;/em&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  When will it be?
&lt;/h2&gt;

&lt;p&gt;Saturday the 9th of July, 2022 - 3 p.m. GMT&lt;/p&gt;



&lt;h2&gt;
  
  
  Where will it be?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://bit.ly/qconfstream2022" rel="noopener noreferrer"&gt;Streamed Live on Youtube (bookmark the link!)&lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  The Speakers, Topics and Schedule
&lt;/h2&gt;

&lt;p&gt;(all times GMT)&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
&lt;strong&gt;Quick Welcome and Intro - 3 p.m.&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;br&gt;
&lt;strong&gt;&lt;u&gt;Talk 1 - 3:05 p.m. -  Five Refactoring Tips For Gorgeous, Reusable Code&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F84vttvtmba2767lrk2no.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F84vttvtmba2767lrk2no.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
Let's make our Quasar code crystal clear and easy to follow, by breaking it into smaller pieces. Luke will show how you can truly separate concerns with little known, powerful refactoring techniques... Techniques that will have your coworkers smiling when they dive into your codebase!&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
&lt;strong&gt;&lt;u&gt;Talk 2 - 3:30 p.m. - Quasar and TypeScript: A Deep Dive &lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy08v4i71efun1d41pewl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy08v4i71efun1d41pewl.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
Yusuf will take us on a deep dive into Quasar's TS generation pipeline and JSON API structure. The history behind these, the progress we've made over the years, and future plans will also be covered. &lt;/p&gt;

&lt;p&gt;&lt;br&gt;
&lt;strong&gt;&lt;u&gt; Talk 3 - 3:55 p.m. - All is Well, When There is Quasar!&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj22gaenc08b8l4kifvn1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj22gaenc08b8l4kifvn1.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
Hari will explain how his and his team used Quasar/VueJS along with AWS &amp;amp; Feathers JS to help them in developing an academic platform in record time. He'll cover how they used the Quasar Ecosystem - and how they built up their Resume Builder, Simple CRUD User Interfaces, Social Feed and a Subscription &amp;amp; Licensing System including short demos showcasing the real world use of their use of Quasar components.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
&lt;strong&gt;&lt;u&gt; Talk 4 - 4:20 p.m. - Using the Composition API with TypeScript to Build Better Forms&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgj890bw576rykrrg1nb4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgj890bw576rykrrg1nb4.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
In this talk, Bruno will cover how you can leverage the Composition API by creating composables to abstract the logic out of your forms, making that logic reusable.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
&lt;strong&gt;&lt;u&gt; Talk 5 - 4:45 p.m. - Quasar Themes and Theming&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zjqcmw3141qprx2iv1g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zjqcmw3141qprx2iv1g.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
In the talk Bart will give you a look at the state of Quasar and theming. We'll go into the provided light and dark themes provided by Quasar and then look at how to expand into more custom themes, based on the gathered knowledge on how Quasar works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt; Talk 6 - 5:10 p.m. - Component Testing Tip &amp;amp; Tricks with Quasar&lt;/u&gt;&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5uu14qb1y4y0a90m5l2o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5uu14qb1y4y0a90m5l2o.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
Quasar has supported Cypress Component Testing out of the box for some months, but there are some caveats due to Quasar feature-packed components having a much more complex HTML structure than native input elements.&lt;/p&gt;

&lt;p&gt;Paolo will cover how you can add Cypress Component Testing to your Quasar project and show you some tips and tricks about testing some of the most complex Quasar components.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
&lt;strong&gt;&lt;u&gt;--- 20 Minute Break ---&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
&lt;strong&gt;&lt;u&gt; Talk 7 - 5:55 p.m. - Wrapping and Extending Quasar Components using TypeScript&lt;/u&gt;&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg4g6wt9wv11dieaj9o72.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg4g6wt9wv11dieaj9o72.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
Evert will showcase 2 options on how to wrap and extend Quasar components. This can be used to set defaults for properties and use your wrapped component instead of the default Quasar one throughout your application. Of course doing all this while preserving as many TypeScript/IDE features that are currently out there, like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;property autocompletion and type checking&lt;/li&gt;
&lt;li&gt;property documentation on hover&lt;/li&gt;
&lt;li&gt;typed component methods&lt;/li&gt;
&lt;li&gt;typed slots&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;br&gt;
&lt;strong&gt;&lt;u&gt; Talk 8 - 6:20 p.m. - Embedding Quasar Apps Into Lightweight Hardware&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F463cmqhoiids3g3lceu7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F463cmqhoiids3g3lceu7.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
Mike will cover workflow and methodology for incorporating Quasar/Vue Apps into resource constrained embedded systems hardware such as the ESP32 processor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt; Talk 9 - 6:45 p.m. - Building Engineering Tools with Quasar&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzoxmhnmgkhg9d8ug0fh1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzoxmhnmgkhg9d8ug0fh1.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
Carlos will show two examples of Quasar apps he developed as engineering tools. He'll demonstrate how Quasar helped him with the rapid development of the tools and how these benefits can also help you. &lt;/p&gt;

&lt;p&gt;&lt;br&gt;
&lt;strong&gt;&lt;u&gt; Talk 10 - 7:10 p.m. - Lessons Learned Migrating an App to Quasar and Vue3&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fczmx8dr0mivoc1ltzb6n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fczmx8dr0mivoc1ltzb6n.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
In early 2022, Martin decided to upgrade one of his side projects from Vue2+Buefy to Vue3+Quasar. His application gets hundreds of thousands of visitors per day, so he had to tread carefully. Martin's talk will go into why he made the decision to migrate, what the migration was like, and how he rolled out the new version. &lt;/p&gt;

&lt;p&gt;&lt;br&gt;
Should you have any questions, please post them in the comments below or join us on &lt;a href="https://chat.quasar.dev" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Although we are planning to carry out the conference as advertised, the schedule is subject to change, without notice. &lt;/p&gt;

&lt;p&gt;&lt;br&gt;
Follow us on:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/quasarframework" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.facebook.com/QuasarFramework" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>It's Back! QuasarConf 2022 - Call for Proposals</title>
      <dc:creator>Scott Molinari</dc:creator>
      <pubDate>Mon, 23 May 2022 11:09:03 +0000</pubDate>
      <link>https://dev.to/quasar/its-back-quasarconf-2022-call-for-proposals-13mn</link>
      <guid>https://dev.to/quasar/its-back-quasarconf-2022-call-for-proposals-13mn</guid>
      <description>&lt;p&gt;We are happy to announce the comeback of our yearly online conference about all things Quasar Framework and Vue. We had success with &lt;a href="https://www.youtube.com/watch?v=6ZKBZ3k4Ebk"&gt;our first ever conference&lt;/a&gt; and we'd like to continue with what we intend to be a tradition. &lt;/p&gt;

&lt;h3&gt;
  
  
  When will it be?
&lt;/h3&gt;

&lt;p&gt;Saturday the 9th of July, 2022 - 3 p.m. GMT&lt;/p&gt;

&lt;h3&gt;
  
  
  Would you like to do a talk?
&lt;/h3&gt;

&lt;p&gt;We are looking for devs in the community, who would like to present their knowledge about anything related to Quasar and/or Vue. &lt;/p&gt;

&lt;p&gt;Your talk should go for 20 minutes max. We'll also be offering the viewers the ability to ask questions in the chat, so after the talk, we'll have a 5 minute Q&amp;amp;A with the speaker. &lt;/p&gt;

&lt;p&gt;If you are interested, &lt;a href="https://forms.gle/F8bPLG8xdtBCF2iLA"&gt;please sign up by filling out our Call for Proposals form&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There is a limited number of available spaces for talks.&lt;br&gt;
Deadline for proposal acceptance is the 9th of June, 2022.  &lt;/p&gt;

&lt;h3&gt;
  
  
  What to expect?
&lt;/h3&gt;

&lt;p&gt;At our last (and first) conference 2 years ago, &lt;strong&gt;we had over 700 live viewers&lt;/strong&gt; and the video has been &lt;strong&gt;watched over 17k times&lt;/strong&gt; since then. Not too shabby for a first conference!&lt;/p&gt;

&lt;p&gt;We hope to be breaking these firsts this year and with your help, it's pretty certain we can. &lt;/p&gt;

&lt;p&gt;If you have any questions, you can either write them down below or &lt;a href="https://chat.quasar.dev"&gt;use our Discord&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;We'll be making more announcements about the conference, the participants and content in later posts. &lt;/p&gt;

&lt;p&gt;We are looking forward to your talk proposals!! &lt;/p&gt;

&lt;p&gt;If you'd like to stay in-tune with conference and other Quasar news, please follow our channels. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.facebook.com/QuasarFramework"&gt;Facebook&lt;/a&gt;&lt;br&gt;
&lt;a href="https://twitter.com/quasarframework"&gt;Twitter &lt;/a&gt;&lt;br&gt;
Follow the tag #quasarconf on Twitter &lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Quasar and Vite - Frontend Application Development at Light Speed</title>
      <dc:creator>Scott Molinari</dc:creator>
      <pubDate>Mon, 14 Mar 2022 19:50:22 +0000</pubDate>
      <link>https://dev.to/quasar/quasar-and-vite-frontend-application-development-at-light-speed-1b4f</link>
      <guid>https://dev.to/quasar/quasar-and-vite-frontend-application-development-at-light-speed-1b4f</guid>
      <description>&lt;p&gt;This week notes the accomplishment of a major milestone in Quasar's roadmap. The integration of Vite as a driver of the Quasar CLI, and as a much better alternative to the slower and more complicated Webpack based CLI. &lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Introduction Video
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/tql0omvnoXg"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Vite?
&lt;/h2&gt;

&lt;p&gt;If you haven't heard about Vite yet and why it is so good, Vite has the following main selling points:&lt;/p&gt;

&lt;p&gt;(from the &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite docs&lt;/a&gt;)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A dev server that provides rich feature enhancements over native ES modules, for example extremely fast Hot Module Replacement (HMR).&lt;/p&gt;

&lt;p&gt;A build command that bundles your code with Rollup, pre-configured to output highly optimized static assets for production.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In other words, the main goal Evan You (creator of Vue) had for creating Vite (pronounced like veet) was to majorly improve the developer experience. He saw that the current process of bundling and then loading the application into the browser and developing with Hot-Module-Replacement (HMR) could be improved upon with the new ES Module resolution system available in all browsers. &lt;/p&gt;

&lt;p&gt;That is the TLDR version. &lt;a href="https://vitejs.dev/guide/why.html#slow-server-start" rel="noopener noreferrer"&gt;If you'd like, you can also read the much more technical reasons.&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Bottom line, the avoidance of the bundling or packing step for the initial build, also during HMR, saves a ton of time, even with the smallest of projects (see below). But, this advantage is especially noticeable, once your project gets even remotely bigger.&lt;/p&gt;

&lt;h4&gt;
  
  
  Initial Loading of a new Quasar project with Webpack
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2Fu76c6Sg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2Fu76c6Sg.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Initial Loading of a new Quasar project with Vite
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FqZOPsVv.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FqZOPsVv.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ok. The difference with an initial project isn't so predominant, but it is there. Think about this though. Once your project starts growing, the Vite-based CLI's performance in building your app stays about the same or will only slow a little for the initial startup. The Webpack performance will degrade much worse as your project size grows. In other words, what you see here as the initial startup speed is about what you'll have for any size project. On top of that, any updates from HMR will be instantaneous with Vite. With Webpack, this performance also degrades with the size of your project.&lt;/p&gt;

&lt;p&gt;It was clear to the team instantly, when Vite came out, that Quasar would need to integrate it. So, it wasn't a matter of "If", but rather "When?". It was just a matter of time, dev availability with Razvan and our prerogatives for it to happen. Our first major goal was to get Quasar onto Vue 3. That happened last year. All the while, Vite was getting better and more stable. And this year, Quasar now has a Vite based CLI. &lt;/p&gt;

&lt;p&gt;How cool is that? 🤩 &lt;/p&gt;

&lt;h3&gt;
  
  
  Getting Started
&lt;/h3&gt;

&lt;p&gt;If you'd like to just get started with Vite in a new project, all you have to do is run...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;yarn create quasar
&lt;span class="c"&gt;# or:&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;npm init quasar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The command &lt;code&gt;quasar create&lt;/code&gt; is no longer usable for a Quasar project with the new CLI (&amp;gt;1.3.0). &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE2: the Vite CLI was still in BETA at the time this article was published. So, it is not production ready, if it is still in beta or RC status!!!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While running the command above, the creation process will pose question to you for the project creation. Answer the questions as best you can. Hit enter for the defaults (except for the Vite CLI), if you are uncertain what to answer. Once the creation process is done, navigate to the newly created project folder and run...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;quasar dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And off you go.. with Lightning fast development at your fingertips!!! &lt;/p&gt;

&lt;h3&gt;
  
  
  Migration
&lt;/h3&gt;

&lt;p&gt;Maybe you have a Quasar project and wish to move it to the new Vite CLI. If that is the case, then let's get you up to.....Vite, &lt;a href="https://quasar.dev/quasar-cli-vite/convert-to-quasar-cli-with-vite" rel="noopener noreferrer"&gt;with the official migration guide.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Roughly, the migration guide takes you through the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new project with the newest version of the (global) Quasar CLI&lt;/li&gt;
&lt;li&gt;Copy specific folders into the new project from your old project, also doing some small edits on specific files.&lt;/li&gt;
&lt;li&gt;Update the &lt;code&gt;quasar.config.js&lt;/code&gt; file notice it's changes from &lt;code&gt;quasar-conf.js&lt;/code&gt;) with the new settings, should you need them.&lt;/li&gt;
&lt;li&gt;Update &lt;code&gt;package.json&lt;/code&gt; to remove the &lt;code&gt;browserlist&lt;/code&gt; entry (if you want). It is no longer valid and not needed, at least for Vite. &lt;/li&gt;
&lt;li&gt;Delete a folder for SSR and move another. &lt;/li&gt;
&lt;li&gt;For PWA, you'll need to move your manifest to &lt;code&gt;quasar.config.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;If you are using BEX mode, you'll also need to port over your manifest files manually. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, not too much work necessary to get a much better DX. &lt;/p&gt;

&lt;p&gt;Again, more details can be found in the &lt;a href="https://quasar.dev/quasar-cli-vite/convert-to-quasar-cli-with-vite" rel="noopener noreferrer"&gt;migration guide&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  That's it!
&lt;/h3&gt;

&lt;p&gt;Let us know in the comments about what you think! Is Vite with Quasar awesome or what?&lt;/p&gt;

&lt;p&gt;Keep in touch with Quasar news. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.quasar.dev/" rel="noopener noreferrer"&gt;Quasar on Twitter&lt;/a&gt;&lt;br&gt;
&lt;a href="https://facebook.quasar.dev/" rel="noopener noreferrer"&gt;Quasar on Facebook&lt;/a&gt;&lt;br&gt;
&lt;a href="https://chat.quasar.dev/" rel="noopener noreferrer"&gt;Quasar on Discord&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/quasarframework" rel="noopener noreferrer"&gt;Quasar on Github&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Quasar Hack-a-May Results and Winners!</title>
      <dc:creator>Scott Molinari</dc:creator>
      <pubDate>Thu, 11 Jun 2020 13:20:29 +0000</pubDate>
      <link>https://dev.to/quasar/quasar-hack-a-may-results-and-winners-34gk</link>
      <guid>https://dev.to/quasar/quasar-hack-a-may-results-and-winners-34gk</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--66Hs1QCy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/Oxnn5p7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--66Hs1QCy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/Oxnn5p7.jpg" alt="" width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Firstly&lt;/em&gt;&lt;/strong&gt; - Thanks to all the participants for their entries. &lt;/p&gt;

&lt;p&gt;Next, we'd like to &lt;a href="https://dev.to/quasar/hack-a-may-quasar-framework-s-community-programming-contest-3k4i"&gt;&lt;strong&gt;remind everyone of the rules we put in place&lt;/strong&gt;&lt;/a&gt; for this contest. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Ok.&lt;/em&gt; So let's get to the awards.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Drum roll please!&lt;/em&gt;..........&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;First place goes to:&lt;/strong&gt; &lt;strong&gt;&lt;a href="https://github.com/kfields/bbex"&gt;BBex&lt;/a&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Author: &lt;a href="https://github.com/kfields"&gt;Kurtis Fields&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Pc6tzaUL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/VqE0WTs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pc6tzaUL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/VqE0WTs.png" alt="" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;BBex is a bookmark tool, which helps you better manage large numbers of book marks. It uses Dexie as a storage system in your browser and also uses Fuse for powerful searches in your bookmarks. &lt;/p&gt;

&lt;p&gt;This BEX is easily installed and works from the gitgo. In fact, it loads up first with a simple button to run the setup, which indexes your bookmarks. After that, you have a great system to manage your bookmarks. &lt;/p&gt;

&lt;p&gt;Congrats to Kurtis on this great little tool and winning the contest.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Second place goes to:&lt;/strong&gt; &lt;strong&gt;&lt;a href="https://github.com/Rolanddoda/quasar-ext-gh-pages-auto-deploy"&gt;Quasar App Extension GH Pages Auto-Deploy&lt;/a&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Author: &lt;a href="https://github.com/Rolanddoda"&gt;Roland Doda&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BD1S2j08--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/KKnrkTR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BD1S2j08--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/KKnrkTR.png" alt="" width="800" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Coming in a very close second is Roland's GH-Pages Auto Deploy App Extension (AE).&lt;/p&gt;

&lt;p&gt;We were really impressed with this little AE. Simply have your app's repo on Github (locally, your app's repo needs to have a GH repo as a remote origin), then install this AE into your app and you have a one-stop script to build and upload/publish your apps to &lt;a href="https://pages.github.com/"&gt;Github Pages&lt;/a&gt; via &lt;code&gt;yarn gh-pages-deploy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A great AE utility for those who use Github Pages and it also shows the versatility of Quasar's App Extension system and thus earns second place.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Third place goes to:&lt;/strong&gt; &lt;strong&gt;&lt;a href="https://github.com/huy-tran/gbtuls-translator"&gt;GBTuls Translator&lt;/a&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Author: &lt;a href="https://github.com/huy-tran"&gt;huy-tran&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---qoUf8mS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/wSymQfw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---qoUf8mS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/wSymQfw.png" alt="" width="800" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is another interesting BEX. It is also a great little tool for the translation of highlighted text on any web page. No longer do you need to cut and paste to get a translation. Had the "Language Target" persisted, it might have even gotten more votes. We also know there are other extensions out there to do the same thing. The fact it was written in Quasar makes it special to us and a well-earned third place.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Honorable Mention #1:&lt;/strong&gt; &lt;a href="https://github.com/siauderman/covidgamebex"&gt;&lt;strong&gt;Covid Game Bex&lt;/strong&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Author: &lt;a href="https://github.com/siauderman"&gt;siauderman&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bNS0Sype--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/lpZDGdy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bNS0Sype--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/lpZDGdy.png" alt="" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we did the voting, totally subjective and with no guidance between the core Quasar team, this remarkable BEX just missed out of placing among the winners. &lt;/p&gt;

&lt;p&gt;This BEX is an interesting game, which not only is a game, but also an interactive way to learn about Covid and how the body fights such diseases on its own. There is even music!&lt;/p&gt;

&lt;p&gt;Awesome work done here and well worth the honorable mention.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Honorable Mention #2:&lt;/strong&gt; &lt;a href="https://github.com/Narcis13/quasar-grouped-table"&gt;&lt;strong&gt;Quasar Grouped Table&lt;/strong&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Author: &lt;a href="https://github.com/Narcis13"&gt;Narcis13&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Wbb7eQ_p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/CdUidgx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Wbb7eQ_p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/CdUidgx.png" alt="" width="800" height="639"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This little AE is the last honorable mention. It shows how the AE system can also work for extended Quasar components. Need a grouped table? Just run &lt;code&gt;quasar ext add q-grouped-table&lt;/code&gt; and you have it. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Thanks again to all the participants. It was amazing to see the diversity of ideas, which just goes to show how Quasar can be used for practically any idea to make an application frontend a reality. &lt;/p&gt;

&lt;p&gt;Those who won, would you please contact me via DM on Discord - Scott (EN-DE)#0052 - to arrange getting the prizes to you. Thanks!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>vue</category>
      <category>quasar</category>
    </item>
    <item>
      <title>Introducing Quasar.Conf</title>
      <dc:creator>Scott Molinari</dc:creator>
      <pubDate>Wed, 03 Jun 2020 18:23:25 +0000</pubDate>
      <link>https://dev.to/quasar/introducing-quasar-conf-52gg</link>
      <guid>https://dev.to/quasar/introducing-quasar-conf-52gg</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;The first Quasar Conference - Online!&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;UPDATED: 30.06.2020&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/quasarframework/quasar/issues/5983" rel="noopener noreferrer"&gt;We asked the community&lt;/a&gt; where the conference should be held and we noticed Quasar is popular across the world. Also, with the Covid-19 situation, it just made good sense to have it online. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Venue&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=6ZKBZ3k4Ebk" rel="noopener noreferrer"&gt;&lt;strong&gt;You'll find us on Youtube Live!&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
Subscribe to the channel or click the "Set Reminder" button to get reminded of the conference's live stream. &lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Save the Date!&lt;/strong&gt;
&lt;/h3&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://calendar.google.com/event?action=TEMPLATE&amp;amp;tmeid=M2drajV1azU2dDU5OXZwcWp1NjJsbGp0NHAgcXVhc2FyZndAbQ&amp;amp;tmsrc=quasarfw%40gmail.com" rel="noopener noreferrer"&gt;Sunday - July 5th, 2020 at 15:00 GMT&lt;/a&gt;
&lt;/h3&gt;







&lt;h3&gt;
  
  
  &lt;strong&gt;Current Speaker Line-up and Topics&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Razvan Stoenescu - Quasar Lead Dev and Founder&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/rstoenescu" rel="noopener noreferrer"&gt;@rstoenescu&lt;/a&gt;&lt;br&gt;
CEO of Pulsardev SRL&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F020md2u136mz0y56cvwt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F020md2u136mz0y56cvwt.png" title="Razvan" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update: &lt;a href="https://forum.quasar-framework.org/topic/6269/razvan-is-taking-some-time-off" rel="noopener noreferrer"&gt;Razvan has fell ill&lt;/a&gt;, and won't be able to be present.&lt;/strong&gt;  &lt;/p&gt;




&lt;h2&gt;
  
  
  Guest Speakers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Natalia Tepluhina&lt;/strong&gt; - Vue Core Dev&lt;br&gt;
&lt;a href="https://github.com/NataliaTepluhina" rel="noopener noreferrer"&gt;@N_Tepluhina&lt;/a&gt;&lt;br&gt;
Staff frontend engineer at &lt;a href="//gitlab.com"&gt;GitLab&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjpil6va8hojds90cvtvm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjpil6va8hojds90cvtvm.png" title="Natalia" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wondering how $attrs will behave in Vue 3? What should you do when you have a multi-root component? What is the new 'emits' component option and should you add it to all existing components when migrating to v3? Natalia will cover all these cases in her Lightning Talk.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Danny Connell&lt;/strong&gt; - Quasar Content Contributor&lt;br&gt;
&lt;a href="https://github.com/dannyconnell" rel="noopener noreferrer"&gt;@dannyconnell&lt;/a&gt;&lt;br&gt;
Indie App Dev &amp;amp; Course Creator&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmaqymulnaepii6bckcic.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmaqymulnaepii6bckcic.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Danny will demonstrate his neat PWA app called "Quasagram" - a gorgeous Instragram Clone built with Quasar &amp;amp; Firebase.&lt;/p&gt;

&lt;p&gt;During the demo, he'll show how he integrated the following core PWA features into the app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Precaching&lt;/li&gt;
&lt;li&gt;Caching&lt;/li&gt;
&lt;li&gt;Background Sync&lt;/li&gt;
&lt;li&gt;Push Notifications&lt;/li&gt;
&lt;li&gt;Home Screen Installation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are interested in building a PWA, then this is a must-see!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Joseph "Yev" Angeles&lt;/strong&gt; - Full Stack Developer&lt;br&gt;
&lt;a href="https://github.com/vycoder" rel="noopener noreferrer"&gt;@vycoder&lt;/a&gt;&lt;br&gt;
Founder of Night Owl Studios&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyqb0yq6zts6e42othvlo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyqb0yq6zts6e42othvlo.png" alt="Yev"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yev is going to be demonstrating his Productivity App called "Qodo". He'll also be introducing some of the techniques he used with the intention of giving new developers coming to Quasar some inspiration via his experiences with developing the app.  &lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Wilson Foo&lt;/strong&gt; - Lawyer by Day, Developer by Night&lt;br&gt;
&lt;a href="https://github.com/siauderman" rel="noopener noreferrer"&gt;@siauderman&lt;/a&gt;&lt;br&gt;
Managing Director at Custom Automated Systems Pte Ltd&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqtq2j8w1ja3adpiv661c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqtq2j8w1ja3adpiv661c.png" alt="Wilson"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wilson will also be demonstrating his Quasar-built "Covid Game" app. He designed it as a game, but it is also a learning experience about how the body copes and fights diseases. Wilson will be demonstrating how Quasar can even be used to build a game application. Quite exotic, but should be interesting. &lt;/p&gt;




&lt;h2&gt;
  
  
  Quasar Dev Speakers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Allan Gaunt&lt;/strong&gt; - Quasar BEX Mode Lead and Senior Dev&lt;br&gt;
&lt;a href="https://github.com/webnoob" rel="noopener noreferrer"&gt;@webnoob&lt;/a&gt;&lt;br&gt;
Freelance Contractor&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr51omatypqanz1w6qksh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr51omatypqanz1w6qksh.png" title="Allan" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have you heard about Quasar's new Browser Extension (BEX) mode which helps you build Browser Extensions with Quasar? Whether you have or not, Allan will introduce you to the new mode by demonstrating a neat little BEX he built and in doing so, show you how to get the most out of the new BEX mode. If you are a Quasar aficionado, you'll probably also want this BEX installed yourself!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Paolo Caleffi&lt;/strong&gt; - Quasar TypeScript and Testing Lead and Senior Dev&lt;br&gt;
&lt;a href="https://github.com/IlCallo" rel="noopener noreferrer"&gt;@IlCallo&lt;/a&gt;&lt;br&gt;
Co-founder and CTO at &lt;a href="//www.dreamonkey.com"&gt;Dreamonkey&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjyhsjyqyjkz4qj7z71fx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjyhsjyqyjkz4qj7z71fx.png" title="Paolo" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking into working with TypeScript, Jest and Cypress without the integration hassle? Paolo will explain why those tools are important for enterprises, how you can set them up in a Quasar project quickly and more.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Jeff Gallbraith&lt;/strong&gt; - Quasar App Extension and ESLint Lead and Senior Dev&lt;br&gt;
&lt;a href="https://github.com/hawkeye64" rel="noopener noreferrer"&gt;@hawkeye64&lt;/a&gt;&lt;br&gt;
Sr. Lead Developer at Intelliview Technologies&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr2ph67ebfa4jp87ba6k5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr2ph67ebfa4jp87ba6k5.png" title="Jeff" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Did you know Quasar is very extensible? Learn to build your first Quasar Framework App Extension as Jeff goes through the topics of using the Quasar Framework UI kit to build an app extension, demonstrates the power of render functions, how to best organize your code and test your work.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Scott Molinari - Quasar Marketing and Support Lead&lt;/strong&gt;&lt;br&gt;
Business Systems and CRM Sr. Manager at Terex&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ff6beo1w8lqcqm662iefu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ff6beo1w8lqcqm662iefu.png" title="Scott" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Moderator and Organizer of Quasar.Conf&lt;/p&gt;

</description>
      <category>quasarframework</category>
      <category>vue</category>
      <category>javascript</category>
      <category>conference</category>
    </item>
    <item>
      <title>Quasar and Browser Extension Development - Getting BEXy - Part 3</title>
      <dc:creator>Scott Molinari</dc:creator>
      <pubDate>Thu, 30 Apr 2020 10:01:59 +0000</pubDate>
      <link>https://dev.to/quasar/quasar-and-browser-extension-development-getting-bexy-part-3-cfe</link>
      <guid>https://dev.to/quasar/quasar-and-browser-extension-development-getting-bexy-part-3-cfe</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;Part 3 - Building and Publishing your Extension&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q63TzOr4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/e0KeUZd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q63TzOr4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/e0KeUZd.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are coming here for the first time, please do start with &lt;strong&gt;&lt;a href="https://dev.to/quasar/quasar-and-browser-extension-development-getting-bexy-part-1-39bl"&gt;the first Part&lt;/a&gt;&lt;/strong&gt;, as it will get you started with Quasar and a BEX project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This article series has 3 parts:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://dev.to/quasar/quasar-and-browser-extension-development-getting-bexy-part-1-39bl"&gt;Part 1 - Introduction&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://dev.to/quasar/quasar-and-browser-extension-development-getting-bexy-part-2-17ea"&gt;Part 2 - Developing your Browser Extension&lt;/a&gt;&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Part 3 - Building and Publishing your Extension (&lt;em&gt;You are here now&lt;/em&gt;)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the past part of the article, we went over our Todo app and how to program it as a browser extension (BEX) with Quasar's BEX mode of development. It was just a general run-through to get you familiar with how a Quasar app and the components are needed to make a browser extension work together. &lt;/p&gt;

&lt;p&gt;Now that you have your latest and greatest app finished, it is ready to be offered to the rest of the world. To do that, it needs to be built and published. &lt;/p&gt;

&lt;h2&gt;
  
  
  Building your Project
&lt;/h2&gt;

&lt;p&gt;This is probably the easiest part of process of creating a BEX and it is all because of Quasar's great CLI. &lt;/p&gt;

&lt;p&gt;In your project's root/ working directory, simply run this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ quasar build -m bex

# ..or the longer form:
$ quasar build --mode bex
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once the build process is finished, you should see something like this in your console showing the build was successful. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x_FHZCXE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/hVPE0Ad.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x_FHZCXE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/hVPE0Ad.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to the noted output folder to get your distributable app and publish it. &lt;/p&gt;

&lt;h2&gt;
  
  
  Publishing your Project
&lt;/h2&gt;

&lt;p&gt;Ok, now that you have your project built for production and are in the newly created &lt;code&gt;dist&lt;/code&gt; folder, have a look at what is waiting for you there under the &lt;code&gt;Packaged&lt;/code&gt; folder. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0dtDWLnq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/E2GsKIH.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0dtDWLnq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/E2GsKIH.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are two zip files under their respective folders for either the &lt;strong&gt;&lt;a href="https://chrome.google.com/webstore/category/extensions"&gt;Chrome's Web Store&lt;/a&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/extensions/"&gt;Firefox Add-on Extensions Store&lt;/a&gt;&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;You can use these zip files to publish to those market places. Each market place has their own process and rules, so please do take care to learn about them. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.chrome.com/webstore/publish"&gt;&lt;strong&gt;Chrome Extension Publication&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://extensionworkshop.com/documentation/publish/"&gt;&lt;strong&gt;Firefox Extension Publication&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In theory, the browser extension you have built should work in any other Chromium based browser, however only these two are currently 100% supported. If you are interested in support for other browsers, please let us know on &lt;strong&gt;&lt;a href="https://github.com/quasarframework/quasar/issues"&gt;Github&lt;/a&gt;&lt;/strong&gt;. Better yet, become a contributor and help us develop BEX mode and the publication process for those other browsers! &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;That's it! You are off to the races as a new browser extension developer with Quasar's BEX mode. &lt;/p&gt;

&lt;p&gt;What do you think of Quasar's new BEX mode? Are you intrigued by how simple it is in the end? We hope you are. Let us know about what you are thinking in the comments below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For more Info:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://quasar.dev/"&gt;The Quasar Website &lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;&lt;a href="https://quasar.dev/quasar-cli/developing-browser-extensions/introduction"&gt;More on BEX Mode&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;&lt;a href="https://quasar.dev/icongenie/introduction"&gt;More about Icon Genie&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>browserextension</category>
      <category>vue</category>
      <category>quasar</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
