<?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: Rodrigo Ramirez</title>
    <description>The latest articles on DEV Community by Rodrigo Ramirez (@xpromx).</description>
    <link>https://dev.to/xpromx</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%2F559152%2Fa622e176-1808-432b-98f1-258f542f73b8.png</url>
      <title>DEV Community: Rodrigo Ramirez</title>
      <link>https://dev.to/xpromx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/xpromx"/>
    <language>en</language>
    <item>
      <title>How Organization Roles Change in the AI Era</title>
      <dc:creator>Rodrigo Ramirez</dc:creator>
      <pubDate>Sun, 01 Mar 2026 14:16:57 +0000</pubDate>
      <link>https://dev.to/xpromx/how-organization-roles-change-in-the-ai-era-1g2b</link>
      <guid>https://dev.to/xpromx/how-organization-roles-change-in-the-ai-era-1g2b</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%2F5ymvmfm8lvqcnt8dcyfn.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%2F5ymvmfm8lvqcnt8dcyfn.png" alt=" " width="650" height="574"&gt;&lt;/a&gt;AI changed how teams build software. But most conversations stop at the tools — which AI to use, how to prompt it, how much code it generates.&lt;/p&gt;

&lt;p&gt;AI changed how teams build software. But most conversations stop at the tools — which AI to use, how to prompt it, how much code it generates.&lt;/p&gt;

&lt;p&gt;The bigger question is different. &lt;strong&gt;How should the organization itself be structured when AI handles execution?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI compresses the execution layer. The value of "I can write code" drops. The value of "I know what to build and why" rises. If AI can generate 80% of a feature, &lt;strong&gt;the bottleneck is not typing — it is judgment.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Leadership Becomes Architecture
&lt;/h2&gt;

&lt;p&gt;When AI takes over execution, the value of leadership shifts. &lt;strong&gt;The most important work becomes making the key decisions, defining the rules, and creating the constraints that others — and AI — operate within.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is what "architect" means in this context. Not just designing structures — but deciding what gets built, how teams work, and what rules AI agents follow. Every leadership role is becoming an architect of constraints in their domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three Domains, Three Architects
&lt;/h2&gt;

&lt;p&gt;An organization needs constraints in three areas. Each one has a different owner.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Designs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Product — strategy, rules, what to build&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Manager&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Operations — tools, teams, processes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tech Architect&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;System — constraints, agents, guardrails&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;PMs are business architects.&lt;/strong&gt; They translate the company vision into detailed business rules that guide daily work. What do we build? Why? What does success look like? These decisions cannot come from AI. They require understanding the market, the customer, and the strategy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Managers are organization architects.&lt;/strong&gt; They design how the company works internally — communication norms, tools, team boundaries, what each team owns. Their job is not to supervise execution. It is to create the environment where people and AI can work well together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Technical architects design the system.&lt;/strong&gt; They define code conventions, build AI agents, set quality guardrails, and create the rules that make AI output consistent and trustable. When something goes wrong, architects improve the rules. They do not review every line — they design the system that catches problems.&lt;/p&gt;

&lt;p&gt;The common thread: &lt;strong&gt;all three design constraints for others to operate within.&lt;/strong&gt; Different domains, same function. None of them are doing the building. All of them are shaping how building happens.&lt;/p&gt;

&lt;h2&gt;
  
  
  Members — Broad Generalists with Judgment
&lt;/h2&gt;

&lt;p&gt;Members build within all three sets of rules. Business rules tell them what to build. Organization rules tell them how to work. Technical rules tell them how the system operates.&lt;/p&gt;

&lt;p&gt;AI handles the execution — writing code, generating tests, scaffolding features. &lt;strong&gt;What members need is broad knowledge and judgment.&lt;/strong&gt; The engineer who can go from customer conversation to problem framing to architecture to shipping is much more valuable than someone who only does one slice.&lt;/p&gt;

&lt;p&gt;This is a shift. Before AI, deep specialization was the most valued skill. A backend expert did not need to touch frontend. Nobody expected them to talk to customers. Now, &lt;strong&gt;specialists become architects. Members become generalists.&lt;/strong&gt; Not because depth does not matter, but because AI fills the gaps in breadth. You do not need to be an expert in React if AI can scaffold 90% of it. Enough judgment to review the output is what matters. The deep expertise lives in the architects who design the rules.&lt;/p&gt;

&lt;p&gt;Members work freely within a safe area. The architects defined the boundaries. The business rules defined the goals. The member's job is to use judgment, solve problems, and deliver — with AI as the execution engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Smaller Teams, Broader Roles
&lt;/h2&gt;

&lt;p&gt;If one engineer with AI can cover what used to take three specialists, teams shrink. Not because people were fired — but because &lt;strong&gt;fewer people carry more responsibility.&lt;/strong&gt; Same output, fewer humans, each one operating more like a product-engineer hybrid.&lt;/p&gt;

&lt;p&gt;The dedicated PM role shrinks. The function — business decisions, strategy, understanding the customer — does not disappear. It gets absorbed by engineers. In small teams, the person who builds also decides what to build. In larger organizations, a dedicated PM still makes sense. But even there, the wall between "person who decides" and "person who builds" gets thinner. Engineers are expected to have opinions about the business — not just take tickets.&lt;/p&gt;

&lt;p&gt;Management changes too. A team of three does not need a full-time people manager. &lt;strong&gt;The role becomes more like a player-coach&lt;/strong&gt; — someone who mostly builds but also coordinates. Less oversight, more contribution.&lt;/p&gt;

&lt;p&gt;The risk is resistance. Some engineers want to stay in the "give me a well-defined ticket" mode. In teams optimizing for AI, that mindset becomes hard to justify. &lt;strong&gt;The engineers who thrive treat AI as a way to expand their scope&lt;/strong&gt; — not just to write code faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Junior Problem Is Real
&lt;/h2&gt;

&lt;p&gt;Juniors are struggling in this new structure. Not because AI is hard to use — but because &lt;strong&gt;AI removed the execution work they used to learn through.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before AI, juniors learned by writing code. They built intuition through repetition — debugging, refactoring, seeing patterns. Now AI handles most of that work. The skills juniors need earlier are the ones that used to come with experience: decision-making, judgment, problem evaluation.&lt;/p&gt;

&lt;p&gt;Architects can help. &lt;strong&gt;Good guardrails create a safer space for juniors to operate.&lt;/strong&gt; Clear rules, defined conventions, and automated quality checks let a junior produce work that meets the baseline. But judgment is still human. The guardrails reduce the risk — they do not replace the learning.&lt;/p&gt;

&lt;p&gt;Training must change. Organizations cannot wait for juniors to accumulate years of experience before they make decisions. &lt;strong&gt;Decision-making and problem-solving must be taught earlier and more deliberately.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Helps You Think — But Does Not Decide for You
&lt;/h2&gt;

&lt;p&gt;AI is more than an execution tool. It can research, propose ideas, surface options, and challenge assumptions. &lt;strong&gt;AI is a powerful thinking partner.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But there is a line. AI can present three approaches to a problem. It can analyze tradeoffs. It can find information faster than any human. &lt;strong&gt;The decision about which option fits your business, your team, your situation — that stays human.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This applies to every role. Architects use AI to explore constraints before defining them. Members use AI to evaluate options before choosing one. PMs use AI to research before setting strategy. In every case, &lt;strong&gt;AI expands what you can consider. The judgment about what to do is yours.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The human who approved the work carries the consequences. AI does not.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Shift
&lt;/h2&gt;

&lt;p&gt;AI did not change what organizations need. It changed where the value sits. Execution is cheap now. &lt;strong&gt;Judgment, constraints, and clarity about who decides what — that is the new bottleneck.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The organizations that get this right will move faster with fewer people. Not because AI replaced anyone — but because the structure made every person and every tool more effective.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>development</category>
    </item>
    <item>
      <title>Software Development in the AI era</title>
      <dc:creator>Rodrigo Ramirez</dc:creator>
      <pubDate>Wed, 17 Dec 2025 02:53:23 +0000</pubDate>
      <link>https://dev.to/xpromx/software-development-in-the-ai-era-3n3k</link>
      <guid>https://dev.to/xpromx/software-development-in-the-ai-era-3n3k</guid>
      <description>&lt;p&gt;Many teams using AI ship more code. Not all of them are shipping better software.&lt;/p&gt;

&lt;p&gt;I'm writing this based on what I've seen in real teams adopting AI in production. Look at the metrics — cycle time, velocity, features delivered. If AI can generate most of the code, you might expect teams to be three or four times faster. Often, they're not. The improvement can be smaller than expected.&lt;/p&gt;

&lt;p&gt;In my view, the tools aren't the limiting factor. The system around them is.&lt;/p&gt;

&lt;p&gt;AI accelerates one part of the process: writing code. But software development is more than writing code. It's requirements, architecture, testing, reviews, QA, and release. These parts are interconnected. When only one part speeds up, the system doesn't improve much. Bottlenecks shift to the parts that weren't designed for this speed.&lt;/p&gt;

&lt;p&gt;Engineers generate more code. But someone needs to review it, and that person needs context to judge correctness. QA can get overloaded. When requirements aren't clear enough, the AI builds the wrong thing. Teams iterate more, but progress can stay flat.&lt;/p&gt;

&lt;p&gt;One pattern I've seen: a team doubles their PR volume after adopting AI. But review capacity stays the same. PRs queue up. Reviewers skim instead of reading. Bugs slip through. The team feels faster, but defect rates climb and cycle time doesn't improve. The bottleneck just moved.&lt;/p&gt;

&lt;p&gt;The solution isn't to slow down AI adoption. It's to use AI across the workflow — but only where the system can safely validate the output. AI can assist with reviews, generate tests, clarify requirements, and automate QA. But for that to work, the system around it must change.&lt;/p&gt;

&lt;p&gt;This post explores &lt;strong&gt;which parts of software development need to change&lt;/strong&gt; to really benefit from AI code agents.&lt;/p&gt;




&lt;h2&gt;
  
  
  The big shift: code is cheap, trust is expensive
&lt;/h2&gt;

&lt;p&gt;AI code agents changed the cost structure of software development.&lt;/p&gt;

&lt;p&gt;Before AI, writing code was the slow and expensive part. Most processes were designed to protect that cost — long reviews, heavy planning upfront, clear separation of roles, manual testing at the end.&lt;/p&gt;

&lt;p&gt;Now this assumption is broken. AI can generate working code very quickly. Creating code is no longer the bottleneck.&lt;/p&gt;

&lt;p&gt;But this does &lt;strong&gt;not&lt;/strong&gt; mean software is easier to build.&lt;/p&gt;

&lt;p&gt;What became expensive is something else: understanding what changed, knowing if the change is correct, knowing if it's safe to deploy, knowing if it will break something later. In other words, &lt;strong&gt;trust&lt;/strong&gt; became the expensive part.&lt;/p&gt;

&lt;p&gt;Teams still own the consequences of changes. Bugs in production. Security issues. Performance regressions. Hard-to-maintain systems. AI doesn't take that responsibility.&lt;/p&gt;

&lt;p&gt;This creates a mismatch.&lt;/p&gt;

&lt;p&gt;One part of the system — code generation — is now very fast. Other parts — review, testing, validation, release — are still slow and human-limited.&lt;/p&gt;

&lt;p&gt;When this happens, teams feel the pain. Pull requests pile up. Reviews become shallow because reviewers lack context. Bugs slip into production. More activity, same output.&lt;/p&gt;

&lt;p&gt;This is why many teams don't see a big improvement in quality, stability, or features delivered per engineer. The system was optimized for a world where &lt;strong&gt;writing code was the hard part&lt;/strong&gt;. In the AI era, the hard part is different.&lt;/p&gt;

&lt;p&gt;Engineering work is shifting from &lt;strong&gt;writing code&lt;/strong&gt; to &lt;strong&gt;creating trust in changes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This trust doesn't come from the AI model. It comes from architecture that limits impact, tests that define what must be true, reviews that focus on intent and risk, and processes that catch problems early. If these parts don't change, faster code generation only creates faster bottlenecks.&lt;/p&gt;

&lt;p&gt;This shift is the foundation for everything else in this post.&lt;/p&gt;




&lt;h2&gt;
  
  
  Codebases: consistency matters more than speed
&lt;/h2&gt;

&lt;p&gt;When AI generates code faster than humans can review it, the main risk is no longer speed. The real risk is &lt;strong&gt;losing coherence&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A codebase is not just a collection of files. It's a shared mental model. When changes are slow, teams can rely on memory, informal knowledge, and manual coordination. When changes are fast, that stops working.&lt;/p&gt;

&lt;p&gt;In the AI era, a codebase must help humans answer one question quickly: &lt;strong&gt;"What does this change affect?"&lt;/strong&gt; If that answer is unclear, trust breaks down.&lt;/p&gt;

&lt;h3&gt;
  
  
  Change must be easy to understand
&lt;/h3&gt;

&lt;p&gt;Fast code generation increases the volume of change. If each change is hard to understand, the system becomes fragile.&lt;/p&gt;

&lt;p&gt;The priority is not writing clever code, maximizing reuse, or reducing lines of code. The priority is clarity of responsibility, clear boundaries, and predictable behavior. A good codebase makes it obvious where logic lives, why it exists, what depends on it, and what doesn't.&lt;/p&gt;

&lt;p&gt;When this is true, reviews are faster and safer — even when AI generates most of the code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local reasoning becomes essential
&lt;/h3&gt;

&lt;p&gt;Humans have limited attention.&lt;/p&gt;

&lt;p&gt;If understanding a small change requires understanding the whole system, AI won't help. It will only accelerate confusion.&lt;/p&gt;

&lt;p&gt;Modern codebases must support &lt;strong&gt;local reasoning&lt;/strong&gt;: you can understand a change by looking at a small part, you don't need global context for every decision, and side effects are controlled and visible. This isn't a tooling problem. It's a design problem.&lt;/p&gt;

&lt;p&gt;Before AI, this was a best practice. Now it's a survival requirement. Engineers used to keep context in their heads because changes were slow enough to remember. Now AI generates code faster than humans can track. The only way to stay in control is to build systems where you don't need to remember everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consistent patterns build trust
&lt;/h3&gt;

&lt;p&gt;You can't make external APIs or distributed systems predictable. But you can control how your code responds to unpredictability — retry patterns, rollbacks, logging, timeouts, error handling. These should be consistent rules in a shared framework, not left to individual judgment.&lt;/p&gt;

&lt;p&gt;When every engineer (and every AI) follows the same patterns for handling failures, the system becomes easier to trust, test, and review. The goal isn't to eliminate unpredictability — it's to make your response to it consistent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structure is a safety mechanism
&lt;/h3&gt;

&lt;p&gt;Structure is not about elegance. In the AI era, structure is a &lt;strong&gt;safety mechanism&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It exists to ensure that faster change doesn't reduce quality, more output doesn't reduce understanding, and automation doesn't remove human control. If the system doesn't protect coherence, AI will expose that weakness very quickly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Testing &amp;amp; QA: defining trust, not finding bugs
&lt;/h2&gt;

&lt;p&gt;When code becomes cheap, testing becomes more important — not less.&lt;/p&gt;

&lt;p&gt;AI makes it easy to generate code, but it also makes it easy to introduce changes that &lt;em&gt;look correct&lt;/em&gt; and still break important behavior. This is why testing and QA change role in the AI era. The goal is no longer mainly to find bugs. The goal is to &lt;strong&gt;define what it means for the system to be correct&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tests as shared truth
&lt;/h3&gt;

&lt;p&gt;In fast-moving systems, people can't rely on memory or manual checks.&lt;/p&gt;

&lt;p&gt;Tests become the most reliable description of system behavior — the place where assumptions are made explicit, the contract between past and future changes. When AI generates code, tests are what allow humans to say "this change is safe," "this behavior is intentional," and "this must never break."&lt;/p&gt;

&lt;p&gt;Without strong tests, faster code generation only increases uncertainty.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quality moves earlier, by necessity
&lt;/h3&gt;

&lt;p&gt;If validation happens late, AI creates pressure. More changes arrive faster. Reviews pile up. Manual QA becomes overloaded. Issues slip into production.&lt;/p&gt;

&lt;p&gt;So quality must move earlier in the process. Not because it's fashionable, but because it's the only way the system can scale. Correctness gets checked close to where changes are made. Feedback is fast. Errors are cheap to fix. When this doesn't happen, teams feel busy but unsafe.&lt;/p&gt;

&lt;h3&gt;
  
  
  QA designs, AI executes
&lt;/h3&gt;

&lt;p&gt;In this context, QA is less about execution and more about &lt;strong&gt;designing safety&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The shift is concrete: QA moves from clicking through pages to find bugs, to defining what should be tested. QA identifies risk areas, creates rules about what makes the system safe, designs end-to-end test scenarios, and specifies what's important to check. Then AI generates the test code, writes the automation, and executes the checks.&lt;/p&gt;

&lt;p&gt;AI can help generate tests, but it can't decide what's critical, what's acceptable to break, or what trade-offs the business allows. Those decisions remain human. The hours are spent differently — designing rules versus executing manual checks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Trust comes from systems, not heroics
&lt;/h3&gt;

&lt;p&gt;In slower environments, teams can rely on manual testing, individual expertise, and last-minute checks. In fast AI-assisted systems, this doesn't scale.&lt;/p&gt;

&lt;p&gt;Trust must come from clear definitions of correctness, automated validation, consistent signals, and repeatable processes. If trust depends on "someone checking carefully," the system will fail under speed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Product and context: clarity becomes the main input
&lt;/h2&gt;

&lt;p&gt;When AI generates code, the quality of the output depends heavily on the quality of the input.&lt;/p&gt;

&lt;p&gt;In traditional development, unclear requirements created friction, but teams could compensate with meetings, back-and-forth, and manual adjustments over time. In AI-assisted development, this compensation doesn't scale. Fast code generation amplifies unclear thinking.&lt;/p&gt;

&lt;h3&gt;
  
  
  Context replaces instructions
&lt;/h3&gt;

&lt;p&gt;AI doesn't understand intent unless it's made explicit.&lt;/p&gt;

&lt;p&gt;The most important input to the system is no longer tasks, tickets, or step-by-step instructions. It's &lt;strong&gt;context&lt;/strong&gt; — why this exists, what problem it solves, what constraints matter, what must not change, and what success looks like. Without context, AI produces code that's technically correct but conceptually wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  Product work moves closer to engineering
&lt;/h3&gt;

&lt;p&gt;This changes how product and engineering interact.&lt;/p&gt;

&lt;p&gt;The work is less about handing over requirements, translating documents, or defining every step upfront. It's more about shaping understanding early, defining boundaries, aligning on intent, and making trade-offs explicit.&lt;/p&gt;

&lt;p&gt;Product and engineering collaborate earlier. Engineers participate more in definition. The gap between "deciding" and "building" becomes smaller.&lt;/p&gt;

&lt;h3&gt;
  
  
  Context is a scalability problem
&lt;/h3&gt;

&lt;p&gt;When teams are small and slow, context can live in people's heads. When teams move fast, this breaks.&lt;/p&gt;

&lt;p&gt;AI increases speed, which means implicit knowledge becomes dangerous, undocumented assumptions cause failures, and misunderstandings scale quickly. This is why &lt;strong&gt;clear context becomes a core engineering concern&lt;/strong&gt;, not only a product one.&lt;/p&gt;

&lt;p&gt;If context is weak, reviews become harder, tests are incomplete, and trust decreases. If context is strong, AI output improves, reviews focus on real risks, and teams move faster with confidence.&lt;/p&gt;

&lt;h3&gt;
  
  
  Think small, iterate fast
&lt;/h3&gt;

&lt;p&gt;Big projects with detailed upfront specs don't work well in the AI era. Instead: think small, prototype quickly, get feedback faster. Since code is cheap, tries are cheap. But cheap tries only help if the team can validate and decide quickly. A/B testing, small releases, rapid iteration — this is how many high-performing teams work now.&lt;/p&gt;

&lt;p&gt;But to iterate quickly and safely, you need to know the impact of each change. That requires clear boundaries, good tests, and fast feedback. Safety mechanisms enable speed, not slow it down.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing less, explaining better
&lt;/h3&gt;

&lt;p&gt;This doesn't mean more documents. It means better signals — clear acceptance criteria, examples over abstractions, explicit constraints, and visible non-goals.&lt;/p&gt;

&lt;p&gt;The system works best when humans focus on &lt;strong&gt;making intent clear&lt;/strong&gt;, and AI focuses on &lt;strong&gt;executing within that intent&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Team shape: smaller teams, higher responsibility
&lt;/h2&gt;

&lt;p&gt;When AI increases individual leverage, team structure must change.&lt;/p&gt;

&lt;p&gt;One engineer can now move faster and cover more ground. This reduces some coordination costs, but it also concentrates responsibility. Adding more people doesn't always help. Sometimes it makes trust harder.&lt;/p&gt;

&lt;h3&gt;
  
  
  Speed changes the failure mode
&lt;/h3&gt;

&lt;p&gt;In slower systems, problems are visible early — delays, blocked tasks, long feedback loops. In fast systems, failures look different. Many changes happen at once. Issues appear later. Responsibility is unclear. Debugging becomes expensive.&lt;/p&gt;

&lt;p&gt;This is why team shape matters more when speed increases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Smaller teams need clearer ownership
&lt;/h3&gt;

&lt;p&gt;When fewer people can deliver more, ownership must be explicit.&lt;/p&gt;

&lt;p&gt;A healthy AI-era team knows what it owns and what it doesn't. It understands the consequences of its changes. It feels responsible for outcomes, not only tasks. Without clear ownership, faster execution creates confusion, not progress.&lt;/p&gt;

&lt;h3&gt;
  
  
  Responsibility moves closer to the work
&lt;/h3&gt;

&lt;p&gt;AI reduces the need for handoffs — waiting for another role, depending on specialists for every step, pushing work downstream. But this also means decisions happen closer to code. Mistakes happen closer to code. Learning happens closer to code.&lt;/p&gt;

&lt;p&gt;Teams that succeed accept this trade-off. They invest in safety mechanisms, fast feedback, clear boundaries, and shared understanding.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI assists both sides
&lt;/h3&gt;

&lt;p&gt;If AI only generates code, smaller teams face a bottleneck: who reviews all this output? The answer is that AI assists review too — checking code against rules, summarizing changes, flagging risks, ensuring consistency.&lt;/p&gt;

&lt;p&gt;Humans don't need to review every line. They decide what to focus on, what risks matter, and whether the intent is correct. AI handles volume; humans handle judgment. This is how fewer people can oversee more output without sacrificing quality.&lt;/p&gt;

&lt;h3&gt;
  
  
  Trust must scale with speed
&lt;/h3&gt;

&lt;p&gt;In high-speed teams, trust can't depend on individuals. It must come from the system — tests, clear ownership, visible signals, and predictable processes.&lt;/p&gt;

&lt;p&gt;If trust depends on heroics, the team will break as speed increases.&lt;/p&gt;




&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;AI doesn't remove engineering work. It changes where the hard work is.&lt;/p&gt;

&lt;p&gt;Writing code is no longer the constraint. Requirements, reviews, QA, and release processes are. Some teams have already adapted — they redesigned their system around clarity, fast feedback, and explicit responsibility. For them, AI is delivering real improvements. For others, the gains are smaller because only one part of the process changed.&lt;/p&gt;

&lt;p&gt;This isn't a universal failure story. It's an explanation of why outcomes vary, and what separates the teams that benefit from those still waiting for the payoff.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>development</category>
      <category>aiops</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Database, Table and Column naming conventions</title>
      <dc:creator>Rodrigo Ramirez</dc:creator>
      <pubDate>Sat, 03 Apr 2021 09:47:23 +0000</pubDate>
      <link>https://dev.to/xpromx/database-table-and-column-naming-conventions-63f</link>
      <guid>https://dev.to/xpromx/database-table-and-column-naming-conventions-63f</guid>
      <description>&lt;p&gt;A naming conversion is a set of rules you should follow to increase your data models' readability.&lt;/p&gt;

&lt;p&gt;In this post, we will talk about the best practice I have found and followed along on my career as a developer (PHP, Node.JS, MySQL, PostgreSQL) and the reasons for each one of them.&lt;/p&gt;

&lt;p&gt;In the end, it's not important which one you follow, but you should follow a naming convention.&lt;/p&gt;




&lt;h2&gt;
  
  
  Table Name
&lt;/h2&gt;

&lt;p&gt;You should use singular nouns for database table names.&lt;/p&gt;

&lt;p&gt;If you have a table to store the users data, this table should be called &lt;code&gt;user&lt;/code&gt; Or &lt;code&gt;users&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Let's analyze both cases to understand the difference between each approach.&lt;/p&gt;

&lt;h4&gt;
  
  
  Plural
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Clear that the table is storing more than one user.&lt;/li&gt;
&lt;li&gt;It reads well in the &lt;code&gt;FROM&lt;/code&gt; clause
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Singular
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;We are not naming a table, we are naming a relation.&lt;/li&gt;
&lt;li&gt;It reads well everywhere else in the SQL query:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;countryId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"Japan"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;It would make less sense if the &lt;code&gt;ON&lt;/code&gt; Clause read &lt;code&gt;users.country_id&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;If you are using an ORM, the class you will store your data is already in singular &lt;code&gt;User&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frsd9ka1zd3upeim1uper.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%2Frsd9ka1zd3upeim1uper.png" alt="Alt Text" width="800" height="182"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Column Name
&lt;/h2&gt;

&lt;p&gt;You should use camelCase for your column names, specially for Node.JS.&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%2Frxsj6png7c3v7fqjuu1a.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%2Frxsj6png7c3v7fqjuu1a.png" alt="Alt Text" width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Snake Case &lt;code&gt;snake_case&lt;/code&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;SQL standards are case insensitive&lt;/li&gt;
&lt;li&gt;Readability is better&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Camel  Case &lt;code&gt;camelCase&lt;/code&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;It's better for data mapping. for a JSON object property &lt;code&gt;user.firstName&lt;/code&gt; is better than &lt;code&gt;user.first_name&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Specially for Javascript standards, &lt;a href="https://www.w3schools.com/js/js_conventions.asp#:~:text=camelCase%3A,with%20many%20JavaScript%20library%20names." rel="noopener noreferrer"&gt;camelCase is recommended&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Faster typing avoiding the _&lt;/li&gt;
&lt;li&gt;Better Readability for short worlds&lt;/li&gt;
&lt;li&gt;Bad Readability for long words

&lt;ul&gt;
&lt;li&gt;githubAccessToken&lt;/li&gt;
&lt;li&gt;facebookAccessToken&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Fields
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Date Fields
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Include the timezone, specially if you are working on a global project.&lt;/li&gt;
&lt;li&gt;As a good practice all  tables should have a &lt;code&gt;createdAt&lt;/code&gt; and &lt;code&gt;updatedAt&lt;/code&gt; column, it will be very useful for debugging.&lt;/li&gt;
&lt;li&gt;Field should finish with &lt;code&gt;At&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;createdAt&lt;/li&gt;
&lt;li&gt;updatedAt&lt;/li&gt;
&lt;li&gt;deletedAt&lt;/li&gt;
&lt;li&gt;lastUpdatedAt&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  Primary Key
&lt;/h4&gt;

&lt;p&gt;Column name must be always named &lt;code&gt;id&lt;/code&gt;.&lt;br&gt;
It's short, simple and you don't have to remember the names of the fields to join tables.&lt;/p&gt;

&lt;h4&gt;
  
  
  Foreign Keys
&lt;/h4&gt;

&lt;p&gt;They should be a combination of the name of the foreign table and the + &lt;code&gt;_id&lt;/code&gt;, examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;user_id&lt;/li&gt;
&lt;li&gt;post_id&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Status Fields
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;use booleans for single status.

&lt;ul&gt;
&lt;li&gt;isActive&lt;/li&gt;
&lt;li&gt;isPublished&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Use enums if you need few columns that can be true or false at the same time.

&lt;ul&gt;
&lt;li&gt;post.status (draft, inactive, published)&lt;/li&gt;
&lt;li&gt;user.status (inactive, active, banned)&lt;/li&gt;
&lt;li&gt;product.status (draft, in_review, approved, disapproved)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Tools
&lt;/h2&gt;

&lt;p&gt;Here are two tools I recommend to design your database schemas. I like them because their UI/UX is good, and I really enjoy using them.&lt;/p&gt;

&lt;h4&gt;
  
  
  DB diagram
&lt;/h4&gt;

&lt;p&gt;A free, simple tool to draw ER diagrams by just writing code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dbdiagram.io/" rel="noopener noreferrer"&gt;https://dbdiagram.io&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FREE&lt;/li&gt;
&lt;li&gt;Online service&lt;/li&gt;
&lt;li&gt;Create your DB diagrams by writing&lt;/li&gt;
&lt;li&gt;One click sharing&lt;/li&gt;
&lt;li&gt;Export to Images and PDF&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  SQLEditor
&lt;/h4&gt;

&lt;p&gt;Makes database design easier than ever!&lt;br&gt;
&lt;a href="https://www.malcolmhardie.com/sqleditor/" rel="noopener noreferrer"&gt;https://www.malcolmhardie.com/sqleditor/&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FREE (for 30 days, but you can continue using)&lt;/li&gt;
&lt;li&gt;Paid ($80 single user license)&lt;/li&gt;
&lt;li&gt;Mac app&lt;/li&gt;
&lt;li&gt;Great usability&lt;/li&gt;
&lt;li&gt;Fast&lt;/li&gt;
&lt;li&gt;Export to Images and PDFs&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>node</category>
      <category>php</category>
      <category>javascript</category>
      <category>database</category>
    </item>
    <item>
      <title>Image Optimization, Processing and Hosting</title>
      <dc:creator>Rodrigo Ramirez</dc:creator>
      <pubDate>Wed, 17 Feb 2021 06:30:37 +0000</pubDate>
      <link>https://dev.to/xpromx/image-optimization-processing-and-hosting-2fl6</link>
      <guid>https://dev.to/xpromx/image-optimization-processing-and-hosting-2fl6</guid>
      <description>&lt;p&gt;Hosting images and processing them is quite complicated. It involves many elements to do this correctly and to be sure it scales with your website.&lt;/p&gt;

&lt;p&gt;Hosting images requires 3 key elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A place to &lt;strong&gt;Storage&lt;/strong&gt; your images&lt;/li&gt;
&lt;li&gt;A way to &lt;strong&gt;Resize&lt;/strong&gt; the images on demand&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;CDN&lt;/strong&gt; to cache and deliver the images to your users as fast as possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can achieve this by implementing your own solution or delegating all the complexity to a third party service like AWS or Cloudinary.&lt;/p&gt;

&lt;p&gt;Let's analyze each one of these elements and their costs and by the end of this post, you will be able to decide which way is right for your project.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Storage&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A place to host the images uploaded by your users. It could be in your own server or using a third-party service like Amazon S3 or Cloudinary. In each case, you will need to consider the cost of hosting the images, and It depends on the amount and traffic you expect to receive to calculate the final price.&lt;/p&gt;

&lt;p&gt;Here is a simple comparison of storage prices without considering the bandwidth.&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%2Fwy7o6wl3y36mvyp6xjc4.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%2Fwy7o6wl3y36mvyp6xjc4.png" alt="Alt Text" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Cheapest Doplet with at least 5GB free for OS+others.&lt;/li&gt;
&lt;li&gt;Up to 50GB is a good option to keep the files on the same server. After that, the prices increase dramatically for storage. It would be better to consider Digital Ocean Spaces at that point.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Amazon S3:&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only S3 storage.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;All in one solution. Difficult to compare individually.&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%2Fgn9cp14cp3ucivgleowu.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%2Fgn9cp14cp3ucivgleowu.png" alt="Alt Text" width="800" height="206"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Image Resizing
&lt;/h2&gt;

&lt;p&gt;After we receive the user's image, you will need to display a resized version on your website. We don't want to make users download a big size image when browsing our website, especially from their mobile devices. Speed is important for UX and SEO purposes.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Resizing Strategies&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;At Upload time&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After we store the user's image, you will need to create the resized versions of the original picture. It will require you to know in advance which dimensions are necessary for your website. If later you require a new size, you will need to regenerate all the previous pictures again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On Demand&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Recommended solutions, but more complex to implement by yourself. &lt;br&gt;
Instead of calling your images directly, you will request them from a special URL that generates the new image, passing in the URL the new size parameters. Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://domain.com/image-resize?source={local-path}&amp;amp;width=500&amp;amp;height=500
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Implementations
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Own Solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The cost, in this case, is the development time and the maintenance of the code.&lt;/p&gt;

&lt;p&gt;If you opt to resize the images at the upload time, you will need to consider doing the resizing in the background to don't make your users wait while you are processing the images.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AWS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With AWS, you will have to create a serverless function that triggers when a new image is uploaded to the S3 bucket or create a URL to execute it on demand and generate the resized images.&lt;/p&gt;

&lt;p&gt;Likely there is a solution provided by amazon that simplifies all these processes and much more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Serverless Image Handler
&lt;a href="https://aws.amazon.com/solutions/implementations/serverless-image-handler/" rel="noopener noreferrer"&gt;https://aws.amazon.com/solutions/implementations/serverless-image-handler/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cloudinary&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cloudinary includes all these features in their service. But the price is very tricky, be sure to check them very carefully.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloudinary Pricing
&lt;a href="https://cloudinary.com/pricing" rel="noopener noreferrer"&gt;https://cloudinary.com/pricing&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5rprsk9p4q8y8afrbbpi.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%2F5rprsk9p4q8y8afrbbpi.png" alt="Alt Text" width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;CDN&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Having a CDN between where your images are hosted and your users is a good practice. It will speed up your website by serving the images to your users from their closes location. If you are using a service to host your images, it probably already includes a CDN.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloudflare&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Suppose you are hosting the images on your own server. In that case, Cloudflare is the best solution for you, they have a free version, and It not only provides a CDN for your images, but It also does for your entire website as well that offers a security layer between your user and your server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.cloudflare.com/" rel="noopener noreferrer"&gt;https://www.cloudflare.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AWS Cloudfront&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;CDN solution from AWS. Very easy to connect with an existing S3 bucket. If you are using the "Serverless Image Handler" solution from AWS, It already includes Cloudfront.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/cloudfront/" rel="noopener noreferrer"&gt;https://aws.amazon.com/cloudfront/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloudinary&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Already provide a CDN by default.&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%2F7p2e9m2m12zkcfvjimeu.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%2F7p2e9m2m12zkcfvjimeu.png" alt="Alt Text" width="800" height="212"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Here we have the summary of the 3 solutions I have mentioned in this post.&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%2Fv6er4x5zcir5eghfsdld.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%2Fv6er4x5zcir5eghfsdld.png" alt="Alt Text" width="800" height="211"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;DigitalOcean / Own Server&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ Good up to 50GB of storage&lt;/p&gt;

&lt;p&gt;✅ Fixed cost&lt;/p&gt;

&lt;p&gt;✅ Cloudflare for CDN and Security&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❌ Image processing requires your own implementation&lt;/p&gt;

&lt;p&gt;❌ If you need more than 50GB, you will need to consider another alternative.&lt;/p&gt;




&lt;h3&gt;
  
  
  AWS
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ Amazon S3 is very cheap&lt;/p&gt;

&lt;p&gt;✅ A popular option for developers to storage files&lt;/p&gt;

&lt;p&gt;✅ Cloudfront for CDN&lt;/p&gt;

&lt;p&gt;✅ Image Server Handler solution from AWS simplifies everything&lt;/p&gt;

&lt;p&gt;✅ It scales infinite, and the prices are low&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❌ No free options, but very cheap&lt;/p&gt;

&lt;p&gt;❌ You will need to understand the basic of AWS&lt;/p&gt;




&lt;h3&gt;
  
  
  Cloudinary
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ Free up to 25GB = 25 credits&lt;/p&gt;

&lt;p&gt;✅ Simples options&lt;/p&gt;

&lt;p&gt;✅ All in one solution&lt;/p&gt;

&lt;p&gt;✅ Extra features (Widgets, Video Hosting, etc.)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❌ It could get costly&lt;/p&gt;

&lt;p&gt;❌ To have a copy of your files, you will need to pay at least $99 monthl&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>aws</category>
      <category>devops</category>
    </item>
    <item>
      <title>GraphQL Schema Best Practices</title>
      <dc:creator>Rodrigo Ramirez</dc:creator>
      <pubDate>Mon, 08 Feb 2021 07:19:13 +0000</pubDate>
      <link>https://dev.to/xpromx/graphql-schema-best-practices-1lbg</link>
      <guid>https://dev.to/xpromx/graphql-schema-best-practices-1lbg</guid>
      <description>&lt;p&gt;Are you creating or managing GraphQL schemas, but you don't know the best practice for creating maintainable schemas that your team or even you can follow to gain confidence in your project?&lt;/p&gt;

&lt;p&gt;In this post, I will explain the best practice I have found by creating high maintainable GraphQL Schemas for the projects I'm working on.&lt;/p&gt;

&lt;h3&gt;
  
  
  General Advice
&lt;/h3&gt;

&lt;p&gt;When designing your GraphQL schema, one of the common mistakes is to replicate your database tables and fields.&lt;/p&gt;

&lt;p&gt;Think in the GraphQL Schema DX (Developer Experience); you want to simplify the use of your schema for your team.&lt;/p&gt;

&lt;p&gt;My advice here will be to create your Schema in the exact way that you need to consume them. Avoid adding fields that you will not need to use or overcomplicate to get the information for your UI.&lt;/p&gt;

&lt;p&gt;Start with the minimum and expand them as you need. Taking too many decisions in advance could lead to feature problems and force you to refactor the code.&lt;/p&gt;




&lt;h3&gt;
  
  
  Naming Fields
&lt;/h3&gt;

&lt;p&gt;Naming fields are very important because they can impact future schema changes; being very explicit early on will make things easier in the future.&lt;/p&gt;

&lt;p&gt;❌ Bad example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;visits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Good example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ProductStats&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;just&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visitsCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ProductStats&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;visitsCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;purchasesCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ImageSize&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ImageSize&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;XS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;SM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;MD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;LG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;ORIGINAL&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Queries
&lt;/h2&gt;

&lt;p&gt;Avoid writing queries named like &lt;code&gt;getProduct&lt;/code&gt; or &lt;code&gt;getAllProducts&lt;/code&gt; These queries will always return something. I consider starting with the word &lt;strong&gt;get&lt;/strong&gt; is redundant and makes your schema difficult to read.&lt;/p&gt;

&lt;p&gt;Don't force your queries to do more than one thing, instead create different queries that are self-explanatory.&lt;/p&gt;

&lt;p&gt;❌ Bad query examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;getProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Good query examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;productById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;productBySlug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Pagination
&lt;/h2&gt;

&lt;p&gt;Returning multiple results in GraphQL could end in a very complicated schema design, but you can opt for a simple solution depending on your project.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Offset Pagination&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Best for page based paginations, users can jump to a specific page. This option may be the right fit for most of the cases. If you are using an ORM it would be easy to implement.&lt;/p&gt;

&lt;p&gt;But It has some disadvantages if your data change often; some results could be potentially skipped or returned duplicated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ProductFilters&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ProductConnection&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ProductConnection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;!]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;pageInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PageInfo&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;totalCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PageInfo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;hasNextPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;hasPreviousPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;currentPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;perPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;lastPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Cursor Pagination (Relay way)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Best for infinite scroll or Load more results. (Facebook, Airbnb uses this style), In this solution, there is no concept of pages.&lt;/p&gt;

&lt;p&gt;This one will scale well for large datasets, but it's the most complicated to implement. With this style, you can prevent the problems of offset pagination.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;after&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;before&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
 &lt;/span&gt;&lt;span class="n"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ProductFilters&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ProductConnection&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ProductConnection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;edges&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ProductEdges&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;pageInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PageInfo&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;totalCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ProductEdges&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PageInfo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;hasNextPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;hasPreviousPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;startCursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;endCursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Related links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://relay.dev/graphql/connections.htm" rel="noopener noreferrer"&gt;https://relay.dev/graphql/connections.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/graphql/graphql-relay-js/issues/94#issuecomment-232410564" rel="noopener noreferrer"&gt;https://github.com/graphql/graphql-relay-js/issues/94#issuecomment-232410564&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.apollographql.com/blog/understanding-pagination-rest-graphql-and-relay-b10f835549e7/" rel="noopener noreferrer"&gt;https://www.apollographql.com/blog/understanding-pagination-rest-graphql-and-relay-b10f835549e7/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Filters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The convention I use here is uppercase for the filters and allowing always to pass an array of IDs to make the filters more flexible. Remember to keep only the filters that you need.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ProductFilters&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ProductConnection&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ProductFilters&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;PRODUCT_IDS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;EXCLUDE_PRODUCTS_IDS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;CATEGORY_IDS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;ORDER_BY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ProductOrderBy&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;SEARCH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ProductOrderBy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;CREATED_AT_ASC&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;CREATED_AT_DESC&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;RANKING_ASC&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;RANKING_DESC&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Mutations
&lt;/h2&gt;

&lt;p&gt;We can summarise the mutation naming conventions into 5 rules&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Mutation are named as verbs &lt;code&gt;CreateProduct&lt;/code&gt; , &lt;code&gt;UpdateProduct&lt;/code&gt; , &lt;code&gt;DeleteProduct&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;There must be a single argument input&lt;/li&gt;
&lt;li&gt;The input type name is the capitalised mutation name with a &lt;code&gt;Input&lt;/code&gt; postfix e.g &lt;code&gt;CreateProductInput&lt;/code&gt; , &lt;code&gt;UpdateProductInput&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The returned value is a new custom type that can contain various fields.&lt;/li&gt;
&lt;li&gt;The return type name is the capitalized mutation name with a &lt;code&gt;Payload&lt;/code&gt; postfix e.g. &lt;code&gt;CreateProductPayload&lt;/code&gt; , &lt;code&gt;UpdateProductPayload&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;CreateProduct&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;CreateProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CreateProductInput&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CreateProductPayload&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CreateProductInput&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;categoryId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CreateProductPayload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;UpdateProduct&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;UpdateProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UpdateProductInput&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UpdateProductPayload&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UpdateProductInput&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;categoryId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UpdateProductPayload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;DeleteProduct&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;DeleteProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DeleteProductPayload&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DeleteProductPayload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="n"&gt;isDeleted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;These best practices are what worked for me, and I hope they are useful for you.&lt;/p&gt;

&lt;p&gt;Just remember to make your schema self-explanatory, even if it requires you to add more queries or mutations.&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>Moving from PHP to NodeJS</title>
      <dc:creator>Rodrigo Ramirez</dc:creator>
      <pubDate>Tue, 02 Feb 2021 07:30:04 +0000</pubDate>
      <link>https://dev.to/xpromx/moving-from-php-to-nodejs-54mb</link>
      <guid>https://dev.to/xpromx/moving-from-php-to-nodejs-54mb</guid>
      <description>&lt;p&gt;I started my career in Web development using PHP. Since that day, PHP was evolving and getting more robust and performant than before. With Frameworks like Laravel, PHP has increased its popularity, keeping it one of the main programming languages that companies choose to create their websites.&lt;/p&gt;

&lt;p&gt;If PHP with Laravel is a very good option for making high scalable websites, why have I decided to switch to the Node.JS/Javascript ecosystem?&lt;/p&gt;

&lt;p&gt;Many reasons make me move from my comfort zone to challenge myself with a new programming language.&lt;/p&gt;

&lt;h2&gt;
  
  
  One programming language
&lt;/h2&gt;

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

&lt;p&gt;When you are creating successful websites/services, one of the most important factors is if they have a good UI/UX. In the past, these interfaces were static, but now, they are more reactive to the users' interactions and require you to combine Javascript with your backend language.&lt;/p&gt;

&lt;p&gt;This combination makes you to master two different programming languages and switches the way you write code from one to another.&lt;/p&gt;

&lt;p&gt;In the end, most of the time is spent on the user interface and less on the backend. The hard work is now on the frontend.&lt;/p&gt;

&lt;p&gt;The first reason for moving to Node.JS is to utilize the same language both on the frontend and backend. And this leads to the next point.&lt;/p&gt;

&lt;h2&gt;
  
  
  One type of programmer
&lt;/h2&gt;

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

&lt;p&gt;Utilizing the same programming languages across all of our projects simplifies the hiring process. Because if you hire a programmer who is good at Javascript/Node.JS, they can participate in the frontend and backend, etc.&lt;/p&gt;

&lt;p&gt;Today companies, need to create their website and mobile applications, and Javascript with hybrid solutions such as React Native allows you to use Javascript to create multi-platform applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sharing responsibilities between the team
&lt;/h2&gt;

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

&lt;p&gt;One common programming language allows having more synergy between your team.&lt;/p&gt;

&lt;p&gt;Now all the team can switch between projects and collaborate with other members.&lt;/p&gt;

&lt;p&gt;There is no more, the backend guy or the just frontend guy. Of course, all of us have our strengths and weaknesses, but It doesn't block to support other members with problems or deadlines.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code review across projects
&lt;/h2&gt;

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

&lt;p&gt;Because all the team members use the same languages, They can review each other code allowing them to strengthen the team.&lt;/p&gt;

&lt;h2&gt;
  
  
  Package compatibility
&lt;/h2&gt;

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

&lt;p&gt;In the PHP world, some libraries depend on a specific version of PHP, but in the Node.JS world, everything is compiled at the end with the help of webpack, etc., so you don't need to worry so much about these problems.&lt;/p&gt;

&lt;p&gt;Same as PHP with composer packages, there are NPM with millions of packages to help you to create sophisticated websites.&lt;/p&gt;

&lt;h2&gt;
  
  
  Speed of Development
&lt;/h2&gt;

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

&lt;p&gt;It's just javascript, As long as you are using the latest version of Node.JS on your computer and, You can share part of your code between all of your projects (web, mobile app, backend).&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

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

&lt;p&gt;Without any doubt, Javascript is very mature when it comes to testing applications. And the good part is that you can use the same testing framework for your website, backend, and mobile apps.&lt;/p&gt;

&lt;p&gt;If you use Javascript with Typescript adding strong typing will save you time catching errors and proving fixes before running code. You will be surprised about how good it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Host Anywhere
&lt;/h2&gt;

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

&lt;p&gt;Because your app mostly depends on Node.JS that comes by default in most of the OS. It's effortless to host your application anywhere.&lt;/p&gt;

&lt;p&gt;Node.JS/JS apps are the best fit for serverless solutions, saving you cost, and ensuring that your applications scale together with your traffic. You don't have to worry anymore about managing servers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Conclusions
&lt;/h2&gt;

&lt;p&gt;PHP still an excellent option. I really like PHP; don't misunderstand me. But at the end of the day, Node.JS makes my developer experience(DX) much better, and It's what the market is requiring.&lt;/p&gt;

</description>
      <category>php</category>
      <category>javascript</category>
      <category>node</category>
      <category>laravel</category>
    </item>
    <item>
      <title>Tailwind CSS vs Styled-components</title>
      <dc:creator>Rodrigo Ramirez</dc:creator>
      <pubDate>Thu, 14 Jan 2021 09:22:00 +0000</pubDate>
      <link>https://dev.to/xpromx/tailwind-css-vs-styled-components-4ai1</link>
      <guid>https://dev.to/xpromx/tailwind-css-vs-styled-components-4ai1</guid>
      <description>&lt;p&gt;Are you considering using Tailwind CSS rather than Styled-components or another CSS in JS solution? In this post, you will learn the advantages and disadvantages of each approach.&lt;/p&gt;

&lt;p&gt;First, Let's start by explaining the good and bad things about each of them, and at the end, let's jump to conclusions where you can see my way to go and decide yours.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Tailwind CSS&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Tailwind CSS is a utility-first CSS framework. It means that they provide a set of CSS classes representing each combination of CSS property and value. For example, &lt;code&gt;p-4&lt;/code&gt; represents &lt;code&gt;padding: 1rem&lt;/code&gt; and &lt;code&gt;block&lt;/code&gt; represents &lt;code&gt;display: block;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So you may be wondering why we need to use classes instead of writing the CSS directly in an HTML style tag? There are many reasons for that, especially with Tailwind CSS that comes equipped with good defaults for sizing, colors, and helpers for responsible classes.&lt;/p&gt;

&lt;p&gt;You can't apply responsive styles directly in your HTML style attribute. You will need to have a CSS file or create a style tag inside your HTML to achieve this.&lt;/p&gt;

&lt;p&gt;Let me show the potential of Tailwind CSS with one example:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTML+CSS&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Click Me
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;

    &lt;span class="nc"&gt;.button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
        &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
        &lt;span class="py"&gt;border-rounded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
        &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;.button&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;768px&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nc"&gt;.button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;4px&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="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tailwind CSS&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-red-400 text-white rounded text-center hover:bg-black md:mb-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    Click Me
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, in the HTML+CSS example, we needed to use a style tag to add a hover state and responsive styles to our button. But with Tailwind CSS, We achieved the same with fewer code lines, and using some specific prefixes to our CSS classes like &lt;code&gt;hover:&lt;/code&gt; or &lt;code&gt;md:&lt;/code&gt;  we can extend the use of the base utilities.&lt;/p&gt;

&lt;p&gt;Another good point of Tailwind CSS is their default settings and the possibility of extending or replacing their defaults. It will allow you to share your theme between different projects and have good defaults when working with the team gaining consistency across your design.&lt;/p&gt;

&lt;p&gt;Finally, Let's talk about the final CSS bundle size delivered to the browser. By default, Tailwind CSS will generate all the CSS utilities class name combinations, but many of those CSS classes will not be used in your project. Minified It's about 399kb.&lt;/p&gt;

&lt;p&gt;We have two solutions to reduce the final bundle size.&lt;/p&gt;

&lt;p&gt;The first one will be by manually adding only the necessary theme settings inside your project, but there is a high chance you to miss some of them, and even with that, you will still delivering unused classes to your bundle.&lt;/p&gt;

&lt;p&gt;The second and the recommended way is to use PurgeCSS, This library is already build-in Tailwind CSS, and It can be activated easily from your Tailwind config file.&lt;/p&gt;

&lt;p&gt;PurgeCSS is in charge of automatically removing the unused classes, providing the paths to your HTML/JS files. This library will scan those files and extract the unused class names from the final bundle.&lt;/p&gt;

&lt;p&gt;For more information check their docs:&lt;br&gt;
&lt;a href="https://tailwindcss.com/docs/optimizing-for-production#purge-css-options" rel="noopener noreferrer"&gt;https://tailwindcss.com/docs/optimizing-for-production#purge-css-options&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To summarize the pros and cons of using Tailwind CSS:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✅ Good defaults&lt;/p&gt;

&lt;p&gt;✅ Extensible theme settings&lt;/p&gt;

&lt;p&gt;✅ Easy to share your theme settings between projects&lt;/p&gt;

&lt;p&gt;✅ Small bundle size&lt;/p&gt;

&lt;p&gt;✅ Very good DX&lt;/p&gt;

&lt;p&gt;✅ Fast for prototyping&lt;/p&gt;

&lt;p&gt;✅ No class names conflict&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;❌ You will need to get used to the class names&lt;/p&gt;

&lt;p&gt;❌ PurgeCSS requires to work to avoid generating the class names dynamically&lt;/p&gt;

&lt;p&gt;❌ Write your logic to add or remove classes from your HTML&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Styled-components&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Styled-components is one of the most famous CSS in JS solutions. It works with React components and allows you to generate presentational components easily using pure CSS syntax.&lt;/p&gt;

&lt;p&gt;With Styled-components, you can use Sass style syntax to write nesting rules. When your components render, they automatically generate unique class names.&lt;/p&gt;

&lt;p&gt;An example of a Button component with styled-components would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="s2"&gt;`
    background-color: red; 
    color: white; 
    border-rounded: 3px; 
    text-align: center;

    &amp;amp;:hover{
        background-color: black;
    }

    @media (min-width: 768px){
        margin-bottom:4px;
    }
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Click me&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the help of webpack, you can generate the critical CSS based on the components rendered for each page and deliver it using SSR with a code-splitting implementation.&lt;/p&gt;

&lt;p&gt;On the client-side, when a new component is rendered the CSS from that component is injected inside a global style tag and removed from it when the component is unmounted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✅ Generate your components and CSS in one time&lt;/p&gt;

&lt;p&gt;✅ Use native CSS syntax&lt;/p&gt;

&lt;p&gt;✅ Write CSS conditionals using Javascript &lt;/p&gt;

&lt;p&gt;✅ Easy to start using&lt;/p&gt;

&lt;p&gt;✅ Good DX&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;❌ No default theme&lt;/p&gt;

&lt;p&gt;❌ Responsive need to be writing by hand&lt;/p&gt;

&lt;p&gt;❌ Rules are needed to keep the consistency in your design.&lt;/p&gt;

&lt;p&gt;❌ With Typescript, the DX decrease.&lt;/p&gt;

&lt;p&gt;❌ Similar components can deliver the same CSS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Both solutions are excellent. I had experience using both of them in production. But lately, I'm more inclined to the Tailwind CSS approach, and the main reason for this is their default theming and their easy way to apply responsive, dark mode, and other utilities to those based classes.&lt;/p&gt;

&lt;p&gt;On my previous projects with styled-components, one of the main challenges I had with my team was defining good defaults to generate consistency between our projects. And we had spent a lot of time creating utilities to apply in the styled-components way responsive and dark mode styles, but it resulted in increasing the complexity of our code.&lt;/p&gt;

&lt;p&gt;Since we started using Tailwind CSS, that problem disappear, and everyone is happy now using it.&lt;/p&gt;

&lt;p&gt;Once you get used to their syntax, I can guarantee that your DX and Development speed will increase considerably.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extra tip:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you are using VScode (not sure about other IDEs), but with the Tailwind CSS IntelliSense plugin, you can have autocompletion for your class names directly from your tailwind theme settings file.&lt;/p&gt;

&lt;p&gt;More information here:&lt;br&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss" rel="noopener noreferrer"&gt;https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss&lt;/a&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>react</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
  </channel>
</rss>
