<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Hashnode's Official Blog]]></title><description><![CDATA[Hashnode's Official Blog]]></description><link>https://hashnode.com/blog</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1698981157543/klffmNgQC.png</url><title>Hashnode&apos;s Official Blog</title><link>https://hashnode.com/blog</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 15 Mar 2026 17:19:10 GMT</lastBuildDate><atom:link href="https://hashnode.com/blog/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><atom:link rel="first" href="https://hashnode.com/blog/rss.xml"/><atom:link rel="next" href="https://hashnode.com/blog/rss.xml?after=NjVmODIxOGViNmExZGIyOTNmNTFmZjg3XzIwMjQtMDMtMThUMTE6MTI6MTQuMDUxWg=="/><item><title><![CDATA[The state of vibe coding in 2026: Adoption won, now what?]]></title><description><![CDATA[<p><strong>tldr:</strong> 92% of US developers use AI coding tools daily. 46% of new code is AI-generated. Trust in that code has dropped from 77% to 60%. Vibe coding won the adoption war. The quality war is just starting.</p>
<hr />
<h2>Vibe coding won. That's not the interesting part.</h2>
<p>Andrej Karpathy coined the term "vibe coding" in early 2025. By the end of that year, Collins Dictionary named it Word of the Year. By February 2026, the debate is over. Everybody vibe codes.</p>
<p><a href="https://x.com/karpathy/status/1886192184808149383?lang=en"><img src="https://cdn.hashnode.com/uploads/covers/54b81b237393d8e81463c55c/d0999182-eb62-4afb-a2b2-5bd8571c8f59.png" alt="Andrej Karpathy's tweet that coined the term &quot;Vibe coding&quot;" style="display:block;margin:0 auto" /></a></p>
<p>The numbers tell the story. 92% of US developers use AI coding tools daily. 82% globally on a weekly basis. GitHub reports 46% of all new code is now AI-generated. Among Y Combinator's Winter 2025 cohort, 21% of startups have codebases that are 91% or more AI-generated. Google says a quarter of their code is already AI-assisted.</p>
<p>For anyone still asking "<a href="https://en.wikipedia.org/wiki/Vibe_coding">what is vibe coding</a>," the definition is simple. You describe what you want in natural language. AI generates the code. You accept it without fully reviewing every line. You iterate by prompting, not by typing code. Andrej Karpathy put it this way: <em>"You fully give in to the vibes, embrace exponentials, and forget that the code even exists."</em></p>
<p>The adoption war is over. AI won. What's interesting now is what that victory actually costs.</p>
<img src="https://cdn.hashnode.com/uploads/covers/54b81b237393d8e81463c55c/5eb02bab-7382-42e1-877a-f6a3928a9cff.png" alt="Vibe coding adoption curve showing 92% US developer usage in 2026 with AI-generated code share rising from 10% in 2023 to 46% in 2026" style="display:block;margin:0 auto" />

<blockquote>
<p>Vibe coding adoption curve showing 92% US developer usage in 2026 with AI-generated code share rising from 10% in 2023 to 46% in 2026.</p>
</blockquote>
<hr />
<h2>The numbers contradict each other</h2>
<p>Here's where it gets uncomfortable.</p>
<p>The same industry that reports 92% AI tool adoption also reports this:</p>
<ul>
<li><p><a href="https://www.coderabbit.ai/">CodeRabbit</a> analyzed 470 open-source GitHub pull requests. AI co-authored code contained 1.7x more major issues than human-written code.</p>
</li>
<li><p><a href="https://www.databricks.com/blog/passing-security-vibe-check-dangers-vibe-coding">45% of AI-generated code samples</a> contain OWASP Top-10 vulnerabilities.</p>
</li>
<li><p>Security firm <a href="https://tenzai.co/">Tenzai</a> tested five popular vibe coding tools (Claude Code, OpenAI Codex, Cursor, Replit, Devin). They built 15 identical apps. Found 69 vulnerabilities. Six were critical.</p>
</li>
<li><p>Code churn is up 41%. Code duplication increased 4x. Refactoring collapsed from 25% of changed lines in 2021 to under 10% by 2024, according to <a href="https://www.gitclear.com/">GitClear</a>.</p>
</li>
<li><p><a href="https://www.secondtalent.com/resources/vibe-coding-statistics/">63% of developers</a> have spent more time debugging AI-generated code than writing the original code themselves would have taken.</p>
</li>
</ul>
<p>And the <a href="https://www.getpanto.ai/blog/vibe-coding-statistics">trust data</a> tells its own story. Developer favorability toward AI tools collapsed from 77% in 2023 to 60% in 2026. Only 33% trust AI code accuracy, down from 43% in 2024.</p>
<p>Usage keeps climbing anyway.</p>
<p>The industry is hooked on something it doesn't trust. That's the state of vibe coding in February 2026.</p>
<img src="https://cdn.hashnode.com/uploads/covers/54b81b237393d8e81463c55c/10225944-610c-4a31-ab92-b662d4a4e300.png" alt="Bar chart comparing vibe coding adoption rates versus developer trust scores from 2023 to 2026 showing diverging trends" style="display:block;margin:0 auto" />

<blockquote>
<p>Bar chart comparing vibe coding adoption rates versus developer trust scores from 2023 to 2026 showing diverging trends.</p>
</blockquote>
<hr />
<h2>Three disasters that shaped the conversation</h2>
<p>These aren't hypotheticals. They happened. They're <a href="https://thenewstack.io/vibe-coding-could-cause-catastrophic-explosions-in-2026/">documented</a>. And they follow the same pattern: vibe coding builds the product, then the product collapses under real-world pressure.</p>
<h3>The Enrichlead collapse</h3>
<img src="https://cdn.hashnode.com/uploads/covers/54b81b237393d8e81463c55c/a74b8992-2a02-4909-908b-aa7dadca4721.jpg" alt="A developer sitting on desk with multiple coding screens open, which feels like vibe coding using AI." style="display:block;margin:0 auto" />

<p>An indie developer built an entire SaaS product with Cursor. Zero hand-written code. He celebrated on social media. It worked. Users signed up.</p>
<p>Within weeks: "Random things are happening, maxed out usage on API keys, people bypassing the subscription, creating random shit on db."</p>
<p>He couldn't debug it. He didn't write it. Cursor kept breaking other parts of the code when he tried to fix things. The product was shut down permanently.</p>
<p>The lesson isn't that vibe coding can't build a product. It clearly can. The lesson is that vibe coding can't maintain one. Not without someone who understands the code well enough to fix it when real users start doing real things.</p>
<h3>The Lovable exposure</h3>
<img src="https://cdn.hashnode.com/uploads/covers/54b81b237393d8e81463c55c/f1b56e2b-043c-4be9-92bd-c5e776dbb69d.png" alt="Screenshot of lovable.dev" style="display:block;margin:0 auto" />

<p><a href="https://lovable.dev/">Lovable</a>, a popular vibe coding platform, generated apps for thousands of users in 2025. Security researchers found that 170 out of 1,645 Lovable-created web applications had vulnerabilities that would allow personal information to be accessed by anyone.</p>
<p>That's more than 10% of apps shipping with user data exposed.</p>
<p>The tool worked. The code it wrote didn't protect anyone's data.</p>
<h3>The honeypot that got hacked</h3>
<p>This one is almost poetic. Security firm <a href="https://www.intruder.io/">Intruder</a> used AI to generate a honeypot, a tool specifically designed to capture attacker traffic. During testing, attackers exploited a vulnerability in the AI-generated honeypot itself.</p>
<p>The AI had added logic to extract client-supplied IP headers and treat them as trusted data. Headers are user-controllable. An attacker injected a payload and gained partial control of program execution.</p>
<p>A security team. Building a security tool. Using AI to write the code. Missed a basic trust violation because the AI put it there and nobody caught it in review.</p>
<p>Expertise doesn't protect you from AI-generated blind spots. That's the uncomfortable truth.</p>
<hr />
<h2>The open source crisis nobody expected</h2>
<p>This section matters because it reveals a second-order effect of vibe coding that nobody predicted.</p>
<p>Daniel Stenberg shut down <a href="https://curl.se/">cURL's</a> six-year bug bounty program in January 2026. Not because of budget. Because AI-generated vulnerability reports were flooding it with noise. Real security researchers couldn't be heard over the slop.</p>
<p>Mitchell Hashimoto banned AI-generated code from <a href="https://ghostty.org/">Ghostty</a>. Steve Ruiz went further. <a href="https://www.tldraw.com/">tldraw</a> now auto-closes all external pull requests. Not just AI-generated ones. All of them. Because maintainers can't distinguish real contributions from AI-generated noise fast enough.</p>
<p><a href="https://tailwindcss.com/">Tailwind CSS</a> saw downloads climb while documentation traffic fell 40% and revenue dropped 80%. Developers are using the framework. They're just not reading the docs. AI reads them instead, sometimes incorrectly, generating code that works until it doesn't.</p>
<p>RedMonk analyst Kate Holterhoff <a href="https://www.infoq.com/news/2026/02/ai-floods-close-projects/">calls it "AI Slopageddon."</a></p>
<p>The pattern: AI generates code fast. It also generates contributions fast. Pull requests. Bug reports. Documentation fixes. The volume is so high and the quality so inconsistent that maintainers can't keep up. So they shut the door entirely.</p>
<p>Vibe coding isn't just a developer productivity story. It's reshaping the economics of open source. The infrastructure that modern software depends on is maintained by humans who are drowning in AI-generated noise.</p>
<hr />
<h2>The METR paradox</h2>
<p>This is the single most counterintuitive finding about vibe coding in 2026. It deserves its own section.</p>
<p><a href="https://metr.org/">METR</a> ran a randomized controlled trial with experienced open-source developers. Real engineers. Real codebases. Real tasks.</p>
<p>The results:</p>
<ul>
<li><p>Developers using AI tools were <strong>19% slower</strong> at completing tasks</p>
</li>
<li><p>Before the study, they predicted they'd be <strong>24% faster</strong></p>
</li>
<li><p>After the study, they still believed they'd been <strong>20% faster</strong></p>
</li>
</ul>
<p>Read that again. They were measurably slower. And they didn't know it. Even after the experiment, they believed AI had helped them.</p>
<p>This isn't a one-off finding. <a href="https://www.getpanto.ai/blog/vibe-coding-statistics">Broader survey data</a> shows 95% of developers report feeling productive while measurably producing lower-quality code. 74% report productivity increases. The subjective experience and the objective measurement diverge.</p>
<p>The explanation is probably straightforward. AI tools make the easy parts faster (scaffolding, boilerplate, repetitive patterns). But they make the hard parts harder (debugging unfamiliar code, understanding hidden assumptions, catching subtle logic errors). The time saved on the easy parts feels significant. The time lost on the hard parts is invisible until something breaks.</p>
<p>This is the core tension of vibe coding in 2026. It feels fast. The data says it's complicated.</p>
<hr />
<h2>What actually works</h2>
<p>Not everything is broken. An honest assessment has to include what vibe coding genuinely excels at.</p>
<p><strong>Prototyping and MVPs.</strong> Median task completion time drops 20-45% for greenfield features. If you're validating an idea and the cost of bugs is low, vibe coding is transformative. Build the prototype in a weekend. Throw it away and build the real thing properly if it works.</p>
<p><strong>Internal tools.</strong> IBM reports 60% reduction in development time for enterprise internal apps using AI-assisted coding. Internal tools have a higher tolerance for bugs and a lower bar for security. This is vibe coding's sweet spot.</p>
<p><strong>Boilerplate and scaffolding.</strong> Nobody misses writing CRUD endpoints by hand. AI handles repetitive, well-understood patterns reliably.</p>
<p><strong>Senior developers, specifically.</strong> Engineers with 10+ years of experience report 81% productivity gains. They know what good code looks like. They can spot when AI generates something wrong. Junior developers show mixed results because they lack the judgment to evaluate what AI produces.</p>
<p>The pattern is clear. Vibe coding works when the cost of failure is low and you have someone who can evaluate the output. It breaks when the code needs to be secure, maintainable, or correct at scale.</p>
<hr />
<h2>The 15 vibe coding tools that matter in 2026</h2>
<p>The vibe coding tools landscape splits into two categories: <strong>AI code editors</strong> that augment developers working in real codebases, and <strong>AI app builders</strong> that generate entire applications from prompts. Most serious teams use one from each category.</p>
<h3>AI code editors</h3>
<p>These require programming knowledge. They make experienced developers faster.</p>
<table style="min-width:75px"><colgroup><col style="min-width:25px"></col><col style="min-width:25px"></col><col style="min-width:25px"></col></colgroup><tbody><tr><th><p>Tool</p></th><th><p>Price</p></th><th><p>Best for</p></th></tr><tr><td><p><a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="https://www.cursor.com/" style="pointer-events:none">Cursor</a></p></td><td><p>\(20/mo (Pro)</p></td><td><p>Deep codebase understanding, multi-file edits. The most popular AI IDE in 2026. \)9.9B valuation.</p></td></tr><tr><td><p><a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="https://windsurf.com/" style="pointer-events:none">Windsurf</a></p></td><td><p>\(15/mo</p></td><td><p>Large codebases, enterprise workflows. Cascade agent handles multi-step reasoning. Acquired by OpenAI.</p></td></tr><tr><td><p><a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="https://claude.ai/" style="pointer-events:none">Claude Code</a></p></td><td><p>Usage-based</p></td><td><p>Terminal-native power users. Best at refactoring, debugging, cross-file changes. Benchmark leader.</p></td></tr><tr><td><p><a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="https://github.com/features/copilot" style="pointer-events:none">GitHub Copilot</a></p></td><td><p>\)10/mo</p></td><td><p>Most affordable. Deep GitHub ecosystem integration. 20M+ users. Best for teams already on GitHub.</p></td></tr><tr><td><p><a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="https://firebase.studio/" style="pointer-events:none">Firebase Studio</a></p></td><td><p>Free (preview)</p></td><td><p>Google's entry. Full-stack AI workspace with Gemini. Prototyping agent builds apps without code. Free during preview.</p></td></tr></tbody></table>

<img src="https://cdn.hashnode.com/uploads/covers/54b81b237393d8e81463c55c/12079264-950a-441d-8c0b-18d472848722.png" alt="Screenshot of Cursor AI IDE showing Composer feature generating multi-file code edits from a natural language prompt" style="display:block;margin:0 auto" />

<h3>AI app builders</h3>
<p>These generate full applications from natural language. Programming knowledge optional.</p>
<table style="min-width:75px"><colgroup><col style="min-width:25px"></col><col style="min-width:25px"></col><col style="min-width:25px"></col></colgroup><tbody><tr><th><p>Tool</p></th><th><p>Price</p></th><th><p>Best for</p></th></tr><tr><td><p><a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="https://lovable.dev/" style="pointer-events:none">Lovable</a></p></td><td><p>\(39/mo (Pro)</p></td><td><p>Non-technical founders. Clean React + Supabase output. Hit \)100M ARR in 8 months. Design quality stands out.</p></td></tr><tr><td><p><a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="http://Bolt.new" style="pointer-events:none">Bolt.new</a></p></td><td><p>\(20/mo (Pro)</p></td><td><p>Fastest prototyping. Runs Node.js in browser. \)40M ARR in 4.5 months. Great for quick iteration.</p></td></tr><tr><td><p><a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="https://replit.com/" style="pointer-events:none">Replit</a></p></td><td><p>\(25/mo</p></td><td><p>Best all-in-one for beginners. 75% of users never write code. Build, run, deploy from one browser tab.</p></td></tr><tr><td><p><a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="https://v0.dev/" style="pointer-events:none">v0 by Vercel</a></p></td><td><p>\)20/mo</p></td><td><p>Frontend UI components. Generates production-ready React with Tailwind and shadcn/ui. Frontend only.</p></td></tr><tr><td><p><a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="https://devin.ai/" style="pointer-events:none">Devin</a></p></td><td><p>Team pricing</p></td><td><p>Autonomous AI software engineer. Plans, codes, debugs, sends PRs. Best as a junior dev on an existing team.</p></td></tr></tbody></table>

<img src="https://cdn.hashnode.com/uploads/covers/54b81b237393d8e81463c55c/6fe70679-877b-499f-b994-721a9d13440d.png" alt="creenshot of v0 by Vercel generating a React UI component with Tailwind CSS from a text description" style="display:block;margin:0 auto" />

<h3>Emerging platforms</h3>
<p>Newer tools gaining traction but not yet at the scale of the above.</p>
<table style="min-width:75px"><colgroup><col style="min-width:25px"></col><col style="min-width:25px"></col><col style="min-width:25px"></col></colgroup><tbody><tr><th><p>Tool</p></th><th><p>Price</p></th><th><p>Best for</p></th></tr><tr><td><p><a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="https://www.tempolabs.ai/" style="pointer-events:none">Tempo Labs</a></p></td><td><p>Varies</p></td><td><p>React-focused design-to-code. Strong collaboration between designers and developers.</p></td></tr><tr><td><p><a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="https://softgen.ai/" style="pointer-events:none">Softgen</a></p></td><td><p>Varies</p></td><td><p>Next.js full-stack apps. Built-in auth, payments, SEO. No-code friendly.</p></td></tr><tr><td><p><a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="http://Create.xyz" style="pointer-events:none">Create.xyz</a></p></td><td><p>Varies</p></td><td><p>Quick app generation from prompts or templates. Good starting point, limited customization.</p></td></tr><tr><td><p><a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="https://emergent.sh/" style="pointer-events:none">Emergent</a></p></td><td><p>Varies</p></td><td><p>YC-backed ($300M valuation). Multi-agent approach: specialized AI agents for design, code, and deploy.</p></td></tr><tr><td><p><a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="https://www.wix.com/" style="pointer-events:none">Wix Harmony</a></p></td><td><p>Varies</p></td><td><p>Wix's answer to vibe coding. Announced January 2026. Targets existing Wix ecosystem users.</p></td></tr></tbody></table>

<p>The best teams in 2026 use two or three tools in combination. A common pattern: prototype in Lovable or Bolt, then move to Cursor or Claude Code for production. The tool matters less than knowing when to switch.</p>
<hr />
<h2>The gap nobody's closing</h2>
<p>Development went AI-native. Testing mostly didn't.</p>
<p>Teams ship 3-5x faster with vibe coding. Their test suites are still written by hand, maintained by hand, broken by hand. The math doesn't work.</p>
<p>41% of developers admit to pushing AI-generated code to production without full review. Companies are finding hardcoded API keys, disabled security checks, and logic bombs in code that passed CI because the test suite was written for a human-speed development process.</p>
<p>The question isn't "should we vibe code?" That's decided. Everyone does. The question is: how do you test at the speed of vibe coding?</p>
<p>Three approaches exist today:</p>
<p><strong>Manual QA.</strong> Doesn't scale. Your team ships in hours. Manual testing takes days. The backlog grows until you skip it entirely or ship without coverage.</p>
<p><strong>Write more tests by hand.</strong> Defeats the purpose. You automated coding but not testing. Your senior engineers spend 10-15 hours per week maintaining test suites they didn't write for code they didn't write. That's \(39K-\)58K per affected engineer annually in hidden cost. (We broke this down in detail: <a href="https://bug0.com/blog/the-2026-quality-tax-ai-assisted-development-qa-budget">The 2026 Quality Tax</a>.)</p>
<p><strong>AI-native testing.</strong> Match the development approach with the testing approach. If code is generated from natural language, tests should be too. If code self-generates, tests should self-heal.</p>
<p>For teams that vibe code without dedicated QA, <a href="https://bug0.com">Bug0</a> applies the same <a href="https://bug0.com/studio">AI-first philosophy to testing</a>. You describe what matters in plain English. AI generates and maintains the tests. No selectors to maintain. No flaky test debugging at 2am.</p>
<p>The irony of 2026: we automated code generation but left testing in 2019.</p>
<hr />
<h2>What 2026 looks like from here</h2>
<p>Vibe coding adoption will keep climbing. The quality gap will too. These aren't opposing trends. They're the same trend viewed from different angles.</p>
<p>The differentiator this year won't be whether your team uses AI tools. Every team does. The differentiator is whether you test what AI produces. Whether you catch the hardcoded API key before your users do. Whether your AI-generated login flow handles edge cases the AI didn't think of.</p>
<p>The best teams will treat vibe coding the way they treat any powerful tool. Use it aggressively. Verify ruthlessly. Don't confuse "it runs" with "it works."</p>
<p>"Vibe coding" as a term might fade. The practice won't. It's just how software gets built now. The companies that survive the quality gap will be the ones that figured out testing before their competitors' vibe-coded apps started breaking in production.</p>
<hr />
<h2>FAQs</h2>
<h3>What is vibe coding?</h3>
<p>Vibe coding is a software development practice where you describe what you want to an AI in natural language and the AI generates the code. The term was coined by AI researcher Andrej Karpathy in early 2025 and named Collins Dictionary Word of the Year. The key distinction: vibe coders accept AI-generated code without fully reviewing every line, relying on prompts and iteration rather than line-by-line coding.</p>
<h3>What does vibe coding mean?</h3>
<p>The term comes from "vibes," describing the shift from precise programming instructions to conversational intent. You describe the feel of what you want. The AI handles the implementation. Karpathy's original framing: "You fully give in to the vibes, embrace exponentials, and forget that the code even exists." It captures a fundamental change in the developer's role, from writing code to directing AI.</p>
<h3>What are the best vibe coding tools in 2026?</h3>
<p>The top vibe coding tools in 2026 span two categories. AI-powered code editors include <a href="https://www.cursor.com/">Cursor</a> (\(20/mo), <a href="https://windsurf.com/">Windsurf</a> (\)15/mo), and <a href="https://claude.ai/">Claude Code</a>. Full-stack app generators include <a href="https://bolt.new/">Bolt</a> (\(29/mo), <a href="https://lovable.dev/">Lovable</a> (\)25/mo), <a href="https://replit.com/">Replit</a>, and <a href="https://v0.dev/">v0</a> by Vercel. Most experienced teams use two to three tools in combination: a generator for prototyping and an AI IDE for production code.</p>
<h3>Is vibe coding safe for production?</h3>
<p>Not without guardrails. Research shows 45% of AI-generated code contains security vulnerabilities. Tenzai found 69 vulnerabilities across 15 test apps built with popular vibe coding tools. Vibe coding works well for prototypes, internal tools, and MVPs. For production applications, you need code review, automated security scanning, and comprehensive testing. The code that "just works" in a demo often fails under real-world conditions.</p>
<h3>How do you test vibe-coded applications?</h3>
<p>Three paths. Manual QA doesn't scale with AI development speed. Writing tests by hand defeats the purpose of vibe coding. AI-native testing tools like <a href="https://bug0.com">Bug0</a> match the development approach: describe critical flows in plain English, AI generates and maintains the tests. The key principle: if your code generation is AI-native, your testing should be too.</p>
<h3>Will vibe coding replace software engineers?</h3>
<p>No. It amplifies them. Senior developers (10+ years) report 81% productivity gains because they can evaluate what AI produces. Architecture decisions, security reviews, debugging, and system design still require human judgment. The role is shifting from writing code to reviewing, directing, and architecting AI-generated systems. The engineers who thrive in 2026 are the ones who understand code well enough to catch what AI gets wrong.</p>
]]></description><link>https://hashnode.com/blog/state-of-vibe-coding-2026</link><guid isPermaLink="true">https://hashnode.com/blog/state-of-vibe-coding-2026</guid><category><![CDATA[vibe coding]]></category><category><![CDATA[AI Coding Tools]]></category><category><![CDATA[Software Testing]]></category><category><![CDATA[Code Quality]]></category><category><![CDATA[AI development]]></category><dc:creator><![CDATA[Syed Fazle Rahman]]></dc:creator></item><item><title><![CDATA[The AI-native stack (2026): From text-to-app to agentic QA]]></title><description><![CDATA[<p><strong>tldr:</strong> The 10x engineer is real in 2026, but only because five tools replaced entire job functions across the SDLC. Here&#39;s the stack we&#39;ve been running, where each tool fits, where the handoffs get messy, and why the testing layer is the one most teams still get wrong.</p>
<hr>
<h2><strong>The velocity trap</strong></h2>
<p>Most engineering teams figured out the coding part. Tools like <a href="https://cursor.com/">Cursor</a> and <a href="https://v0.app/">v0</a> turned &quot;describe what you want&quot; into &quot;here&#39;s the working code.&quot; A single engineer can scaffold a full-stack application in an afternoon. Features that took a sprint take a session.</p>
<img src="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/54b81b237393d8e81463c55c/a7eebe16-16c0-4399-8f24-d20922971fbf.png" alt="Screenshot of the v0.app" style="display: block; margin: 0 auto;" />

<p>But here&#39;s what caught everyone off guard: the bottleneck didn&#39;t disappear. It just moved downstream. Writing code isn&#39;t the hard part anymore. Knowing whether the code actually works is.</p>
<p>If you generate code 10x faster, you generate bugs 10x faster. Your CI pipeline doesn&#39;t care that Cursor wrote the component in 30 seconds. It cares that the login flow breaks because the AI renamed a CSS class without telling you. Your users don&#39;t care that v0 generated a beautiful dashboard. They care that the checkout button doesn&#39;t respond on mobile.</p>
<p>You cannot solve 2026 speed with 2020 testing. Manual QA, hand-written Selenium scripts, and even basic Playwright suites maintained by humans can&#39;t keep pace with agentic workflows that produce dozens of PRs per day.</p>
<p>And here&#39;s what the &quot;AI does everything&quot; crowd gets wrong. We&#39;re past that hype. The real workflow is human-in-the-loop: the AI proposes, the engineer evaluates. Cursor generates a PR plan, you review it before execution. Bug0 generates a test suite, you audit the assertions before they gate production. The industry calls this &quot;evals,&quot; and it&#39;s the difference between teams that ship confidently and teams that ship recklessly.</p>
<p>The other shift: multi-agent orchestration. One agent writes the code. Another agent automatically triggers the test. A third surfaces the results. Tools like GitHub Copilot Workspace and OpenAI&#39;s Codex started this pattern. The AI-native stack turns it into a pipeline where agents hand off to agents, and the human supervises the chain.</p>
<p>Here&#39;s what that chain looks like in practice:</p>
<table style="min-width: 75px;"><colgroup><col style="min-width: 25px;"><col style="min-width: 25px;"><col style="min-width: 25px;"></colgroup><tbody><tr><th colspan="1" rowspan="1"><p>Step</p></th><th colspan="1" rowspan="1"><p>Agent / Tool</p></th><th colspan="1" rowspan="1"><p>Action</p></th></tr><tr><td colspan="1" rowspan="1"><p>1. Intent</p></td><td colspan="1" rowspan="1"><p>v0</p></td><td colspan="1" rowspan="1"><p>Generates UI component code from a prompt</p></td></tr><tr><td colspan="1" rowspan="1"><p>2. Logic</p></td><td colspan="1" rowspan="1"><p>Cursor</p></td><td colspan="1" rowspan="1"><p>Integrates component, writes backend logic based on <code>.cursorrules</code></p></td></tr><tr><td colspan="1" rowspan="1"><p>3. Verify</p></td><td colspan="1" rowspan="1"><p>Bug0</p></td><td colspan="1" rowspan="1"><p>Generates a Playwright test against the new PR automatically</p></td></tr><tr><td colspan="1" rowspan="1"><p>4. Deploy</p></td><td colspan="1" rowspan="1"><p>Vercel</p></td><td colspan="1" rowspan="1"><p>Creates a preview deployment, runs the Bug0 suite against it</p></td></tr><tr><td colspan="1" rowspan="1"><p>5. Loop</p></td><td colspan="1" rowspan="1"><p>Sentry</p></td><td colspan="1" rowspan="1"><p>Monitors for errors, suggests a fix-PR if the agent's logic fails in production</p></td></tr></tbody></table>

<p>Each step triggers the next. The human reviews at steps 2 and 3. The rest runs automatically. In theory. In practice, you&#39;ll spend a non-trivial amount of time on glue code: GitHub Actions configs, webhook integrations, environment variable wrangling. The tools don&#39;t natively talk to each other yet. You&#39;re the orchestration layer until someone builds the meta-agent that connects them.</p>
<p>You need a fully AI-native lifecycle. Every stage, from design to observability, powered by generative AI tools purpose-built for that stage. With humans reviewing the seams.</p>
<p>We&#39;ve audited the landscape to find the best generative AI tools for every stage of the SDLC. Five stages. Five tools. One stack that gives a 5-person team the output of 50.</p>
<img src="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/54b81b237393d8e81463c55c/af78c8c5-aec2-4a68-ae21-444030f306f6.png" alt="Diagram of the AI-native SDLC showing five connected stages: Design, Development, Testing, Deployment, and Observability, linked by a neural data flow line" style="display: block; margin: 0 auto;" />

<hr>
<h2><strong>Stage 1: Design (the &quot;no-Figma&quot; era)</strong></h2>
<p><strong>The tool:</strong> <a href="https://v0.dev/">v0 by Vercel</a></p>
<p>The designer-to-developer handoff used to be a weeks-long process. Figma files. Redlines. &quot;Can you move this 2px to the left?&quot; conversations. Design reviews that blocked sprint planning.</p>
<p>v0 collapsed that entire workflow into a prompt.</p>
<p>You type: &quot;Dashboard with dark mode, sidebar navigation, and Shadcn UI components.&quot; You get React code. Not a mockup. Not a wireframe. Production-ready JSX with Tailwind classes and proper component structure. You paste it into your project and it works.</p>
<p>v0 goes further now. Design Mode lets you edit by clicking, not just prompting. Select a component, drag to reposition, change colors visually, and the code updates underneath. It&#39;s Figma-speed iteration with code-first output. For engineers who think spatially, this changes the workflow from &quot;describe what I want&quot; to &quot;show what I want.&quot;</p>
<p>The caveat: v0 is excellent at generating standard UI patterns. Ask for a dashboard, a settings page, a landing section, and you get clean code. Ask for something highly custom, an interactive data visualization or a non-standard navigation pattern, and you&#39;ll spend more time wrestling with the output than building it yourself. Know when to prompt and when to code.</p>
<p>This isn&#39;t &quot;AI-assisted design.&quot; It&#39;s design-as-code. The prompt is the spec. The output is the implementation. There&#39;s no handoff because there&#39;s nothing to hand off.</p>
<h3><strong>Design-to-code vs. full-stack prompting</strong></h3>
<p>v0 excels at UI. But &quot;text-to-app&quot; now means more than components. Tools like <a href="https://bolt.new/">Bolt.new</a> and <a href="https://replit.com/">Replit Agent</a> handle the full stack in one prompt: database schema, authentication, server logic, and UI. You describe the product. You get a deployable app with a Postgres database, OAuth, and API routes.</p>
<p>The distinction matters. v0 is design-to-code: the best tool for crafting specific UI components and pages with pixel-level control. Bolt.new and Replit Agent are full-stack prompting: better for prototyping entire applications from scratch. Most production teams use v0 for the interface layer and Cursor for the full-stack logic. But if you&#39;re a solo founder validating an idea, full-stack prompting tools get you to a working prototype in hours, not days.</p>
<p><a href="https://lovable.dev/">Lovable</a> sits between these approaches. Describe the product. Get a deployable app with a clean UI. It&#39;s opinionated about design in a way the general-purpose tools aren&#39;t.</p>
<h3><strong>The handoff is dead, but the pressure is real</strong></h3>
<p>When design becomes instant, the downstream pressure on development and testing increases exponentially. You&#39;re not waiting two weeks for mockups anymore. You&#39;re generating UI faster than your team can verify it works. The designer bottleneck is gone. The QA bottleneck just got worse.</p>
<hr>
<h2><strong>Stage 2: Development (the agentic IDE)</strong></h2>
<p><strong>The tool:</strong> <a href="https://cursor.com/">Cursor</a> (Composer Mode)</p>
<img src="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/54b81b237393d8e81463c55c/003cda9f-4e86-48e1-a2f1-6bd053328faf.png" alt="Screenshot of Cursor in action" style="display: block; margin: 0 auto;" />

<p>The shift here is from copilot to agent.</p>
<p>GitHub Copilot (2022-era) was autocomplete. It finished your line. Cursor&#39;s Composer Mode is a collaborator. It reads your entire codebase, understands the architecture, and makes multi-file edits in a single prompt. You don&#39;t type functions. You tab through entire features.</p>
<p>Tell Composer: &quot;Add Stripe subscription billing with a pricing page, webhook handler, and database migration.&quot; It creates the pricing component, writes the API route, sets up the webhook endpoint, generates the Prisma schema change, and updates the navigation. Across six files. In one shot.</p>
<p>This only works because of how Cursor indexes your project. It builds a semantic map of your entire codebase, your documentation, your <code>.cursorrules</code>, and your git history, then retrieves the relevant context for each edit. Two years ago, you had to paste individual files and pray the model understood the architecture. Now the tooling retrieves the right context automatically, and million-token context windows mean the model can hold enough of your project in memory to make coherent multi-file changes.</p>
<p>This is what agentic workflows look like in practice. The AI isn&#39;t waiting for you to guide it line by line. It plans the work, executes across files, and presents the result.</p>
<p>Professional teams don&#39;t use Composer raw. They use <code>.cursorrules</code> files, project-level instructions that constrain the AI&#39;s behavior. These context rules are the difference between an agent that respects your architecture and one that rewrites it on a whim.</p>
<p>A real <code>.cursorrules</code> looks something like this:</p>
<pre><code class="language-text">- Never rename existing CSS classes or data-testid attributes.
- Always use the component library in src/components/ui/. Do not create new base components.
- Follow the auth pattern in src/lib/auth.ts for all protected routes.
- Use TypeScript interfaces, never &#39;any&#39;. If a component exceeds 100 lines, suggest a refactor.
</code></pre>
<p>Three minutes to write. Saves hours of &quot;why did the AI restructure my entire auth flow?&quot;</p>
<h3><strong>The hidden tax of confident AI</strong></h3>
<p>Cursor is confident. Sometimes too confident.</p>
<p>It refactors CSS classes without mentioning it. It renames variables across files because it &quot;improved readability.&quot; It imports a library that doesn&#39;t exist in your <code>node_modules</code> because it hallucinated the package name from training data. It restructures a component hierarchy because its architecture opinion differed from yours. And it does all of this silently, buried in a 200-line diff you might not fully review.</p>
<p>When Cursor changes that <code>submit-btn</code> class to <code>btn-primary</code> at 2am during a coding session, every test that references the old selector breaks. Every visual regression baseline shifts. Your CI goes red, and nobody knows why until someone diffs every file the AI touched.</p>
<h3><strong>Shadow code: the maintenance debt you didn&#39;t sign up for</strong></h3>
<p>Here&#39;s the deeper problem. If your engineer didn&#39;t write those 200 lines, they may not understand them well enough to maintain them. AI-generated code that nobody fully comprehends becomes shadow code. It works today. It breaks tomorrow. And when it breaks, debugging takes 3x longer because the developer is reverse-engineering the AI&#39;s decisions instead of their own.</p>
<p>Tools like <a href="https://sourcegraph.com/cody">Sourcegraph Cody</a> help with context retrieval, letting engineers ask &quot;why was this code written this way?&quot; across the full codebase. AI-augmented code review, where a second AI model reviews the first model&#39;s output, is becoming standard practice.</p>
<img src="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/54b81b237393d8e81463c55c/be20b91b-d15e-48dd-aa49-0f8be19f9c37.png" alt="Sourcegraph website screenshot" style="display: block; margin: 0 auto;" />

<p>The practical defense: AI-proof your documentation. Every module gets a <code>DECISIONS.md</code> that explains <em>why</em> the code is structured this way, not just <em>what</em> it does. When Cursor generates code, it reads these files and follows established patterns. When a new engineer debugs shadow code six months later, they have the reasoning, not just the implementation. Teams that skip this step pay for it in debugging hours. Teams that adopt it consistently report faster onboarding, especially in codebases where most code was AI-generated.</p>
<p>But documentation alone doesn&#39;t eliminate the core risk: code moving faster than human comprehension.</p>
<p>This is the core tension of agentic development. The speed is real. The risk is also real. You need something equally agentic on the verification side.</p>
<p>You need an agent to verify what the agent built.</p>
<hr>
<h2><strong>Stage 3: Testing (the quality layer)</strong></h2>
<p>This is where most AI-native stacks fall apart.</p>
<p>Teams adopt v0 for design. They adopt Cursor for development. Then they test with the same Playwright scripts they wrote by hand in 2023. Or worse, they skip testing and hope staging catches the bugs.</p>
<p>The math doesn&#39;t work. If Cursor generates 15 PRs a day, and each PR requires 30 minutes of manual test verification, you need a full-time engineer just to keep up with testing. And that engineer will still miss the visual regression Cursor introduced by silently changing a Tailwind class.</p>
<blockquote>
<p>You can&#39;t test at the speed of AI with manual scripts. If you use Cursor to build, you need an agent to verify.</p>
</blockquote>
<p>This is where generative AI in testing stops being a nice-to-have and becomes the part of your stack that everything else depends on.</p>
<p>In ML, &quot;evals&quot; verify that a model&#39;s output matches intent. Bug0 applies the same principle to the UI. It&#39;s the eval layer for your frontend: verifying that what the agent built visually matches what the engineer intended. Not string-matching HTML. Not asserting DOM structure. Evaluating whether the user experience works.</p>
<h3><strong>The solution: Bug0 Studio</strong></h3>
<p>Think of <a href="https://bug0.com/studio">Bug0 Studio</a> as the Cursor for QA. It&#39;s an <a href="https://bug0.com/studio">AI-native end-to-end testing platform</a> that uses AI to generate, run, and heal <a href="https://playwright.dev/">Playwright</a>-based tests using the same agentic approach Cursor applies to development.</p>
<p>One detail that matters more than most teams realize:</p>
<blockquote>
<p><strong>Bug0 generates standard Playwright code.</strong> Not a proprietary DSL. Not a custom format you can&#39;t migrate away from. Standard <code>.spec.ts</code> files that run in your CI with <code>npx playwright test</code>. If you leave Bug0, you keep every test. No export process. No vendor lock-in.</p>
</blockquote>
<p>This is the question every CTO should ask before signing an AI testing contract: &quot;If we cancel, do we keep our tests?&quot; With Bug0, yes. With most competitors, no.</p>
<img src="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/54b81b237393d8e81463c55c/0f9935aa-48e4-4684-80cc-a5dcf6cd3fb6.png" alt="Bug0 Studio generating Playwright test from video upload, showing the video-to-code conversion interface with AI analysis and editable test steps" style="display: block; margin: 0 auto;" />

<h3><strong>Feature 1: Video-first engineering (the killer workflow)</strong></h3>
<p>Record a 30-second Loom of the happy path. Upload it to Bug0. That&#39;s it.</p>
<p>The AI watches the recording frame by frame. It identifies every click, every form input, every navigation event. It understands the intent behind each action, not just the coordinates. Then it generates a complete Playwright test suite.</p>
<p>Not a rough draft you spend an hour cleaning up. A working test that passes on the first run.</p>
<p>Other tools claim video-to-code. Most produce output that needs 30-60 minutes of manual editing before it passes. Bug0&#39;s vision models have been trained specifically on browser interactions, so the generated tests match what actually happened in the recording. Timing, scroll behavior, hover states, dynamic content. All captured. One honest limitation: vision models still struggle with ultra-fast animations and heavy CSS transitions. If your flow relies on a 150ms slide-in drawer that changes DOM state mid-animation, expect to hand-tune that step. The model sees the before and after, but the in-between gets noisy.</p>
<p>The workflow: Record. Upload. Run. Done.</p>
<h3><strong>Feature 2: Self-healing (and where it breaks)</strong></h3>
<p>Connect this back to Stage 2.</p>
<p>Cursor renames your <code>Submit</code> button class from <code>submit-btn</code> to <code>btn-primary</code>. Your hand-written Selenium script breaks. Your Cypress test referencing <code>[data-testid=&quot;submit-btn&quot;]</code> fails. Your CI goes red. A developer spends 45 minutes debugging what changed.</p>
<p>Bug0 sees the button is still there visually. Same position. Same text. Same behavior. It heals the test automatically. The selector updates. The test passes on the next run. No alerts. No manual fixes. No 45-minute debugging sessions.</p>
<p>A team we work with shipped a redesign of their settings page at 11pm on a Thursday. Cursor had rewritten 14 component files. The old class names were gone. Their hand-maintained Playwright suite would have produced 23 failures and a very long Friday morning. Bug0&#39;s self-healing caught all 23 selector changes, updated them, and the scheduled 6am test run passed clean. Nobody got paged. Nobody debugged anything. The engineer who shipped the redesign found out the tests healed when they checked the dashboard Monday morning.</p>
<p>To be clear: self-healing doesn&#39;t handle everything. <strong>If Cursor removes a feature entirely or changes business logic (not just selectors), Bug0 flags it as a real failure, not something to auto-fix.</strong> The healing works on structural changes: renamed classes, moved elements, updated component hierarchies. For logic changes, you still get a failure report with video, AI analysis, and console logs. You still have to look at it. The point is that 80% of the test breakage from agentic development is structural, and that&#39;s the 80% you shouldn&#39;t be debugging manually.</p>
<h3><strong>Feature 3: The managed option</strong></h3>
<p>Some teams don&#39;t want to operate testing tools at all. They want outcomes.</p>
<p><a href="https://bug0.com/managed-testing-services">Bug0 Managed</a> pairs AI-generated tests with forward-deployed QA engineers who maintain your entire test suite. You define what &quot;working&quot; means. They make sure it stays working. Starting at $2,500/month with flat billing and no surprises.</p>
<p>For decision-makers evaluating build vs. buy: this is the &quot;buy&quot; option that doesn&#39;t lock you into proprietary formats. Every test is standard Playwright. You own the code.</p>
<h3><strong>Quick look: Top generative AI testing tools (2026)</strong></h3>
<p>If you&#39;re evaluating ai tools for testing, here&#39;s where the landscape stands. These are the generative AI testing tools that matter for production use, not demos.</p>
<table style="min-width: 75px;"><colgroup><col style="min-width: 25px;"><col style="min-width: 25px;"><col style="min-width: 25px;"></colgroup><tbody><tr><th colspan="1" rowspan="1"><p>Tool</p></th><th colspan="1" rowspan="1"><p>Best for</p></th><th colspan="1" rowspan="1"><p>Starting price</p></th></tr><tr><td colspan="1" rowspan="1"><p><strong>Bug0 Studio</strong></p></td><td colspan="1" rowspan="1"><p>Agentic E2E and video-to-code</p></td><td colspan="1" rowspan="1"><p>\(250/mo</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Applitools</strong></p></td><td colspan="1" rowspan="1"><p>Pure visual regression</p></td><td colspan="1" rowspan="1"><p>Enterprise (\)10K+/yr)</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Qodo (formerly CodiumAI)</strong></p></td><td colspan="1" rowspan="1"><p>Unit and code-level tests</p></td><td colspan="1" rowspan="1"><p>Free / \(19/mo</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>QA Wolf</strong></p></td><td colspan="1" rowspan="1"><p>Done-for-you managed service</p></td><td colspan="1" rowspan="1"><p>\)5K+/mo</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Mabl</strong></p></td><td colspan="1" rowspan="1"><p>Low-code test automation</p></td><td colspan="1" rowspan="1"><p>~$400/mo</p></td></tr></tbody></table>

<p>Bug0 occupies the gap between &quot;write all your tests by hand&quot; and &quot;pay someone else to handle everything.&quot; You get AI-generated Playwright tests with self-healing and video-to-code, at a price point that doesn&#39;t require enterprise procurement approval.</p>
<h3><strong>The regulatory reality check</strong></h3>
<p>The EU AI Act is in phased enforcement, with prohibited AI practices and GPAI governance rules already active and the majority of high-risk obligations hitting in August 2026. Global regulations around AI-generated code, data handling, and automated decision-making are no longer theoretical. If your AI testing tool processes production data or user recordings, you need to know: where does that data go? Who trains on it? Is the tool SOC 2 compliant?</p>
<p>Enterprise buyers now ask a question that didn&#39;t exist two years ago:</p>
<blockquote>
<p><strong>Where are our agentic traces stored?</strong> Every time Cursor edits a file, Bug0 runs a test, or Sentry analyzes an error, that interaction generates a log. Those logs contain code, user flows, and error context. If your team is in the EU and your agentic traces live on a US server without a Data Processing Agreement, you have a compliance problem.</p>
</blockquote>
<p>Data residency for agentic traces is the new &quot;where is our data stored?&quot; It applies to every tool in the stack, not just your database.</p>
<p>Every tool in this stack should have a clear answer. Cursor offers privacy mode that prevents code from being used for training. Bug0 runs tests on isolated infrastructure with SOC 2 compliance. Vercel&#39;s data residency controls satisfy GDPR requirements. PostHog offers self-hosted deployments for teams that can&#39;t send telemetry to third-party servers.</p>
<p>&quot;Does it have a privacy mode?&quot; is now as important as &quot;Does it work?&quot;</p>
<hr>
<h2><strong>Stage 4: Deployment and ops (the invisible infra)</strong></h2>
<p><strong>The tool:</strong> <a href="https://vercel.com/">Vercel</a></p>
<p>Deployment used to be a ceremony. Merge to main. Trigger the pipeline. Wait for builds. Check staging. Approve production. Hope nothing breaks.</p>
<p>Vercel turned deployment into a side effect of pushing code. Every PR gets a preview URL. Every merge to main deploys to production. The infrastructure disappears.</p>
<p>In the AI-native stack, this matters because of volume. When Cursor generates 15 PRs a day and Bug0 validates them automatically, you need deployment infrastructure that doesn&#39;t bottleneck the flow. Vercel handles this with preview deployments for every branch, automatic rollbacks, and edge functions that scale without configuration.</p>
<p>The bigger shift: Infrastructure as Code is becoming Infrastructure from Intent. Tools like <a href="https://spacelift.io/">Spacelift</a> and Vercel&#39;s own configuration layer let you describe infrastructure goals and let the platform figure out the implementation. &quot;I need a globally distributed API with sub-100ms latency&quot; instead of writing Terraform files.</p>
<p>For the AI-native stack, deployment is the stage that should require the least human attention. Push code. Tests pass. Deploy happens. Move on.</p>
<hr>
<h2><strong>Stage 5: Observability (the feedback loop)</strong></h2>
<p><strong>The tool:</strong> <a href="https://posthog.com/">PostHog</a> or <a href="https://sentry.io/">Sentry</a></p>
<p>You shipped fast. The tests passed. The deploy succeeded. Now what?</p>
<p>Observability closes the loop. It tells you what&#39;s happening in production after the tests have run. Today, observability tools are getting the same AI treatment as every other stage.</p>
<p>PostHog&#39;s Max AI is adding session replay summarization. Instead of watching a 12-minute recording of a user struggling with your checkout flow, you get a paragraph: &quot;User attempted to apply a discount code three times. The input field cleared on each attempt due to a re-render triggered by the cart total component. User abandoned checkout after 4 minutes.&quot;</p>
<p>Sentry&#39;s error grouping uses AI to cluster related errors and explain root causes. Instead of a stack trace that points to line 247 of a minified bundle, you get: &quot;This TypeError occurs when the user&#39;s session token expires mid-checkout. The refresh logic fails silently because the error boundary catches the 401 but doesn&#39;t retry the original request.&quot;</p>
<p>The addition that closes the loop entirely: Sentry now suggests the fix directly and can open a PR in your repository. A production error triggers an AI analysis, generates a patch, and creates a pull request, routing it straight back to Stage 2. The engineer reviews the suggested fix in Cursor, Bug0 runs the regression suite against the PR, and the fix deploys through Vercel. From error to fix to production without a single Jira ticket.</p>
<h3><strong>Why this stage completes the stack</strong></h3>
<p>Observability is what turns the AI-native SDLC from a linear pipeline into a loop. Production errors feed back into Bug0 as new test cases. User behavior captured by PostHog becomes the next Loom recording you upload for test generation. Sentry alerts map directly to regression tests and, increasingly, to automated fix PRs.</p>
<p>The stack isn&#39;t five separate tools. It&#39;s a cycle: Design -&gt; Build -&gt; Test -&gt; Deploy -&gt; Observe -&gt; Fix -&gt; Test -&gt; Deploy. Each stage feeds the next. Each AI tool makes the others more effective. And the human stays in the loop at every seam, reviewing the AI&#39;s proposals before they hit production.</p>
<hr>
<h2><strong>The 1-person unicorn</strong></h2>
<img src="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/54b81b237393d8e81463c55c/4789abe6-d36f-4cf9-8a93-5739367ecec7.jpg" alt="Illustration of Unicorn" style="display: block; margin: 0 auto;" />

<p>Here&#39;s the full stack.</p>
<table style="min-width: 75px;"><colgroup><col style="min-width: 25px;"><col style="min-width: 25px;"><col style="min-width: 25px;"></colgroup><tbody><tr><th colspan="1" rowspan="1"><p>Stage</p></th><th colspan="1" rowspan="1"><p>Tool</p></th><th colspan="1" rowspan="1"><p>What it replaces</p></th></tr><tr><td colspan="1" rowspan="1"><p>Design</p></td><td colspan="1" rowspan="1"><p>v0 / Lovable</p></td><td colspan="1" rowspan="1"><p>Figma + designer handoff</p></td></tr><tr><td colspan="1" rowspan="1"><p>Development</p></td><td colspan="1" rowspan="1"><p>Cursor (Composer)</p></td><td colspan="1" rowspan="1"><p>Manual coding + code review overhead</p></td></tr><tr><td colspan="1" rowspan="1"><p>Testing</p></td><td colspan="1" rowspan="1"><p>Bug0 Studio</p></td><td colspan="1" rowspan="1"><p>Hand-written test suites + manual QA</p></td></tr><tr><td colspan="1" rowspan="1"><p>Deployment</p></td><td colspan="1" rowspan="1"><p>Vercel</p></td><td colspan="1" rowspan="1"><p>DevOps team + CI/CD babysitting</p></td></tr><tr><td colspan="1" rowspan="1"><p>Observability</p></td><td colspan="1" rowspan="1"><p>PostHog / Sentry</p></td><td colspan="1" rowspan="1"><p>Manual log analysis + session review</p></td></tr></tbody></table>

<p>With this stack, a single engineer has the output of a pre-2024 product team. Not because they work harder. Because every stage of the lifecycle has an AI agent handling the repetitive work while the human focuses on evaluation and decisions.</p>
<p>v0 proposes design. The engineer reviews it. Cursor proposes implementation. The engineer reviews the diff and checks it against <code>.cursorrules</code>. Bug0 generates verification. The engineer audits the assertions. Vercel deploys. PostHog and Sentry report back. The cycle continues.</p>
<p>Notice the pattern. Every stage is &quot;AI proposes, human evaluates.&quot; Not &quot;AI does everything.&quot; Not &quot;human does everything.&quot; A loop where agents handle volume and humans handle judgment.</p>
<p>This is the 10x engineer, and it&#39;s not about typing speed. It&#39;s about tool selection and the discipline to stay in the loop.</p>
<p>Start with the hardest part first: fixing the quality bottleneck. The gap between &quot;AI can build it&quot; and &quot;AI can verify it&quot; is where most teams are stuck. Close that gap, and the rest of the stack follows.</p>
<p><a href="https://bug0.com/studio">Try Bug0 Studio</a> to turn your next screen recording into a test suite.</p>
<h3><strong>Your human-in-the-loop checklist</strong></h3>
<p>Before every ship, verify the seams:</p>
<ul>
<li><p>[ ] Did you review the Cursor diff, not just the summary?</p>
</li>
<li><p>[ ] Are your <code>.cursorrules</code> up to date with current architecture decisions?</p>
</li>
<li><p>[ ] Did you audit Bug0&#39;s generated assertions, not just the pass/fail?</p>
</li>
<li><p>[ ] Does your Vercel preview deployment match staging behavior?</p>
</li>
<li><p>[ ] Are Sentry&#39;s auto-fix PRs reviewed before merge, not auto-merged?</p>
</li>
<li><p>[ ] Do you know where your agentic traces are stored and who can access them?</p>
</li>
</ul>
<p>The stack handles volume. You handle judgment. This checklist is where the two meet.</p>
<hr>
<h2><strong>FAQs</strong></h2>
<h3><strong>What is an AI-native SDLC?</strong></h3>
<p>An AI-native SDLC is a software development lifecycle where every stage, from design to observability, uses AI tools built specifically for that stage. Not AI-assisted (bolt-on copilots) but AI-native (the tool was designed around AI from day one). v0 doesn&#39;t add AI to Figma. It replaces the Figma workflow entirely. Bug0 doesn&#39;t add AI to Selenium. It replaces the test-writing workflow entirely.</p>
<h3><strong>Is the &quot;1-person unicorn&quot; actually realistic</strong></h3>
<p>Mostly realistic for output volume, misleading for everything else. One engineer with this stack can match a traditional team&#39;s feature velocity, test coverage, and deploy cadence. But a solo engineer doesn&#39;t have anyone to argue with about architecture decisions, catch their blind spots in code review, or tell them the feature they&#39;re building isn&#39;t what customers want. The stack replaces execution headcount. It doesn&#39;t replace the judgment that comes from a team with diverse experience.</p>
<h3><strong>What is generative AI in software testing?</strong></h3>
<p>Generative AI in software testing means using large language models and vision models to create complete test suites from natural language descriptions, video recordings, or application analysis. The AI generates new tests from scratch, not just autocompleting test code you started. Bug0 Studio is an example: you upload a screen recording, and it generates a full Playwright test suite that runs immediately.</p>
<h3><strong>How does agentic testing differ from traditional test automation?</strong></h3>
<p>Traditional automation follows a script: click element A, type text B, assert element C. When element A moves or gets renamed, the test breaks. Agentic testing receives a goal (&quot;complete the checkout flow&quot;) and figures out the steps dynamically. When the UI changes, the agent finds a new path to the same outcome. It&#39;s the difference between turn-by-turn GPS directions and telling someone the destination.</p>
<h3><strong>Why do you keep saying testing is the bottleneck? My deploys are fine.</strong></h3>
<p>Your deploys might be fine because you&#39;re not testing enough. Most teams that &quot;ship fast&quot; with AI tools are actually shipping with less verification than they had in 2023. They&#39;ve traded slow, thorough testing for fast, minimal testing, and the bugs show up in production instead of CI. The bottleneck isn&#39;t visible until you measure how many post-deploy hotfixes you&#39;re shipping, how often users hit broken flows, or how many Sentry alerts your team is ignoring.</p>
<h3><strong>How much does this full stack cost?</strong></h3>
<p>v0 has a free tier, with Pro at \(20/month. Cursor is \)20/month. Bug0 Studio starts at \(250/month. Vercel has a free tier, with Pro at \)20/month. PostHog has a generous free tier. For a solo engineer or small team, the full AI-native stack costs roughly \(300-350/month. Compare that to the \)15K-25K/month a traditional team of designers, developers, QA engineers, and DevOps would cost.</p>
<h3><strong>What about security and compliance with AI tools?</strong></h3>
<p>Every tool in this stack handles data differently. Ask three questions before adopting any AI tool: Does it offer a privacy mode that prevents your code from being used for model training? Is it SOC 2 compliant? Does it satisfy your data residency requirements (GDPR, EU AI Act)? Cursor, Bug0, and Vercel all offer privacy controls. PostHog offers self-hosted deployment. Don&#39;t assume compliance. Verify it.</p>
<h3><strong>What is &quot;shadow code&quot; and how do I prevent it?</strong></h3>
<p>Shadow code is AI-generated code that works but nobody on your team fully understands. It becomes a maintenance liability when it breaks. Prevent it with three practices: use <code>.cursorrules</code> or similar context files to constrain AI output to your team&#39;s patterns. Use AI-augmented code review tools (like Sourcegraph Cody) to help engineers understand generated code. And run agentic tests (Bug0) against every AI-generated PR so that even if the code is opaque, the behavior is verified.</p>
<h3><strong>What if I already have a Playwright test suite?</strong></h3>
<p>You don&#39;t have to start over. Bug0 works alongside existing test suites. Use it to generate new tests from video recordings or natural language while keeping your current tests running. Over time, the self-healing AI tests reduce the maintenance burden on your hand-written suite. Most teams transition gradually, not all at once.</p>
]]></description><link>https://hashnode.com/blog/the-ai-native-stack-2026-from-text-to-app-to-agentic-qa</link><guid isPermaLink="true">https://hashnode.com/blog/the-ai-native-stack-2026-from-text-to-app-to-agentic-qa</guid><category><![CDATA[AI]]></category><category><![CDATA[#ai-tools]]></category><category><![CDATA[vibe coding]]></category><category><![CDATA[1 person unicorn]]></category><category><![CDATA[Agentic QA]]></category><dc:creator><![CDATA[Syed Fazle Rahman]]></dc:creator></item><item><title><![CDATA[12 best generative AI testing tools (2026): Ranked and reviewed for QA engineers]]></title><description><![CDATA[<p><strong>tldr:</strong> Generative AI testing moved from demos to production pipelines. The tools that matter now use agentic testing, video-to-code, and self-healing to replace brittle scripts with intent-based QA. Here are 12 ranked by what holds up in real CI/CD.</p>
<hr />
<h2><strong>The testing tools you picked last year are already outdated</strong></h2>
<p>Selenium is still everywhere. It defined browser automation, and its <a href="https://www.selenium.dev/documentation/webdriver/">WebDriver protocol</a> became a W3C standard. Playwright replaced it technically (using <a href="https://playwright.dev/docs/api/class-cdpsession">CDP</a> instead of WebDriver), but Selenium's patterns and mental models still influence how most teams think about test automation. It's not going away. But the layer on top of raw browser protocols is changing fast.</p>
<p>A year ago, most "AI testing" tools were wrappers around GPT that generated flaky Cypress scripts. You'd spend an hour cleaning up what the AI produced, then another hour debugging why it failed in CI. <em>The value proposition was shaky.</em></p>
<p><strong>That's shifted.</strong> The newer tools use vision models that interpret your UI the way a human tester would. They navigate dynamically instead of following hardcoded selectors. When your team redesigns the settings page, the test finds the new path to the same outcome. Some tools call this agentic testing. Others call it self-healing. The labels vary. The capability is real, when it works.</p>
<p>The problem: most tools still don't work reliably in production CI/CD. They demo well on a clean todo app. They break on your actual product with auth flows, modals, and third-party iframes.</p>
<p>This ranking focuses on what holds up in real pipelines, not what looks good in a 3-minute walkthrough.</p>
<p><strong>Scope note:</strong> This list is weighted toward browser-based E2E and visual regression, but includes mobile-native (#9 Maestro) and LLM evaluation (#11 Promptfoo) because no honest 2026 testing list can ignore them. Accessibility-specific tooling and synthetic data generation are addressed in "What's not on this list" below.</p>
<table style="min-width:100px"><colgroup><col style="min-width:25px"></col><col style="min-width:25px"></col><col style="min-width:25px"></col><col style="min-width:25px"></col></colgroup><tbody><tr><th><p>Tool</p></th><th><p>Best for</p></th><th><p>Core tech</p></th><th><p>Pricing model</p></th></tr><tr><td><p><strong>Applitools</strong></p></td><td><p>Visual regression</p></td><td><p>Visual AI</p></td><td><p>~\(10K-50K/yr</p></td></tr><tr><td><p><strong>Bug0 Studio</strong></p></td><td><p>Agentic E2E and video-to-code</p></td><td><p>Playwright + vision models</p></td><td><p>~\)250/mo (usage)</p></td></tr><tr><td><p><strong>QA Wolf</strong></p></td><td><p>Done-for-you service</p></td><td><p>Human + AI hybrid</p></td><td><p>~\(5K+/mo</p></td></tr><tr><td><p><strong>Testim / Tricentis</strong></p></td><td><p>Enterprise legacy</p></td><td><p>Smart locators</p></td><td><p>~\)30K-100K/yr</p></td></tr><tr><td><p><strong>Qodo</strong> (formerly CodiumAI)</p></td><td><p>Unit test generation</p></td><td><p>Code analysis</p></td><td><p>Free / \(30/user/mo</p></td></tr><tr><td><p><strong>Mabl</strong></p></td><td><p>Low-code teams</p></td><td><p>SaaS cloud</p></td><td><p>~\)499/mo</p></td></tr><tr><td><p><strong>Functionize</strong></p></td><td><p>Data-heavy apps</p></td><td><p>ML engine</p></td><td><p>~\(20K-60K/yr</p></td></tr><tr><td><p><strong>Diffblue</strong></p></td><td><p>Java unit testing</p></td><td><p>AI code gen</p></td><td><p>~\)500/seat/yr</p></td></tr><tr><td><p><strong>Maestro</strong></p></td><td><p>Mobile-native testing</p></td><td><p>Accessibility tree + YAML DSL</p></td><td><p>Open source / ~\(250/mo per device</p></td></tr><tr><td><p><strong>Percy</strong></p></td><td><p>Visual snapshots</p></td><td><p>Pixel comparison</p></td><td><p>~\)399/mo</p></td></tr><tr><td><p><strong>Promptfoo</strong></p></td><td><p>LLM output evaluation</p></td><td><p>Assertion framework</p></td><td><p>Open source / enterprise custom</p></td></tr><tr><td><p><strong>Checkie.AI</strong> (now Testers.AI)</p></td><td><p>Autonomous testing agent</p></td><td><p>Vision AI</p></td><td><p>~$1,777/yr</p></td></tr></tbody></table>

<hr />
<h2><strong>How we ranked these tools</strong></h2>
<p>Three criteria matter when evaluating generative AI testing tools. Everything else is noise.</p>
<h3><strong>Agentic capabilities</strong></h3>
<p>Can the tool explore your UI without hardcoded steps? Agentic testing means the AI navigates your application like a real user. It reads the screen, decides where to click, and adapts when the layout changes. Most tools still require you to define every step. A few actually think for themselves.</p>
<p>The difference matters in practice. A traditional test says "click the button with id <code>submit-btn</code>." An agentic test says "submit the form." When your designer renames that button or moves it to a different section, the agentic test still works. The traditional test breaks.</p>
<img src="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/54b81b237393d8e81463c55c/d77d50cd-0e79-4f3e-9011-e375173eed46.png" alt="Diagram showing two flows side by side: a linear scripted test that breaks when a button selector changes versus an agentic test that re-navigates to the same goal through a different path after a UI redesign" style="display:block;margin:0 auto" />

<h3><strong>Self-healing tests</strong></h3>
<p>Every tool claims self-healing. Few deliver it. Real self-healing means when your <code>#add-to-cart</code> button becomes <code>.btn-cart</code>, the test updates its own selectors and passes on the next run. No alerts. No manual fixes. 90% of tools claim this capability. Maybe 20% handle it reliably in production CI/CD runs.</p>
<p>We evaluated each tool by running identical UI changes against their test suites and measuring how many tests survived without human intervention.</p>
<h3><strong>Tech stack and lock-in</strong></h3>
<p>Does the tool generate standard <a href="https://playwright.dev/">Playwright</a> code, or does it lock you into a proprietary format you can never leave? This matters more than most teams realize. If you build 500 tests on a platform that uses a custom DSL, you're stuck. If it generates Playwright under the hood, your tests have value beyond the vendor.</p>
<p>We also factored in pricing model. The industry is moving from flat SaaS subscriptions to usage-based billing (per test minute, per agent hour, per inference call). When comparing tools, we normalized to cost-per-test-run rather than sticker price. A tool at \(250/month that runs 200 tests and a tool at \)2,000/month that runs 5,000 tests have very different unit economics.</p>
<hr />
<h2><strong>#1: Applitools (best for visual AI)</strong></h2>
<p>Applitools built visual AI testing before the rest of the industry cared about it. Their "Eyes" technology compares screenshots across builds, browsers, and viewports using AI that understands layout rather than pixel-matching. It catches the visual regressions that functional tests miss entirely.</p>
<img src="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/54b81b237393d8e81463c55c/73a47db8-a783-4223-997a-03813c3d47f8.png" alt="Screenshot of Applitools in action." style="display:block;margin:0 auto" />

<p><strong>Starting price:</strong> Custom enterprise (typically $10K-50K/year depending on test volume and browser matrix)</p>
<p><strong>Best for:</strong> Teams with existing test suites who need visual regression coverage across browsers and devices.</p>
<p>Applitools earns the #1 spot because of maturity and reliability. They've been solving visual testing for years, and their AI has been trained on millions of screenshots. The Ultrafast Grid runs your visual checks across dozens of browser/viewport combinations in seconds, not minutes.</p>
<p>Their root cause analysis feature (shipped originally in 2018, refined since) surfaces the DOM and CSS differences behind visual failures. When a test fails, the platform shows which specific CSS property or DOM change caused the layout shift. That saves your team 15-20 minutes per failure investigation.</p>
<p><strong>What works:</strong></p>
<ul>
<li><p>Visual AI that distinguishes meaningful layout changes from harmless rendering differences</p>
</li>
<li><p>Ultrafast Grid renders across dozens of browser/viewport/device combinations in parallel</p>
</li>
<li><p>Integrates with Playwright, Cypress, Selenium, and most existing frameworks</p>
</li>
<li><p>Root cause analysis that surfaces the specific CSS or DOM change behind visual regressions</p>
</li>
</ul>
<p><strong>What doesn't:</strong></p>
<ul>
<li><p>You still need to write the test scripts yourself. Applitools validates what you see, not what you do</p>
</li>
<li><p>Enterprise pricing puts it out of reach for startups and small teams</p>
</li>
<li><p>Setup requires SDK integration into your existing test framework</p>
</li>
<li><p>No test generation. It's a validation layer, not a creation tool</p>
</li>
</ul>
<p><strong>The verdict:</strong> If your users see it, Applitools catches it. But you still need another tool to generate the tests in the first place.</p>
<hr />
<h2><strong>#2: Bug0 Studio (best for agentic E2E and video-to-code)</strong></h2>
<p>Bug0 Studio takes three types of input (plain English, video uploads, browser screen recordings) and converts them into Playwright-based test steps. The platform runs tests on its own infrastructure and auto-heals selectors when UI changes break locators.</p>
<p><strong>Starting price:</strong> ~$250/month (pay-as-you-go for test minutes, scales with usage)</p>
<p><strong>Best for:</strong> Engineering teams that want to generate E2E tests from recordings or natural language without writing Playwright code themselves.</p>
<p>The video-to-code feature is the main differentiator. You record yourself walking through a user flow. The AI produces a Playwright test from the recording. Other tools attempt this, but most generate outputs that need significant manual cleanup before they pass in CI. Bug0's output tends to be closer to runnable on the first attempt, though complex flows with auth tokens or multi-step modals still need editing.</p>
<img src="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/54b81b237393d8e81463c55c/cc6fa320-947c-4121-bad7-b0e7b03ec82c.png" alt="Bug0 Studio interface converting a screen recording into Playwright test steps with editable step list and run controls" style="display:block;margin:0 auto" />

<p>The agentic testing angle is real but worth qualifying. When you write a step like "complete the checkout flow," the AI agent navigates your app dynamically rather than replaying exact coordinates. If the checkout page gets redesigned, the agent looks for the new path. It works well for standard flows (forms, navigation, CRUD operations). It struggles with highly custom UI patterns and edge cases the way any AI agent does.</p>
<p>Self-healing runs during scheduled and manual test runs. When a selector breaks, the AI updates the locator. When it can't fix it, you get an alert. The failure mode is explicit, which matters more than the success rate.</p>
<p>It's a younger platform than most on this list, which cuts both ways. Fast iteration on features, but less battle-testing in large-scale production environments.</p>
<p><strong>What works:</strong></p>
<ul>
<li><p>Video-to-code produces Playwright tests that are close to runnable from screen recordings</p>
</li>
<li><p>Natural language test creation lowers the barrier for non-Playwright teams</p>
</li>
<li><p>Failed test reports include video, AI analysis, network logs, and console traces</p>
</li>
<li><p>GitHub Actions integration for CI/CD</p>
</li>
</ul>
<p><strong>What doesn't:</strong></p>
<ul>
<li><p>Newer platform with a smaller community. Less Stack Overflow coverage when you hit edge cases</p>
</li>
<li><p>Tests run on Bug0's infrastructure only. You can't export standalone Playwright scripts and can't debug tests locally in VS Code the way you would with standard Playwright</p>
</li>
<li><p>No self-serve signup yet. Requires a demo call to get started</p>
</li>
<li><p>Complex auth flows and custom UI components still need manual step editing</p>
</li>
</ul>
<p><strong>The verdict:</strong> The strongest option for generating E2E tests from video or natural language. The trade-off is platform maturity and vendor lock-in on test execution. Worth a trial if your team doesn't have Playwright expertise in-house.</p>
<hr />
<h2><strong>#3: QA Wolf (best for service-based hybrid)</strong></h2>
<p>QA Wolf isn't a tool. It's a service. You don't write tests. They do.</p>
<p><strong>Starting price:</strong> Custom pricing (typically $5K+/month)</p>
<p><strong>Best for:</strong> Teams that want test coverage without any involvement in test creation or maintenance.</p>
<p>QA Wolf pairs human QA engineers with AI automation to deliver end-to-end test suites. You get coverage. They handle everything: planning, writing, maintaining, and verifying test results. Their pitch is simple. You build features. They make sure nothing breaks.</p>
<p>The model works well for teams that don't have QA headcount and don't want to hire. You get a dedicated team that writes Playwright tests, maintains them when UI changes, and reviews every failure before it reaches your engineers.</p>
<img src="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/54b81b237393d8e81463c55c/511d38d8-c14c-4ecd-b08c-373be774412e.png" alt="Screenshot of QA Wolf dashboard that displays the list of tests." style="display:block;margin:0 auto" />

<p><strong>What works:</strong></p>
<ul>
<li><p>Zero maintenance burden on your team. They own the test suite end-to-end</p>
</li>
<li><p>Human verification of every failure. No false positives reaching your developers</p>
</li>
<li><p>Strong Playwright expertise. Tests are well-structured and reliable</p>
</li>
<li><p>Guaranteed coverage timelines</p>
</li>
</ul>
<p><strong>What doesn't:</strong></p>
<ul>
<li><p>Expensive for smaller teams. The service model has higher minimums than self-serve tools</p>
</li>
<li><p>Less control over test creation. You're trusting their judgment on what to test</p>
</li>
<li><p>Slower iteration. Requesting new tests means going through their team, not clicking a button</p>
</li>
<li><p>Dependency on their capacity. Scaling up means waiting for their availability</p>
</li>
</ul>
<p><strong>The verdict:</strong> If you'd rather buy results than operate tools, QA Wolf delivers. The trade-off is cost and control. Compare this to Bug0 Studio if you want the same AI-powered testing but with self-serve control at a lower price point.</p>
<hr />
<h2><strong>#4: Testim by Tricentis (best for enterprise stability)</strong></h2>
<img src="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/54b81b237393d8e81463c55c/84290ef0-fe76-461c-8c97-35f1ca08acb3.png" alt="Testim tool screenshot." style="display:block;margin:0 auto" />

<p>Testim is the tool your procurement team already approved.</p>
<p><strong>Starting price:</strong> Custom enterprise (typically $30K-100K+/year depending on seat count and modules licensed)</p>
<p><strong>Best for:</strong> Large organizations (500+ employees) with existing Tricentis contracts or compliance-driven QA processes.</p>
<p>Tricentis acquired Testim in early 2022 for $200M and integrated it into their enterprise suite alongside Tosca and qTest. (Testim remains a separately branded, actively maintained product.) The specific feature that matters: Smart Locators. These use a weighted algorithm across multiple element attributes (text content, CSS class, XPath, surrounding DOM structure, visual position) to identify elements. When one attribute changes, the locator falls back to the others. The practical result: fewer false failures from routine UI changes compared to single-attribute selectors.</p>
<p>In practice, Smart Locators handle straightforward UI changes well (button text changes, class renames, minor layout shifts). They struggle when multiple attributes change simultaneously, like during a major redesign. That's the gap between "adaptive locators" and actual agentic testing.</p>
<p>The platform also includes Testim's root cause analysis feature, which groups related test failures and identifies the likely source commit. This works through Git integration, not AI inference. It's useful when 15 tests break from one deploy and you need to know which PR caused it.</p>
<p><strong>What works:</strong></p>
<ul>
<li><p>Smart Locators using weighted multi-attribute element identification reduce false failures</p>
</li>
<li><p>Root cause analysis links test failures to specific commits via Git integration</p>
</li>
<li><p>SOC2, SAML SSO, RBAC, audit logs. The full enterprise compliance checklist</p>
</li>
<li><p>Embedded in the Tricentis ecosystem (Tosca, qTest, NeoLoad) if you already use their stack</p>
</li>
</ul>
<p><strong>What doesn't:</strong></p>
<ul>
<li><p>Tricentis ships major feature updates quarterly. Smaller competitors iterate weekly</p>
</li>
<li><p>Pricing is five or six figures annually. You're paying for the enterprise wrapper</p>
</li>
<li><p>Initial setup involves professional services. Expect 4-8 weeks to full deployment</p>
</li>
<li><p>The AI features (test generation from NLP) were added post-acquisition and feel bolted on compared to the core locator tech</p>
</li>
</ul>
<p><strong>The verdict:</strong> If you already use Tricentis products or your security team requires vendor questionnaires with SOC2 Type II attestation, Testim is the path of least resistance. The AI capabilities are real but conservative. You're buying reliability, not innovation.</p>
<hr />
<h2><strong>#5: Qodo (formerly CodiumAI) (best for unit testing and developer workflows)</strong></h2>
<p>Qodo (rebranded from CodiumAI in September 2024) solves a different problem than the other tools on this list. It generates unit and integration tests, not browser-based E2E tests.</p>
<img src="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/54b81b237393d8e81463c55c/c4b05825-172e-4ed3-8678-ed7f68c7bf66.png" alt="Qodo homepage screenshot." style="display:block;margin:0 auto" />

<p><strong>Starting price:</strong> Free tier (75 credits/month). Teams at $30/user/month.</p>
<p><strong>Best for:</strong> Individual developers who want AI-generated unit tests inside their IDE.</p>
<p>Qodo Gen (formerly Codiumate) analyzes your code and generates test cases that cover edge cases, boundary conditions, and error paths. It works inside VS Code and JetBrains IDEs, generating tests as you write code. The AI understands your function signatures, dependencies, and logic flow to produce meaningful tests.</p>
<p>This is valuable for improving code-level coverage. But it doesn't replace E2E testing. Qodo won't tell you if your checkout flow breaks after a deploy. It tells you if your <code>calculateTotal()</code> function handles null inputs correctly.</p>
<p><strong>What works:</strong></p>
<ul>
<li><p>Fast, contextual unit test generation inside the IDE</p>
</li>
<li><p>Good at finding edge cases developers miss</p>
</li>
<li><p>Free tier (75 credits/month) is generous enough for individual use</p>
</li>
<li><p>Supports Python, JavaScript, TypeScript, Java, and more</p>
</li>
</ul>
<p><strong>What doesn't:</strong></p>
<ul>
<li><p>Not an E2E testing tool. No browser automation. No visual testing</p>
</li>
<li><p>Generated tests sometimes need manual adjustment for complex business logic</p>
</li>
<li><p>Doesn't integrate with CI/CD as a standalone QA solution</p>
</li>
<li><p>Limited value for QA teams. This is a developer tool</p>
</li>
</ul>
<p><strong>The verdict:</strong> Great for developers who want better unit test coverage. Wrong tool for QA engineers evaluating E2E solutions. Include it in your developer toolkit, but don't count on it as your testing strategy.</p>
<hr />
<h2><strong>#6: Mabl (best for low-code testing)</strong></h2>
<p>Mabl makes test automation accessible to people who don't write code. That's its strength and its ceiling.</p>
<img src="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/54b81b237393d8e81463c55c/530389ee-2d9b-43b3-9cbf-d75d7b7ea97f.png" alt="Mabl tool screenshot" style="display:block;margin:0 auto" />

<p><strong>Starting price:</strong> Around $499/month for small teams</p>
<p><strong>Best for:</strong> Teams transitioning from manual testing to automation, with non-technical QA members.</p>
<p>Mabl's visual test builder lets you create tests by clicking through your application. The platform records your actions and generates tests with built-in assertions. AI-powered auto-healing updates selectors when elements change. It runs tests in Mabl's cloud, so there's no infrastructure to manage.</p>
<p>The onboarding experience is genuinely good. Non-technical QA team members can create meaningful tests within hours. The learning curve is shallow by design.</p>
<p><strong>What works:</strong></p>
<ul>
<li><p>Visual test builder requires zero coding</p>
</li>
<li><p>Auto-healing keeps tests running after UI changes</p>
</li>
<li><p>Cloud execution with no infrastructure management</p>
</li>
<li><p>Good onboarding for non-technical team members</p>
</li>
</ul>
<p><strong>What doesn't:</strong></p>
<ul>
<li><p>Pricing scales up quickly as test volume grows</p>
</li>
<li><p>Limited flexibility for complex testing scenarios</p>
</li>
<li><p>You'll hit the ceiling fast if your application has intricate workflows</p>
</li>
<li><p>Proprietary format. Your tests live in Mabl. No easy migration path</p>
</li>
</ul>
<p><strong>The verdict:</strong> Solid training wheels for test automation. If your team is new to automated testing, Mabl gets you started quickly. But expect to outgrow it within 12-18 months as your testing needs mature.</p>
<hr />
<h2><strong>#7-#12: Six more tools worth knowing</strong></h2>
<h3><strong>#7: Functionize (best for data-heavy applications)</strong></h3>
<p>Functionize runs ML models against your historical test execution data to predict which tests are likely to fail after a given code change. The platform prioritizes test runs based on risk scoring, so your CI pipeline runs the most relevant tests first.</p>
<p><strong>Starting price:</strong> Custom enterprise (typically $20K-60K/year based on test volume).</p>
<p>The core feature is adaptive test maintenance. Functionize tracks how your application's DOM structure changes over time and uses that history to update selectors before they break, not after. This works better than reactive self-healing for applications with predictable change patterns (e.g., a dashboard that adds new widgets regularly). NLP-based test creation is available but inconsistent. The plain-English-to-test conversion works for simple flows. Multi-step workflows with conditional logic need manual scripting.</p>
<p><strong>The verdict:</strong> Useful if your bottleneck is test prioritization across a large suite (500+ tests). The ML-based risk scoring saves CI minutes. But the enterprise-only pricing and 6-8 week onboarding make it hard to justify unless your test suite is already large enough to benefit from intelligent prioritization.</p>
<h3><strong>#8: Diffblue (best for Java unit testing)</strong></h3>
<p>Diffblue Cover automatically writes unit tests for Java code. It analyzes your codebase and generates JUnit tests that achieve high code coverage. The company raised $6.3M in late 2024 from existing investors and remains independently operated, focused exclusively on Java.</p>
<p><strong>Starting price:</strong> Per-seat licensing (typically $500+/seat/year).</p>
<p><strong>The verdict:</strong> If your stack is Java and you need unit test coverage fast, Diffblue does it better than any general-purpose AI. Useless for anything else.</p>
<h3><strong>#9: Maestro (best for mobile-native agentic testing)</strong></h3>
<p>Maestro is the closest thing to Playwright-style agentic testing for iOS and Android. You write flows in a YAML-based DSL, and the framework navigates native UI elements without relying on brittle XPath selectors. It reads the screen's accessibility tree and matches elements by label, type, and hierarchy.</p>
<p><strong>Starting price:</strong> Open source (free). Maestro Cloud starts at ~$250/month per device for CI execution.</p>
<p>The framework includes auto-wait logic that adapts to animation timing and network latency. MaestroGPT can help generate YAML flows, but the primary authoring experience is YAML, not natural language. (The team actually built and shut down a pure NL testing product, concluding that declarative YAML was more reliable.) It handles the problem that kills most Appium tests: timing flakiness on real devices. The limitation is ecosystem. Maestro's community is smaller than Playwright's, and complex gestures (multi-finger swipe, drag-and-drop) still need manual scripting.</p>
<p><strong>The verdict:</strong> If you ship mobile apps alongside your web product, Maestro is the only tool on this list that covers native iOS/Android. Open source core keeps costs low. But expect to invest in writing flows manually. The AI generation layer isn't as mature as web-side tools.</p>
<h3><strong>#10: Percy by BrowserStack (best for visual snapshot testing)</strong></h3>
<p>Percy captures screenshots of your application during test runs and flags visual differences between builds. BrowserStack acquired Percy to complement their browser testing infrastructure.</p>
<p><strong>Starting price:</strong> Starts at ~$399/month for the Team plan. Free tier includes 5,000 monthly screenshots.</p>
<p>Percy integrates with your existing test framework (Playwright, Cypress, Selenium) and adds a visual review layer. The review UI lets your team approve or reject visual changes per build.</p>
<p><strong>The verdict:</strong> A lighter, cheaper alternative to Applitools for teams that need visual regression coverage without the enterprise pricing. Less sophisticated AI, but covers the basics.</p>
<h3><strong>#11: Promptfoo (best for LLM output evaluation)</strong></h3>
<p>Promptfoo is an open-source framework for testing LLM outputs. If your product includes AI features (chatbots, summarization, search), you need to verify that model responses are accurate, safe, and consistent. Promptfoo runs test suites against your prompts and scores responses on criteria like factual accuracy, toxicity, and format compliance.</p>
<p><strong>Starting price:</strong> Open source (free). Promptfoo Enterprise for team collaboration uses custom pricing.</p>
<p>This isn't browser testing. It's a different category entirely. But including it matters because the biggest QA challenge for many teams isn't "does the button work" but "does the AI hallucinate." Promptfoo lets you define assertions like "response must not contain PII" or "answer must reference only provided context documents" and runs them against hundreds of prompt variations. Red teaming presets test for jailbreaks and safety violations out of the box.</p>
<p><strong>The verdict:</strong> If you ship LLM-powered features, you need an evaluation framework alongside your browser E2E suite. Promptfoo is the most accessible option: open source, CLI-first, and integrates with CI/CD via an official GitHub Action. Different category than the other tools here, but arguably more critical for teams building AI products.</p>
<h3><strong>#12: Checkie.AI / Testers.AI (best for autonomous AI agent testing)</strong></h3>
<p>Checkie.AI rebranded to Testers.AI and now positions itself as a "virtual test team." It uses vision AI agents to test web applications by looking at the screen rather than parsing the DOM.</p>
<p><strong>Starting price:</strong> Core Coverage at \(1,777/year. Pro at \)4,777/year.</p>
<p>The vision-first approach means it can test applications that resist traditional automation (heavy canvas rendering, complex SVGs, WebGL). The rebrand reflects a shift from pure vision testing to a broader autonomous testing agent that covers functionality, performance, and security.</p>
<p><strong>The verdict:</strong> No longer early access but still a small player. Worth evaluating if your application has unusual rendering that breaks traditional DOM-based automation.</p>
<hr />
<h2><strong>What's not on this list (but should be on your radar)</strong></h2>
<p>This ranking includes mobile (#9 Maestro) and LLM evaluation (#11 Promptfoo) alongside the browser-focused tools. Three categories still didn't make the cut but affect most teams.</p>
<h3><strong>Accessibility testing under the European Accessibility Act</strong></h3>
<p>The European Accessibility Act (EAA) enforcement started in mid-2025. If you serve EU customers, automated accessibility testing is a compliance requirement, not a nice-to-have. axe-core handles rule-based a11y checks. The newer tools (Evinced, accessiBe's CI scanner, and Arc Toolkit) use AI to detect issues that rule-based systems miss: poor color contrast in dynamic themes, keyboard navigation dead ends, screen reader incompatibility in SPAs. None of the 12 tools above handle this well. You need a dedicated a11y layer in your pipeline. Budget for it separately.</p>
<h3><strong>Synthetic test data generation</strong></h3>
<p>Most AI testing tools focus on scripts and ignore the data problem. Your E2E tests need realistic user data: names, emails, addresses, payment details. Using production data in staging is a PII risk. Hardcoding test data makes tests brittle and tightly coupled to specific database states. Tools like Tonic.ai, Gretel, and Snaplet generate synthetic datasets that match your production schema without exposing real user data. If your test failures are caused by bad test data more often than bad scripts, this is where to invest first.</p>
<h3><strong>Pricing models are shifting under you</strong></h3>
<p>The pricing models on this list still mostly reflect the SaaS subscription era. The industry is moving toward usage-based billing: cost per test minute, per agent hour, or per inference call. When comparing tools, normalize costs to "price per test run on my actual app" rather than comparing monthly stickers. A tool at \(200/month that runs 100 tests and a tool at \)2,000/month that runs 10,000 tests have very different unit economics. Ask vendors for their cost-per-test-run on your specific application before signing anything.</p>
<hr />
<h2><strong>Glossary: What the marketing terms actually mean</strong></h2>
<p>Every vendor uses these terms. Most define them loosely. Here's what to look for when a tool claims each capability.</p>
<h3><strong>Agentic testing</strong></h3>
<p>A test system that receives a goal and decides the navigation steps at runtime. Concrete example: you write "add an item to the cart and check out." The agent opens your app, finds a product (even if the product grid layout changed since last run), clicks "Add to cart," navigates to checkout, and fills the form. If your team moves the cart icon from the header to a sidebar, the agent locates it in the new position. The key distinction from record-and-replay: agentic tests don't store a fixed sequence of DOM interactions. They re-plan each run.</p>
<h3><strong>Self-healing</strong></h3>
<p>The test runner detects that a selector (<code>#submit-btn</code>) no longer matches any element, searches for the most likely replacement (maybe <code>button.primary-action</code> or the button with text "Submit"), updates the locator, and passes. This happens during the CI run, not after a human intervenes. When evaluating vendors, ask: "What's your self-heal success rate on production UI changes, not demo apps?" Most won't give you a number. The ones that do are worth talking to.</p>
<img src="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/54b81b237393d8e81463c55c/046d056a-df2c-4143-a3d3-66b1f0b1bd08.png" alt="Process diagram of self-healing test mechanics: selector fails, AI searches for replacement by text content and DOM position and visual location, updates locator, re-runs assertion, passes or alerts human" style="display:block;margin:0 auto" />

<h3><strong>Video-to-code</strong></h3>
<p>You record a Loom (or any screen recording) of yourself completing a user flow. The tool's vision model watches the recording frame-by-frame, identifies each interaction (clicks, typing, scrolling, waiting for elements to load), and outputs a Playwright test script. The practical test: upload a 60-second recording of your actual app's login-to-dashboard flow. If the output passes without edits, the tool works. If you spend 20 minutes fixing selectors and adding waits, it doesn't.</p>
<h3><strong>Generative AI in software testing</strong></h3>
<p>AI that creates complete, new test cases rather than assisting with ones you've already written. The distinction matters: Copilot autocompleting your <code>expect()</code> statement is AI-assisted testing. A tool that analyzes your app's routes and produces 50 test cases covering happy paths, error states, and edge cases is generative AI in software testing. The output is a full test suite, not a code suggestion.</p>
<h3><strong>Intent-based testing</strong></h3>
<p>Writing test assertions as outcomes ("user sees confirmation page with order number") rather than implementation steps (<code>await page.waitForSelector('.order-confirmation'); expect(page.locator('.order-id')).toBeVisible()</code>). The testing system translates the intent into specific DOM interactions based on the current state of the page. When the confirmation page gets redesigned, the intent stays the same. The implementation steps update automatically.</p>
<img src="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/54b81b237393d8e81463c55c/dd4c7e1e-a8c7-4e17-8f21-58058744e6b3.png" alt="Diagram comparing traditional selector-based testing flow versus intent-based agentic testing flow, showing how each handles a UI redesign" style="display:block;margin:0 auto" />

<hr />
<h2><strong>Stop writing scripts, start auditing results</strong></h2>
<p>The generative AI testing tools market has real options now, not just demos. The right choice depends on your constraint.</p>
<p><strong>If pixel-perfect UI matters most,</strong> Applitools remains the gold standard for visual regression. Pair it with any test generation tool.</p>
<p><strong>If you want to describe tests in English or record a video and get working Playwright suites,</strong> <a href="https://bug0.com/">Bug0 Studio</a> is the strongest option for agentic testing and video-to-code.</p>
<p><strong>If you want zero involvement in testing,</strong> QA Wolf and similar managed services handle everything. You pay more, but you do less.</p>
<p><strong>If enterprise procurement drives your decisions,</strong> Testim by Tricentis checks every compliance box.</p>
<p>The common thread across the best tools: they test intent, not implementation. They heal when UI changes. They generate <a href="https://playwright.dev/">Playwright</a> code, not proprietary scripts. Your job isn't to write tests anymore. It's to define what "working" means and let the tools prove it.</p>
<hr />
<h2><strong>FAQs</strong></h2>
<h3><strong>What is generative AI testing?</strong></h3>
<p>AI that produces complete test cases from inputs like natural language, video recordings, or application analysis. The "generative" part distinguishes it from AI-assisted testing (like Copilot autocompleting your test code). A generative tool takes "test the login flow with invalid credentials" and outputs a full Playwright script with navigation, input, submission, and error assertion. You run it. It either passes or it doesn't.</p>
<h3><strong>How is agentic testing different from traditional test automation?</strong></h3>
<p>Traditional automation stores a fixed sequence: click <code>#login-btn</code>, type into <code>#email-field</code>, assert <code>.dashboard</code> is visible. If any selector changes, the test fails. Agentic testing stores the goal: "log in and verify the dashboard loads." At runtime, the agent inspects the current page, identifies the login form regardless of its selectors, fills it, and checks the result. The practical difference shows up after a UI redesign. Traditional tests need manual updates. Agentic tests re-plan the steps automatically. The limitation: agents still fail on ambiguous UIs where multiple valid paths exist, or when your app requires non-obvious interaction patterns.</p>
<h3><strong>Do video-to-code tools actually work in production?</strong></h3>
<p>Run this test yourself: record a 90-second flow through your actual app (not a demo). Include a login, at least one form interaction, and a page navigation. Upload it to the tool. If the generated test passes in CI without edits, the tool works for your use case. In our evaluation, most tools required 15-40 minutes of manual cleanup per recording on real applications. A few produced near-runnable output. The variable is your app's complexity, specifically dynamic content, custom components, and third-party embeds are where video-to-code breaks down.</p>
<h3><strong>Can AI testing replace QA engineers?</strong></h3>
<p>It replaces the tasks nobody wants to do: maintaining 300 selectors, re-running regression suites manually, writing boilerplate test setup. It doesn't replace the judgment calls. Deciding which flows are critical, interpreting whether a visual change is intentional or a bug, understanding that "the button works but the UX is confusing" those need a human. The teams getting the most value use AI for coverage and repetition while their QA engineers focus on test strategy, exploratory testing, and release decisions.</p>
<h3><strong>Which tool should I choose for my team?</strong></h3>
<p>Start with your biggest problem, not the most impressive demo. If your tests break every sprint from UI changes, you need self-healing (Applitools, Bug0 Studio, Testim). If you have no tests at all, you need generation (Bug0 Studio, Qodo, Mabl). If you don't have anyone to own the test suite, you need a service (QA Wolf). If your procurement process takes 6 months and you need to start now, pick a tool with a free tier (Qodo, Maestro) and evaluate enterprise options in parallel.</p>
<h3><strong>How much does Bug0 Studio cost?</strong></h3>
<p>Starts at ~\(250/month pay-as-you-go for test minutes. Scales with usage. Unlimited tests, test suites, and AI credits included. Bug0 Managed (done-for-you QA with dedicated engineers) starts at ~\)2,500/month flat. For comparison, Applitools runs \(10K-50K/year, Testim/Tricentis runs \)30K-100K/year, and QA Wolf starts around $5K/month.</p>
<h3><strong>What should I test during a vendor evaluation?</strong></h3>
<p>Don't use the vendor's demo app. Record your actual application's most complex user flow, the one that breaks the most. Upload it or describe it in natural language. Run the generated test in your staging environment. Then change something in the UI (rename a button, move a section) and run the test again without updating it. That second run tells you whether the self-healing actually works. Most vendors will happily demo on their own app. The ones that let you test on yours during the evaluation are the ones worth shortlisting.</p>
]]></description><link>https://hashnode.com/blog/best-generative-ai-testing-tools-2026</link><guid isPermaLink="true">https://hashnode.com/blog/best-generative-ai-testing-tools-2026</guid><category><![CDATA[AI]]></category><category><![CDATA[AI QA]]></category><category><![CDATA[AI Testing Tools]]></category><dc:creator><![CDATA[Syed Fazle Rahman]]></dc:creator></item><item><title><![CDATA[From ChatGPT for Testing to Full Automation: Why I Built My Own AI Testing Tool]]></title><description><![CDATA[<h2 id="heading-i-got-tired-of-pasting-dom-snippets-so-i-built-a-tool-that-uses-video-to-generate-playwright-scripts">I got tired of pasting DOM snippets, so I built a tool that uses video to generate Playwright scripts.</h2>
<p>If you are anything like us, your browser history is likely a graveyard of Gemini conversations and ChatGPT threads named "Fix this Playwright Selector" or "Generate Test Script."</p>
<p>We have all tried using <strong>ChatGPT for testing</strong>. It usually goes like this: you open the dev tools, copy a massive chunk of your DOM, paste it into ChatGPT, and pray it understands which <code>&lt;button&gt;</code> is actually the "Submit" button.</p>
<p>It works, but it is exhausting. It feels less like "full automation" and more like advanced copy-pasting.</p>
<p>We recently went down a rabbit hole looking for a better <strong>AI testing tool</strong>. We needed something that could take the logic of an LLM but apply it directly to the browser without the manual friction. When we couldn't find exactly what we needed, we teamed up with our co-founder, <a target="_blank" href="https://x.com/Sandeepg33k">Sandeep</a>, and the Bug0 crew to build it.</p>
<p>It is called <strong>Bug0 Studio</strong> (at <a target="_blank" href="https://vibe.bug0.com?utm_source=hashnode.com/blog&amp;utm_medium=article">vibe.bug0.com</a>), and it has completely shifted how we generate Playwright scripts. It is the same core technology we use to serve our enterprise customers in our <a target="_blank" href="https://bug0.com?utm_source=hashnode.com/blog&amp;utm_medium=article">Forward Deployed Engineering (FDE) model in QA testing</a>, so we knew it had to be robust.</p>
<p>Here is the story of why we built it, and why it has become the <strong>best AI software testing tool</strong> for our own workflow.</p>
<h2 id="heading-the-problem-why-text-prompts-arent-enough">The Problem: Why Text Prompts Aren't Enough</h2>
<p>The biggest limitation we faced when <strong>using ChatGPT for usability testing</strong> or script generation was <em>blindness</em>. An LLM (Large Language Model) doesnt see your site; it only reads the text you feed it.</p>
<p>Sure, you can use <strong>ChatGPT for guerilla usability testing</strong> ideas. You can ask it to generate user personas or hypothetical scenarios. But when it comes to the actual <em>execution</em>, specifically writing the code that clicks the button, it often fails because it lacks context. It doesn't know that your "Login" button is actually hidden behind a cookie banner, or that your specific React component renders differently on mobile.</p>
<p>We wanted a workflow that felt like ChatGPT. It needed to be conversational and smart, but we needed it to have "eyes" on our application.</p>
<h2 id="heading-enter-bug0-studio-the-vibe-testing-approach">Enter Bug0 Studio: The "Vibe" Testing Approach</h2>
<p>We designed Bug0 Studio as a <strong>vibe testing platform</strong>. The idea was straightforward: instead of writing code or messing with complex prompts, we simply wanted to show the AI the "vibe" of the user journey and have it generate the script.</p>
<p>We designed the workflow to be as simple as possible:</p>
<ol>
<li><p><strong>Record, Upload, or Type:</strong> We made it flexible - you can record your browser tab directly, upload a video file (mp4/webm), or just describe the flow in natural language text.</p>
</li>
<li><p><strong>Describe:</strong> You tell it what you are testing in plain English.</p>
</li>
<li><p><strong>Get Code:</strong> It processes the video recording along with your text description and spits out a fully working Playwright test.</p>
</li>
</ol>
<p>We needed a real <strong>AI tool for automation testing</strong> that connects the user's view directly to the code logic.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763622661026/15cbf7c2-b2c8-45d0-a8ad-69e0f0616e06.png" alt="A screenshot of the Bug0 Studio landing page showing the &quot;Record Tab&quot; and &quot;Upload Video&quot; options side-by-side." class="image--center mx-auto" /></p>
<p><em>Bug0 Studio Screenshot: The entry point is simple: either record live or upload a video.</em></p>
<h2 id="heading-the-lazy-developers-dream-setup">The "Lazy Developer's" Dream Setup</h2>
<p>What we focused on most wasn't just the AI generation, but the specific configuration options. Most <strong>AI tools for testing</strong> require a lot of boilerplate setup. We tried to identify the exact pain points developers (including ourselves) have when setting up test suites.</p>
<p>When you start a session, we designed a configuration panel that handles the boring stuff:</p>
<ol>
<li><p><strong>Site Setup:</strong> You just drop in your <strong>Base URL</strong>.</p>
</li>
<li><p><strong>Login Credentials:</strong> You can provide optional Email/Password fields so the AI understands authentication flows.</p>
</li>
<li><p><strong>Storage State JSON:</strong> This is the killer feature we knew we needed.</p>
</li>
</ol>
<p>We are paranoid about security, so we made a specific design choice here. We designed the system so that your Base URL and credentials stay in localStorage on your machine. They aren't stored permanently on our servers, which is a huge relief.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763622814890/b631c182-6d57-4594-9e06-f76d73a08ec4.png" alt="A close-up screenshot of the Bug0 Studio configuration panel. Specifically highlighting the &quot;Storage State JSON&quot; field and the Login Credentials section. " class="image--center mx-auto" /></p>
<p><em>Being able to paste a Playwright storage state JSON means you can test deep-link flows without re-logging in every time.</em></p>
<p>If you have ever written E2E tests for a dashboard behind a login wall, you know the pain. Usually, you have to script the login steps for <em>every single test</em>. With Bug0, you can just paste your Playwright <code>storageState</code> JSON, and the AI assumes that session. It effectively acts as an <strong>AI tool for manual testing</strong> logic that automates the setup for you.</p>
<h2 id="heading-a-practical-example">A Practical Example</h2>
<p>A simple checkout flow is the best way to show how we use it effectively. This is usually a nightmare for brittle selectors.</p>
<p><strong>The Workflow:</strong></p>
<ol>
<li><p>We clicked "Record Tab" in Bug0 Studio.</p>
</li>
<li><p>We clicked on a product, added it to the cart, and proceeded to checkout.</p>
</li>
<li><p>We stopped the recording.</p>
</li>
<li><p><strong>The Validation Step:</strong> We didn't want it to be a "black box," so we built an intermediate step. The AI analyzes the video and extracts a list of <strong>ordered steps</strong>. We can actually edit, add, or remove steps right there. This allows us to fix a logic error we made during recording <em>before</em> the AI writes any code.</p>
</li>
<li><p>We verified the steps and hit "Generate."</p>
</li>
</ol>
<p><strong>The Result:</strong> Once the generation started, the tool spun up a <strong>live cloud browser</strong> session. We watched a split-screen view: on the left, the AI was explaining its logic in real-time; on the right, we saw a live preview of the test actually running on the cloud browser.</p>
<p>It wasn't just "guessing" based on HTML; it was executing the "vibe" of the user journey in front of our eyes, ending with a generated Playwright script that used robust locators like <code>getByRole</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763623460017/0f6bcf1f-efc8-4f35-a41a-dae1de0b394d.png" alt="A split-screen image. On the left, a frame of the video recording showing the checkout. On the right, the generated code block showing the Playwright script." class="image--center mx-auto" /></p>
<h2 id="heading-the-landscape-why-we-built-this">The Landscape: Why We Built This</h2>
<p>When searching for an AI testing tool, we mostly found three types of solutions. Here is why we found them frustrating enough to build our own solution:</p>
<h3 id="heading-1-the-chatbots-chatgpt-claude">1. The Chatbots (ChatGPT, Claude)</h3>
<p>We love them, but they are <strong>blind</strong>. You have to feed them HTML snapshots or screenshot uploads manually. If the DOM changes or uses dynamic classes (like CSS modules), the bot often hallucinates selectors that look correct but fail immediately.</p>
<p>Zero real-time visual context; requires constant manual copy-pasting.</p>
<h3 id="heading-2-the-literal-recorders-playwright-codegen">2. The "Literal" Recorders (Playwright Codegen)</h3>
<p>These tools are technically impressive, but they are literal to a fault. If we accidentally click the wrong field and then correct ourselves, the recorder scripts <em>both</em> actions. They also tend to default to specific hierarchical selectors (e.g., <code>div:nth-child(3)</code>) which break the moment we add a new UI element.</p>
<p>Brittle scripts. They record actions, not intent.</p>
<h3 id="heading-3-the-black-box-enterprise-suites">3. The "Black Box" Enterprise Suites</h3>
<p>There are plenty of "Autonomous Testing Agents" out there. They promise self-healing and zero-code, but they usually require us to install their heavy SDKs, run tests on their specific cloud infrastructure, and pay enterprise pricing.</p>
<p>Vendor lock-in. We designed Bug0 Studio to just give us standard Playwright code that we can run in our own local VS Code or CI/CD pipeline.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>We are seeing a flood of AI tools right now, and it is hard to tell which ones are actually useful. But if you are looking for a <strong>ChatGPT for testing</strong> alternative that is purpose-built for modern web apps, we invite you to check out what we've built.</p>
<p>It solves the context problem by using video, and it solves the setup problem by handling Auth and Storage States natively.</p>
<p>Give it a spin at <a target="_blank" href="https://vibe.bug0.com?utm_source=hashnode.com/blog&amp;utm_medium=article"><strong>Bug0 Studio</strong></a>. Its surprisingly fun to just upload a video and watch clean code appear. We truly believe this is not just a temporary fix, but the blueprint for the <strong>best AI software testing tool</strong> of the future.</p>
<p>Feel free to hop on into our <a target="_blank" href="https://go.bug0.com/discord">Discord</a> and share your thoughts or feature requests.</p>
]]></description><link>https://hashnode.com/blog/chatgpt-for-testing-alternative-playwright-automation</link><guid isPermaLink="true">https://hashnode.com/blog/chatgpt-for-testing-alternative-playwright-automation</guid><category><![CDATA[ChatGPT for Testing]]></category><category><![CDATA[Vibe Testing Tool]]></category><category><![CDATA[AI Testing Tools]]></category><category><![CDATA[Bug0]]></category><dc:creator><![CDATA[Syed Fazle Rahman]]></dc:creator></item><item><title><![CDATA[Tech's secret weapon: The complete 2026 guide to the forward deployed engineer (role, salary, and interviews)]]></title><description><![CDATA[<p><strong>tldr:</strong> The Forward Deployed Engineer is the hottest role in tech right now, with an 800% spike in job listings and total compensation ranging from $200K to $630K+. Here's everything you need to know about the role, who's hiring, and how to land the job.</p>
<hr />
<p>As AI and data platforms grow more complex, one role keeps showing up in every hiring pipeline: the <strong>Forward Deployed Engineer</strong>.</p>
<p>Companies like OpenAI and Palantir are scaling these teams fast. Job postings are exploding, with some reports citing an <strong>800% spike in FDE job listings</strong> this year (<a target="_blank" href="https://radicaldatascience.wordpress.com/2025/11/04/ai-news-briefs-bulletin-board-for-november-2025/">Source: <em>Radical Data Science / Indeed Report</em></a>). Top-tier VC firms and tech media have dubbed it the "hottest job in startups" (<a target="_blank" href="https://news.crunchbase.com/ai/forward-deployed-software-engineer-sales-team-coker-felicis/">Source: <em>Crunchbase News</em></a>). Why? Because this role is about one thing: <strong>execution.</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762340298888/7cf243fd-0739-47ca-b9f2-c0d5a953f7b3.jpeg" alt="A smart software engineering sitting infront of desktop and super focused on work." class="image--center mx-auto" /></p>
<h3 id="heading-what-is-a-forward-deployed-engineer">What is a forward deployed engineer?</h3>
<p>A <strong>Forward Deployed Engineer (FDE)</strong>, or <strong>Forward Deployed Software Engineer (FDSE)</strong>, is an elite, hybrid technical role. These are your best engineers, the ones you embed directly with your biggest customers to solve their hardest, highest-stakes problems.</p>
<p>They operate with the autonomy of a founder but the technical rigor of a staff engineer. "Deployed" from HQ to the customer's "forward" position: their offices, their data centers, their messy reality. Empowered to build, design, and ship production code to make that customer win.</p>
<p>They aren't just engineers. They aren't just consultants. They are hybrid, high-ownership builders. Below is a breakdown of the current salary data, core responsibilities, and the specific "decomposition" interview format used by firms like <strong>Palantir</strong> and <strong>OpenAI</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762340975997/f3412f96-1043-4dbf-b2b8-62589b654990.jpeg" alt="A stock image displaying Palantir's logo in 3D style." class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-what-is-a-forward-deployed-engineer-the-definition-and-meaning">What is a forward deployed engineer? The definition and meaning</h2>
<p>The <strong>forward deployed engineer definition</strong> is simple. It's built on two concepts:</p>
<ol>
<li><p><strong>"Forward Deployed":</strong> This is a military term. It means you're on the front lines. You're not safe at headquarters. For an FDE, this means leaving the comfort of the office and living inside the customer's world: with their messy data, their complex security, and their urgent, real-world problems.</p>
</li>
<li><p><strong>"Engineer":</strong> This is the critical part. An FDE is not a sales rep, a consultant, or a support agent. They are hands-on-keyboard builders. They write, debug, and ship production-grade code. They build data pipelines. They deploy systems. They <em>build</em>.</p>
</li>
</ol>
<p>The <strong>meaning</strong> of the role <em>in practice</em> is to be the human bridge between a powerful, generic platform (like Palantir's Foundry or OpenAI's GPT models) and a customer's unique, specific problem. They make the technology <em>work</em> for that client.</p>
<hr />
<h2 id="heading-what-does-a-forward-deployed-engineer-do-role-and-responsibilities">What does a forward deployed engineer do? (Role and responsibilities)</h2>
<p>The <strong>forward deployed engineer role</strong> has one central mission: <strong>own the customer's technical success. Whatever it takes.</strong></p>
<h3 id="heading-a-look-at-a-forward-deployed-engineer-job-description">A look at a forward deployed engineer job description</h3>
<p>Look at any <strong>OpenAI forward deployed engineer job description</strong>. You'll see these <strong>role responsibilities</strong>:</p>
<ul>
<li><p>Embed deeply with customers. Lead complex, high-stakes deployments.</p>
</li>
<li><p>Map customer problems, structure the solution, and ship it. Fast.</p>
</li>
<li><p>Design, build, and deploy full-stack systems and custom data pipelines that create real value.</p>
</li>
<li><p>Act as the primary technical owner. Build trust. Guide the customer's own teams.</p>
</li>
<li><p>Find reusable patterns. Bring field insights back to your core product team.</p>
</li>
<li><p>Troubleshoot the most complex production outages. Be the last line of defense.</p>
</li>
</ul>
<h3 id="heading-the-day-to-day-an-fdes-four-stage-loop">The day-to-day: An FDE's four-stage loop</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762341043073/1e77dabe-c713-4241-af47-72a72bee3d1e.jpeg" alt="An illustration displaying an FDE's Four-Stage Loop" class="image--center mx-auto" /></p>
<p>An FDE's work is a four-stage loop:</p>
<ol>
<li><p><strong>Scoping:</strong> You get a vague problem: "We need to cut fraud" or "We want to use AI in our factory." You dig in, find the <em>real</em> problem, and define a concrete technical plan.</p>
</li>
<li><p><strong>Prototyping:</strong> You move fast. You build a proof-of-concept (PoC). This is rapid, hands-on coding to show the customer what's possible. You get fast feedback.</p>
</li>
<li><p><strong>Deployment:</strong> The PoC works. Now, you harden it. You rewrite it to be production-grade, scalable, and secure. You navigate the client's infrastructure and get it live.</p>
</li>
<li><p><strong>Feedback:</strong> You're the company's eyes and ears. You see what customers <em>need</em>. You take these insights back to the core product and research teams. You help build better products.</p>
</li>
</ol>
<hr />
<h2 id="heading-forward-deployed-engineer-vs-software-engineer-vs-solutions-architect">Forward deployed engineer vs. software engineer vs. solutions architect</h2>
<p>Don't confuse the FDE with other roles. The difference is about <em>shipping</em> and <em>ownership</em>.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Role</strong></td><td><strong>Primary goal</strong></td><td><strong>Key activity</strong></td><td><strong>Customer interaction</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Forward Deployed Engineer</strong></td><td>Customer success via <em>custom, production-grade solutions.</em></td><td><strong>Building and deploying</strong></td><td>Deeply embedded, long-term partner.</td></tr>
<tr>
<td><strong>Software Engineer (core)</strong></td><td>Build and maintain the <em>core, scalable product</em> for all users.</td><td><strong>Coding features</strong></td><td>Minimal; filtered through product managers.</td></tr>
<tr>
<td><strong>Solutions Architect / Sales Engineer</strong></td><td>Get the technical "win" <em>during the sales process.</em></td><td><strong>Designing and demoing</strong></td><td>Pre-sales; high-level and strategic.</td></tr>
</tbody>
</table>
</div><p>The Sales Engineer <em>sells</em> the dream. The core Software Engineer <em>builds</em> the toolbox. The Forward Deployed Engineer <em>uses</em> that toolbox to build the custom, finished solution for the client.</p>
<hr />
<h2 id="heading-which-companies-hire-forward-deployed-engineers">Which companies hire forward deployed engineers?</h2>
<p>This role is hottest at companies selling complex, high-value platforms. It's not a job. It's a go-to-market strategy for products that need deep, technical integration to win.</p>
<h3 id="heading-the-pioneer-palantir">The pioneer: Palantir</h3>
<p>The <strong>Palantir Forward Deployed Software Engineer</strong> (or FDSE) is the original. Palantir built its entire multi-billion dollar company on this model. They embed these elite engineers with massive government and commercial clients (think military, banks, manufacturing) to solve huge, complex data problems. The <strong>Palantir forward deployed engineer role</strong> is legendary for its autonomy, high stakes, and massive impact. They are the definition of "owning the problem."</p>
<ul>
<li><strong>Job Portal:</strong> <a target="_blank" href="https://www.palantir.com/careers/">Palantir Careers</a></li>
</ul>
<h3 id="heading-the-new-wave-the-ai-and-data-giants">The new wave: The AI and data giants</h3>
<p>The AI boom created an explosive need for FDEs. GPT-4 is a raw API. The FDE is the one building the enterprise-grade application, RAG pipelines, and security layers that make it usable for a bank or a hospital. This is the new talent war.</p>
<ul>
<li><p><strong>OpenAI:</strong> An <strong>OpenAI Forward Deployed Engineer</strong> is on the front line of the AI revolution. They embed with Fortune 500s to <em>apply</em> generative AI, fine-tuning models, building new agentic workflows, and proving the business case.</p>
<ul>
<li><strong>Job Portal:</strong> <a target="_blank" href="https://openai.com/careers">OpenAI Careers</a></li>
</ul>
</li>
<li><p><strong>Anthropic:</strong> As a primary competitor to OpenAI, Anthropic's FDEs (often called "Applied AI Engineers") have the same mission: embed with enterprises to make their Claude models solve real, specific, high-value problems.</p>
<ul>
<li><strong>Job Portal:</strong> <a target="_blank" href="https://www.anthropic.com/careers">Anthropic Careers</a></li>
</ul>
</li>
<li><p><strong>Cohere:</strong> Another major AI lab, Cohere hires FDEs to work on their "Agentic Platform," helping businesses build and deploy custom AI agents.</p>
<ul>
<li><strong>Job Portal:</strong> <a target="_blank" href="https://cohere.com/careers">Cohere Careers</a></li>
</ul>
</li>
<li><p><strong>Databricks:</strong> The data and AI giant hires "AI Engineers, FDE" to help customers build and productionize first-of-their-kind AI applications on the Databricks platform.</p>
<ul>
<li><strong>Job Portal:</strong> <a target="_blank" href="https://www.databricks.com/company/careers">Databricks Careers</a></li>
</ul>
</li>
<li><p><strong>Scale AI:</strong> The data infrastructure leader for AI hires "Forward Deployed Data Scientist/Engineers" who thrive on "ambiguity" and "first-principles thinking" to architect data solutions for top AI labs and enterprises.</p>
<ul>
<li><strong>Job Portal:</strong> <a target="_blank" href="https://scale.com/careers">Scale AI Careers</a></li>
</ul>
</li>
</ul>
<h3 id="heading-the-new-breed-modern-startups-and-scale-ups">The new breed: Modern startups and scale-ups</h3>
<p>The FDE model is now the strategic weapon for the most ambitious, high-growth startups. They build their go-to-market <em>around</em> this role.</p>
<ul>
<li><p><strong>Ramp:</strong> This fintech unicorn hires <strong>Ramp Forward Deployed Engineers</strong> to handle complex enterprise migrations and build custom integrations. Their own engineering blog calls the role a "strategic unlock for modern B2B companies."</p>
<ul>
<li><strong>Job Portal:</strong> <a target="_blank" href="https://ramp.com/careers">Ramp Careers</a></li>
</ul>
</li>
<li><p><strong>Bug0:</strong> A clear example of the FDE model evolving into "Outcome-as-a-Service." <a target="_blank" href="https://bug0.com">Bug0</a> offers two tiers: <strong>Studio</strong> for self-serve teams who generate their own AI-powered Playwright tests, and <strong>Managed</strong> for teams who want a full FDE pod. The Managed pod owns the entire QA lifecycle: test planning, AI-assisted generation (from natural language or video recordings), human verification, bug filing with repro steps, and release gating. It's the FDE-as-revenue-multiplier model applied to testing, removing the need for a full in-house QA department.</p>
<ul>
<li><strong>Website:</strong> <a target="_blank" href="https://bug0.com/">Bug0</a></li>
</ul>
</li>
<li><p><strong>Superblocks:</strong> A fast-growing internal tools platform, their job postings for "Founding Forward Deployed Engineer" explicitly look for people who are "all-in and committed to building a generational AI company, far beyond a 9 to 5 job."</p>
<ul>
<li><strong>Job Portal:</strong> <a target="_blank" href="https://www.superblocks.com/careers">Superblocks Careers</a></li>
</ul>
</li>
<li><p><strong>HoneyHive:</strong> An AI observability startup, they hire their "first Forward Deployed Engineer" to be a "foundational role" in the company, acting as the technical bridge to their enterprise customers.</p>
<ul>
<li><strong>Job Portal:</strong> <a target="_blank" href="https://careers.honeyhive.ai/">HoneyHive Careers</a></li>
</ul>
</li>
<li><p><strong>Matta:</strong> An AI startup for manufacturing, their FDE job description is pure founder-speak: "This isn't a role with a playbook You'll roll up your sleeves and get problems sorted."</p>
<ul>
<li><strong>Job Portal:</strong> <a target="_blank" href="https://www.matta.ai/careers">Matta Careers</a></li>
</ul>
</li>
<li><p><strong>Adobe:</strong> This model is now being adopted by established tech giants. Adobe hires "Forward Deployed AI Engineers" to help customers build with its Firefly AI models, proving the FDE role is here to stay.</p>
<ul>
<li><strong>Job Portal:</strong> <a target="_blank" href="https://www.adobe.com/careers.html">Adobe Careers</a></li>
</ul>
</li>
</ul>
<hr />
<h2 id="heading-forward-deployed-engineer-salary-why-its-one-of-techs-highest-paid-roles">Forward deployed engineer salary: Why it's one of tech's highest-paid roles</h2>
<p>The <strong>forward deployed engineer salary</strong> is massive for one reason: skill scarcity. You need to be a strong engineer <em>and</em> a high-empathy communicator who can manage a multi-million dollar relationship.</p>
<p><em>Note: TC = Total Compensation (base + stock + bonus). The 2024/2025 hype was driven by "AI FOMO." The 2026 market has shifted toward proven ROI. Companies are paying these premiums only for engineers who can demonstrate a direct link between their deployments and customer retention.</em></p>
<h3 id="heading-the-benchmark-palantir-forward-deployed-engineer-salary">The benchmark: Palantir forward deployed engineer salary</h3>
<p>Palantir pays. Average TC for an FDE is now <strong>$238,000</strong>, with the range typically between <strong>$205,000 and $486,000</strong>. Staff-level FDEs are clearing <strong>$630,000+</strong>.</p>
<h3 id="heading-the-new-standard-openai-forward-deployed-engineer-salary">The new standard: OpenAI forward deployed engineer salary</h3>
<p>AI labs are in a talent war. OpenAI and Anthropic TC packages have stabilized at <strong>$350,000 - $550,000</strong> for mid-to-senior levels. These roles are benchmarked against top researchers. They need engineers who can fine-tune models <em>and</em> handle a Fortune 500 CTO.</p>
<h3 id="heading-general-salary-expectations">General salary expectations</h3>
<p>For a <strong>forward deployed engineer salary</strong> at other companies:</p>
<ul>
<li><p><strong>Entry-level / new grad:</strong> $180,000 - $250,000 TC</p>
</li>
<li><p><strong>Mid-level (3-5+ yrs):</strong> $250,000 - $400,000+ TC</p>
</li>
</ul>
<h3 id="heading-where-the-jobs-are">Where the jobs are</h3>
<p>One shift worth noting: <strong>New York (35% of FDE postings)</strong> has surpassed San Francisco (11%) as the primary hub. The demand is concentrated in fintech and highly regulated industries where FDEs navigate complex compliance requirements alongside technical integration.</p>
<p>The high pay reflects the high-stress, high-impact, and high-travel nature of the job. You're paid for leverage.</p>
<hr />
<h2 id="heading-how-to-become-a-forward-deployed-engineer">How to become a forward deployed engineer</h2>
<p>Getting a <strong>forward deployed engineer job</strong> is hard. The interviews are designed to break you. They test for technical skill, problem-solving, and personal grit. You can't just be book-smart. You have to be a builder who can ship.</p>
<h3 id="heading-what-background-do-you-need">What background do you need?</h3>
<p>Companies don't just hire former FDEs. They look for people who have <em>acted</em> like one. The best backgrounds are:</p>
<ul>
<li><p><strong>Early-stage startup engineer:</strong> This is the #1 predictor. If you were one of the first 10 engineers at a startup, you've already done this job. You've talked to customers, worn all the hats, and shipped code to save the company.</p>
</li>
<li><p><strong>Hands-on solutions architect:</strong> Not the SAs who only make diagrams. The ones who build the PoC themselves, write custom scripts, and live in the terminal.</p>
</li>
<li><p><strong>Data engineer / ML engineer (with engineering chops):</strong> If you don't just live in notebooks and you've built and deployed data pipelines or productionized models, you're a fit.</p>
</li>
<li><p><strong>Full-stack engineer (with product sense):</strong> A developer who doesn't just take tickets but talks to the product manager to question <em>why</em> they're building something.</p>
</li>
</ul>
<h3 id="heading-the-must-have-skills-a-t-shaped-profile">The must-have skills: A "T-shaped" profile</h3>
<p>FDE hiring looks for "T-shaped" people. Deep expertise in one area, broad skills in many others.</p>
<h4 id="heading-deep-technical-bar-the-vertical-i">Deep technical bar (the vertical "I")</h4>
<p>You must be a strong, hands-on engineer. "Good enough" isn't good enough.</p>
<ul>
<li><p><strong>Coding:</strong> You need to be fluent in <strong>Python</strong>. It's the language of data and AI. Familiarity with <strong>Java</strong>, <strong>Go</strong>, or <strong>TypeScript/JavaScript</strong> is also key for building full-stack solutions.</p>
</li>
<li><p><strong>Data:</strong> "I know SQL" is the bare minimum. You need to understand data processing (e.g., <strong>Spark</strong>), data pipelines (e.g., <strong>Airflow</strong>), and database trade-offs (SQL vs. NoSQL, OLAP vs. OLTP).</p>
</li>
<li><p><strong>Systems (DevOps/MLOps):</strong> You're deploying production code. You must understand the stack:</p>
<ul>
<li><p><strong>Cloud:</strong> Deep knowledge of <strong>AWS</strong>, <strong>GCP</strong>, or <strong>Azure</strong>.</p>
</li>
<li><p><strong>Containers:</strong> You must know <strong>Docker</strong> and <strong>Kubernetes</strong>.</p>
</li>
<li><p><strong>Infrastructure:</strong> Experience with <strong>Terraform</strong> or other IaC tools is a huge plus.</p>
</li>
</ul>
</li>
<li><p><strong>AI / ML (for AI FDEs):</strong> This is the 2026 non-negotiable skill set. The industry has moved past chatbots into <strong>agentic workflows</strong>, where AI systems autonomously execute multi-step tasks (filing claims, routing supply chain parts, running QA suites).</p>
<ul>
<li><p><strong>Core concepts:</strong> You must understand <strong>RAG</strong> (Retrieval-Augmented Generation), fine-tuning, vector databases, and <strong>agentic orchestration</strong> (frameworks like <strong>LangGraph</strong> or <strong>CrewAI</strong>).</p>
</li>
<li><p><strong>Evaluation frameworks (evals):</strong> You need to know how to build and run <strong>evals</strong> that prove an AI agent won't go rogue in production. This is what separates a demo from a deployment.</p>
</li>
<li><p><strong>AI observability and guardrails:</strong> The 2026 FDE is the person who proves to the customer's security team that the agent is safe. Tools like <strong>LangSmith</strong>, <strong>Braintrust</strong>, or <strong>HoneyHive</strong> for tracing, monitoring, and constraining agent behavior.</p>
</li>
<li><p><strong>Frameworks:</strong> Hands-on experience with <strong>PyTorch</strong> or <strong>TensorFlow</strong> and <strong>HuggingFace</strong>.</p>
</li>
</ul>
</li>
</ul>
<h4 id="heading-broad-execution-skills-the-horizontal-bar">Broad execution skills (the horizontal bar)</h4>
<p>This is what separates an FDE from a core engineer. This is the hard part.</p>
<ul>
<li><p><strong>Customer fluency and empathy:</strong> You can't just talk to engineers. You must be able to explain a complex system to a non-technical executive <em>and</em> understand their business problem. You translate business needs into technical specs.</p>
</li>
<li><p><strong>Grit and radical ownership:</strong> A deployment fails at 2 AM. You don't file a ticket. You don't blame another team. You don't go to sleep. You fix it. Period. You own the problem from end to end.</p>
</li>
<li><p><strong>Problem decomposition:</strong> You must thrive in chaos. You can take a massive, vague, scary problem (like "Our supply chain is broken") and break it into a clear, shippable, step-by-step plan.</p>
</li>
<li><p><strong>Product sense:</strong> You're the eyes of the product team. You have to spot patterns. When you build the same custom script for three different customers, you identify it and tell the product team to build it into the platform.</p>
</li>
</ul>
<h3 id="heading-the-interview-process-how-to-win">The interview process: How to win</h3>
<p>The process is multi-stage. Each round tests a different part of your "T".</p>
<ol>
<li><p><strong>Behavioral / fit interview:</strong> This is the "horizontal bar" test.</p>
<ul>
<li><p>Questions: "Why an FDE?", "Tell me about a time you handled a demanding stakeholder," "Describe a complex project you owned from 0 to 1," "Tell me about a time you failed."</p>
</li>
<li><p><strong>How to win:</strong> Use the <strong>STAR method</strong> (Situation, Task, Action, Result). Show ownership, not just participation. Your stories <em>must</em> be about you shipping code and solving a problem, not just being on a team.</p>
</li>
</ul>
</li>
<li><p><strong>Technical deep dive(s):</strong> This is the "vertical bar" test.</p>
<ul>
<li><p><strong>Coding:</strong> This won't be a simple LeetCode problem. It will be a practical, real-world task. (e.g., "Here's a messy 1GB JSON file, parse it, clean it, and expose an API to query it.")</p>
</li>
<li><p><strong>System design:</strong> This will be data-heavy. (e.g., "Design a real-time analytics pipeline for a million IoT devices," "Architect a RAG system for a company's internal wikis.").</p>
</li>
</ul>
</li>
<li><p><strong>The case study / decomposition interview:</strong> This is the hardest round.</p>
<ul>
<li><p>This is the famous <strong>Palantir forward deployed engineer interview</strong>. It's now used by almost every company hiring FDEs.</p>
</li>
<li><p>You get a massive, ambiguous, real-world problem on a whiteboard.</p>
</li>
<li><p><strong>Classic example:</strong> "A major city wants to use our platform to reduce 911 emergency response times. They have 911 call data, traffic data, and ambulance GPS data. You have 60 minutes. Go."</p>
</li>
<li><p><strong>2026 agentic example:</strong> "A global logistics firm wants an AI agent to handle automated rerouting for delayed shipments. They have SAP data, real-time weather APIs, and 500 different warehouse managers. How do you build the eval suite to ensure the agent doesn't overspend on shipping while maintaining a 99% delivery rate?"</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-how-to-prep-and-pass-the-decomposition-interview">How to prep and pass the "decomposition" interview</h3>
<p>This isn't about getting the "right answer." It's about showing <em>how you think</em>.</p>
<ol>
<li><p><strong>Do not jump to a solution.</strong> Your first instinct will be "Build an AI to predict traffic!" Don't. You will fail.</p>
</li>
<li><p><strong>Ask questions (clarify and scope):</strong> Start by interviewing your interviewer.</p>
<ul>
<li><p>"What's the <em>actual</em> goal? Is it 30 seconds or 10 minutes?"</p>
</li>
<li><p>"Who is the <em>user</em>? The 911 operator? The ambulance driver? The public?"</p>
</li>
<li><p>"What does the data <em>look like</em>? Is it clean? How often does it update?"</p>
</li>
<li><p>"What are the <em>constraints</em>? What's the budget? What's the timeline?"</p>
</li>
</ul>
</li>
<li><p><strong>Decompose the problem:</strong> Break the big problem into small, solvable chunks.</p>
<ul>
<li><p>"Okay, I see three main problems to solve:</p>
<ol>
<li><p><strong>Ingestion:</strong> We need to get all this messy data in one place.</p>
</li>
<li><p><strong>Visibility:</strong> The operators need a real-time map of all ambulances and new incidents.</p>
</li>
<li><p><strong>Optimization:</strong> We need a model to suggest the <em>best</em> ambulance for a new incident."</p>
</li>
</ol>
</li>
</ul>
</li>
<li><p><strong>Propose an MVP (version 1):</strong> Propose the <em>simplest possible thing</em> that delivers value.</p>
<ul>
<li>"Forget the AI model for now. V1 will be a simple data pipeline and a real-time dashboard. Just <em>seeing</em> all the ambulances on a map would be a huge win for the operators."</li>
</ul>
</li>
<li><p><strong>Iterate and discuss trade-offs:</strong> The interviewer will now push you. "Okay, the data is messy, what do you do?" "How do you scale that?"</p>
<ul>
<li>Talk through your trade-offs. "I'd use Kafka for ingestion because we need real-time, but it's complex. A simple polling API might be better for the MVP."</li>
</ul>
</li>
</ol>
<p>Most candidates fail because they try to show off their knowledge of a specific tool (like Kafka or Pinecone) before they even understand the user's latency requirements. Don't be that person. Be the engineer who cares more about the 911 operator's workflow than the database schema.</p>
<p>To win, <strong>think out loud</strong>. Show them your structured, logical, first-principles thinking. Show them you're a builder who can handle chaos and own a problem.</p>
<hr />
<h2 id="heading-the-future-of-the-fde-role">The future of the FDE role</h2>
<p>The Forward Deployed Engineer is not a trend. It's the future of high-value B2B tech.</p>
<h3 id="heading-the-integration-wall">The integration wall</h3>
<p>Most AI projects fail not because the model is bad, but because it can't talk to the customer's legacy SQL databases, handle their OIDC/SAML authentication, or meet their data residency requirements. This is the "integration wall," and it's where FDEs earn their compensation.</p>
<p>The 2026 FDE is the person who breaks through this wall. They understand that getting a demo working in a sandbox is 20% of the job. The other 80% is navigating enterprise SSO, legacy ETL pipelines, regulatory constraints, and the politics of getting production credentials from a customer's security team. No amount of prompt engineering fixes those problems. You need someone on-site, with production access, who can ship.</p>
<h3 id="heading-why-fdes-are-the-new-revenue-multiplier">Why FDEs are the new revenue multiplier</h3>
<p>Companies are realizing that the most advanced platform is useless if it sits on a shelf. The <strong>AI Forward Deployed Engineer</strong> is the key to <em>getting real results</em> from AI. In a world where platforms are becoming commodities, the ability to deploy them and create value is the only thing that matters.</p>
<hr />
<h2 id="heading-faqs">FAQs</h2>
<h3 id="heading-what-does-forward-deployed-engineer-mean">What does "forward deployed engineer" mean?</h3>
<p>A Forward Deployed Engineer (FDE) is a hybrid technical role where engineers embed directly with customers to solve their hardest problems. They write production code, build custom solutions, and own the customer's technical success end to end. They're embedded at the customer's site, working on the customer's problems, with the customer's data.</p>
<h3 id="heading-how-much-does-a-forward-deployed-engineer-make-in-2026">How much does a forward deployed engineer make in 2026?</h3>
<p>Forward Deployed Engineer salaries are among the highest in tech. At Palantir, average TC is $238,000, ranging from $205,000 to $486,000, with staff-level FDEs clearing $630,000+. OpenAI and Anthropic have stabilized at $350,000-$550,000 for mid-to-senior levels. New grad TC at most companies starts at $180,000-$250,000. New York (35% of postings) has surpassed San Francisco (11%) as the primary FDE hub due to fintech and regulated-industry demand.</p>
<h3 id="heading-whats-the-difference-between-a-forward-deployed-engineer-and-a-software-engineer">What's the difference between a forward deployed engineer and a software engineer?</h3>
<p>A core software engineer builds the product for all users. A Forward Deployed Engineer takes that product and builds custom, production-grade solutions for specific customers. The FDE is deeply embedded with the client, owns the relationship, and ships code to solve that customer's unique problems. Core engineers rarely interact with customers directly.</p>
<h3 id="heading-who-hires-forward-deployed-engineers-in-2026">Who hires forward deployed engineers in 2026?</h3>
<p>Palantir pioneered the role. Today, AI companies (OpenAI, Anthropic, Cohere, Databricks, Scale AI), fintech companies (Ramp), AI-native QA platforms (<a target="_blank" href="https://bug0.com">Bug0</a>), and established giants like Adobe all hire FDEs. Job listings for the role have spiked 800% as companies realize they need engineers who can deploy complex platforms for enterprise customers.</p>
<h3 id="heading-how-do-i-prepare-for-a-forward-deployed-engineer-interview">How do I prepare for a forward deployed engineer interview?</h3>
<p>FDE interviews typically include three stages: behavioral/fit interviews testing communication and ownership, technical deep dives testing coding and system design, and the famous "decomposition" case study. For the case study, don't jump to solutions. Ask clarifying questions, break the problem into solvable chunks, propose a simple MVP, then iterate. Think out loud and show structured, first-principles reasoning.</p>
<h3 id="heading-what-skills-do-forward-deployed-engineers-need-in-2026">What skills do forward deployed engineers need in 2026?</h3>
<p>FDEs need a "T-shaped" profile. Deep technical skills in coding (Python, TypeScript), data (SQL, Spark), and systems (AWS/GCP, Docker, Kubernetes). Plus broad execution skills: customer empathy, radical ownership, problem decomposition, and product sense. For AI FDEs in 2026, the bar has shifted to agentic orchestration (LangGraph, CrewAI), evaluation frameworks, and AI observability/guardrails, on top of RAG and fine-tuning fundamentals.</p>
<h3 id="heading-is-the-forward-deployed-engineer-role-the-same-as-a-solutions-architect">Is the forward deployed engineer role the same as a solutions architect?</h3>
<p>No. A solutions architect designs solutions and demos them during the sales process. A Forward Deployed Engineer builds and deploys production-grade solutions after the deal is signed. The SA sells the dream. The FDE makes it real. FDEs write code, deploy systems, and own the customer's technical success long-term.</p>
<h3 id="heading-how-does-bug0-use-forward-deployed-engineers">How does Bug0 use forward deployed engineers?</h3>
<p><a target="_blank" href="https://bug0.com">Bug0</a> applies the FDE model to quality assurance as "Outcome-as-a-Service." They offer two tiers: Studio (self-serve AI test generation) and Managed (a full FDE pod that owns your QA). The Managed pod plans tests, generates them using Bug0's agentic AI engine from natural language or video recordings, verifies results with human judgment, files bugs with repro steps, and gates releases. It's a clear example of how the FDE model is expanding beyond data platforms into specialized domains like testing.</p>
]]></description><link>https://hashnode.com/blog/a-complete-2026-guide-to-the-forward-deployed-engineer</link><guid isPermaLink="true">https://hashnode.com/blog/a-complete-2026-guide-to-the-forward-deployed-engineer</guid><category><![CDATA[AI]]></category><category><![CDATA[Forward-Deployed Engineer]]></category><category><![CDATA[openai]]></category><category><![CDATA[palantir]]></category><category><![CDATA[Bug0]]></category><category><![CDATA[AI QA]]></category><category><![CDATA[FDE]]></category><dc:creator><![CDATA[Syed Fazle Rahman]]></dc:creator></item><item><title><![CDATA[How AI is transforming QA testing: from manual tests to fully autonomous agents]]></title><description><![CDATA[<p>Software teams have automated almost everything, except QA. Even with modern tools, testing slows releases, breaks pipelines, and eats engineering time.</p>
<p>Most teams still depend on manual testers or complex automation setups that constantly need fixing. QA was built to ensure quality. Somewhere along the way, it became the blocker.</p>
<h2 id="heading-the-broken-state-of-qa-today"><strong>The broken state of QA today</strong></h2>
<p>Manual QA doesnt scale. Every UI change means another round of tests. Bugs slip through. Automation helped. But it also created a new mess. Scripts break. Maintenance piles up. Regressions drag.</p>
<p>Your stack is moving at 2025 speed. Your QA is stuck in 2015.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762267577156/ebfda79f-033f-4920-851e-a98746f802b2.png" alt="Screenshot displaying various tabs in a QA Test report." class="image--center mx-auto" /></p>
<h2 id="heading-the-first-wave-automation-and-scripts"><strong>The first wave: automation and scripts</strong></h2>
<p>Tools like Selenium and Cypress helped, but only to a point. Someone still writes, maintains, and fixes tests after every UI update.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762267619309/f5715846-e12c-4d35-90a0-1edd9bf9ddc9.png" alt="Screenshot displaying the logos of Selenium and Cypress testing frameworks." class="image--center mx-auto" /></p>
<p>Even solid QA teams struggle to cross 60% coverage. When tests flake, they get disabled just to ship. Sound familiar?</p>
<h2 id="heading-the-second-wave-ai-assisted-qa"><strong>The second wave: AI-assisted QA</strong></h2>
<p>Then AI entered the picture. Generative models could finally read user flows and turn them into test scripts. Self-healing systems began fixing broken selectors. Coverage improved. Maintenance dropped.</p>
<p>The problem is AI-only tools are dumb. They miss context. They can't tell a critical flow from a minor visual change. AI was a good first step. But it still needed a human to be reliable.</p>
<p>This was also the phase when <strong>AI QA tools</strong> and <strong>AI testing tools for QA automation</strong> started emerging. They proved AI could work. But they failed at real scale. They couldn't handle edge cases.</p>
<h2 id="heading-the-next-leap-agentic-qa-with-human-in-loop"><strong>The next leap: agentic QA with human-in-loop</strong></h2>
<p>Now we have agentic AI. This AI acts like a real QA engineer. It thinks for itself.</p>
<p>You still need a human in the loop. You get AI speed <em>and</em> human precision. This hybrid model is the new standard.</p>
<h2 id="heading-the-rise-of-the-forward-deployed-engineer-fde-model"><strong>The rise of the Forward-Deployed Engineer (FDE) model</strong></h2>
<p>Modern AI QA now runs automated browser tests on every pull request without slowing developers. This creates faster feedback loops and smoother CI/CD workflows.</p>
<p><a target="_blank" href="https://bug0.com/">Bug0</a> is pioneering the Forward-Deployed Engineer (FDE) model. It's the next evolution. AI handles test creation, execution, and maintenance. FDEs verify results, catch false positives, and align QA with your sprint goals.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762267649462/501a8bce-a779-4847-a054-1a7ef46055ef.png" alt="Screenshot of Bug0's homepage, bug0.com, displaying the tagline Meet your AI QA Engineer." class="image--center mx-auto" /></p>
<h3 id="heading-how-it-works"><strong>How it works</strong></h3>
<ul>
<li><p><strong>AI creates and maintains</strong> all critical browser tests automatically.</p>
</li>
<li><p><strong>FDEs validate and triage</strong> issues in real time.</p>
</li>
<li><p><strong>CI/CD integration</strong> ensures every release is tested before users touch it.</p>
</li>
</ul>
<p>Results:  100% of critical flows covered in 7 days  80% total coverage in 4 weeks  Zero setup required</p>
<p>Its QA built for the AI era. Machines handle the volume. Humans ensure the precision.</p>
<h2 id="heading-why-this-model-scales-faster-than-hiring-or-agencies"><strong>Why this model scales faster than hiring or agencies</strong></h2>
<p>Manual QA isnt just slow; its expensive in ways most teams overlook. Bug0 ran the numbers. Most startups waste $600K a year on hidden <a target="_blank" href="https://bug0.com/blog/hire-qa-engineer-2025-salary-true-cost-alternatives">QA costs</a>. That's developer time, release delays, and test maintenance. These costs add up fast and make traditional QA one of the biggest drains on engineering budgets.</p>
<p>Hiring QA engineers takes months and costs a fortune. Agencies lack product context.</p>
<p>The FDE model gives you both speed and context. Your QA runs inside your sprint. Coverage scales instantly. And it costs far less than building a QA team in-house.</p>
<h2 id="heading-real-world-outcomes"><strong>Real-world outcomes</strong></h2>
<p>The ROI from AI QA is real. Teams that switch from manual QA to automated AI-driven models recover hidden expenses within months. Many see positive ROI in just two or three months.</p>
<p>Teams using this hybrid AI + human model report:</p>
<ul>
<li><p>98% of bugs caught before production</p>
</li>
<li><p>10K+ per month saved compared to traditional QA</p>
</li>
<li><p>Full regression coverage in under a week</p>
</li>
</ul>
<p>Bug0 sees this happen all the time. This FDE model helps teams ship faster.</p>
<p>Modern <strong>AI QA platforms</strong> like Bug0 show that combining automation, AI-driven QA, and human oversight is the fastest way to scale. These systems reduce friction, improve developer velocity, and eliminate most hidden costs.</p>
<h2 id="heading-the-future-of-qa-is-outcome-driven"><strong>The future of QA is outcome-driven</strong></h2>
<p>Real AI-native QA plugs right into your CI/CD. It tests every single pull request. Developers get instant feedback. This aligns QA with the pace of modern software teams and ensures it scales with pull requests, not after them. Learn more in <a target="_blank" href="https://bug0.com/blog/pull-request-testing-how-to-automate-qa-without-slowing-down-developers-in-2025">Bug0s deep dive on pull request testing</a>.</p>
<p>QA isnt about writing test cases anymore. Its about outcomes. The AI learns and adapts on its own. The FDEs keep the AI accountable. They make sure it's aligned with your goals.</p>
<p>The future isnt manual or automated. Its <strong>AI for QA testing</strong> that is AI-native and agentic. And that future is already here.</p>
<h2 id="heading-closing-thoughts"><strong>Closing thoughts</strong></h2>
<p>AI QA with forward-deployed engineers isnt hype. Its how modern teams ship faster and sleep better. Its a safety net. It just catches bugs before your users do.</p>
]]></description><link>https://hashnode.com/blog/ai-qa-testing-evolution</link><guid isPermaLink="true">https://hashnode.com/blog/ai-qa-testing-evolution</guid><category><![CDATA[Forward-Deployed Engineer]]></category><category><![CDATA[FDE]]></category><category><![CDATA[AI QA Testing]]></category><category><![CDATA[AI Testing Tools]]></category><category><![CDATA[AI QA Engineer]]></category><category><![CDATA[ai testing]]></category><dc:creator><![CDATA[Syed Fazle Rahman]]></dc:creator></item><item><title><![CDATA[AI QA Engineer: Definition, jobs, and the Rise of Intelligent Testing]]></title><description><![CDATA[<hr />
<h2 id="heading-tldr">TL;DR:</h2>
<p>The <strong>AI QA Engineer</strong> is the next evolution of software testing. It's an AI-native system that replaces slow, expensive, and brittle manual scripting. This modern approach, pioneered by companies like <strong>Bug0</strong>, uses AI to autonomously generate, run, and self-heal <strong>Playwright</strong> tests. It operates on an <strong>AI+Human</strong> model. AI handles execution and scale while humans verify critical logic, ensuring production-grade reliability. Unlike a <strong>fully autonomous AI QA engineer</strong>, this hybrid model provides the necessary context for complex applications. For QA professionals, this signals a shift toward orchestrating AI and mastering modern tools. Ultimately, the <strong>AI QA Engineer</strong> enables teams to build faster, reduce QA overhead, and ship with confidence.</p>
<hr />
<p>QA was once slow, manual, and repetitive. Then came automation. Now AI is redefining the discipline.</p>
<p><strong>AI for QA engineer</strong> workflows is bridging the gap between speed and accuracy.</p>
<p>This transformation gave rise to the <strong>AI QA Engineer</strong>.</p>
<p>Its evolution in motion. QA moved from writing scripts to building intelligence. The AI QA Engineer is not a human role. Its an automated intelligence that behaves like one. It understands your product, tests it continuously, and adapts to every change.</p>
<p><a target="_blank" href="https://bug0.com/?utm_source=hashnode&amp;utm_medium=blog&amp;utm_campaign=hashnode_referral"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760718962555/87e8f399-4293-41d1-afaf-502f7bf361f0.png" alt="AI QA Engineer - Bug0's homepage screenshot" class="image--center mx-auto" /></a></p>
<p><a target="_blank" href="https://bug0.com/?utm_source=hashnode&amp;utm_medium=blog&amp;utm_campaign=hashnode_referral"><strong>Bug0</strong></a> coined the term and introduced it with its forward-deployed QA team model. Launched a few months back in public beta, it already works with several Series A and B companies that want to stay leaner and ship faster with confidence. It watches your app, creates tests automatically, runs them fast, and keeps you in the loop. Its QA pods verify nuanced cases that AI cant yet interpret perfectly. The result is powerful: faster shipping, fewer regressions, and a testing process that keeps getting smarter.</p>
<h2 id="heading-what-is-an-ai-qa-engineer">What is an AI QA Engineer?</h2>
<p>An AI QA Engineer isnt just a concept. Its a category defined and coined by Bug0. It represents a testing system that behaves like a QA engineer powered by AI. Instead of depending on repetitive scripts or fragile selectors, it uses intelligence to understand your product, learn flows, and keep your test coverage up to date automatically.</p>
<p>Bug0 introduced this model through its forward-deployed QA team structure. Launched recently in public beta, it already supports several Series A and B companies that want to stay lean while maintaining high-quality releases. These teams use Bug0 to scale QA without scaling headcount, blending automation and human expertise.</p>
<p>In practice, the AI QA Engineer operates as an AI teammate. It observes how users interact with the product, identifies key paths, and builds tests dynamically. When the interface or logic shifts, it adapts and self-heals.</p>
<p><strong>QA AI Engineer vs AI QA Engineer:</strong> both terms describe this modern hybrid of automation and intelligence, with human QA ensuring quality and context for every change.</p>
<blockquote>
<p><strong>Definition</strong></p>
<p><strong>AI QA Engineer:</strong> an AI-native testing system that autonomously generates, maintains, and validates tests with human-in-loop verification. Bug0 is the first production-ready platform to implement this definition at scale.</p>
</blockquote>
<p>This marks QAs real turning point; from code-heavy scripts to proactive, self-learning systems that keep improving with every release.</p>
<h2 id="heading-why-qa-missed-real-automation">Why QA missed real automation</h2>
<p>For years, QA teams believed they had automation figured out. In reality, it was still manual, just wrapped in code. Most companies spent months writing Selenium or Cypress scripts tied to fragile locators, selectors, and XPath structures. A single UI change could break hundreds of tests, forcing engineers to rewrite the same flows over and over.</p>
<p>Enterprise teams poured money into these setups. They hired large QA teams and bought expensive automation tools, yet the maintenance load kept rising. In many cases, budgets ballooned without meaningful coverage gains.</p>
<p>According to Bug0s research in its article <a target="_blank" href="https://bug0.com/blog/2025-qa-reality-check-why-your-engineering-budget-is-600k-higher-than-you-think?utm_source=hashnode&amp;utm_medium=blog&amp;utm_campaign=hashnode_referral">2025 QA Reality Check: Why Your Engineering Budget is $600k Higher Than You Think</a>, mid-sized companies now spend over <strong>$600,000 annually</strong> just maintaining outdated test automation stacks. Most of that cost comes from human hours wasted on script maintenance and flaky test triage.</p>
<p>The AI QA Engineer model emerged from this pain. It was built to end brittle, script-based automation and replace it with intelligent, self-healing systems that truly scale.</p>
<h2 id="heading-evolution-from-human-only-to-human-verified-intelligence">Evolution: from human-only to human-verified intelligence</h2>
<p>Testing intelligence has evolved through three clear phases, each shaping how teams approach automation and quality.</p>
<ul>
<li><p><strong>Human-Only Intelligence:</strong> For decades, QA engineers manually wrote and maintained every test case. This era was dominated by tools like Selenium and Cypress, where automation meant writing code rather than reducing human effort. Tests relied on fragile selectors, XPath, and locators that broke with every UI change. Companies deployed large QA teams and bought expensive automation suites, yet still spent millions fixing flaky tests and chasing false positives.</p>
</li>
<li><p><strong>Human-Directed AI:</strong> The next step came when AI began assisting human engineers. These <strong>QA Engineer AI</strong> workflows improved speed but still required humans to define strategies and write scripts. As detailed in the last article <a target="_blank" href="https://hashnode.com/blog/ai-testing-tools-2025">Best AI Testing Tools in 2025</a>, this stage was a partial improvement. AI accelerated test authoring, but humans remained in control. It was faster manual work, not true autonomy.</p>
</li>
<li><p><strong>Human-Verified AI:</strong> The current era, defined by Gen AI QA Engineer systems like <strong>Bug0s AI QA Engineer</strong>, has flipped the paradigm. AI now drives testing independently, generating and maintaining coverage automatically. Humans act as verifiers, adding strategic oversight and contextual understanding. This hybrid model blends AI scale with human precision for production-grade reliability.</p>
</li>
</ul>
<p>QAs shift from manual to human-verified AI mirrors the rise of the AI QA Engineer. Tools like Bug0 have proven that when AI takes the lead and humans validate, testing becomes faster, smarter, and finally scalable.</p>
<h2 id="heading-the-rise-of-ai-human-hybrid-models">The rise of AI + human hybrid models</h2>
<p>Imagine a pilot and co-pilot. The AI takes control of navigation, flight paths, and monitoring. The human verifies, strategizes, and ensures safety.</p>
<p>That is exactly how hybrid QA models work.</p>
<p>AI agents explore the app, detect issues, and build coverage. QA experts validate tricky UX paths or business-critical logic. The result is predictable quality and confidence at enterprise scale.</p>
<p>Bug0 and QA Wolf take two very different paths to the same goal. <strong>Bug0</strong> uses natural language-based Playwright agents to generate and heal tests intelligently. Its AI takes the lead, while its forward-deployed QA team verifies results. This is an <strong>AI+Human</strong> model built for speed and scale. This approach allows Bug0 to serve both startups and growth-stage companies effectively, providing enterprise-grade QA without enterprise-level overhead.</p>
<p>In contrast, <strong>QA Wolf</strong> operates as a <strong>Human+AI</strong> platform. Its model still relies on human engineers who write and maintain tests using traditional identifiers like IDs, selectors, and locators. While it offers reliability and structure, QA Wolfs human-heavy setup can become expensive and less flexible for early-stage startups.</p>
<p>Both tools blend automation with human input, but <strong>Bug0</strong> reverses the equation. It lets AI lead while humans refine. It scales up effortlessly from small teams to Series B companies, offering an adaptable model that grows with your product.</p>
<p><strong>Rainforest QA</strong>, on the other hand, represents the older, more traditional managed QA model. It operates more like an agency, deploying human testers supported by light automation. While it offers scale through manpower, it lacks the deep AI-native foundation that newer tools like Bug0 bring to the table.</p>
<p>This mix of old-school human-heavy agencies like Rainforest and next-gen platforms like Bug0 and QA Wolf shows how fast the QA world is changing. Bug0s AI+Human structure delivers scalable intelligence. QA Wolfs Human+AI balance delivers structured reliability. Rainforest, though reliable, reflects the past era of manual QA packaged as a service.</p>
<p>This new wave of hybrid QA proves that when AI owns execution and humans guide judgment, testing finally becomes as fast as development.</p>
<h2 id="heading-what-makes-a-true-ai-native-qa-engineer">What makes a true AI-native QA Engineer</h2>
<p>A true AI-native QA Engineer works the way <strong>Bug0</strong> does. It is built AI-first, not AI-added. It combines agentic reasoning with human judgment, delivering continuous, production-ready QA.</p>
<ul>
<li><p>Learns user flows from observation instead of manual scripting.</p>
</li>
<li><p>Generates Playwright tests through natural language instructions.</p>
</li>
<li><p>Uses self-healing logic to repair broken selectors automatically.</p>
</li>
<li><p>Verifies results via forward-deployed QA pods trained on customer context.</p>
</li>
<li><p>Runs hundreds of parallel tests integrated directly into CI/CD pipelines.</p>
</li>
</ul>
<p>This is what separates Bug0s model from AI-assisted tools. Instead of adding AI on top of traditional frameworks, it lets AI lead and humans refine. The result is an adaptive QA system that gets smarter and more reliable with every run.</p>
<h2 id="heading-skills-and-tools-behind-an-ai-qa-engineer">Skills and tools behind an AI QA Engineer</h2>
<p>Under the hood, an AI QA Engineer uses:</p>
<ul>
<li><p>Multi-agent orchestration to plan, generate, and heal tests.</p>
</li>
<li><p>LLMs to turn natural language into executable logic.</p>
</li>
<li><p>Playwright for cross-browser execution at scale.</p>
</li>
<li><p>Deep integrations with GitHub, Slack, and CI/CD workflows.</p>
</li>
</ul>
<p>For testers, this is the <strong>QA to AI Engineer</strong> path. Learn how AI agents reason, how they debug failures, and how they adapt over time.</p>
<p>This shift turns QA engineers into strategic operators guiding AI systems. You will shape how your testing evolves, not just how it runs.</p>
<h2 id="heading-a-day-in-the-life">A day in the life</h2>
<ol>
<li><p>The system observes your app and learns your user journeys.</p>
</li>
<li><p>It builds a library of tests automatically, with no code needed.</p>
</li>
<li><p>Every commit in each PR triggers automated test runs through CI/CD pipelines. Reports are generated instantly. Notifications are sent directly to GitHub, GitLab, Slack, Linear, or wherever your team works.</p>
</li>
<li><p>No more waiting for days or weeks for QA teams to review manually, fix scripts, and report bugs.</p>
</li>
<li><p>Issues are flagged automatically, validated by Bug0s QA pods, and ready for immediate review by developers.</p>
</li>
<li><p>It self-heals broken selectors or DOM shifts, ensuring tests remain consistent across versions.</p>
</li>
<li><p>This speed justifies every dollar spent on tools like Copilot or Cursor. Developers ship faster with full confidence that their code is tested.</p>
</li>
<li><p>Feedback from each run feeds the model for continuous improvement.</p>
</li>
</ol>
<p>Every loop makes it smarter. Over time, your <strong>AI QA Engineer</strong> integrates deeper into your workflow. It matches the velocity of your development team and ensures QA never slows you down.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760719249449/afd1c5d4-e282-4cac-87b8-157aba9ef239.png" alt="Screenshot of sample report generated by Bug0 during regression testing" class="image--center mx-auto" /></p>
<h2 id="heading-ai-qa-engineer-vs-the-fully-autonomous-ai-qa-engineer">AI QA Engineer vs. The Fully Autonomous AI QA Engineer</h2>
<p>Modern QA now divides into two practical models: the <strong>AI QA Engineer</strong> and the <strong>Fully Autonomous AI QA Engineer</strong>.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Model</td><td>Human role</td><td>Key advantage</td><td>Ideal use case</td></tr>
</thead>
<tbody>
<tr>
<td><strong>AI QA Engineer (Bug0)</strong></td><td>Human verifies context and strategy</td><td>AI leads with natural language Playwright tests, self-healing automation, and instant CI/CD feedback</td><td>Perfect for startups to growth companies that want scalability, accuracy, and collaboration</td></tr>
<tr>
<td><strong>Fully Autonomous AI QA Engineer</strong></td><td>None</td><td>Hands-free automation, no human checks</td><td>Suitable for R&amp;D and internal testing where context accuracy is less critical</td></tr>
</tbody>
</table>
</div><p><strong>Bug0s AI QA Engineer</strong> model defines the new standard for practical autonomy. It blends AIs adaptability and reasoning with a human layer for judgment. Every PR automatically runs end-to-end tests, posts reports to GitHub, GitLab, or Slack, and integrates with developer tools like Linear. Developers act instantly instead of waiting days for manual QA feedback.</p>
<p>By contrast, a <strong>fully autonomous AI QA engineer</strong> chases complete hands-off automation but often lacks reliability in real-world products. These systems, sometimes referred to under various names like an <strong>AIQA, Autonomous AI QA Engineer</strong>, risk missing edge cases and business logic without human verification.</p>
<p>Bug0s <strong>AI+Human</strong> balance delivers the reliability enterprises need and the agility startups love. It is the most scalable and dependable QA model today.</p>
<h2 id="heading-the-true-cost-of-qa-salary-jobs-and-modern-skills">The True Cost of QA: Salary, Jobs, and Modern Skills</h2>
<h3 id="heading-ai-qa-engineer-salary-amp-the-true-cost-of-hiring-2025">AI QA Engineer Salary &amp; The True Cost of Hiring (2025)</h3>
<p>The <strong>AI QA Engineer salary</strong> is a major factor for companies in 2025, but it's only one part of the equation. As detailed in a recent analysis on the <a target="_blank" href="https://bug0.com/blog/hire-qa-engineer-2025-salary-true-cost-alternatives"><strong>true cost of hiring a QA engineer</strong></a>, the actual annual investment is much higher. When you factor in benefits, recruiting costs, tools, and the hidden cost of developer time spent on bug triage, the total expenditure for a single QA engineer in the U.S. can easily range from <strong>$102,000 to over $196,000</strong>. This financial reality is pushing companies to seek more efficient, scalable alternatives to traditional hiring.</p>
<h3 id="heading-ai-qa-engineer-jobs-and-job-openings">AI QA Engineer Jobs and Job Openings</h3>
<p>As companies grapple with the high cost of manual QA, expect a spike in <strong>AI QA Engineer jobs</strong> and <strong>AI QA Engineer job openings</strong>. These roles are for professionals who can manage and scale AI-native testing systems, with a strong emphasis on expertise in modern frameworks like Playwright. The focus is shifting from writing scripts to orchestrating intelligent automation, blending SDET practices with AI model interpretation.</p>
<h3 id="heading-ai-qa-engineer-job-description">AI QA Engineer Job Description</h3>
<p>A forward-looking <strong>AI QA Engineer job description</strong> typically includes:</p>
<ul>
<li><p>Building, monitoring, and refining AI test agents.</p>
</li>
<li><p>Proficiency in Playwright, including its test generator and new agentic features.</p>
</li>
<li><p>Designing self-healing strategies.</p>
</li>
<li><p>Managing human-in-loop verification.</p>
</li>
<li><p>Connecting test insights into CI/CD for faster iteration.</p>
</li>
<li><p>Reporting performance and anomaly trends across builds.</p>
</li>
</ul>
<h3 id="heading-ai-courses-for-qa-engineer">AI Courses for QA Engineer</h3>
<p>If you are upskilling, the most critical tool to master is Playwright. For any aspiring QA AI Engineer, the path forward is to learn Playwright directly from the official documentation at <a target="_blank" href="https://playwright.dev/"><strong>playwright.dev</strong></a>. Playwright is the future of testing because it simplifies complexities that older tools struggled with. Its powerful auto-waits eliminate most flakiness, it handles single-page applications seamlessly, and it offers deep browser context control. With the introduction of <a target="_blank" href="https://bug0.com/blog/playwright-test-agents">Playwright's Test Agents</a>, you can now generate robust tests using natural language. This makes the process faster and more intuitive than ever before. Explore <strong>AI courses for QA Engineer</strong> that are heavily focused on Playwright automation and AI integration.</p>
<h2 id="heading-the-agentic-and-generative-future">The agentic and generative future</h2>
<p>The <strong>gen AI QA engineer</strong> is rising fast.</p>
<p>Future frameworks will combine multiple AI agents that coordinate. These will include a planner, generator, healer, and reviewer. Each plays a role in continuous, intelligent QA.</p>
<p>Natural language test creation will become standard. The system will analyze every commit, update test coverage automatically, and simulate user flows without human intervention.</p>
<p>The AI QA Engineer of the near future wont just execute tests. It will reason about them, prioritize coverage gaps, and learn from production logs. Thats the real promise of continuous QA, which is a system that evolves with your app.</p>
<h2 id="heading-definition-box">Definition box</h2>
<blockquote>
<p><strong>AI QA Engineer:</strong> an AI-native testing system that autonomously creates, maintains, and validates tests with human-in-loop verification. Bug0 is a production-grade example of this approach using a forward-deployed team model.</p>
</blockquote>
<h2 id="heading-bug0-in-action">Bug0 in action</h2>
<p>Bug0 is the first production-grade AI QA Engineer, already helping Series A and B companies ship faster and leaner. Here's how it delivers on its promise of AI-native, human-verified testing:</p>
<ul>
<li><p><strong>Rapid Coverage:</strong> Achieves 100% critical flow coverage in the first week and expands to 80% total coverage within a month.</p>
</li>
<li><p><strong>Massive Parallelization:</strong> Executes over 500 parallel Playwright tests in under 5 minutes, integrated directly into the CI/CD pipeline.</p>
</li>
<li><p><strong>Agentic Reliability:</strong> Uses self-healing AI agents to ensure tests are always up-to-date and reliable.</p>
</li>
<li><p><strong>Human Verification:</strong> Includes dedicated QA pods that provide the human context and verification needed for production-grade confidence.</p>
</li>
</ul>
<p>Bug0 combines autonomous AI with human oversight into a single managed service. It eliminates setup pain and gives teams immediate clarity and control. <a target="_blank" href="https://bug0.com/">Learn more.</a></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The AI QA Engineer marks the next chapter of how we test software. AI takes care of repetition. Humans focus on insight. Together, they form the foundation for dependable, high-speed development.</p>
<p>Teams adopting this hybrid approach gain something crucial: peace of mind that every release is battle-tested by both machine precision and human intuition.</p>
<hr />
<h2 id="heading-faqs">FAQs</h2>
<h3 id="heading-are-companies-hiring-ai-qa-engineers-right-now">Are companies hiring AI QA Engineers right now?</h3>
<p>Yes. Companies across SaaS, fintech, and healthtech are actively hiring for <strong>AI QA Engineer jobs</strong> to modernize quality processes. Many of Bug0s customers are already expanding their QA teams with AI-native roles focused on automation and Playwright testing.</p>
<h3 id="heading-whats-the-difference-between-ai-qa-engineer-and-fully-autonomous-ai-qa-engineer">Whats the difference between AI QA Engineer and fully autonomous AI QA Engineer?</h3>
<p>A <strong>fully autonomous AI QA Engineer</strong> removes humans completely. The <strong>AI QA Engineer model</strong>, like Bug0s, includes human verification for greater reliability and context awareness in production systems. This hybrid approach balances AI automation with human judgment.</p>
<h3 id="heading-what-should-an-ai-qa-engineer-job-description-include">What should an AI QA Engineer job description include?</h3>
<p>A modern <strong>AI QA Engineer job description</strong> includes ownership of AI pipelines, self-healing frameworks, CI/CD integration, and QA verification design. Teams using Bug0 often look for engineers experienced with Playwright and AI-assisted testing workflows.</p>
<h3 id="heading-where-can-i-find-ai-courses-for-qa-engineer">Where can I find AI courses for QA Engineer?</h3>
<p>Explore hands-on programs teaching <strong>Playwright</strong>, <strong>LLMs</strong>, agentic design, and autonomous testing frameworks. Search for <strong>AI courses for QA Engineer</strong> or <strong>AI QA Engineer course</strong> to upskill. Bug0s blog and Playwright documentation are great places to start learning.</p>
<h3 id="heading-im-a-qa-how-do-i-become-an-ai-engineer">Im a QA  how do I become an AI Engineer?</h3>
<p>Follow the <strong>QA to AI Engineer</strong> journey. Learn <strong>Playwright</strong>, agentic logic, and model evaluation. Practice building AI test agents until you can connect automation to business outcomes. Bug0s training content and case studies outline this career path clearly.</p>
<h3 id="heading-why-do-i-see-terms-like-spur-ai-qa-engineer-in-my-search">Why do I see terms like Spur AI QA Engineer in my search?</h3>
<p>You might see terms like <strong>Spur AI QA Engineer</strong>, <strong>Spur AI QA Engineer official website</strong>, or <strong>homepage</strong> because the market is curious and new players are emerging. Its important to evaluate which platforms are truly <strong>AI-native</strong> and which use surface-level AI features. Bug0 is the first production-grade platform implementing this concept at scale.</p>
<h3 id="heading-how-does-an-ai-qa-engineer-differ-from-traditional-qa-automation">How does an AI QA Engineer differ from traditional QA automation?</h3>
<p>Traditional QA automation relies on manual scripting and brittle locators. An <strong>AI QA Engineer</strong>, like Bug0s model, learns user flows, generates <strong>Playwright tests</strong> autonomously, and self-heals  reducing human effort while improving reliability and coverage.</p>
]]></description><link>https://hashnode.com/blog/ai-qa-engineer-definition-jobs-and-the-rise-of-intelligent-testing</link><guid isPermaLink="true">https://hashnode.com/blog/ai-qa-engineer-definition-jobs-and-the-rise-of-intelligent-testing</guid><category><![CDATA[Browser Testing Automation]]></category><category><![CDATA[Spur AI QA Engineer]]></category><category><![CDATA[Bug0]]></category><category><![CDATA[AI QA Engineer]]></category><category><![CDATA[AI QA]]></category><category><![CDATA[QA testing tools]]></category><dc:creator><![CDATA[Syed Fazle Rahman]]></dc:creator></item><item><title><![CDATA[Best AI testing tools in 2026: from autonomous agents to human-verified QA]]></title><description><![CDATA[<p><strong>tldr:</strong> Most "AI testing tools" are still wrappers around old frameworks. The ones worth paying for in 2026 generate tests from user behavior, heal themselves when your UI changes, and run without a QA engineer babysitting every selector.</p>
<hr />
<blockquote>
<h3 id="heading-what-are-ai-testing-tools">What are AI testing tools?</h3>
<p><strong>AI testing tools</strong> use artificial intelligence to automate how tests are created, run, and maintained. The basic promise: less manual scripting, fewer flaky tests, faster feedback on whether your app actually works after a deploy. In practice, the "AI" ranges from a GPT wrapper that writes Cypress boilerplate to a fully autonomous agent that generates, heals, and runs tests without human involvement. The gap between those two extremes is what this article is about.</p>
</blockquote>
<p>In 2024, most "AI testing" meant a GPT wrapper generating flaky Cypress scripts. You'd spend an hour cleaning up the output. Then another hour debugging why it failed in CI.</p>
<p>2025 changed that. Real agentic tools emerged. Vision models that interpret your UI the way a human tester would. Self-healing selectors that survive redesigns. Multi-agent frameworks like <a target="_blank" href="https://playwright.dev/docs/test-agents">Playwright Test Agents</a> that plan, generate, and fix tests independently.</p>
<p>Now, in 2026, the question isn't whether AI testing works. It's which category of tool matches your team's reality. The term "AI" still gets used as marketing more than a technical descriptor. Some tools are true autonomous systems. Others sprinkled machine learning on a legacy framework and updated their landing page. This post separates signal from noise across the real landscape of <strong>AI tools for testing in 2026</strong>.</p>
<hr />
<h2 id="heading-the-intelligence-behind-testing-has-shifted">The intelligence behind testing has shifted</h2>
<p>Where the "intelligence" comes from tells you everything about a tool's capability.</p>
<p>For decades, testing intelligence was 100% human. QA engineers wrote every script. Maintained every selector. When a button moved three pixels, the test broke. The tools were dumb executors. This is still how most teams operate.</p>
<p>Then came the assistant era. AI helped humans write tests faster. Smart locators, element discovery, auto-maintenance. Useful, but the human still decided what to test, when to test, and what a failure meant. Most "AI-assisted" tools on the market today are still here.</p>
<p>The interesting shift is what's happening now. The best tools generate their own intelligence. They observe user behavior in production, figure out which flows matter, and build tests without anyone asking. The human stops writing scripts and starts reviewing results. You go from operating a tool to auditing an outcome. That's a fundamentally different job.</p>
<p>Understanding where a tool falls on this spectrum, executor, assistant, or autonomous agent, is the single most important factor when choosing an <strong>AI-powered software testing tool</strong>.</p>
<hr />
<h2 id="heading-the-ai-testing-landscape-in-2026">The AI testing landscape in 2026</h2>
<p>Understanding the nuances between different <strong>AI software testing tools</strong> is critical for any team investing in QA tooling. It helps you look past marketing claims and evaluate how much of the testing burden actually gets removed. For those building their first QA strategy, the fundamentals of <a target="_blank" href="https://bug0.com/blog/software-testing-basics">software testing basics</a> are a good starting point.</p>
<p>Every <strong>AI automation testing tool</strong> on the market falls into one of five categories.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Category</strong></td><td><strong>Core idea</strong></td><td><strong>Example tools</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>AI-native + human layer (managed AI QA)</strong></td><td>AI automation paired with human QA experts for verification and reliability.</td><td><a target="_blank" href="https://bug0.com/">Bug0</a>, <a target="_blank" href="https://qawolf.com/">QA Wolf</a>, <a target="_blank" href="https://rainforestqa.com/">Rainforest QA</a></td></tr>
<tr>
<td><strong>AI-native (autonomous)</strong></td><td>Fully AI-driven agents that explore, generate, and maintain tests without human input.</td><td><a target="_blank" href="https://www.momentic.ai/">Momentic</a>, <a target="_blank" href="https://prodperfect.com/">ProdPerfect</a>, <a target="_blank" href="https://meticulous.ai/">Meticulous</a>, <a target="_blank" href="http://Testers.AI">Testers.AI</a></td></tr>
<tr>
<td><strong>AI-assisted</strong></td><td>AI helps write or maintain tests, but humans still drive the workflow.</td><td><a target="_blank" href="https://testrigor.com/">TestRigor</a>, <a target="_blank" href="https://www.virtuoso.qa/">Virtuoso QA</a>, <a target="_blank" href="https://autify.com/">Autify</a>, <a target="_blank" href="https://www.mabl.com/">Mabl</a>, <a target="_blank" href="https://www.functionize.com/">Functionize</a>, <a target="_blank" href="https://www.accelq.com/">ACCELQ</a>, <a target="_blank" href="https://testsigma.com/">Testsigma</a>, <a target="_blank" href="https://www.blinq.io/">BlinqIO</a>, <a target="_blank" href="https://www.browserstack.com/test-observability">BrowserStack Test Observability</a>, <a target="_blank" href="https://www.lambdatest.com/">LambdaTest KaneAI</a>, <a target="_blank" href="http://TestResults.io">TestResults.io</a></td></tr>
<tr>
<td><strong>Legacy + AI-flavored</strong></td><td>Traditional tools that bolted on AI features for marketing.</td><td><a target="_blank" href="https://katalon.com/">Katalon</a>, <a target="_blank" href="https://www.tricentis.com/">Tricentis</a>, <a target="_blank" href="https://www.lambdatest.com/">LambdaTest</a>, <a target="_blank" href="https://www.tricentis.com/products/testim-mobile">Testim</a></td></tr>
<tr>
<td><strong>Visual / niche AI</strong></td><td>Focus on visual, accessibility, or UX validation using AI.</td><td><a target="_blank" href="https://applitools.com/">Applitools</a>, <a target="_blank" href="http://Reflect.run">Reflect.run</a></td></tr>
</tbody>
</table>
</div><p>This categorization answers one question: how much of the testing process is actually automated, and how much still depends on humans to create, maintain, and validate?</p>
<hr />
<h2 id="heading-what-makes-a-tool-truly-ai-native">What makes a tool truly AI-native</h2>
<p>AI-native tools are built differently from the ground up. No pre-written scripts. No static element locators. They adapt like a human tester would.</p>
<p>The capability that separates real AI-native tools from everything else is <strong>autonomous test generation</strong>. The tool analyzes real user traffic, identifies which flows matter most, and generates tests. No human writes a script. This sounds like magic until you realize it's pattern matching on production clickstreams. The hard part isn't generating the test. It's generating one that's stable enough to run 500 times in CI without a false positive.</p>
<p>Then there's self-healing. Every tool on this list claims it. Your <code>#submit-btn</code> becomes <code>.btn-primary</code>? The good ones update the locator and pass. The bad ones flag it as a failure and email you at 3am. Here's a useful filter: ask vendors for their self-heal success rate on production apps, not on their demo todo list. Most won't give you a number. The ones that do are worth talking to.</p>
<p>Continuous learning across runs? Every tool claims this, few prove it. Fast CI/CD integration? Table stakes in 2026. These aren't differentiators anymore.</p>
<p>That's the core difference between the <strong>best AI test automation tools</strong> and the rest. A tool that helps you do a task versus a system that owns the outcome.</p>
<hr />
<h2 id="heading-the-rise-of-ai-human-hybrid-models">The rise of AI + human hybrid models</h2>
<p>A powerful category has matured in the past year: AI tools paired with a human verification layer. The premise is simple. Pure automation can't catch everything.</p>
<p>These platforms combine the speed and scale of AI with the judgment of human QA experts. The AI does the heavy lifting: exploring the app, generating tests, running them continuously. Human experts verify edge cases, investigate complex business logic failures, and catch subtle UX issues that AI misses.</p>
<p><a target="_blank" href="https://bug0.com/">Bug0</a> is built on this model, but it started self-serve. Bug0 Studio lets you describe a test in plain English or upload a video of your user flow. It generates Playwright-based tests that self-heal when your UI changes. $250/mo, pay-as-you-go. For teams who want the outcome without the involvement, Bug0 Managed adds a Forward-Deployed Engineer pod that handles planning, verification, and release gating. $2,500/mo flat.</p>
<p><a target="_blank" href="https://qawolf.com/">QA Wolf</a> and <a target="_blank" href="https://rainforestqa.com/">Rainforest QA</a> operate in similar territory, offering managed QA services on top of their automation platforms.</p>
<p>I think this model wins for most teams under 200 engineers. You don't have the headcount to build and maintain a testing platform. You don't want to hire three QA engineers just to keep your regression suite alive. You want someone to tell you "your checkout flow broke after the last deploy" before your customers do.</p>
<h2 id="heading-deep-dive-by-category">Deep dive by category</h2>
<h3 id="heading-ai-native-human-layer-managed-ai-qa">AI-native + human layer (managed AI QA)</h3>
<p>Self-learning automation plus expert validation. AI agents with human-in-the-loop QA for a complete, managed solution.</p>
<ul>
<li><p><a target="_blank" href="https://bug0.com/"><strong>Bug0</strong></a>: Self-serve via Bug0 Studio: describe tests in plain English, upload video, or record your screen. Playwright-based, self-healing, from $250/mo. For done-for-you QA, Bug0 Managed adds a dedicated <a target="_blank" href="https://bug0.com/managed-qa">AI QA Engineer</a> pod. 100% critical flow coverage in weeks. $2,500/mo flat.</p>
</li>
<li><p><a target="_blank" href="https://qawolf.com/"><strong>QA Wolf</strong></a>: Managed service that reaches 80% test coverage by pairing their testing library with human QA engineers.</p>
</li>
<li><p><a target="_blank" href="https://rainforestqa.com/"><strong>Rainforest QA</strong></a>: QA-as-a-service combining automation with a global community of human testers.</p>
</li>
</ul>
<h3 id="heading-ai-native-autonomous">AI-native (autonomous)</h3>
<p>Full autonomy. AI agents crawl your app, learn patterns, and generate regression suites without scripting. For teams that want to go completely hands-off.</p>
<ul>
<li><p><a target="_blank" href="https://www.momentic.ai/"><strong>Momentic</strong></a>: No-code AI that generates and maintains tests by observing user traffic.</p>
</li>
<li><p><a target="_blank" href="https://prodperfect.com/"><strong>ProdPerfect</strong></a>: Analyzes real user behavior to build, run, and maintain E2E test suites.</p>
</li>
<li><p><a target="_blank" href="https://meticulous.ai/"><strong>Meticulous</strong></a>: Catches UI regressions automatically by replaying real user sessions against new code changes.</p>
</li>
<li><p><a target="_blank" href="http://Testers.AI"><strong>Testers.AI</strong></a>: Autonomous testing where vision AI agents discover, write, and execute tests with minimal human intervention.</p>
</li>
</ul>
<h3 id="heading-ai-assisted-testing">AI-assisted testing</h3>
<p>This is the biggest category and the most crowded. AI helps testers write or maintain tests faster, but human input still drives the process. Many <strong>generative AI testing tools</strong> fall here, using LLMs to turn plain-language prompts into test scripts.</p>
<p>Three stand out:</p>
<ul>
<li><p><a target="_blank" href="https://testrigor.com/"><strong>TestRigor</strong></a>: The best plain-English test authoring experience. You write "login with valid credentials and verify the dashboard loads." NLP handles execution. If your QA team doesn't write code, start here.</p>
</li>
<li><p><a target="_blank" href="https://www.mabl.com/"><strong>Mabl</strong></a>: Low-code, cloud-hosted, genuinely good onboarding. ML-powered auto-healing keeps tests running after UI changes. The ceiling is low for complex apps, but the floor is high for teams new to automation.</p>
</li>
<li><p><a target="_blank" href="https://autify.com/"><strong>Autify</strong></a>: Monitors UI changes and auto-maintains tests. Good for teams transitioning from manual testing who need something that doesn't break every sprint.</p>
</li>
</ul>
<p>The rest of this category is a long tail of tools solving similar problems with different packaging (if I listed the pros and cons of all 15, we'd both be here all day): <a target="_blank" href="https://www.virtuoso.qa/">Virtuoso QA</a> (NLP + self-healing), <a target="_blank" href="https://www.functionize.com/">Functionize</a> (ML for test prioritization), <a target="_blank" href="https://www.accelq.com/">ACCELQ</a> (codeless for CD pipelines), <a target="_blank" href="https://testsigma.com/">Testsigma</a> (unified web/mobile/API), <a target="_blank" href="https://www.blinq.io/">BlinqIO</a> (Cucumber-focused), <a target="_blank" href="https://www.browserstack.com/test-observability">BrowserStack Test Observability</a> (root-cause analysis), <a target="_blank" href="https://www.lambdatest.com/">LambdaTest KaneAI</a> (NL test generation), and <a target="_blank" href="http://TestResults.io">TestResults.io</a> (visual AI locators). They're all fine. None are transformative.</p>
<h3 id="heading-legacy-ai-flavored-tools">Legacy + AI-flavored tools</h3>
<p>Traditional testing platforms that added AI to stay relevant. ML-based locators or dashboards, but the core is still a legacy framework.</p>
<ul>
<li><p><a target="_blank" href="https://katalon.com/"><strong>Katalon</strong></a>: Bolted AI features like smart wait and self-healing locators onto its existing platform.</p>
</li>
<li><p><a target="_blank" href="https://www.tricentis.com/"><strong>Tricentis</strong></a>: Enterprise-focused platform with AI for risk-based analysis and improved object recognition.</p>
</li>
<li><p><a target="_blank" href="https://www.tricentis.com/products/testim-mobile"><strong>Testim</strong></a>: Now part of Tricentis. Uses ML to speed up test authoring, execution, and maintenance.</p>
</li>
</ul>
<h3 id="heading-visual-and-niche-ai-testing">Visual and niche AI testing</h3>
<p>Visual regressions, accessibility bugs, and layout issues that functional tools miss entirely.</p>
<p><a target="_blank" href="https://applitools.com/"><strong>Applitools</strong></a> is the gold standard here. Their Visual AI compares screenshots across browsers and viewports using layout-aware comparison, not pixel matching. It's overkill for 90% of early-stage startups, but if your users care about pixel-perfect UI (finance, healthcare, e-commerce), nothing else comes close. <a target="_blank" href="http://Reflect.run"><strong>Reflect.run</strong></a> offers a lighter alternative, combining functional and visual testing with automatic change detection.</p>
<h2 id="heading-comparison-matrix">Comparison matrix</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Feature</strong></td><td><strong>AI-native</strong></td><td><strong>AI + human layer</strong></td><td><strong>AI-assisted</strong></td><td><strong>Legacy</strong></td><td><strong>Visual AI</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Autonomous test generation</td><td>Yes</td><td>Yes</td><td>Partial</td><td>No</td><td>No</td></tr>
<tr>
<td>Human verification</td><td>No</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr>
<tr>
<td>Continuous learning</td><td>Yes</td><td>Yes</td><td>Partial</td><td>No</td><td>Partial</td></tr>
<tr>
<td>Self-healing</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Partial</td><td>No</td></tr>
<tr>
<td>Setup time</td><td>Minutes (demo), hours (real app)</td><td>Days</td><td>Days to weeks</td><td>Weeks+</td><td>Varies</td></tr>
<tr>
<td>Typical users</td><td>Startups</td><td>Mid-size, enterprise</td><td>QA teams</td><td>Legacy orgs</td><td>Design QA</td></tr>
</tbody>
</table>
</div><hr />
<h2 id="heading-trends-shaping-ai-testing-in-2026">Trends shaping AI testing in 2026</h2>
<p>The landscape of <strong>ai automation testing tools</strong> is shifting fast. Two developments stand out this year:</p>
<p><strong>Multi-agent testing frameworks went from research to production.</strong> What started with <a target="_blank" href="https://playwright.dev/docs/test-agents">Playwright's Test Agents</a> has spread across the ecosystem. A <code>planner</code> explores the app and creates a test plan. A <code>generator</code> turns it into code. A <code>healer</code> fixes tests that fail. This isn't a monolithic AI. It's composable, modular, and you can swap out individual agents. The principles of <a target="_blank" href="https://www.freecodecamp.org/news/how-to-write-qa-documentation-that-will-actually-work/">writing effective QA documentation</a> still matter here. Someone has to review what the planner decided to test.</p>
<p><strong>Playwright MCP changed the build vs. buy equation.</strong> The <a target="_blank" href="https://bug0.com/blog/playwright-mcp-changes-ai-testing-2026">Model Context Protocol</a> lets AI agents control browsers through structured APIs instead of screen scraping. 2-5KB of accessibility tree data versus 500KB-2MB screenshots per interaction. 10-100x faster. Every team building AI testing internally now evaluates whether MCP makes DIY feasible, or whether the operational overhead still favors buying. This is the most consequential technical shift in testing since Playwright replaced Selenium's WebDriver protocol with CDP.</p>
<p>Three smaller trends worth tracking: <strong>AI penetration testing tools</strong> that simulate attack vectors are moving out of research labs. <strong>Free AI testing tools</strong> and open-source frameworks make agentic testing accessible to solo developers. And natural language test generation inside IDEs is blurring the line between "who writes tests" and "who defines quality," letting product managers contribute directly.</p>
<hr />
<h2 id="heading-how-to-choose-the-right-tool">How to choose the right tool</h2>
<p>Choosing the right <strong>AI tool for automation testing</strong> depends on team size, goals, and resources. This guide focuses on AI-driven E2E platforms, but a complete QA strategy includes stack-specific tools too. PHP teams have <a target="_blank" href="https://www.sitepoint.com/8-must-have-php-quality-assurance-tools/">code-level QA tools</a> for static analysis and unit testing that complement E2E solutions.</p>
<p>For the E2E layer, one fundamental question: continue with <a target="_blank" href="https://townhall.hashnode.com/why-diy-qa-doesnt-work-anymore-a-2025-guide-to-e2e-testing-for-modern-web-apps">DIY QA</a>, or offload the process entirely?</p>
<p><strong>No QA headcount.</strong> Managed AI QA gives you the coverage of a full QA team without the hiring. Engineers stay focused on building.</p>
<p><strong>Existing QA team.</strong> AI-assisted tools like <a target="_blank" href="https://testrigor.com/">TestRigor</a> or <a target="_blank" href="https://www.mabl.com/">Mabl</a> boost your team's efficiency without changing workflows.</p>
<p><strong>Enterprise.</strong> AI-native platforms with SOC2 compliance handle complexity, security, and scale across multiple teams.</p>
<p><strong>Design-heavy products.</strong> Visual AI tools like <a target="_blank" href="https://applitools.com/">Applitools</a> catch what functional tests miss.</p>
<hr />
<h2 id="heading-where-to-start-tomorrow">Where to start tomorrow</h2>
<p>Stop evaluating tools based on their demo. Record your actual app's most painful user flow, the one that breaks every other sprint. Upload it or describe it in plain English. Run the generated test in staging. Then change something in the UI and run it again without updating the test.</p>
<p>That second run tells you everything. If it passes, the self-healing works. If it fails with a clear alert, the failure mode is honest. If it silently passes with wrong assertions, walk away.</p>
<p>The AI testing market has real options now. The trap is spending three months evaluating twelve of them. Pick the category that matches your constraint, trial one tool for a week, and ship it into CI. You'll learn more from one real pipeline run than from ten vendor demos.</p>
<hr />
<h2 id="heading-faqs">FAQs</h2>
<h3 id="heading-are-ai-testing-tools-actually-autonomous-or-is-it-marketing-hype">Are AI testing tools actually autonomous or is it marketing hype?</h3>
<p>Mostly hype. Most tools marketed as "AI testing" are AI-assisted at best. They help humans work faster. True autonomy means the system watches how your users behave, figures out what to test, and generates or heals tests without anyone asking. Only a handful of tools do this today. The rest are using "AI" the way food companies use "natural."</p>
<h3 id="heading-how-do-ai-human-hybrid-qa-models-differ-from-regular-automation">How do AI + human hybrid QA models differ from regular automation?</h3>
<p>A tool gives you software. A managed service gives you an outcome. With hybrid QA, the vendor's AI generates and heals tests while their human team writes, maintains, and verifies results. You get a Slack message when something breaks. With a regular automation tool, you get a dashboard and a backlog of maintenance work. The trade-off is cost versus control.</p>
<h3 id="heading-are-ai-testing-tools-suitable-for-startups-or-only-large-enterprises">Are AI testing tools suitable for startups or only large enterprises?</h3>
<p>Both. Startups need coverage without hiring. Enterprises need scale across teams. Different reasons, same tools.</p>
<h3 id="heading-do-i-need-ai-testing-tools-if-i-already-have-a-qa-team">Do I need AI testing tools if I already have a QA team?</h3>
<p>Probably not an autonomous platform, but AI-assisted tools can make your team faster. The bigger question is whether your QA team is spending their time on judgment calls (exploratory testing, release decisions) or on maintenance (fixing selectors, re-running flaky tests). If it's mostly maintenance, AI can take that off their plate.</p>
<h3 id="heading-how-fast-do-ai-powered-qa-platforms-deliver-results">How fast do AI-powered QA platforms deliver results?</h3>
<p>Most AI-native or managed platforms automate 100% of critical flows within a week. 80% overall coverage within a month. Compare that to the 3-6 months it typically takes to build a meaningful Playwright suite from scratch.</p>
<h3 id="heading-can-ai-testing-tools-replace-human-testers">Can AI testing tools replace human testers?</h3>
<p>No. And the teams that think they can are the ones filing P0 bugs in production.</p>
<p>AI catches regressions. It catches selector breakage, broken flows, API failures. It's good at "did the thing that worked yesterday still work today?" What it can't do is look at your checkout page and notice that the discount code field is technically functional but visually buried under a fold that 80% of mobile users will never scroll past. Or that your date picker works perfectly in every test but confuses European users because it defaults to MM/DD/YYYY. Or that the loading spinner runs for 4 seconds on a page that used to load in 1, and that's not a bug by any test assertion, but your users will notice.</p>
<p>The tools handle repetitive coverage. Your team handles the judgment calls. Trying to eliminate the human entirely is how you end up with a green CI dashboard and a support queue full of angry customers.</p>
<h3 id="heading-how-do-ai-testing-tools-handle-flaky-tests">How do AI testing tools handle flaky tests?</h3>
<p>AI-native systems use self-healing locators. When attributes change, the AI identifies elements using text content, DOM position, visual location, and surrounding structure. Flakiness from selector breakage drops to near zero. Flakiness from timing issues and network instability is a different problem, and most tools still struggle with it.</p>
<h3 id="heading-what-is-next-for-ai-in-software-testing">What is next for AI in software testing?</h3>
<p>Multi-agent systems. Different AI agents for planning, generation, debugging, and healing, each specialized, working together. <a target="_blank" href="https://bug0.com/blog/playwright-mcp-changes-ai-testing-2026">Playwright MCP</a> gives these agents structured browser control. QA stops being a phase and becomes a continuous, autonomous feedback loop on every deploy.</p>
]]></description><link>https://hashnode.com/blog/ai-testing-tools-2026</link><guid isPermaLink="true">https://hashnode.com/blog/ai-testing-tools-2026</guid><category><![CDATA[AI]]></category><category><![CDATA[AI QA]]></category><category><![CDATA[AI Testing Tools]]></category><category><![CDATA[AI QA Engineer]]></category><category><![CDATA[Automated Testing]]></category><category><![CDATA[Automated Browser Testing ]]></category><category><![CDATA[browser testing]]></category><dc:creator><![CDATA[Syed Fazle Rahman]]></dc:creator></item><item><title><![CDATA[Writing Great API Documentation: Best Practices with OpenAPI and Hashnode's Docs Product]]></title><description><![CDATA[<p>If you are a devtool company or any tech company catering to developers and you provide APIs, the most effective way to encourage them to use your product is by offering well-crafted API documentation.</p>
<p>API documentation typically includes code examples, tutorials, and detailed information about functions, classes, and return types. It offers developers all the necessary information to create integrations with the API and make API calls with the software.</p>
<p>API documentation provides a clear explanation of the endpoints, describes the purposes for using them, and offers specific examples of their usage.</p>
<h2 id="heading-tips-to-write-great-api-documentation">Tips to write great API documentation</h2>
<p>For documentation in general, the simple rule to follow is: keep it simple, know the personas reading the documentation, and document every detail.</p>
<p>For API documentation, however, this is the part that will show developers how to walk the talk, and using this is how you will onboard more developers to your tool.</p>
<p>Here are five top tips to write great API docs:</p>
<ol>
<li><p><strong>Understand the API</strong>: Before you start documenting, make sure you have hands-on experience with the APIs. Use it to test endpoints and get a first-hand understanding of how it works. This will help you guide users accurately, and improve the overall quality of your documentation.</p>
</li>
<li><p><strong>Use consistent naming conventions</strong>: Ensure endpoints, parameters, and response fields follow a standardized naming convention (e.g., camelCase or snake_case) and maintain consistency across the API.</p>
</li>
<li><p><strong>Include every detail:</strong> Include every detail needed to correctly learn and build with the APIs. Explain authentication methods (like API keys or OAuth) and any permissions needed for each endpoint. Also, list HTTP error codes (such as 400, 404, 500) and what they mean for each endpoint. Add troubleshooting tips for common problems to help users fix them on their own.</p>
</li>
<li><p><strong>Add examples:</strong> The API docs should be written so that developers can copy and paste the examples and get them running. Make sure to include examples in multiple languages and frameworks, and have an interactive API playground that makes it easy for developers to test the APIs.</p>
</li>
<li><p><strong>Explain rate limits and usage quotas</strong>: Specify rate limits and quota restrictions for each endpoint to help users manage API usage effectively. This prevents unexpected throttling and ensures a smoother integration experience.</p>
</li>
</ol>
<h2 id="heading-how-openapi-and-hashnode-docs-can-help-in-writing-good-api-documentation">How OpenAPI and Hashnode Docs can help in writing good API documentation</h2>
<p>If you've worked with REST APIs, you likely know OpenAPI and its benefits. If not, <a target="_blank" href="https://hashnode.com/blog/getting-started-with-openapi-how-hashnodes-new-docs-product-can-simplify-your-api-documentation">this article is a good starting point</a>.</p>
<p>OpenAPI helps with:</p>
<ul>
<li><p>Generating documentation, tests, and mock servers</p>
</li>
<li><p>Integrating with tools and services for better documentation</p>
</li>
<li><p>Team collaboration and communication</p>
</li>
<li><p>Enhancing API security and quality</p>
</li>
</ul>
<p>Documenting APIs with OpenAPI is a great start, but your documentation needs more. This is where Hashnode Docs helps, making API documentation simpler and more interactive.</p>
<p><strong>Hashnode Docs features that help in writing great API docs:</strong></p>
<ol>
<li><p><strong>One-Click API reference setup and interactive playground -</strong> With Hashnode, teams can easily create API reference docs by importing OpenAPI or Swagger specs - all in just one click. This also creates a playground for you that lets developers interact with the API, run requests, and see live responses.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729848638403/d9d30a3d-e784-43be-8feb-6fc2500eec92.png?auto=compress,format&amp;format=webp" alt /></p>
</li>
<li><p><strong>GitHub Sync</strong>: Manage your docs wherever you feel comfortable - in GitHub or directly in Hashnodes editor. The GitHub sync feature keeps both your codebase and docs up-to-date effortlessly.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729679646666/2996774e-1041-4527-bbb1-a3d82cf585d3.png?auto=compress,format&amp;format=webp" alt /></p>
</li>
<li><p><strong>Enterprise-level features</strong>: Hashnode offers enterprise features like version control, SOC2 and ISO 27001 readiness, and team collaboration tools that make managing your OpenAPI docs seamless and secure.</p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>For devtool companies, having solid API documentation is key to getting more developers to use your tool. Make sure it follows all the tips from the article above, and pick the right tool to document it. APIs can quickly become outdated, and writing documentation at the same time can be a lengthy process, so choose tools or processes that make updates easier. That's where a tool like <a target="_blank" href="https://hashnode.com/products/docs?source=docsarticle"><strong>Docs by Hashnode</strong></a> comes in handy. It takes care of the heavy lifting, so you can focus on writing examples and other details.</p>
<p>I hope this article has given you a good idea of how to write effective API documentation.</p>
]]></description><link>https://hashnode.com/blog/writing-great-api-documentation-best-practices-with-openapi-and-hashnodes-docs-product</link><guid isPermaLink="true">https://hashnode.com/blog/writing-great-api-documentation-best-practices-with-openapi-and-hashnodes-docs-product</guid><category><![CDATA[Developer]]></category><category><![CDATA[Technical writing ]]></category><category><![CDATA[APIs]]></category><dc:creator><![CDATA[Haimantika Mitra]]></dc:creator></item><item><title><![CDATA[Getting Started with OpenAPI: How Hashnode's new docs product can simplify your API documentation]]></title><description><![CDATA[<p>OpenAPI is the go-to standard for defining and documenting APIs. It helps streamline API integration, makes everything clearer, and provides a consistent framework that developers love. For many companies and developers, using OpenAPI boosts collaboration and productivity. But managing OpenAPI specs and turning them into developer-friendly docs can be tough. That's where Hashnode's <a target="_blank" href="https://hashnode.com/products/docs">new documentation product</a> comes in.</p>
<p><a target="_blank" href="https://hashnode.com/products/docs"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729535269576/96410421-64ac-4736-b754-ba8b844aa846.png" alt class="image--center mx-auto" /></a></p>
<h3 id="heading-what-is-openapi">What is OpenAPI?</h3>
<p>OpenAPI, also called the <a target="_blank" href="https://swagger.io/docs/specification/v3_0/about/">OpenAPI Specification</a> (OAS), is a standard way to define RESTful APIs. It lets developers create a structured, machine-readable description of their API, which can then be used to generate docs, client libraries, server stubs, and more. With OpenAPI, your APIs are easy to understand, simple to integrate, and well-documented for anyone who needs them.</p>
<p>Whether you're building a public-facing API or an internal service, OpenAPI helps bridge the gap between development and users, providing a clear roadmap for how your services are used.</p>
<h3 id="heading-why-good-documentation-matters-for-openapi">Why good documentation matters for OpenAPI</h3>
<p>Good documentation is key to using APIs effectively. Developers need more than just code  they need context, examples, guidelines, and other information to help them integrate smoothly. Great documentation makes for a smooth onboarding experience, while poor docs can lead to endless support requests.</p>
<p>OpenAPI is both human-readable and machine-readable, which is a huge plus. You can use your OpenAPI definition to generate detailed docs, but not all tools are great at presenting the content in a user-friendly way. Traditional methods might need custom setups or force developers to juggle multiple tools to get the job done.</p>
<h3 id="heading-meet-docs-by-hashnode-content-engine-for-your-openapi-needs">Meet Docs by Hashnode - Content engine for your OpenAPI needs</h3>
<p>Hashnode's new docs product is built to simplify the whole API documentation journey - especially for teams using OpenAPI. It's designed to transform OpenAPI specs into beautiful, easy-to-use docs, combining speed, customization, and usability.</p>
<h4 id="heading-key-features-for-openapi-docs">Key Features for OpenAPI Docs</h4>
<ol>
<li><p><strong>One-Click API reference setup</strong></p>
<p> With Hashnode, teams can easily create API reference docs by importing OpenAPI or Swagger specs - all in just one click. This means you can go from raw API definitions to polished docs almost instantly, saving hours of manual work.</p>
<p> <a target="_blank" href="https://docs.requestly.com/public-api/apireference/post_%2Fgroups"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729535379144/18487871-cd83-473d-bed8-0a6225c3c57b.png" alt="Requestly's API reference created using Hashnode" class="image--center mx-auto" /></a></p>
</li>
<li><p><strong>Rich Visual Editor</strong></p>
<p> The new docs product offers a WYSIWYG MDX editor, letting developers add rich context, examples, diagrams, and other content that elevates basic API docs. This editor makes sure you dont just document your endpoints, but also tell the story around their use.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729535458480/bdae6eb6-8fd5-4ecd-af4f-612f68484e20.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Interactive API Playground</strong></p>
<p> Hashnode's API playground lets developers interact with the API, run requests, and see live responses. This hands-on element encourages experimentation and gives developers a quick way to learn how your API works.</p>
</li>
<li><p><strong>Super-Fast Search and Ask AI integration</strong></p>
<p> Docs by Hashnode come with a blazing-fast Algolia-powered search so developers can find exactly what they need without any hassle. Plus, teams can upgrade to AI-powered search to make finding the right information even easier.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729535533851/c8985f3b-1440-407e-874f-edc5feb94524.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<h3 id="heading-why-choose-hashnode-for-openapi-documentation">Why choose Hashnode for OpenAPI documentation?</h3>
<ul>
<li><p><strong>Speed and Convenience</strong>: Creating great OpenAPI docs shouldn't take forever. Hashnode's simple setup means rapid deployment, giving developers more time to focus on what matters.</p>
</li>
<li><p><strong>Customization for your team</strong>: Teams can fully customize the look, structure, and integration of their docs. Whether you need a sub-path like <code>/docs</code> or a complete headless setup, Hashnode's got you covered.</p>
</li>
<li><p><strong>Enterprise-Level Features</strong>: Hashnode offers enterprise features like version control, SOC2 and ISO 27001 readiness, and team collaboration tools that make managing your OpenAPI docs seamless and secure.</p>
</li>
<li><p><strong>Two-Way GitHub Sync</strong>: Manage your docs wherever you feel comfortable - in GitHub or directly in Hashnodes editor. The two-way GitHub sync keeps both your codebase and docs up-to-date effortlessly.</p>
</li>
</ul>
<h3 id="heading-make-your-openapi-docs-shine">Make your OpenAPI docs shine</h3>
<p>If your current OpenAPI docs feel lackluster or hard to use, Hashnodes docs product could be just what you need. It's designed for flexibility and rapid implementation, helping you create docs that scale with your APIs and engage your developer community.</p>
<p>With Hashnode's seamless integration, you can link your public or internal docs with your community blog or knowledge hub, creating one unified platform where developers can learn, discuss, and solve problems together.</p>
<h3 id="heading-getting-started-is-easy">Getting started is easy</h3>
<p>Ready to see the difference in your OpenAPI docs? Docs by Hashnode is now available for startups, enterprises, and open-source projects. If you have existing docs with tools like Docusaurus, ReadMe, GitBook, or Mintlify, Hashnode even offers one-day migration support to make the switch smooth and easy.</p>
<p>Try Docs by Hashnode and transform how you document your OpenAPI specs. Visit <a target="_blank" href="https://hashnode.com/docs">hashnode.com/docs</a> to learn more and get started today.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>OpenAPI is an amazing asset for API design and collaboration, but great documentation is what makes it all work. Hashnode's new docs product is here to make that process as simple and effective as possible. With rapid setup, seamless integration, and a rich feature set, Hashnode helps you ensure your OpenAPI docs are as reliable and informative as your APIs.</p>
<p>Your developers deserve great docs, and so do your users. Hashnode is here to make that happen.</p>
]]></description><link>https://hashnode.com/blog/getting-started-with-openapi-how-hashnodes-new-docs-product-can-simplify-your-api-documentation</link><guid isPermaLink="true">https://hashnode.com/blog/getting-started-with-openapi-how-hashnodes-new-docs-product-can-simplify-your-api-documentation</guid><dc:creator><![CDATA[Hashnode]]></dc:creator></item><item><title><![CDATA[5 must-haves for open-source success: how great docs and community drive developer adoption]]></title><description><![CDATA[<p>Building and maintaining an open-source project is hard. It is even harder when you are a solo maintainer or have a very small team. This article includes 5 top tips that you can follow to have a successful and thriving open-source project.</p>
<p>To begin, clearly outline your goals for the project. Whether you aim to increase monthly active users (MAU), enhance the product, or expand the community, having a clear direction is crucial.</p>
<p>Remember that an open-source project should truly embrace openness. It should be receptive to feedback, welcoming to contributions, and open to improvements.</p>
<p>All the successful projects that you see today (or even use today) have these 5 things:</p>
<h2 id="heading-1-write-good-documentation">1. Write good documentation</h2>
<p>Building a technical project and writing documentation for it should be a simultaneous process. You might be building the most helpful solution out there, but without documentation, you wont be able to onboard developers. We all know that documentation can be an extensive process, and to ease your job, you should opt for tools that make it easier for you to document, manage, and build effective documentation.</p>
<p>If you're looking for tips on writing good documentation, check out this article I wrote on <a target="_blank" href="https://hashnode.com/blog/5-tips-to-write-good-developer-documentation-in-2024">5 Tips to Write Good Developer Documentation</a>.</p>
<p>Once you know how to write documentation well, you should find a tool that:</p>
<ul>
<li><p>Offers a great developer experience</p>
</li>
<li><p>Includes AI features like assisted writing, search, and support assistance</p>
</li>
<li><p>Supports markdown</p>
</li>
<li><p>Syncs with GitHub (so people can contribute to your docs)</p>
</li>
<li><p>Provides interactive code blocks and API playgrounds</p>
</li>
</ul>
<p>Docs by Hashnode offers all of it along with a <a target="_blank" href="https://forms.hashnode.com/apply-for-open-source-license">free lifetime access for all open-source projects</a>.</p>
<p>If you would like to see more of Docs by Hashnode, watch this webinar here 👇</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=aQnljz9Ap1A">https://www.youtube.com/watch?v=aQnljz9Ap1A</a></div>
<p> </p>
<h2 id="heading-2-build-a-community">2. Build a community</h2>
<p>Community forms the foundation for most open-source projects. They not only help you give direction to your product and build it, but also help you reach your target audience through word of mouth. A lot of open-source tools that I use today are because someone told me, Oh, you should use this open-source alternative. Invest time in building that community.</p>
<p>Key things that work out are:</p>
<ul>
<li><p>Being empathetic with your community members. Making them feel welcome and heard.</p>
</li>
<li><p>Setting up channels for them to communicate. It does not need to be something fancy. You can start with GitHub discussions and then maybe move to Discord or any forum of choice.</p>
</li>
<li><p>Communication. Communicate with your community members about the roadmap, the features you are shipping, and the problems you are facing. They will feel like they are a part of it, and that is what the true open-source spirit is about.</p>
</li>
</ul>
<h2 id="heading-3-be-active-and-responsive">3. Be active and responsive</h2>
<p>Maintaining an open-source project is challenging, and staying consistent is particularly tough. However, the health of your project relies on how active it is.</p>
<p>Here are some methods to maintain activity:</p>
<ul>
<li><p>Push frequent updates.</p>
</li>
<li><p>Publish changelogs monthly/weekly.</p>
</li>
<li><p>Respond to bug reports or feature requests.</p>
</li>
</ul>
<p>Although these tasks may seem daunting, you can use tools and automation to assist you.</p>
<p>For instance, if you have bug reports or feature requests and users are waiting to be assigned, you can implement a GitHub bot that assigns users to issues when they use a command like <code>/assign</code> or <code>/take</code>.</p>
<p>Heres what the Kubernetes community does:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729162503102/1611770b-069d-4409-9b7e-71b893062d05.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-4-be-open">4. Be open</h2>
<p>The entire idea of open-source is to collaborate, have more people contribute, and support the community.</p>
<p>Some must-haves while building your open-source projects are:</p>
<ul>
<li><p><strong>A good README</strong> - Contributors and users should know what your project is about and how to use it from the start, which is why a good README is essential.</p>
</li>
<li><p><strong>Have a contributing guide</strong> - You want more contributors to contribute to your project and improve it. The best way to do that is by writing a contributing guide. <a target="_blank" href="https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions/setting-guidelines-for-repository-contributors">Follow this guide by GitHub to learn how to write one</a>.</p>
</li>
<li><p>Have a License - Include an open-source license that allows others to use, copy, modify, and contribute to your project. This is the first thing you should do when creating an open-source project. Read more about it <a target="_blank" href="https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/licensing-a-repository">here</a>.</p>
</li>
</ul>
<h2 id="heading-5-have-automations-in-place">5. Have automations in place</h2>
<p>CI/CD is an important concept in software development and helps to avoid bugs and code failures. Since it requires less human intervention, it is even more important in open-source projects.</p>
<p>One of the most common examples of CI is: Each time you receive a pull request, the tests are automatically run, and it clearly shows if all the tests pass with the new patch or if something needs to be fixed. This is useful for both contributors and maintainers. You get to maintain a certain quality for PRs, and even contributors get to know if something is breaking or not.</p>
<p>Heres a list of CI services that you can use for your projects 👇</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/ligurio/awesome-ci">https://github.com/ligurio/awesome-ci</a></div>
<p> </p>
<h2 id="heading-ending-notes">Ending notes</h2>
<p>Maintaining an open-source project is a big feat, and I am proud of each one of you for your contributions. However, it requires a lot of commitment and patience to get the first big hit. The worst part of open-source is having a great product, high monthly active users, and checking all the boxes for a good open-source project, yet not having enough funds to run it.</p>
<p>We, at Hashnode, are doing our part to contribute to the open-source community. We recently launched our documentation tool - <a target="_blank" href="https://hashnode.com/products/docs?source=blog">Docs by Hashnode</a>, and we are offering it for free to all open-source projects (of any size and number).</p>
<p>All you need to do is fill out the form below, and either I or somebody from the team will reach out to you!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://forms.hashnode.com/docs/open-source?source=blog">https://forms.hashnode.com/docs/open-source?source=blog</a></div>
]]></description><link>https://hashnode.com/blog/5-must-haves-for-open-source-success-how-great-docs-and-community-drive-developer-adoption</link><guid isPermaLink="true">https://hashnode.com/blog/5-must-haves-for-open-source-success-how-great-docs-and-community-drive-developer-adoption</guid><category><![CDATA[Open Source]]></category><category><![CDATA[community]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Haimantika Mitra]]></dc:creator></item><item><title><![CDATA[Automate TL;DR posts on X using Hashnode Webhooks and Vercel AI]]></title><description><![CDATA[<p>AI has fascinated us since last year, and as developers, we have been using it to automate or simplify tasks that would otherwise take up a lot of our time.</p>
<p>In this article, we will learn how to generate a summary of the technical articles you write on Hashnode, and post it on X.</p>
<p>We covered this in a live webinar. If you prefer a video format, head over to our YouTube channel:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://hshno.de/jMrOpp9">https://hshno.de/jMrOpp9</a></div>
<p> </p>
<p>Technologies that will be used to build the solution:</p>
<ul>
<li><p><a target="_blank" href="https://support.hashnode.com/en/articles/8488809-blog-webhooks">Hashnode Webhooks</a></p>
</li>
<li><p><a target="_blank" href="https://nextjs.org/">Next.js</a></p>
</li>
<li><p><a target="_blank" href="https://developer.x.com/en/docs/x-api">X API</a></p>
</li>
<li><p><a target="_blank" href="https://sdk.vercel.ai/docs/introduction">Vercel AI SDK</a></p>
</li>
</ul>
<h2 id="heading-what-are-webhooks">What are Webhooks?</h2>
<p>A webhook is a way to automate responses in software. Theyre like "event-based APIs." This means when something happens, like a new post created or a specific action, the webhook triggers a response as its set up to do. Webhooks are great for real-time communication and can activate actions in other applications based on certain events.</p>
<p><a target="_blank" href="https://support.hashnode.com/en/articles/8488809-blog-webhooks">Hashnode's webhook feature</a> lets you get instant notifications for specific events related to your publication. You can set up webhooks to watch for six main events:</p>
<ul>
<li><p>Post published</p>
</li>
<li><p>Post deleted</p>
</li>
<li><p>Post updated</p>
</li>
<li><p>Static page published</p>
</li>
<li><p>Static page edited</p>
</li>
<li><p>Static page deleted</p>
</li>
</ul>
<h2 id="heading-getting-started">Getting started</h2>
<p>The application flow is simple: Hashnode webhook fetches article details, sends them to Vercels AI SDK to summarize and generate a TL;DR, and then posts it using the X API.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727339877416/b6c441ea-74a6-408c-a5ab-e415b24a1a46.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-step-1-fetching-posts-from-hashnode">Step 1: Fetching posts from Hashnode</h2>
<p>Before we move on to fetching posts from Hashnode, you need to add a webhook and you can do that from the <a target="_blank" href="https://hshno.de/dashboard">blog dashboard</a>.</p>
<p>The video below shows how you can add it:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.loom.com/share/72b6504eeee740dcbb12539614d5afc0?sid=9582962d-8d61-4c22-a25a-e2f859a7ba2c">https://www.loom.com/share/72b6504eeee740dcbb12539614d5afc0?sid=9582962d-8d61-4c22-a25a-e2f859a7ba2c</a></div>
<p> </p>
<p>Fill in the following details:</p>
<ul>
<li><p><strong>Endpoint URL:</strong> Should look something like <code>https://example.com/path</code></p>
</li>
<li><p><strong>Events:</strong> Check the <code>post_published</code> box.</p>
</li>
<li><p><strong>Secret:</strong> Keep it copied, as we will need it for the next steps.</p>
</li>
</ul>
<p><strong><em>Note:</em></strong> <em>Make sure to create an</em><code>.env.local</code> <em>file. You can copy the keys from</em> <a target="_blank" href="https://github.com/devendershekhawat/hashnode-webhook-demo-webinar/blob/main/.env.example"><em>.env.example</em></a> <em>file and add the values.</em></p>
<p>The next step is to write handler for the webhook and verify it.</p>
<p><strong><em>Why you need to verify your webhooks?</em></strong></p>
<p>Webhooks are simply REST APIs deployed on your server, making them public. You only want these endpoints to be called by Hashnode when an event like <code>post_published</code> occurs. You definitely don't want anyone else to call the webhook endpoint and publish a tweet on your behalf.</p>
<p>Every webhook you create comes with a webhook secret that you copied above. Hashnode sends the payload signed with a secret and also send the resulting signature in the headers of the request sent to your webhook endpoint.</p>
<p>To verify your signature, you need to write some logic, and we've got you covered! Click on the link that says <a target="_blank" href="https://support.hashnode.com/en/articles/8488809-blog-webhooks#h_ca60049898"><em>Learn how it works</em></a>, and copy the code block that starts with <code>import crypto from 'crypto';</code>. You will need to install the <code>crypto</code> npm package for this to work.</p>
<p>This code comes with a <code>validateSignature</code> function that can be used like this</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> payload = <span class="hljs-keyword">await</span> req.json();
<span class="hljs-comment">// This is sent by hashnode with header</span>
<span class="hljs-keyword">const</span> signature = req.headers.get(<span class="hljs-string">'x-hashnode-signature'</span>);
<span class="hljs-comment">// The secret you copied</span>
<span class="hljs-keyword">const</span> webhookSecret = process.env.HASHNODE_WEBHOOK_SECRET;
<span class="hljs-keyword">const</span> { isValid } = validateSignature({
    <span class="hljs-attr">incomingSignatureHeader</span>: signature,
    <span class="hljs-attr">secret</span>: webhookSignature,
});
</code></pre>
<p>Now if <code>isValid</code> is false you can return a <code>401 Unauthorized</code>. If <code>true</code> you can proceed.</p>
<p>Once the webhook is created, we write the code that fetches the post using Hashnodes GraphQL APIs 👇</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getPostById = <span class="hljs-keyword">async</span> (postId: <span class="hljs-built_in">string</span>) =&gt; {
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'https://gql.hashnode.com'</span>, {
        method: <span class="hljs-string">'POST'</span>,
        headers: {
            <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
            <span class="hljs-string">'Authorization'</span>: <span class="hljs-string">`Bearer <span class="hljs-subst">${process.env.HASHNODE_ACCESS_TOKEN}</span>`</span>,
        },
        body: <span class="hljs-built_in">JSON</span>.stringify({
            query: <span class="hljs-string">`
                query GetPostById {
                    post(id: "<span class="hljs-subst">${postId}</span>") {
                        id
                        title
                        url
                        content {
                            markdown
                        }
                    }
                }
            `</span>,
        })
    })

    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.json();
    <span class="hljs-keyword">return</span> data.data.post;
}
</code></pre>
<p>The <code>getPostById</code> function sends a POST request to Hashnode's GraphQL API to fetch details of a post by its <code>postId</code>, including the title, URL, and markdown content. It returns the post data as a JSON object after handling the response.</p>
<h2 id="heading-step-2-summarise-the-fetched-article">Step 2: Summarise the fetched article</h2>
<p>Now that we have fetched the article details, the next step is to create a summary for it, and for that we will be using the <a target="_blank" href="https://sdk.vercel.ai/providers/ai-sdk-providers/openai">Vercel AI SDK</a>.</p>
<p>First, you need to generate an <a target="_blank" href="https://platform.openai.com/docs/overview">OpenAI API key</a> and add it to your <code>.env</code> file.</p>
<p>Then, use the following code to generate the summary:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { openai } <span class="hljs-keyword">from</span> <span class="hljs-string">'@ai-sdk/openai'</span>;
<span class="hljs-keyword">import</span> { generateText } <span class="hljs-keyword">from</span> <span class="hljs-string">'ai'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> generateTLDR = <span class="hljs-keyword">async</span> (content: <span class="hljs-built_in">string</span>) =&gt; {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> { text } = <span class="hljs-keyword">await</span> generateText({
            model: openai(<span class="hljs-string">'gpt-4-turbo'</span>),
            prompt: <span class="hljs-string">`Summarize this article in a concise, engaging TLDR suitable for a tweet. Article content: <span class="hljs-subst">${content}</span>`</span>,
            temperature: <span class="hljs-number">0.7</span>, <span class="hljs-comment">// Adjust for creativity; lower values make the output more deterministic</span>
        });

        <span class="hljs-keyword">return</span> { text: text.trim() };   
    } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Exception caught while generating TLDR:'</span>, error);
        <span class="hljs-keyword">return</span> { error: <span class="hljs-string">'Exception occurred during TLDR generation. Please try again.'</span> }    ;
    }
}
</code></pre>
<p>The <code>generateTLDR</code> function send the prompt to OpenAI to summarize a given article. The prompt specifically requests a concise and engaging TLDR suitable for a tweet, using the provided article content.</p>
<h2 id="heading-step-3-post-the-generated-summary-on-x">Step 3: Post the generated summary on X</h2>
<p>The final step is to use the summary generated by OpenAI to create a post on X.</p>
<p>First, create a <a target="_blank" href="https://developer.x.com/en">Developer account on the X developer platform</a>. Then, create a project and within that project, create an app for free. After creating the app, generate and copy the keys and tokens.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727339641890/0a25c5d1-5d22-4f40-a799-a70096102ecf.png" alt class="image--center mx-auto" /></p>
<p>Once that is done, move to your IDE and write the code below to make a post on X:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { TwitterApi } <span class="hljs-keyword">from</span> <span class="hljs-string">'twitter-api-v2'</span>;

<span class="hljs-keyword">const</span> client = <span class="hljs-keyword">new</span> TwitterApi({
    appKey: process.env.X_API_KEY!,
    appSecret: process.env.X_API_KEY_SECRET!,
    accessToken: process.env.X_ACCESS_TOKEN!,
    accessSecret: process.env.X_ACCESS_TOKEN_SECRET!,
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> tweetThread = <span class="hljs-keyword">async</span> (content: <span class="hljs-built_in">string</span>, postUrl: <span class="hljs-built_in">string</span>) =&gt; {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> tweets = [
            content,
            <span class="hljs-string">`Here is the link to the post: <span class="hljs-subst">${postUrl}</span>`</span>
        ];
        <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> client.v2.tweetThread(tweets);
        <span class="hljs-keyword">return</span> { success: <span class="hljs-literal">true</span>, data: response };
    } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Failed to tweet thread:'</span>, error);
        <span class="hljs-keyword">return</span> { success: <span class="hljs-literal">false</span>, error: <span class="hljs-string">'Failed to tweet thread. Please check the logs for more details.'</span> };
    }
}
</code></pre>
<p>We initialize the X API client and define the <code>tweetThread</code> function, which takes the summary and a post URL as parameters. This function creates a tweet thread containing the summary from the <code>generateTLDR</code> function (that we generated in <strong>Step 2</strong>) and a link to the original post (that is fetched in <strong>Step 1)</strong>, then posts it to X.</p>
<h2 id="heading-resources">Resources</h2>
<p>With that, you can see how to easily create a workflow using AI and webhooks to help you make social media posts from your articles.</p>
<p>Here are some resources to help you learn more:</p>
<ul>
<li><p><a target="_blank" href="https://github.com/devendershekhawat/hashnode-webhook-demo-webinar">GitHub repository for the application</a></p>
</li>
<li><p><a target="_blank" href="https://support.hashnode.com/en/articles/8488809-blog-webhooks">Hashnode webhook docs</a></p>
</li>
<li><p><a target="_blank" href="https://developer.x.com/en/docs/x-api">X API docs</a></p>
</li>
<li><p><a target="_blank" href="https://sdk.vercel.ai/docs/introduction">Vercel AI SDK docs</a></p>
</li>
</ul>
]]></description><link>https://hashnode.com/blog/automate-tldr-posts-on-x-using-hashnode-webhooks-and-vercel-ai</link><guid isPermaLink="true">https://hashnode.com/blog/automate-tldr-posts-on-x-using-hashnode-webhooks-and-vercel-ai</guid><category><![CDATA[Web Development]]></category><category><![CDATA[AI]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Haimantika Mitra]]></dc:creator></item><item><title><![CDATA[Setup a rich API playground documentation for developers with one click from OpenAPI specification.]]></title><description><![CDATA[<p>This article will show you how to create a rich API playground for your products <a target="_blank" href="https://hashnode.com/blog/getting-started-with-openapi-how-hashnodes-new-docs-product-can-simplify-your-api-documentation">documentation using OpenAPI</a> or Swagger with Hashnodes new documentation tool.</p>
<p>Hashnode is a top publishing platform with millions of developers and companies using it to share articles on their <a target="_blank" href="https://hashnode.com/products/blogs">blog</a> and build <a target="_blank" href="https://hashnode.com/products/docs">product and API docs</a>.</p>
<h3 id="heading-why-you-should-choose-hashnode-for-your-developer-documentation">Why you should choose Hashnode for your developer documentation:</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727185986389/b2fe1a6a-d271-498d-8b6b-282cd77aa85e.png" alt class="image--center mx-auto" /></p>
<ol>
<li><p><strong>Easy to start</strong>  Hashnode makes creating product and <a target="_blank" href="https://hashnode.com/products/docs">API docs</a> simple. Just sign up and follow the steps on the homepage. You can use the hosted version of the docs and map it to a custom domain or subdomain. No coding, no infrastructure, no maintenance. The docs are SEO-optimized from the get-go.</p>
</li>
<li><p><strong>Create multiple guides and API references in one project</strong>  With Hashnode, you can create unlimited textual guides and API references under the same project. No need for separate licenses to cover all your products or projects.</p>
</li>
<li><p><strong>Write docs like in Notion or Google Docs </strong> Hashnodes rich visual MDX editor lets you create and edit docs just like working in Notion or Google Docs. It supports all Markdown syntax for those who prefer it and offers visual tools like slash commands and formatting toolbars for easy styling.</p>
</li>
<li><p><strong>Collaborative editing and comments </strong> Hashnode enables real teamwork. Your whole team can edit the same document simultaneously, leave review comments, and move quickly.</p>
</li>
<li><p><strong>Headless mode for advanced customization </strong> Many developers leave products like Readme and GitBook because they don't offer headless options. Teams then turn to open-source tools like Docusaurus (which are tough to manage) or build docs in-house. Hashnodes headless mode lets your frontend team fork Hashnodes Next.js + TailwindCSS docs starter kit, which uses our GraphQL APIs. Your team can deploy this code anywhere, make unlimited tweaks, add custom components, and remove anything they dont need.</p>
</li>
<li><p><strong>Faster documentation UX </strong> Hashnode's hosted and headless frontends are optimized for speed, performance, and SEO, ensuring a great experience for your users. Both perform exceptionally well on Lighthouse scores.</p>
</li>
<li><p><strong>Ask AI search </strong> Every Hashnode docs site includes an Ask AI feature thats always up-to-date with your published content. Its accurate, free of hallucinations, and gives instant answers to user queries. This is my favorite feature! ;)</p>
</li>
</ol>
<p>In addition to these features, Hashnode provides an advanced dashboard to track user analytics and insights from your docs. You can also create custom pages, add team members with different roles, and more. <a target="_blank" href="https://hashnode.com/products/docs">Create your developer docs for free.</a></p>
<h2 id="heading-openapi-reference-setup">OpenAPI Reference Setup</h2>
<p>Creating an API reference from an OpenAPI spec or Swagger on Hashnode takes under 3 minutes.</p>
<ol>
<li><p>Log in to your Hashnode account.</p>
</li>
<li><p>On your homepage, click the New docs button. If you already have a doc, skip this step.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727186051032/c8e78c4d-202a-481b-a57d-29aa4e42ddf7.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Enter the docs name, choose a sub-domain (you can link a custom domain later), optionally add a logo, and click Create.</p>
</li>
<li><p>Your docs project will appear under the Docs section. Click the dashboard button to access it.</p>
</li>
<li><p>In the dashboard, go to the guides section.</p>
</li>
<li><p>Click the New button, then select New API reference.</p>
</li>
<li><p>Enter the OpenAPI spec URL, name your guide (e.g., Acme API reference), choose a slug like <code>api-reference</code>, and click Import and create.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727185990261/3227bbb8-627a-427c-ac85-b449fbb7adde.png" alt class="image--center mx-auto" /></p>
<p>Your API reference playground will be ready and live instantly. You can view and test it on your docs site. For easy access, you can add a link to the API reference in the Navbar settings in the dashboard.</p>
<hr />
<p>We built Hashnodes docs product to help you create and scale developer documentation and API references that evolve with your code. Its designed for teams needing full control, customization, and Stripe-level qualitywithout the hassle. Sign up now and create a free doc today!</p>
]]></description><link>https://hashnode.com/blog/create-a-rich-api-playground-documentation-for-developers-with-one-click-from-openapi-specification</link><guid isPermaLink="true">https://hashnode.com/blog/create-a-rich-api-playground-documentation-for-developers-with-one-click-from-openapi-specification</guid><category><![CDATA[api documentation]]></category><category><![CDATA[documentation]]></category><category><![CDATA[Hashnode]]></category><dc:creator><![CDATA[Syed Fazle Rahman]]></dc:creator></item><item><title><![CDATA[5 tips to write good developer documentation]]></title><description><![CDATA[<p>All developer tools go through five stages: discover, evaluate, learn, build, and scale.</p>
<p>While you are in the discovery stage and moving towards the evaluation phase, this is where you should maximize focus on your docs. As they say, Documentation is the product. Your aim should be to have a great developer experience and to reduce the time to hello world (TTHW) to five minutes or less.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726140258344/daa1c3af-023c-4ad6-909f-e00829c0fcb9.webp" alt class="image--center mx-auto" /></p>
<p>When developers discover your tool, you only have a few minutes to get their attention. You need to make sure that your docs provide a good developer experience, have more code, and offer a smooth developer journey.</p>
<p>In this article, I will share the top 5 tips on how to write effective developer documentation that you can follow to write good Stripe-like <a target="_blank" href="https://hashnode.com/products/docs">developer documentation</a>.</p>
<p>Here are some of my favorite developer docs today:</p>
<ol>
<li><p><a target="_blank" href="https://docs.stripe.com/">Stripe</a> - Every technical writer I know has taken reference from the Stripe docs. It is their simplicity, attention to detail, and structure that make it one of the best developer documentation.</p>
</li>
<li><p><a target="_blank" href="https://www.twilio.com/docs">Twilio</a> - As somebody who has used Twilio a lot, one of the main reasons why I chose it over other alternatives is because of their quickstarts. Twilio has a great time to hello world (TTHW), which makes developers stick to it.</p>
</li>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/docs/">Microsoft</a> - Microsoft docs are extensive and well-structured, showing Microsoft's commitment to developer education. The developer journey, module structure, and sandbox environments make their docs a complete package.</p>
</li>
<li><p><a target="_blank" href="https://docs.aws.amazon.com/">AWS</a> - AWS docs are extensive and detailed. They include potential errors and solutions, preventing developers from getting stuck and switching between support forums, which also helps with developer retention.</p>
</li>
<li><p><a target="_blank" href="https://appwrite.io/docs">Appwrite</a> - Appwrite treats its documentation as a product. With tutorials and quickstarts in multiple frameworks, it's easy for any developer to get started. They excel in search and versioning, addressing common issues developers face due to version differences and updated methods not well-documented.</p>
</li>
</ol>
<p>Lets see what made them to the top five developer documentation:</p>
<h2 id="heading-1-knowing-your-audience">1. Knowing your audience.</h2>
<p>The first step to writing good documentation is to know who you are writing it for. There are multiple types of developers depending on experience, tech stack, and more.</p>
<p>Who is your target audience? Who are you writing it for? To know the answers, build developer personas, and talk to the developer community.</p>
<p>Here are some ways to identify your audience:</p>
<ol>
<li><p>Use social media (ask questions, do polls, gather as much information as you can).</p>
</li>
<li><p>If you have a developer community, send out user feedback forms and learn what your developers want.</p>
</li>
<li><p>Use community tools that help you follow a developers journey on your product, and use that to improve your product and docs.</p>
</li>
</ol>
<h2 id="heading-2-choosing-the-right-documentation-tool">2. Choosing the right documentation tool.</h2>
<p>Developer tools grow fast, and you need to ship your documentation simultaneously. Investing in the right documentation tool is very crucial, as it can build or break the developer experience.</p>
<p>You need to make sure that you choose a tool that:</p>
<ul>
<li><p>Is easy to set up and get started (Documentation in itself is a lengthy process, and you cannot be stuck on getting started using a platform).</p>
</li>
<li><p>Offers a good developer experience and also gives you all the control to tailor your own experience (like branding, embeddings, and more).</p>
</li>
<li><p>Allows developers to experiment with your product. Developers want to build, and the best way to get them to use your tool is by providing a playground within your documentation. So, ensure the documentation tool you choose has an option to add a playground.</p>
</li>
<li><p>Has AI tools that help you fix spelling, grammar, and other details (In this AI era, you shouldnt have to juggle multiple applications and extensions to fix a semicolon).</p>
</li>
<li><p>Helps you understand how your documentation is performing and includes a feedback system.</p>
</li>
</ul>
<p>A tool that does everything I just mentioned is <a target="_blank" href="https://hashnode.com/products/docs?source=docsarticle">Docs by Hashnode</a> - you get all the goodness built within.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/yqMlbZh-eeY?si=q_sccPuE2H_pCJh2">https://youtu.be/yqMlbZh-eeY?si=q_sccPuE2H_pCJh2</a></div>
<p> </p>
<h2 id="heading-3-writing-code-samples-and-api-references-that-are-easy-to-follow">3. Writing code samples and API references that are easy to follow.</h2>
<p>Less talk, more code should be your mantra when writing developer documentation. Every concept needs a code example or real-life implementation. Include API references, quickstarts, examples in various frameworks, and integrations.</p>
<p>If you are not aware, there is a credit card hell that most developer tools have. Before a developer gives you their card details, you need to convince them 100% that they need it and that you are actually a developer tool that makes their lives easier. It is your docs that will do the convincing.</p>
<p>Heres an example of documentation built with <a target="_blank" href="https://hashnode.com/products/docs?source=docsarticle">Hashnodes documentation tool</a> that includes an API reference and a playground, making it easy for developers to follow:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://x.com/fazlerocks/status/1830598276841644529">https://x.com/fazlerocks/status/1830598276841644529</a></div>
<p> </p>
<h2 id="heading-4-having-a-well-defined-structure">4. Having a well-defined structure.</h2>
<p>Your documentation should have a structure that is easy for your developer audience to follow. Take an example of the <a target="_blank" href="https://learn.microsoft.com/en-us/docs/">Microsoft</a> docs, despite of being extensive, it is very structured. This helps in onboarding all levels of developers quickly, while also educating them about the product.</p>
<p>To improve developer documentation for beginners, you need to create a developer journey that makes it easy for them to build with your tool. Think of it like learning to write: we start with alphabets, then simple words, sentences, and paragraphs. Your developer documentation would follow a similar structurebasic introduction, installation, and a "hello world" program.</p>
<p>Your product adoption relies on both <strong>documentation</strong> and <strong>support</strong>. In fact, your documentation is the main source of truth for support. Having an AI-powered chatbot within your documentation can help developers ask questions and get answers instantly. This prevents them from switching between a community channel and the docs, allowing them to get help directly from the source.</p>
<p>The Requestly docs, powered by <a target="_blank" href="https://hashnode.com/products/docs?source=docsarticle">Docs by Hashnode</a>, are a great example of how clear navigation and AI-powered search and chat can improve the developer experience with built-in features.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.loom.com/share/25c6eb6e77a44e65a2bdda7da5787d9e?sid=7bd97192-713f-4b4e-be13-b6a042a63184">https://www.loom.com/share/25c6eb6e77a44e65a2bdda7da5787d9e?sid=7bd97192-713f-4b4e-be13-b6a042a63184</a></div>
<p> </p>
<h2 id="heading-5-introducing-a-feedback-loop-to-improve-your-documentation">5. Introducing a feedback loop to improve your documentation.</h2>
<p>Documentation is a continuous process. You need to keep improving it as new frameworks come up, software architecture evolves, and reading patterns change. The best way to do this is by having a feedback loop. Listen to your users and improve based on their input. This is why having a feedback system and tracking analytics is important.</p>
<p>This is where a product like <a target="_blank" href="https://hashnode.com/products/docs?source=docsarticle">Hashnodes documentation tool</a> can help. With a built-in feedback system, you hear directly from users about your documentation's quality and areas for improvement. It also features a dashboard with detailed analytics and smart reports.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726213598018/9ec0108a-b863-4fa8-83ce-a4610d82e851.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Writing developer documentation is challenging, even more so than writing code. You need to balance providing the right amount of information and enough examples while focusing on the developer experience.</p>
<p>Building developer experience in-house can be a very time-consuming process. Instead, you can choose a documentation tool like <a target="_blank" href="https://hashnode.com/products/docs?source=docsarticle">Docs by Hashnode</a> that handles all of it for you, making it easier for you to focus on the content and the code.</p>
<p>I hope this article has helped you get a good start and understand the key areas that can make your documentation better, especially when writing user-friendly developer guides.</p>
]]></description><link>https://hashnode.com/blog/5-tips-to-write-good-developer-documentation-in-2024</link><guid isPermaLink="true">https://hashnode.com/blog/5-tips-to-write-good-developer-documentation-in-2024</guid><category><![CDATA[APIDocumentation]]></category><category><![CDATA[documentation]]></category><category><![CDATA[Hashnode]]></category><dc:creator><![CDATA[Haimantika Mitra]]></dc:creator></item><item><title><![CDATA[GraphQL 101: Learn to Build with GraphQL APIs]]></title><description><![CDATA[<p>Whether you are someone who is getting started with tech or a junior software engineer, APIs are something that you will come across almost every day in your job.</p>
<p>REST and GraphQL APIs are the most widely used ones in the industry, and in this article, we will cover the basics, along with a demo on how you can integrate GraphQL APIs.</p>
<p><strong>TL;DR</strong></p>
<p>Check out the webinar on GraphQL 101, that covers everything we mention in this article:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=2LyhUvdMCbI">https://www.youtube.com/watch?v=2LyhUvdMCbI</a></div>
<p> </p>
<hr />
<h2 id="heading-understanding-how-graphql-works">Understanding how GraphQL works</h2>
<p>When working with REST APIs, data is retrieved from specific endpoints. Each endpoint has a defined structure for the information it returns. This means the data requirements of a client are embedded in the URL it connects to.</p>
<p>GraphQL takes a different approach. Instead of multiple endpoints with fixed data structures, GraphQL APIs usually expose only <em>a</em> <strong><em>single endpoint</em></strong>. This is possible because the data structure is not fixed. Instead, it is flexible and allows the client to specify what data is needed.</p>
<h3 id="heading-key-concepts">Key Concepts</h3>
<ul>
<li><p><strong>Schema</strong>: Defines the structure of your API, the types of data that can be queried, and how they relate to each other.</p>
</li>
<li><p><strong>Fields:</strong>  Specific pieces of data you request from a type in a query.</p>
</li>
<li><p><strong>Queries</strong>: The method by which you request specific data.</p>
</li>
<li><p><strong>Mutations</strong>: Used to modify data (create, update, delete).</p>
</li>
<li><p><strong>Types</strong>: The building blocks of a schema, representing the shape and structure of data (e.g., String, Int, User, etc.).</p>
</li>
</ul>
<h3 id="heading-schema-and-types">Schema and types</h3>
<p>A GraphQL server connects the client to data sources, allowing flexible and efficient data queries and manipulations. When a client sends a request, the server uses the <code>GraphQL Schema</code> to validate and execute it, then responds with the data or errors. The server relies on its <code>Schema</code> to handle these requests and define available operations.</p>
<p>Types are the building blocks of a GraphQL schema. They describe the shape of the data that can be queried. A <code>GraphQL Type</code> defines entities with their fields. Here are the different available types:</p>
<ul>
<li><p>Scalar Type</p>
</li>
<li><p>Object Type</p>
</li>
<li><p>Input Types</p>
</li>
<li><p>Enumeration Type</p>
</li>
<li><p>Union and Interface Type</p>
</li>
<li><p>Lists and Non-Null</p>
</li>
</ul>
<p>Let us understand it with an example query from <a target="_blank" href="https://apidocs.hashnode.com/">Hashnode API</a>, which checks if a custom domain is available or not:</p>
<pre><code class="lang-graphql"><span class="hljs-keyword">query</span> CheckCustomDomainAvailability(<span class="hljs-variable">$input</span>: CheckCustomDomainAvailabilityInput!) {
  checkCustomDomainAvailability(<span class="hljs-symbol">input:</span> <span class="hljs-variable">$input</span>) {
    domainAvailable
  }
}
</code></pre>
<p>In this example:</p>
<ol>
<li><p><strong>Schema elements:</strong></p>
<ul>
<li><p><code>CheckCustomDomainAvailability</code> is the name of the query operation.</p>
</li>
<li><p><code>checkCustomDomainAvailability</code> is a field on the root Query type in the schema.</p>
</li>
</ul>
</li>
<li><p><strong>Types:</strong></p>
<ul>
<li><p><code>CheckCustomDomainAvailabilityInput!</code> is an input type. The <code>!</code> indicates that it's a non-nullable type, meaning it's required.</p>
</li>
<li><p>There's an implied return type for the <code>checkCustomDomainAvailability</code> field, which includes a <code>domainAvailable</code> field. This return type isn't named in the query, but it exists in the schema.</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-mutation">Mutation</h3>
<p>A mutation in GraphQL is an operation used to modify data on the server. While queries are used to read data, mutations are used to create, update, or delete data. Mutations are essential for any operation that changes the state of the data on the server.</p>
<p>Let us understand with an example. The <code>acceptInviteToPublication</code> mutation in <a target="_blank" href="https://apidocs.hashnode.com/">Hashnode GraphQL APIs</a> is used to accept an invitation to join a publication.</p>
<pre><code class="lang-graphql"><span class="hljs-keyword">mutation</span> AcceptInviteToPublication(<span class="hljs-variable">$input</span>: AcceptInviteToPublicationInput!) {
  acceptInviteToPublication(<span class="hljs-symbol">input:</span> <span class="hljs-variable">$input</span>) {
    success
  }
}
</code></pre>
<p>In this example:</p>
<ol>
<li><p><code>mutation</code> is the operation type, indicating that this is a mutation rather than a query.</p>
</li>
<li><p><code>AcceptInviteToPublication</code> is the name of the mutation operation.</p>
</li>
<li><p><code>$input: AcceptInviteToPublicationInput!</code> is a variable declaration. It specifies that this mutation expects an input of type <code>AcceptInviteToPublicationInput</code>, and the <code>!</code> indicates that this input is required (non-nullable).</p>
</li>
<li><p><code>acceptInviteToPublication(input: $input)</code> is the actual mutation being called. It's a field on the root Mutation type in the schema, and it takes the <code>input</code> argument.</p>
</li>
<li><p><code>success</code> is a field on the return type of the <code>acceptInviteToPublication</code> mutation, a boolean indicating whether the operation was successful.</p>
</li>
</ol>
<hr />
<h2 id="heading-graphql-integrations-with-client">GraphQL Integrations with Client</h2>
<p>Now that you have an idea of GraphQL schema, types, and mutations, lets go over several ways to make requests to Hashnode GrapQL API, for example. The same examples used for Hashnode GraphQL API can be used for all GraphQL APIs. Since our client application is mostly built with JavaScript, lets see how to make Graphql API requests with just Vanilla JavaScript before using <a target="_blank" href="https://commerce.nearform.com/open-source/urql/">URQL a graphql client</a> for the final example.</p>
<h3 id="heading-basic-graphql-query"><strong>Basic GraphQL Query</strong></h3>
<p>A basic query allows you to fetch specific fields from the GraphQL API. In the example below, well get the user <strong>Favourite</strong> and these fields <strong>name, username, profilePicture,</strong> and <strong>tagline</strong> from the <a target="_blank" href="https://gql.hashnode.com/">Hashnode Graphql API</a>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> query = <span class="hljs-string">`
  query GetUserProfile {
    user(username: "Favourite") {
      id
      username
      name
      profilePicture
      tagline
    }
  }
`</span>;

fetch(<span class="hljs-string">'https://gql.hashnode.com/'</span>, {
  <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
  <span class="hljs-attr">headers</span>: {
    <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
  },
  <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
    query,
  })
})
.then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
.then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(data))
.catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error:'</span>, error));
</code></pre>
<ul>
<li><p><strong>query</strong>: Defined is the GraphQL query operation as a string.</p>
</li>
<li><p><strong>fetch</strong>: This sends a POST request to the GraphQL endpoint.</p>
</li>
<li><p><strong>URL</strong>: The Hashnode GraphQL API endpoint (<a target="_blank" href="https://api.hashnode.com/">https://api.hashnode.com/</a>).</p>
</li>
<li><p><strong>Headers</strong>: The Content-Type is set to <code>application/json</code></p>
</li>
<li><p><strong>Body</strong>: The request body includes the query serialized into JSON.</p>
</li>
</ul>
<h3 id="heading-query-with-aliases"><strong>Query with Aliases</strong></h3>
<p>GraphQL aliases allow you to fetch the same field multiple times with different arguments or rename the results for better clarity. Lets see how we can achieve this below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> query = <span class="hljs-string">`
   query {
      favUser: user(username: "Favourite") {
        name
      }
      anotherUser: user(username: "Haimantika") {
        name
      }
  }
`</span>

fetch(<span class="hljs-string">'https://gql.hashnode.com/'</span>, {
  <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
  <span class="hljs-attr">headers</span>: {
    <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
  },
  <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
    query,
  })
})
.then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
.then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(data))
.catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error:'</span>, error));
</code></pre>
<ul>
<li>From the query <strong>favUser</strong> and <strong>anotherUser</strong> are aliases that rename the results, allowing you to query multiple users - (Favourite &amp; Haimantika) in one request.</li>
</ul>
<p>The result of the query would be in this structure, where you have different names of users with one request.</p>
<pre><code class="lang-javascript">{
  <span class="hljs-attr">data</span>: {
    <span class="hljs-attr">favUser</span>: { <span class="hljs-attr">name</span>: <span class="hljs-string">'Favourite Jome'</span> },
    <span class="hljs-attr">anotherUser</span>: { <span class="hljs-attr">name</span>: <span class="hljs-string">'Haimantika Mitra'</span> }
  }
}
</code></pre>
<h3 id="heading-query-with-arguments"><strong>Query with Arguments</strong></h3>
<p>Arguments are inputs you provide to fields or queries to filter or modify the data you retrieve. They allow you to pass specific parameters to control the query results.</p>
<p>If you didnt notice, weve been using arguments in the previous examples to get the user information from a specific user - <strong>Favourite.</strong> In the example below, we pass two new arguments to a field - <strong>posts.</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> query = <span class="hljs-string">`
  query GetUserWithPosts {
    user(username: "Favourite") {
      id
      name
      posts(page: 1, pageSize: 5) {
        nodes {
          id
          title
        }
      }
    }
  }
`</span>;

fetch(<span class="hljs-string">'https://gql.hashnode.com/'</span>, {
  <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
  <span class="hljs-attr">headers</span>: {
    <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
  },
  <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
    query,
  })
})
.then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
.then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(data))
.catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error:'</span>, error));
</code></pre>
<p>Here, <code>page: 1</code> and <code>pageSize: 5</code> are arguments passed to the user field, telling the API to return five posts from the user publications on the first page.</p>
<h3 id="heading-query-with-variables"><strong>Query with Variables</strong></h3>
<p>Queries with variables allow you to pass dynamic inputs into a query, making the query flexible and reusable instead of hard-coded like the previous examples. Heres how to query with variables:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> query = <span class="hljs-string">`
  query GetUserWithPosts(
    $username: String!, 
    $page: Int!, 
    $pageSize: Int!
  ) {
    user(username: $username) {
      id
      name
      posts(page: $page, pageSize: $pageSize) {
        nodes {
          id
          title
        }
      }
    }
  }
`</span>;

<span class="hljs-keyword">const</span> variables = {
    <span class="hljs-attr">username</span>: <span class="hljs-string">"Haimantika"</span>,
    <span class="hljs-attr">page</span>: <span class="hljs-number">1</span>,
    <span class="hljs-attr">pageSize</span>: <span class="hljs-number">5</span>
}

fetch(<span class="hljs-string">'https://gql.hashnode.com/'</span>, {
  <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
  <span class="hljs-attr">headers</span>: {
    <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
  },
  <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
    query,
    variables
  })
})
.then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
.then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(data))
.catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error:'</span>, error));
</code></pre>
<p><strong>Explanation</strong>:</p>
<ul>
<li><p><strong>Query Name:</strong> GetUserWithPosts is the query name that accepts three variables</p>
</li>
<li><p><strong>Variables:</strong> The query accepts three variables:</p>
<ul>
<li><p><strong>$username:</strong> String!  a required string for the username.</p>
</li>
<li><p><strong>$page:</strong> Int!  a required integer to define the page of posts.</p>
</li>
<li><p><strong>$pageSize:</strong> Int!  a required integer to define the number of posts per page.</p>
</li>
</ul>
</li>
<li><p><strong>Query</strong>: The query requests the <code>id</code> and <code>name</code> of the user, along with their posts <code>id</code> and title, using pagination (<code>page</code> and <code>pageSize</code>).</p>
</li>
</ul>
<h3 id="heading-query-with-fragments">Query with Fragments</h3>
<p>Fragments allow you to reuse query fields in different parts of the query or across multiple queries. In the example below, we have a fragment named <strong>PostDetails</strong>, which will be used for the type <strong>Post.</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> fragment = <span class="hljs-string">`
  fragment PostDetails on Post {
    id
    title
    brief
    publishedAt
  }
`</span>;

<span class="hljs-keyword">const</span> query = <span class="hljs-string">`
  <span class="hljs-subst">${fragment}</span>  # Include the fragment in the query
  query GetUserWithPosts($username: String!) {
    user(username: $username) {
      name
      posts(page: 1, pageSize: 2) {
        nodes {
          ...PostDetails  # Using the fragment here
        }
      }
    }
  }
`</span>;


<span class="hljs-keyword">const</span> variables = {
  <span class="hljs-attr">username</span>: <span class="hljs-string">"Favourite"</span>
};

fetch(<span class="hljs-string">'https://gql.hashnode.com/'</span>, {
  <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
  <span class="hljs-attr">headers</span>: {
    <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
  },
  <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
    query,
    variables
  })
})
.then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
.then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(data))
.catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error:'</span>, error));
</code></pre>
<p>To see how fragment shines, in the same query, lets get the publication details of a blog using the same fragment <strong>PostDetails.</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> fragment = <span class="hljs-string">`
  fragment PostDetails on Post {
    id
    title
    brief
    publishedAt
  }
`</span>;

<span class="hljs-keyword">const</span> query = <span class="hljs-string">`
  <span class="hljs-subst">${fragment}</span>  # Include the fragment in the query
  query GetUserWithPosts($username: String!) {
    user(username: $username) {
      name
      posts(page: 1, pageSize: 2) {
        nodes {
          ...PostDetails  # Use the fragment here
        }
      }
    }
    publication(host: "blog.favouritejome.dev") {
      id
      title
      post(slug: "why-learn-nextjs-if-i-already-know-reactjs") {
          ...PostDetails # Use the fragment here
      }
    }
  }
`</span>;


<span class="hljs-keyword">const</span> variables = {
  <span class="hljs-attr">username</span>: <span class="hljs-string">"Favourite"</span>
};

fetch(<span class="hljs-string">'https://gql.hashnode.com/'</span>, {
  <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
  <span class="hljs-attr">headers</span>: {
    <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
  },
  <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
    query,
    variables
  })
})
.then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
.then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(data))
.catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error:'</span>, error));
</code></pre>
<h3 id="heading-mutation-1">Mutation</h3>
<p>As mentioned earlier, mutation operation allows for the modification of data. When creating, deleting or updating action needs to be done, we use a mutation.</p>
<p>With Hashnode API, all mutations require an authentication header to make sure the correct user is updating their data, and you can get your Personal Access Token from the <a target="_blank" href="https://hashnode.com/settings/developer">developer settings</a>.</p>
<p>Once youve got your Personal Access Token, lets see how we can create a draft post using the <code>createDraft</code> mutation from <a target="_blank" href="https://apidocs.hashnode.com/#mutation-createDraft">Hashnode API</a>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> mutation = <span class="hljs-string">`
  mutation CreateDraft($input: CreateDraftInput!) {
    createDraft(input: $input) {
      draft {
        id
        title
        slug
      }
    }
  }
`</span>;

<span class="hljs-keyword">const</span> variables = {
  <span class="hljs-attr">input</span>: {
    <span class="hljs-attr">title</span>: <span class="hljs-string">"My New Post"</span>,
    <span class="hljs-attr">slug</span>: <span class="hljs-string">'new-post'</span>,
    <span class="hljs-attr">publicationId</span>: <span class="hljs-string">"PUBLICATION_ID"</span>,
    <span class="hljs-attr">contentMarkdown</span>: <span class="hljs-string">"This is the content of the post."</span>,
    <span class="hljs-attr">tags</span>: [],
  }
};

fetch(<span class="hljs-string">'https://gql.hashnode.com/'</span>, {
  <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
  <span class="hljs-attr">headers</span>: {
    <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
    <span class="hljs-string">'Authorization'</span>: <span class="hljs-string">`YOUR_PERSONAL_ACCESS_TOKEN`</span> <span class="hljs-comment">// Replace with your API key</span>
  },
  <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
    <span class="hljs-attr">query</span>: mutation,
    variables
  })
})
.then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
.then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(data))
.catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error:'</span>, error));
</code></pre>
<p>You need to get the <code>PUBLICATION_ID</code> from your dashboard URL:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726146738666/647a1128-6aad-4ff5-9166-4aab2ded413d.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-starter-kit-code-example">Starter Kit Code Example</h2>
<p>Now that you have a solid foundation of GraphQL operations, that is, query and mutations, lets go over the <a target="_blank" href="https://github.com/Hashnode/starter-kit">Hashnode starter-kit</a>, to build with GraphQL in production. In the example, well be making use of the <strong>hashnode</strong> theme.</p>
<blockquote>
<p>To follow along, kindly clone the starter-kit repository: <a target="_blank" href="https://github.com/Hashnode/starter-kit">https://github.com/Hashnode/starter-kit</a></p>
</blockquote>
<p>We will be using <a target="_blank" href="https://hashnode.com/legacy-api">Hashnodes GraphQL APIs</a>, to list the followers our publication has, and this is how it will look 👇</p>
<p><img src="https://cdn.discordapp.com/attachments/1199373948329144420/1283773013732364298/841_2x_shots_so.png?ex=66e43649&amp;is=66e2e4c9&amp;hm=bc454ef4bc22afb4f5166489ce11d66c2c9788324e0529ad6b11432112c21d19&amp;=" alt /></p>
<p>Lets start by creating a new file in the queries folder: <strong><em>lib/api/queries/UserFollowers.graphql</em></strong></p>
<pre><code class="lang-graphql"><span class="hljs-keyword">query</span> UserFollowers(<span class="hljs-variable">$username</span>: String!, <span class="hljs-variable">$page</span>: Int!, <span class="hljs-variable">$pageSize</span>: Int!) {
  user(<span class="hljs-symbol">username:</span> <span class="hljs-variable">$username</span>) {
    id
    followers(<span class="hljs-symbol">page:</span> <span class="hljs-variable">$page</span>, <span class="hljs-symbol">pageSize:</span> <span class="hljs-variable">$pageSize</span>) {
      nodes {
        <span class="hljs-punctuation">...User
</span>      }
    }
  }
}
</code></pre>
<p>And the user fragment: <strong><em>lib/api/fragments/User.graphql</em></strong></p>
<pre><code class="lang-graphql"><span class="hljs-keyword">fragment</span> User <span class="hljs-keyword">on</span> User {
  id
  username
  profilePicture
  name
  tagline
}
</code></pre>
<p>In the <code>pages</code> folder, create a <code>followers.tsx</code> file with the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> request <span class="hljs-keyword">from</span> <span class="hljs-string">'graphql-request'</span>;
<span class="hljs-keyword">import</span> { GetServerSideProps } <span class="hljs-keyword">from</span> <span class="hljs-string">'next'</span>;
<span class="hljs-keyword">import</span> Head <span class="hljs-keyword">from</span> <span class="hljs-string">'next/head'</span>;
<span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useQuery } <span class="hljs-keyword">from</span> <span class="hljs-string">'urql'</span>;
<span class="hljs-keyword">import</span> { AppProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">'../components/contexts/appContext'</span>;
<span class="hljs-keyword">import</span> { Header } <span class="hljs-keyword">from</span> <span class="hljs-string">'../components/header'</span>;
<span class="hljs-keyword">import</span> { Layout } <span class="hljs-keyword">from</span> <span class="hljs-string">'../components/layout'</span>;
<span class="hljs-keyword">import</span> {
    PublicationByHostDocument,
    PublicationByHostQuery,
    PublicationByHostQueryVariables,
    PublicationFragment,
    UserFollowersDocument,
    UserFragment,
} <span class="hljs-keyword">from</span> <span class="hljs-string">'../generated/graphql'</span>;

<span class="hljs-keyword">const</span> GQL_ENDPOINT = process.env.NEXT_PUBLIC_HASHNODE_GQL_ENDPOINT;

type Props = {
    <span class="hljs-attr">publication</span>: PublicationFragment;
};

<span class="hljs-keyword">const</span> Followers = <span class="hljs-function">(<span class="hljs-params">props: Props</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> { publication } = props;

    <span class="hljs-keyword">const</span> [page, setPage] = useState(<span class="hljs-number">1</span>);
    <span class="hljs-keyword">const</span> [followersList, setFollowersList] = useState&lt;UserFragment[]&gt;([]); <span class="hljs-comment">// To append followers</span>
    <span class="hljs-keyword">const</span> [loadingMore, setLoadingMore] = useState(<span class="hljs-literal">false</span>);

    <span class="hljs-keyword">const</span> [{ data, fetching }] = useQuery({
        <span class="hljs-attr">query</span>: UserFollowersDocument,
        <span class="hljs-attr">variables</span>: {
            <span class="hljs-attr">username</span>: publication.author.username!,
            page: page,
            <span class="hljs-attr">pageSize</span>: <span class="hljs-number">20</span>,
        },
    });

    <span class="hljs-comment">// Effect to append new followers when data changes</span>
    useEffect(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">if</span> (data?.user?.followers?.nodes) {
            setFollowersList(<span class="hljs-function">(<span class="hljs-params">prev</span>) =&gt;</span> [...prev, ...data?.user?.followers.nodes!]);
            setLoadingMore(<span class="hljs-literal">false</span>); <span class="hljs-comment">// Stop loading state after fetching</span>
        }
    }, [data]);

    <span class="hljs-comment">// Load more function to increment the page</span>
    <span class="hljs-keyword">const</span> loadMore = <span class="hljs-function">() =&gt;</span> {
        setLoadingMore(<span class="hljs-literal">true</span>);
        setPage(<span class="hljs-function">(<span class="hljs-params">prevPage</span>) =&gt;</span> prevPage + <span class="hljs-number">1</span>);
    };

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">AppProvider</span> <span class="hljs-attr">publication</span>=<span class="hljs-string">{publication}</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">Layout</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">Head</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Followers - {publication.title}<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">Head</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> <span class="hljs-attr">isHome</span>=<span class="hljs-string">{true}</span> /&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"feed-width mx-auto my-10 md:w-2/3"</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mb-5 text-3xl font-bold"</span>&gt;</span>Followers<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

                        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"grid grid-cols-2 gap-2"</span>&gt;</span>
                            {followersList?.map((follower) =&gt; (
                                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{follower.id}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-2 bg-slate-400/20 p-3"</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
                                        <span class="hljs-attr">src</span>=<span class="hljs-string">{follower.profilePicture!}</span>
                                        <span class="hljs-attr">alt</span>=<span class="hljs-string">{follower.name}</span>
                                        <span class="hljs-attr">className</span>=<span class="hljs-string">"h-10 w-10 rounded-full"</span>
                                    /&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex-1"</span>&gt;</span>
                                        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"font-bold"</span>&gt;</span>{follower.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
                                        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{follower.username}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                            ))}
                        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

                        {/* Load More Button */}
                        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mt-5 text-center"</span>&gt;</span>
                            {!fetching &amp;&amp; (
                                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                                    <span class="hljs-attr">onClick</span>=<span class="hljs-string">{loadMore}</span>
                                    <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-primary-600 rounded-full  px-4 py-2 text-white"</span>
                                    <span class="hljs-attr">disabled</span>=<span class="hljs-string">{loadingMore}</span>
                                &gt;</span>
                                    {loadingMore ? 'Loading...' : 'Load More'}
                                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                            )}
                        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">Layout</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">AppProvider</span>&gt;</span>
        <span class="hljs-tag">&lt;/&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Followers;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getServerSideProps: GetServerSideProps = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> request&lt;PublicationByHostQuery, PublicationByHostQueryVariables&gt;(
        GQL_ENDPOINT,
        PublicationByHostDocument,
        {
            <span class="hljs-attr">host</span>: process.env.NEXT_PUBLIC_HASHNODE_PUBLICATION_HOST,
        },
    );

    <span class="hljs-keyword">const</span> publication = data.publication;
    <span class="hljs-keyword">if</span> (!publication) {
        <span class="hljs-keyword">return</span> {
            <span class="hljs-attr">notFound</span>: <span class="hljs-literal">true</span>,
        };
    }

    <span class="hljs-keyword">return</span> {
        <span class="hljs-attr">props</span>: {
            publication,
        },
    };
};
</code></pre>
<hr />
<h2 id="heading-resources">Resources</h2>
<p>If you have made it this far, we hope you have not only learned the basics but also how to integrate GraphQL APIs into your code.</p>
<p>Here are some resources to help you learn more:</p>
<ul>
<li><p><a target="_blank" href="https://graphql.org/learn/">GraphQL documentation</a></p>
</li>
<li><p><a target="_blank" href="https://apidocs.hashnode.com/">Hashnode API documentation</a></p>
</li>
<li><p><a target="_blank" href="https://commerce.nearform.com/open-source/urql/docs/">URQL documentation</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/Hashnode/starter-kit">Hashnode starter kit</a></p>
</li>
</ul>
]]></description><link>https://hashnode.com/blog/graphql-101-learn-to-build-with-graphql-apis</link><guid isPermaLink="true">https://hashnode.com/blog/graphql-101-learn-to-build-with-graphql-apis</guid><category><![CDATA[APIs]]></category><category><![CDATA[GraphQL]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Developer]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Haimantika Mitra]]></dc:creator></item><item><title><![CDATA[Create a Standout Developer Portfolio: Build Your Personal Brand with HTML, Tailwind, Hashnode, and Vercel.]]></title><description><![CDATA[<p>The job market is tough, and if you are looking for opportunities, you need to stand out. A good way to do that, is by building a developer portfolio. It can not only help you have a proof of work, but also help create your personal brand.</p>
<p>Even if we all know the importance of having a portfolio, we often end up not building at all, because of contemplation or wanting to over-complicate it.</p>
<p>In this article, I will show you how you can build a simple yet effective portfolio using:</p>
<ul>
<li><p>HTML</p>
</li>
<li><p>Tailwind CSS</p>
</li>
<li><p>Hashnode and</p>
</li>
<li><p>Vercel for deployment</p>
</li>
</ul>
<p>You can either follow this guide or watch me build it live here:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=tBXIIStRRVg">https://www.youtube.com/watch?v=tBXIIStRRVg</a></div>
<p> </p>
<h2 id="heading-getting-started">Getting started</h2>
<p>The first step in building a portfolio or any project is to have a clear design or structure in mind. For a developer portfolio, we need to include a homepage that introduces us and highlights our skills, a section showcasing our projects, a list of articles that we have written, and links to our social media profiles.</p>
<p>Here's how I envisioned it to be 👇</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725540802243/dfcf330e-a72c-4acb-9e0b-356188390236.png" alt class="image--center mx-auto" /></p>
<p>Let us divide it into three smaller tasks:</p>
<ul>
<li><p>Building the homepage that includes our bio, and projects.</p>
</li>
<li><p>Using Hashnode to build our blog section</p>
</li>
<li><p>Deploying it using Vercel.</p>
</li>
</ul>
<h2 id="heading-part-1-building-the-homepage">Part 1: Building the homepage</h2>
<p>To get started, make sure you have a <a target="_blank" href="https://docs.github.com/en/repositories/creating-and-managing-repositories/quickstart-for-repositories">repository setup on GitHub</a>, and have cloned it on an IDE of your choice.</p>
<p>The next step is to <a target="_blank" href="https://tailwindcss.com/docs/installation">install Tailwind</a>:</p>
<ol>
<li><p>On your terminal type <code>npm install -D tailwindcss</code> followed by <code>npx tailwindcss init</code>.</p>
</li>
<li><p>Add the paths to all of your template files in your <code>tailwind.config.js</code> file.</p>
<pre><code class="lang-javascript"> <span class="hljs-comment">/** <span class="hljs-doctag">@type <span class="hljs-type">{import('tailwindcss').Config}</span> </span>*/</span>
 <span class="hljs-built_in">module</span>.exports = {
   <span class="hljs-attr">content</span>: [<span class="hljs-string">"./src/**/*.{html,js}"</span>],
   <span class="hljs-attr">theme</span>: {
     <span class="hljs-attr">extend</span>: {},
   },
   <span class="hljs-attr">plugins</span>: [],
 }
</code></pre>
</li>
<li><p>Add the <code>@tailwind</code> directives for each of Tailwinds layers to your main CSS file.</p>
<pre><code class="lang-bash"> @tailwind base; 
 @tailwind components; 
 @tailwind utilities;
</code></pre>
</li>
<li><p>Run the CLI tool to scan your template files for classes and build your CSS <code>npx tailwindcss -i ./src/input.css -o ./src/output.css --watch</code></p>
</li>
<li><p>On your <code>index.html</code> file, add <code>&lt;link href="./output.css" rel="stylesheet"</code>\&gt;</p>
</li>
</ol>
<p>For this demo, we will be using <a target="_blank" href="https://flowbite.com/docs/getting-started/introduction/">Flowbite</a> components to design the portfolio.<br />Here are the commands to get started:</p>
<ul>
<li><p><code>npm install flowbite</code></p>
</li>
<li><p>On you <code>tailwind.config.js</code> file add <code>flowbite</code> as the plugin:</p>
<pre><code class="lang-javascript">  <span class="hljs-built_in">module</span>.exports = {

      <span class="hljs-attr">plugins</span>: [
          <span class="hljs-built_in">require</span>(<span class="hljs-string">'flowbite/plugin'</span>)
      ]

  }
</code></pre>
</li>
<li><p>Before the end of the body tag, add the JavaScript code that powers the interactive elements: <code>&lt;script src="../path/to/flowbite/dist/flowbite.min.js"&gt;&lt;/script&gt;</code></p>
</li>
</ul>
<p><strong>Building the header and the bio section:</strong></p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-white border-gray-200 dark:bg-gray-900"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"max-w-screen-xl flex flex-wrap items-center justify-between mx-auto p-4"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://www.linkedin.com/in/haimantika-mitra/"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex items-center space-x-3 rtl:space-x-reverse"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"w-10 h-10 rounded-full"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"img/hm.jpg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Rounded avatar"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"self-center text-2xl font-semibold whitespace-nowrap dark:text-white"</span>&gt;</span>Haimantika Mitra<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">data-collapse-toggle</span>=<span class="hljs-string">"navbar-default"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"inline-flex items-center p-2 w-10 h-10 justify-center text-sm text-gray-500 rounded-lg md:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600"</span> <span class="hljs-attr">aria-controls</span>=<span class="hljs-string">"navbar-default"</span> <span class="hljs-attr">aria-expanded</span>=<span class="hljs-string">"false"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"sr-only"</span>&gt;</span>Open main menu<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"w-5 h-5"</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://www.w3.org/2000/svg"</span> <span class="hljs-attr">fill</span>=<span class="hljs-string">"none"</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 17 14"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">path</span> <span class="hljs-attr">stroke</span>=<span class="hljs-string">"currentColor"</span> <span class="hljs-attr">stroke-linecap</span>=<span class="hljs-string">"round"</span> <span class="hljs-attr">stroke-linejoin</span>=<span class="hljs-string">"round"</span> <span class="hljs-attr">stroke-width</span>=<span class="hljs-string">"2"</span> <span class="hljs-attr">d</span>=<span class="hljs-string">"M1 1h15M1 7h15M1 13h15"</span>/&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hidden w-full md:block md:w-auto"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"navbar-default"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"font-medium flex flex-col p-4 md:p-0 mt-4 border border-gray-100 rounded-lg bg-gray-50 md:flex-row md:space-x-8 rtl:space-x-reverse md:mt-0 md:border-0 md:bg-white dark:bg-gray-800 md:dark:bg-gray-900 dark:border-gray-700"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#home"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"block py-2 px-3 text-white bg-blue-700 rounded md:bg-transparent md:text-blue-700 md:p-0 dark:text-white md:dark:text-blue-500"</span> <span class="hljs-attr">aria-current</span>=<span class="hljs-string">"page"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://starter-kit-ophg-git-new-portfolio-haimantikas-projects.vercel.app/blog"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"block py-2 px-3 text-gray-900 rounded hover:bg-gray-100 md:hover:bg-transparent md:border-0 md:hover:text-blue-700 md:p-0 dark:text-white md:dark:hover:text-blue-500 dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent"</span>&gt;</span>Blog<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#projects"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"block py-2 px-3 text-gray-900 rounded hover:bg-gray-100 md:hover:bg-transparent md:border-0 md:hover:text-blue-700 md:p-0 dark:text-white md:dark:hover:text-blue-500 dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent"</span>&gt;</span>Projects<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>

        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"max-w-4xl mx-auto flex flex-col"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"home"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex flex-col sm:flex-row p-20 items-center gap-8 mb-12"</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-4 text-3xl font-extrabold text-gray-900 dark:text-white md:text-5xl lg:text-6xl"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-transparent bg-clip-text bg-gradient-to-r to-emerald-600 from-sky-400"</span>&gt;</span>Generalist &amp; <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span> Developer Advocate.<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-lg font-normal text-gray-500 lg:text-xl dark:text-gray-400"</span>&gt;</span>Hello, I am Haimantika. Currently working as a Developer Advocate at Hashnode. I help B2D+ companies bridge the gap between developers and the product with code, content and community. As a community builder and a product of the community myself, I strongly believe that technology is for everyone. I am passionate about learning, sharing, and building with the community.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

    <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
</code></pre>
<p><strong>Building the projects section using Flowbite's card component:</strong></p>
<pre><code class="lang-xml"> <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"max-w-4xl mx-auto flex flex-col"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"home"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex flex-col sm:flex-row p-20 items-center gap-8 mb-12"</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-4 text-3xl font-extrabold text-gray-900 dark:text-white md:text-5xl lg:text-6xl"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-transparent bg-clip-text bg-gradient-to-r to-emerald-600 from-sky-400"</span>&gt;</span>Generalist &amp; <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span> Developer Advocate.<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-lg font-normal text-gray-500 lg:text-xl dark:text-gray-400"</span>&gt;</span>Hello, I am Haimantika. Currently working as a Developer Advocate at Hashnode. I help B2D+ companies bridge the gap between developers and the product with code, content and community. As a community builder and a product of the community myself, I strongly believe that technology is for everyone. I am passionate about learning, sharing, and building with the community.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

    <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"max-w-4xl mx-auto flex flex-col"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"projects"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex flex-col sm:flex-row p-20 items-center gap-8 mb-12"</span>&gt;</span>


<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"max-w-sm p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h5</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white"</span>&gt;</span>Melody Matcher<span class="hljs-tag">&lt;/<span class="hljs-name">h5</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-3 font-normal text-gray-700 dark:text-gray-400"</span>&gt;</span>Happy? Sad? Angry? Want a music blend made just for you? Try out the soul music generator. Built using: Next.JS, and QuickBlox API.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://music-suggester.vercel.app/"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"inline-flex items-center px-3 py-2 text-sm font-medium text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"</span>&gt;</span>
        Try it here
        <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"rtl:rotate-180 w-3.5 h-3.5 ms-2"</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://www.w3.org/2000/svg"</span> <span class="hljs-attr">fill</span>=<span class="hljs-string">"none"</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 14 10"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">path</span> <span class="hljs-attr">stroke</span>=<span class="hljs-string">"currentColor"</span> <span class="hljs-attr">stroke-linecap</span>=<span class="hljs-string">"round"</span> <span class="hljs-attr">stroke-linejoin</span>=<span class="hljs-string">"round"</span> <span class="hljs-attr">stroke-width</span>=<span class="hljs-string">"2"</span> <span class="hljs-attr">d</span>=<span class="hljs-string">"M1 5h12m0 0L9 1m4 4L9 9"</span>/&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>



<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"max-w-sm p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h5</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white"</span>&gt;</span>Diss Track<span class="hljs-tag">&lt;/<span class="hljs-name">h5</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-3 font-normal text-gray-700 dark:text-gray-400"</span>&gt;</span>Got hate comments? Time to turn it into a rap! Try out Diss Track. Built using: TailwindCSS (DaisyUI components), and QuickBlox API.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://disstrack.vercel.app/"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"inline-flex items-center px-3 py-2 text-sm font-medium text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"</span>&gt;</span>
        Try it here
        <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"rtl:rotate-180 w-3.5 h-3.5 ms-2"</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://www.w3.org/2000/svg"</span> <span class="hljs-attr">fill</span>=<span class="hljs-string">"none"</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 14 10"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">path</span> <span class="hljs-attr">stroke</span>=<span class="hljs-string">"currentColor"</span> <span class="hljs-attr">stroke-linecap</span>=<span class="hljs-string">"round"</span> <span class="hljs-attr">stroke-linejoin</span>=<span class="hljs-string">"round"</span> <span class="hljs-attr">stroke-width</span>=<span class="hljs-string">"2"</span> <span class="hljs-attr">d</span>=<span class="hljs-string">"M1 5h12m0 0L9 1m4 4L9 9"</span>/&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
</code></pre>
<p><strong>Building the footer:</strong></p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">footer</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-white rounded-lg shadow dark:bg-gray-900 m-4"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"w-full max-w-screen-xl mx-auto p-4 md:py-8"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"sm:flex sm:items-center sm:justify-between"</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex flex-wrap items-center mb-6 text-sm font-medium text-gray-500 sm:mb-0 dark:text-gray-400"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://www.linkedin.com/in/haimantika-mitra/"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hover:underline me-4 md:me-6"</span>&gt;</span>LinkedIn<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hover:underline me-4 md:me-6"</span>&gt;</span>GitHub<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hover:underline me-4 md:me-6"</span>&gt;</span>Twitter<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hover:underline"</span>&gt;</span>Resume<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">footer</span>&gt;</span>
</code></pre>
<h2 id="heading-part-2-building-the-blog-section">Part 2: Building the blog section</h2>
<p>To build the blog section, we will make use of Hashnode in Headless mode and it's <a target="_blank" href="https://github.com/Hashnode/starter-kit">open-source starter kit</a>.</p>
<ol>
<li><p>The first step is to fork it and create your own copy.</p>
</li>
<li><p>Clone it locally using any IDE of your choice.</p>
</li>
<li><p>Currently, Hashnode has three themes: personal, hashnode and enterprise. You can use any, but in this demo, we will use the <strong>enterprise</strong> theme.</p>
</li>
<li><p>It's a monorepo, so cd into <code>packages/blog-starter-kit/themes/enterprise</code>, and then type <code>pnpm install</code> to install all the necessary packages.</p>
</li>
<li><p>The repository, will include a <code>.env.example</code> file. Copy the contents and create a <code>.env</code> file that includes your blog publication details. You will only need to update <code>NEXT_PUBLIC_HASHNODE_PUBLICATION_HOST</code>, rest everything remains the same.</p>
</li>
</ol>
<p>    This is where you will find your Hashnode publication name, for me, it is <code>haimantika.dev</code> 👇</p>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725540790395/a4cc6f1d-9782-42e1-a7b8-e63e0c558d36.png" alt class="image--center mx-auto" /></p>
<ol start="6">
<li><p>Once all of it is done, use the command <code>npm run dev</code> to run it locally.</p>
</li>
<li><p>The starter kit uses Next.js and Tailwind, allowing you to customize the styling. In this demo, we modify the footer to match our homepage footer. The code for that looks like:</p>
<pre><code class="lang-typescript"> <span class="hljs-keyword">import</span> Link <span class="hljs-keyword">from</span> <span class="hljs-string">'next/link'</span>;
 <span class="hljs-keyword">import</span> { Container } <span class="hljs-keyword">from</span> <span class="hljs-string">'./container'</span>;
 <span class="hljs-keyword">import</span> { useAppContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'./contexts/appContext'</span>;
 <span class="hljs-keyword">import</span> { SocialLinks } <span class="hljs-keyword">from</span> <span class="hljs-string">'./social-links'</span>;

 <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> Footer = <span class="hljs-function">() =&gt;</span> {

     <span class="hljs-keyword">return</span> (
         &lt;footer className=<span class="hljs-string">"bg-white rounded-lg shadow dark:bg-gray-900 m-4"</span>&gt;
     &lt;div className=<span class="hljs-string">"w-full max-w-screen-xl mx-auto p-4 md:py-8"</span>&gt;
         &lt;div className=<span class="hljs-string">"sm:flex sm:items-center sm:justify-between"</span>&gt;
             &lt;ul className=<span class="hljs-string">"flex flex-wrap items-center mb-6 text-sm font-medium text-gray-500 sm:mb-0 dark:text-gray-400"</span>&gt;
                 &lt;li&gt;
                     &lt;a href=<span class="hljs-string">"https://www.linkedin.com/in/haimantika-mitra/"</span> className=<span class="hljs-string">"hover:underline me-4 md:me-6"</span>&gt;LinkedIn&lt;/a&gt;
                 &lt;/li&gt;
                 &lt;li&gt;
                     &lt;a href=<span class="hljs-string">"#"</span> className=<span class="hljs-string">"hover:underline me-4 md:me-6"</span>&gt;GitHub&lt;/a&gt;
                 &lt;/li&gt;
                 &lt;li&gt;
                     &lt;a href=<span class="hljs-string">"#"</span> className=<span class="hljs-string">"hover:underline me-4 md:me-6"</span>&gt;Twitter&lt;/a&gt;
                 &lt;/li&gt;
                 &lt;li&gt;
                     &lt;a href=<span class="hljs-string">"#"</span> className=<span class="hljs-string">"hover:underline"</span>&gt;Resume&lt;/a&gt;
                 &lt;/li&gt;
             &lt;/ul&gt;
         &lt;/div&gt;
     &lt;/div&gt;
 &lt;/footer&gt;

     );
 }
</code></pre>
</li>
</ol>
<p>If you want to make other changes, check out this video:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=oH8QG8E0Txk&amp;t=9s">https://www.youtube.com/watch?v=oH8QG8E0Txk&amp;t=9s</a></div>
<p> </p>
<h2 id="heading-part-3-deploying-it-using-vercel">Part 3: Deploying it using Vercel</h2>
<p>We will need to deploy the homepage and the blog separately. To deploy the homepage, you can follow <a target="_blank" href="https://vercel.com/docs/deployments/overview">Vercel's documentation</a>.</p>
<p>Let us learn how to deploy the blog section:</p>
<ul>
<li><p>Create a new project on Vercel and connect this starter-kit repo.</p>
</li>
<li><p>Since it's a monorepo, and you choose the enterprise theme, you need to choose <code>packages/blog-starter-kit/themes/enterprise</code>as the root directory while importing on Vercel.</p>
</li>
<li><p>Choose <code>Next.js</code> as framework preset.</p>
</li>
<li><p>Set the following environment variables</p>
<pre><code class="lang-bash">  NEXT_PUBLIC_HASHNODE_GQL_ENDPOINT=https://gql.hashnode.com 
  NEXT_PUBLIC_HASHNODE_PUBLICATION_HOST=engineering.hashnode.com -&gt; Change this to your Hashnode blog URL i.e. handle.hashnode.dev 
  NEXT_PUBLIC_BASE_URL=/blog -&gt; This could be /blog <span class="hljs-keyword">if</span> you are installing on subpath; otherwise remove this var 
  NEXT_PUBLIC_MODE=production
</code></pre>
</li>
<li><p>Then click on deploy. If you see a 404 error, do not worry, as you set the subpath as <code>/blog</code> you need to add it to Vercel's auto generated domain to see your blog.</p>
</li>
</ul>
<h3 id="heading-hosting-your-blog-to-your-domains-subpath">Hosting your blog to your domains subpath</h3>
<p>The next step is to map your blog to <code>yourdomain.com/blog</code>. Currently, the homepage and blog is hosted in two different domains, but we want it to be on the same domain with the <code>/blog</code> subpath. Something like 👉 <a target="_blank" href="https://haimantika.dev/blog">https://haimantika.dev/blog</a></p>
<p>Since, we have used HTML and TailwindCSS to build the portfolio, we will need to work with <a target="_blank" href="https://workers.cloudflare.com/">Cloudflare workers</a>.</p>
<p><em>Note: If you decide to build your portfolio with Next.js at any point in the future, you do not need to go through the Cloudflare route and you can simply follow the steps mentioned</em> <a target="_blank" href="https://github.com/Hashnode/starter-kit?tab=readme-ov-file#vercel"><em>here</em></a><em>.</em></p>
<p><strong>Deploy the Worker, and updating the script and map it to</strong> <code>yourdomain.com/blog</code><strong>:</strong></p>
<ul>
<li><p>Login/Signup on <a target="_blank" href="http://cloudflare.com">Cloudflare</a>.</p>
</li>
<li><p>Create and deploy worker as shown in the image below.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725540835439/ee99938f-a471-47d7-ac08-55566188545c.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Once deployed, click on <code>Edit code</code> to update the worker script.</p>
</li>
<li><p>Add the following code and save it.</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> subpath = <span class="hljs-string">'/blog'</span>; <span class="hljs-comment">// Replace with your subpath</span>
  <span class="hljs-keyword">const</span> blogBaseUrl = <span class="hljs-string">'https://yourdomain.com'</span>; <span class="hljs-comment">// Replace with your blog URL</span>

  addEventListener(<span class="hljs-string">'fetch'</span>, <span class="hljs-function"><span class="hljs-params">event</span> =&gt;</span> {
    event.respondWith(handleRequest(event.request))
  })

  <span class="hljs-comment">/**
   * Respond to the request
   * <span class="hljs-doctag">@param <span class="hljs-type">{Request}</span> <span class="hljs-variable">request</span></span>
   */</span>
  <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleRequest</span>(<span class="hljs-params">request</span>) </span>{
    <span class="hljs-keyword">const</span> url = <span class="hljs-keyword">new</span> URL(request.url)

    <span class="hljs-keyword">if</span> (url.pathname.startsWith(subpath)) {
      <span class="hljs-comment">// Proxy blog requests</span>
      <span class="hljs-keyword">return</span> proxyBlog(request)
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-comment">// Passthrough everything else</span>
      <span class="hljs-keyword">return</span> fetch(request)
    }
  }

  <span class="hljs-comment">/**
   * Proxy blog requests
   * <span class="hljs-doctag">@param <span class="hljs-type">{Request}</span> <span class="hljs-variable">request</span></span>
   */</span>
  <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">proxyBlog</span>(<span class="hljs-params">request</span>) </span>{
    <span class="hljs-keyword">const</span> path = <span class="hljs-keyword">new</span> URL(request.url).pathname;
    <span class="hljs-keyword">return</span> fetch(<span class="hljs-string">`<span class="hljs-subst">${blogBaseUrl}</span><span class="hljs-subst">${path}</span>`</span>, request)
  }
</code></pre>
<p>  Once you've deployed the worker, the next step is to add the worker to your website domain on cloudfare.  </p>
<p>  For the domain you'll be using on your Cloudflare account, you need to add a worker route. The route should be <code>*</code>, and the worker should be the script you created in the steps above.  </p>
<p>  <em>Note: Make sure that your domain -</em> <code>yourdomain.com</code> <em>is on Cloudflare. If not, you should transfer it to make it work!</em></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725540910597/170fe42e-229e-410a-85bd-1665ebd74d8c.png" alt class="image--center mx-auto" /></p>
<p>  For the final step, go to the <a target="_blank" href="https://hshno.de/dashboard">Hashnode blog dashboard</a>, and under the <code>Domain</code> section, make sure to turn on the Headless mode and mention the blog base URL.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725540975376/18eb6f1f-1ffa-4ab7-9cd4-b545e2eea43c.png" alt class="image--center mx-auto" /></p>
<p>  And now you are done! When you browse to <code>yourdomain.com/blog</code> you will see your blog live on the subpath!</p>
</li>
</ul>
<hr />
<h2 id="heading-resources">Resources</h2>
<p>Thank you for reading to the end. If you have followed the tutorial or the webinar and created a portfolio, feel free to tag us on X (Twitter) <a target="_blank" href="https://x.com/hashnode">@Hashnode</a>, and we will retweet it!</p>
<p>Here are some resources to help you learn more:</p>
<ul>
<li><p><a target="_blank" href="https://github.com/Hashnode/starter-kit">Hashnode's open-source starter kit</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/Haimantika/demo-portfolio-livestream">Portfolio code</a></p>
</li>
<li><p><a target="_blank" href="https://tailwindcss.com/docs/installation">TailwindCSS documentation</a></p>
</li>
<li><p><a target="_blank" href="https://vercel.com/docs">Vercel documentation</a></p>
</li>
</ul>
]]></description><link>https://hashnode.com/blog/create-a-standout-developer-portfolio-build-your-personal-brand-with-html-tailwind-hashnode-and-vercel</link><guid isPermaLink="true">https://hashnode.com/blog/create-a-standout-developer-portfolio-build-your-personal-brand-with-html-tailwind-hashnode-and-vercel</guid><category><![CDATA[Beginner Developers]]></category><category><![CDATA[HTML5]]></category><category><![CDATA[CSS]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Haimantika Mitra]]></dc:creator></item><item><title><![CDATA[Announcing — Docs by Hashnode:  The content engine for API and product documentation ✨ 📃]]></title><description><![CDATA[<p><em>Today is a big day for Hashnode.</em></p>
<p>Millions of developers use Hashnode daily to read and share stories. We've always been focused on providing the best platform for developers and teams to run and host their blogs.</p>
<blockquote>
<p>Our goal has always been to help individuals share their knowledge and enable teams to maintain a strong brand voice.</p>
</blockquote>
<p>As we've grown, one of the most requested features has been the ability to create and manage detailed documentation. This aligns perfectly with our mission.</p>
<p>So today, I'm excited to introduce <a target="_blank" href="https://hashnode.com/products/docs">Docs by Hashnode</a>  the content engine for developers to build and run API and product documentation on Hashnode.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/yqMlbZh-eeY?si=DsquySclXgent744">https://youtu.be/yqMlbZh-eeY?si=DsquySclXgent744</a></div>
<p> </p>
<h3 id="heading-why-we-built-another-documentation-saas-for-developers"><strong>Why we built another documentation SaaS for developers?</strong></h3>
<p>We believe developer documentation should be more than an afterthought  it should be a seamless extension of your brand. With Docs by Hashnode, were empowering teams to build, customize, and scale their docs just as quickly as they code.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724831998107/0157a5c9-a347-4f77-a93e-923907a94e50.png" alt class="image--center mx-auto" /></p>
<p>We hate rigid templates and endless maintenance ourselves. It's time for documentation that evolves with your product.</p>
<p>Our vision is clear: we want to give you full control over your documentation while ensuring it integrates effortlessly into your product. This means providing <strong>headless mode</strong> with <strong>first-class support for GraphQL APIs</strong>.</p>
<p>Youll have the flexibility to design your frontend exactly as you envision it, with all the power and scalability you need to keep pace with your development.</p>
<h3 id="heading-why-is-docs-by-hashnode-ideal-for-large-teams-and-companies">Why is Docs by Hashnode ideal for large teams and companies?</h3>
<p>Our docs tool provides features that give you full control and ensure a smooth user experience:</p>
<h3 id="heading-headless-mode-with-graphql-support"><strong>Headless mode with GraphQL support.</strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724832314018/ec0926f1-bcaf-4337-a813-13bb49b543dc.png" alt class="image--center mx-auto" /></p>
<p>Take control with headless mode and GraphQL support. Integrate your docs easily, scale without hassle, and give your developers the flexibility they need.</p>
<p>Customizing and optimizing the theme is as simple as tweaking the TailwindCSS classes in our docs starter kit. This allows you to match your theme with your main website and even host the frontend code on <code>/docs</code>.</p>
<h3 id="heading-creating-and-editing-docs">Creating and editing docs.</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724832361946/279928b1-2b48-45c6-a282-c5d8aeee12d5.png" alt class="image--center mx-auto" /></p>
<p>We've prioritized editing and performance to make sure your docs not only look great but also run at lightning speed:</p>
<ul>
<li><p><strong>Best-in-class editor powered by MDX:</strong> Our visual WYSIWYG editor, powered by MDX, allows you to create interactive docs that seamlessly blend Markdown with React components.</p>
</li>
<li><p><strong>Lightning-fast speed and SEO optimization:</strong> Our docs are built for speed and optimized for SEO, ensuring top performance in Lightspeed tests and a fast experience for your users.</p>
</li>
</ul>
<h3 id="heading-search-discovery-and-api-management"><strong>Search, discovery, and API management.</strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724832411082/bfa58813-74a3-4028-b1e4-1f2ca6adb993.png" alt class="image--center mx-auto" /></p>
<p>Finding the right information is crucial, and our tools are built to make it effortless:</p>
<ul>
<li><p><strong>AI-Powered search and chat:</strong> For teams looking to enhance their search, upgrade to AI-powered search. It evolves into a chat-like experience, making it easier for users to find the right content.</p>
</li>
<li><p><strong>Super fast search powered by Algolia:</strong> Get instant results with our Algolia-powered search, delivering fast and reliable results to keep your users moving forward.</p>
</li>
</ul>
<p>Managing your API references is now simpler than ever:</p>
<ul>
<li><p><strong>API reference playground:</strong> Quickly set up API references with a one-click import of Swagger or OpenAPI specs. It's fast, developer-friendly, and perfect for modern teams.</p>
</li>
<li><p><strong>Show custom code samples:</strong> Our docs can auto-generate code examples for your APIs, but you can also add custom snippets. Whether it's JavaScript, Python, or another language, provide clear examples to help developers easily understand and use your APIs.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724832461401/8ffd35b8-54df-48f3-8d75-bace50b53626.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-insights-feedback-and-collaboration"><strong>Insights, feedback, and collaboration.</strong></h3>
<p>Understanding how your documentation is used and enabling smooth team collaboration are crucial for improving your docs:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724832569653/ceed7282-fb49-4f19-a054-1e070669904d.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p><strong>Analytics and intelligence:</strong> Gain insights with detailed analytics and smart reports to help you improve your content.</p>
</li>
<li><p><strong>User feedback feature:</strong> Allow users to send feedback directly from the docs. Gather insights on API performance, report errors, fix typos, and enhance guidesall in one place.</p>
</li>
<li><p><strong>Scale to unlimited members:</strong> Grow your team without limits, enabling everyone to contribute to your docs, regardless of your organization's size.</p>
</li>
<li><p><strong>Versioning and permissions:</strong> Maintain control with robust versioning and permissionsperfect for managing complex documentation workflows.</p>
</li>
</ul>
<p>Docs by Hashnode is designed for seamless team collaboration. With real-time editing and reviewing, your team can work together in one editor:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724832600082/5a31f511-5ea8-4ef5-9c31-bafe4433855c.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p><strong>Real-time editing:</strong> Collaborate with your team instantly, ensuring everyone stays aligned without version conflicts.</p>
</li>
<li><p><strong>Inline review comments:</strong> Simplify feedback with inline comments directly in the editor. Team members can review and suggest improvements, maintaining clarity and accuracy at every step.</p>
</li>
<li><p><strong>Collaborative workflow with roles:</strong> Assign roles to team members to control who can edit, review, or approve docs. Keep workflows organized by assigning the right tasks to the right people.</p>
</li>
</ul>
<h2 id="heading-built-for-growing-teams-and-enterprises"><strong>Built for growing teams and enterprises.</strong></h2>
<p>Security, scale, and reliability are central to Docs by Hashnode. We offer SSO, audit logs, custom SLAs, and uptime guarantees to keep your docs secure and always available. By the end of 2024, we'll also be SOC2 and ISO 27001 ready, giving your enterprise peace of mind.</p>
<h2 id="heading-join-us-on-this-journey">Join us on this journey.</h2>
<p>Were incredibly proud of what weve built with <a target="_blank" href="https://hashnode.com/products/docs">Docs by Hashnode</a>, and this is just the beginning. As we step into this new chapter, we invite you to join the waitlist and be among the first to experience the future of developer documentation.</p>
<p>Thank you for being part of the Hashnode community and for inspiring us to keep pushing the boundaries of whats possible. We cant wait to see what you create with our new docs product.</p>
<p>GA Fall 2024.</p>
<p><strong>Available in public beta today.</strong> <a target="_blank" href="https://hashnode.com/products/docs"><strong>Sign up.</strong></a> 🚀</p>
<p><em>PS: A tip to get early access fasteruse your company email address when signing up. :)</em></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://x.com/hashnode/status/1828769325878038768">https://x.com/hashnode/status/1828769325878038768</a></div>
]]></description><link>https://hashnode.com/blog/announcing-docs-by-hashnode-the-content-engine-for-api-and-product-documentation</link><guid isPermaLink="true">https://hashnode.com/blog/announcing-docs-by-hashnode-the-content-engine-for-api-and-product-documentation</guid><category><![CDATA[Hashnode]]></category><category><![CDATA[General Programming]]></category><category><![CDATA[APIDocumentation]]></category><category><![CDATA[docs]]></category><dc:creator><![CDATA[Syed Fazle Rahman]]></dc:creator></item><item><title><![CDATA[Publishing a blog post to Hashnode using a custom editing interface]]></title><description><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Today, were going to learn how to publish blog posts using our custom editing interface. We will use <a target="_blank" href="https://apidocs.hashnode.com/">Hashnode API</a> and <a target="_blank" href="https://github.com/mdx-editor/editor">MDXEditor</a> for demo purposes.</p>
<h2 id="heading-step-1-creating-a-new-react-project">Step 1: Creating a new React project</h2>
<p>With <code>node.js</code>, <code>npm</code> installed, please run the following command to install the React boilerplate using <code>Vite</code>.</p>
<pre><code class="lang-bash">npm create vite@latest my-editor -- --template react-ts
</code></pre>
<p>Dont worry if you dont have <code>Vite</code> installed locally, <code>npm</code> will prompt you to do so. Lets install all the dependencies, including <code>MDXEditor</code>:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> my-editor
npm install --save @mdxeditor/editor
</code></pre>
<p>Now, we are ready to serve our project using the CLI command <code>npm run dev</code>:</p>
<pre><code class="lang-bash">npm run dev

  VITE v5.1.3  ready <span class="hljs-keyword">in</span> 80 ms

    Local:   http://localhost:5173/
    Network: use --host to expose
    press h + enter to show <span class="hljs-built_in">help</span>
</code></pre>
<p>Hot Reloading is enabled by default. Any changes will have an immediate effect on the browser window. Navigate to <a target="_blank" href="http://localhost:5173/">http://localhost:5173/</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708767391400/69666be8-38bb-4393-8969-c0335e035d23.png" alt="A screenshot of a computer browser displaying a simple web application interface with the title &quot;Vite + React&quot; and logos of Vite and React, showing a counter set to zero." /></p>
<h3 id="heading-step-12-styling">Step 1.2: Styling</h3>
<p>Vite serves our project from <code>src/main.tsx</code>. We also have an example component in <code>src/App.tsx</code>. Lets clean up the boilerplate code in the following places:</p>
<ul>
<li><p>Delete <code>public/vite.svg</code></p>
</li>
<li><p>Delete <code>src/assets/react.svg</code></p>
</li>
<li><p>Clean up everything in <code>src/index.css</code>, so the file should be completely empty. Were going to add Tailwind in the next steps and use this file.</p>
</li>
<li><p>Delete <code>src/App.css</code></p>
</li>
<li><p>Clean up the <code>src/App.tsx</code> The <code>App</code> component should look like this after the cleanup:</p>
</li>
</ul>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    &lt;&gt;
        &lt;h1&gt;My Blog Editor&lt;/h1&gt;
    &lt;/&gt;
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App
</code></pre>
<h3 id="heading-step-13-setting-up-tailwind">Step 1.3: Setting up Tailwind</h3>
<p>Install Tailwind and <code>@tailwindcss/typograph</code> package, using <code>npm</code> and <code>npx</code>,</p>
<pre><code class="lang-bash">npm install -D tailwindcss postcss autoprefixer @tailwindcss/typography
npx tailwindcss init -p
</code></pre>
<p>We also need to set up the Tailwind config file, <code>tailwind.config.js</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/** <span class="hljs-doctag">@type <span class="hljs-type">{import('tailwindcss').Config}</span> </span>*/</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
  <span class="hljs-attr">content</span>: [
    <span class="hljs-string">"./index.html"</span>,
    <span class="hljs-string">"./src/**/*.{js,ts,jsx,tsx}"</span>,
  ],
  <span class="hljs-attr">theme</span>: {
    <span class="hljs-attr">extend</span>: {},
  },
  <span class="hljs-attr">plugins</span>: [
    <span class="hljs-built_in">require</span>(<span class="hljs-string">'@tailwindcss/typography'</span>),
  ],
}
</code></pre>
<p>Next, we can add the base Tailwind styles in the <code>src/index.css</code> file:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@tailwind</span> base;  
<span class="hljs-keyword">@tailwind</span> components;  
<span class="hljs-keyword">@tailwind</span> utilities;
</code></pre>
<p>Were ready to use Tailwind. Now, the <code>npm run dev</code> command will build Tailwind styles too! We can already wrap our app into a container by adding the following in <code>main.tsx</code>:</p>
<pre><code class="lang-typescript">  &lt;React.StrictMode&gt;
      &lt;div className=<span class="hljs-string">"container mx-auto px-4 w-1/2 py-8"</span>&gt;
          &lt;App/&gt;
      &lt;/div&gt;
  &lt;/React.StrictMode&gt;
</code></pre>
<p>Thats it! We will continue with styling later when we set up our custom editor interface.</p>
<h2 id="heading-step-2-setting-up-the-editor">Step 2: Setting up the editor</h2>
<p>We can import the <code>MDXEditor</code> React component and use it in our project. We need to include the CSS file as well, we can do this directly in our <code>App</code> component:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { MDXEditor } <span class="hljs-keyword">from</span> <span class="hljs-string">'@mdxeditor/editor'</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'@mdxeditor/editor/style.css'</span>
</code></pre>
<p>This is the basic setup, and this setup doesnt allow advanced text editing. It only supports <strong>bold</strong>, <em>italic</em>, underline, and <code>inline code</code>. We can already add some other plugins to support advanced editing. <code>MDXEditor</code> is highly customizable, you can head to the <a target="_blank" href="https://mdxeditor.dev/editor/docs/basic-formatting">MDXEditor docs</a> and get more information about all available plugins and usages. For demo purposes, we will only add some of them. Lets set up the editor component with plugins:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> {
  MDXEditor,
  BlockTypeSelect,
  UndoRedo,
  BoldItalicUnderlineToggles,
  toolbarPlugin,
  headingsPlugin,
  markdownShortcutPlugin,
  linkPlugin,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@mdxeditor/editor"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@mdxeditor/editor/style.css"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> editorRef = React.useRef&lt;MDXEditorMethods&gt;(<span class="hljs-literal">null</span>);

  <span class="hljs-keyword">return</span> (
    &lt;&gt;
      &lt;h1 className=<span class="hljs-string">"text-5xl"</span>&gt;My Blog Editor&lt;/h1&gt;

      &lt;div className=<span class="hljs-string">"prose max-w-none"</span>&gt;
        &lt;MDXEditor
          ref={editorRef}
          className=<span class="hljs-string">"my-5"</span>
          markdown=<span class="hljs-string">"Hello world"</span>
          plugins={[
            headingsPlugin(),
            linkPlugin(),
            markdownShortcutPlugin(),
            toolbarPlugin({
              toolbarContents: <span class="hljs-function">() =&gt;</span> (
                &lt;&gt;
                  {<span class="hljs-string">" "</span>}
                  &lt;UndoRedo/&gt;
                  &lt;BlockTypeSelect/&gt;
                  &lt;BoldItalicUnderlineToggles/&gt;
                &lt;/&gt;
              ),
            }),
          ]}
        /&gt;
      &lt;/div&gt;
    &lt;/&gt;
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Viola! Were ready to write our blog posts! 🎉</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708767400055/82c43ab6-8e4f-47bd-936b-17b15f302094.png" alt="A screenshot of a blog editor interface with a toolbar and sample text, displayed on a web browser with a purple wavy background." /></p>
<h3 id="heading-step-22-adding-the-title-input-and-publish-button">Step 2.2 Adding the title input and publish button</h3>
<p>Lets create an input to write our blog titles! We can replace the h1 <code>My Blog Editor</code> element with a text input. Then, we can add the Publish button next to it. Its really easy to style them using Tailwind. We just need to wrap it into an outer box and add the <code>button</code> after the <code>h1</code> element. We will also leverage <code>flexbox</code> and <code>ml-auto</code> Tailwind class:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> [title, setTitle] = useState&lt;<span class="hljs-built_in">string</span>&gt;(<span class="hljs-string">''</span>);  

<span class="hljs-keyword">return</span> (  
  &lt;&gt;  
    &lt;div className=<span class="hljs-string">"flex"</span>&gt;  
      &lt;input  
        onChange={<span class="hljs-function">(<span class="hljs-params">event: React.ChangeEvent&lt;HTMLInputElement&gt;</span>) =&gt;</span> setTitle(event.target.value)}  
        value={title}  
        className=<span class="hljs-string">"text-3xl focus:outline-none"</span>  
        placeholder=<span class="hljs-string">"Title..."</span> /&gt;  
      &lt;button  
        onClick={publishPost}  
        className=<span class="hljs-string">"ml-auto bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"</span>&gt;Publish  
      &lt;/button&gt;  
    &lt;/div&gt;
    {<span class="hljs-comment">/* Editor code... */</span>}
  &lt;/&gt;  
);
</code></pre>
<p>Here is our initial editor design!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708767404372/c126f773-5662-4a6b-9dad-536313be2605.png" alt="A screenshot of a web-based text editor interface with a document titled &quot;Title...&quot; that includes sample text and headings. The editor toolbar shows formatting options and a &quot;Publish&quot; button." /></p>
<p>Did you notice the <code>publishPost</code> reference on <code>onClick</code> attribute? Now, we can program its functionality, the <code>publishPost</code> method itself. First, lets define the API request were going to send to Hashnode GraphQL API. We'll use the <code>publishPost</code> mutation but if you don't want to publish your posts immediately, you can also use the <code>createDraft</code> mutation.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// imports</span>

<span class="hljs-keyword">const</span> publishPostMutation = <span class="hljs-string">`
mutation ($input: PublishPostInput!) {
  publishPost(input: $input) {
     post {
      url
     }
  }
}
`</span>

<span class="hljs-comment">// App component</span>
</code></pre>
<p>Lets create a corresponding type to this request so we can map the response output and use it in a type-safe way.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// imports</span>

<span class="hljs-keyword">type</span> ApiResponse = {
  data: {
    publishPost: {
      post: {
        url: <span class="hljs-built_in">string</span>
      }
    }
  }
}

<span class="hljs-comment">// mutation</span>

<span class="hljs-comment">// App component</span>
</code></pre>
<p>Almost all Hashnode GraphQL <strong>queries</strong> can be accessed without any authentication mechanism. But, all <strong>mutations</strong> need an authentication header. Were going to use <code>publishPost</code> mutation for this tutorial, therefore, we need to authenticate our user. Its really easy to do, we just need to include our <strong>Personal Access Token (PAT)</strong> in the <code>Authorization</code> header. Please go ahead and grab your token from the <a target="_blank" href="https://hashnode.com/settings/developer">Hashnode Developer Settings</a> page. Click the Generate new token button and copy the generated token.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708767409893/b1bfca73-8f86-44d5-92de-ef7584253454.png" alt="A screenshot of a webpage interface for managing Personal Access Tokens, featuring a description of the token's purpose and a &quot;Generate new token&quot; button." /></p>
<p>Lets put this in a <code>const</code>, so we can use it later. Of course, in a bigger project, you can store this information somewhere secure, and access it as you wish. For the demo purposes, we will store in a <code>const</code>.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> PERSONAL_ACCESS_TOKEN = <span class="hljs-string">'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'</span>;
</code></pre>
<p>Next, we need our publication ID. We can easily copy the publication ID from our blogs dashboard URL.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708767421385/d081200c-84b0-4d64-96a0-42e3dc3f774a.png" alt="A screenshot of a user settings page on the Hashnode website, displaying sections for profile, basic info, social media links, and blog management options." /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708767423913/70a1beab-5698-41ba-82fd-d0046df945f0.png" alt="Web browser screenshot showing the Hashnode website with an arrow pointing to the URL in the address bar." /></p>
<p>Now, using both the recently generated token and the publication ID, we can send a publish post request. Lets go back to creating the <code>publishPost</code> function:</p>
<pre><code class="lang-typescript">  <span class="hljs-keyword">const</span> publishPost = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"https://gql.hashnode.com"</span>, {
      method: <span class="hljs-string">"POST"</span>,
      headers: {
        <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
        Accept: <span class="hljs-string">"application/json"</span>,
        Authorization: PERSONAL_ACCESS_TOKEN,
      },
      body: <span class="hljs-built_in">JSON</span>.stringify({
        query: publishPostMutation,
        variables: {
          input: {
            publicationId: <span class="hljs-string">"65d99cd9447d15d98a2fc264"</span>,
            title: title,
            contentMarkdown: editorRef.current?.getMarkdown(),
          },
        },
      }),
    });
  };
</code></pre>
<h2 id="heading-step-3-showing-success-message">Step 3: Showing success message</h2>
<p>Now, we can add a little container that gives us feedback when we successfully publish our blog post! We can store preview URL in state and show that container based on the <code>previewUrl</code> state changes.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> [previewUrl, setPreviewUrl] = useState&lt;<span class="hljs-built_in">string</span>&gt;(<span class="hljs-string">""</span>);  

<span class="hljs-keyword">return</span> (  
  &lt;&gt;  
    &lt;div id=<span class="hljs-string">"preview-link"</span> className={previewLink === <span class="hljs-string">""</span> ? <span class="hljs-string">"hidden"</span> : <span class="hljs-string">""</span> + <span class="hljs-string">"absolute top-20 z-10 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-green-200 border-2 border-green-500 rounded-lg w-1/2 px-8 py-4"</span>}&gt;  
       Successfully published the blog post! &lt;br /&gt;  
      &lt;a href={previewLink} className=<span class="hljs-string">"text-blue-900"</span> target=<span class="hljs-string">"_blank"</span>&gt;{previewLink}&lt;/a&gt;  
    &lt;/div&gt;
    {<span class="hljs-comment">/* Other parts */</span>}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708767432702/23da3857-b903-423f-b3f9-c6d06c67c0b5.png" alt="A screenshot of a web development environment displaying a preview of a webpage with text content and a link notification." /></p>
<p>Lets add a state modifier to our request function and combine things:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> publishPost = <span class="hljs-keyword">async</span> () =&gt; {
<span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"https://gql.hashnode.com"</span>, {
  method: <span class="hljs-string">"POST"</span>,
  headers: {
    <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
    Accept: <span class="hljs-string">"application/json"</span>,
    Authorization: PERSONAL_ACCESS_TOKEN,
  },
  body: <span class="hljs-built_in">JSON</span>.stringify({
    query: publishPostMutation,
    variables: {
      input: {
        publicationId: <span class="hljs-string">"65d99cd9447d15d98a2fc264"</span>,
        title: title,
        contentMarkdown: editorRef.current?.getMarkdown(),
      },
    },
  }),
});

<span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> response.json() <span class="hljs-keyword">as</span> ApiResponse;

setPreviewLink(result.data.publishPost.post.url);
};
</code></pre>
<p>Ta-da! 🎉 We can click on the preview URL and see our new shiny blog post!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708767439280/2bfa260b-865b-4909-ad58-35fc22de73cd.png" alt="A screenshot of a blog post titled &quot;Testing post&quot; on Ozan Akman's team blog, featuring a brief text content and various user interaction icons." /></p>
<p>Here is everything combined, the whole code of the <code>App.tsx</code> component:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> {
  MDXEditor,
  BlockTypeSelect,
  UndoRedo,
  BoldItalicUnderlineToggles,
  toolbarPlugin,
  headingsPlugin,
  markdownShortcutPlugin,
  linkPlugin, MDXEditorMethods,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@mdxeditor/editor"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@mdxeditor/editor/style.css"</span>;
<span class="hljs-keyword">import</span> React, {useState} <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">type</span> ApiResponse = {
  data: {
    publishPost: {
      post: {
        url: <span class="hljs-built_in">string</span>
      }
    }
  }
}

<span class="hljs-keyword">const</span> PERSONAL_ACCESS_TOKEN = <span class="hljs-string">"REPLACE_THIS_WITH_YOUR_PERSONAL_ACCESS_TOKEN"</span>;

<span class="hljs-keyword">const</span> publishPostMutation = <span class="hljs-string">`
  mutation ($input: PublishPostInput!) {
    publishPost(input: $input) {
       post {
        url
       }
    }
  }
`</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [title, setTitle] = useState&lt;<span class="hljs-built_in">string</span>&gt;(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [previewLink, setPreviewLink] = useState&lt;<span class="hljs-built_in">string</span>&gt;(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> editorRef = React.useRef&lt;MDXEditorMethods&gt;(<span class="hljs-literal">null</span>);

  <span class="hljs-keyword">const</span> publishPost = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"https://gql.hashnode.com"</span>, {
      method: <span class="hljs-string">"POST"</span>,
      headers: {
        <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
        Accept: <span class="hljs-string">"application/json"</span>,
        Authorization: PERSONAL_ACCESS_TOKEN,
      },
      body: <span class="hljs-built_in">JSON</span>.stringify({
        query: publishPostMutation,
        variables: {
          input: {
            publicationId: <span class="hljs-string">"65d99cd9447d15d98a2fc264"</span>,
            title: title,
            contentMarkdown: editorRef.current?.getMarkdown(),
          },
        },
      }),
    });

    <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> response.json() <span class="hljs-keyword">as</span> ApiResponse;

    setPreviewLink(result.data.publishPost.post.url);
  };

  <span class="hljs-keyword">return</span> (
    &lt;&gt;
      &lt;div id=<span class="hljs-string">"preview-link"</span> className={previewLink === <span class="hljs-string">""</span> ? <span class="hljs-string">"hidden"</span> : <span class="hljs-string">""</span> + <span class="hljs-string">"absolute top-20 z-10 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-green-200 border-2 border-green-500 rounded-lg w-1/2 px-8 py-4"</span>}&gt;
         Here is your preview link: &lt;br /&gt;
        &lt;a href={previewLink} className=<span class="hljs-string">"text-blue-900"</span> target=<span class="hljs-string">"_blank"</span>&gt;{previewLink}&lt;/a&gt;
      &lt;/div&gt;
      &lt;div className=<span class="hljs-string">"flex"</span>&gt;
        &lt;input
          onChange={<span class="hljs-function">(<span class="hljs-params">event: React.ChangeEvent&lt;HTMLInputElement&gt;</span>) =&gt;</span> setTitle(event.target.value)}
          value={title}
          className=<span class="hljs-string">"text-3xl w-full focus:outline-none"</span>
          placeholder=<span class="hljs-string">"Title..."</span>/&gt;
        &lt;button
          onClick={publishPost}
          className=<span class="hljs-string">"ml-auto bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"</span>&gt;Publish
        &lt;/button&gt;
      &lt;/div&gt;

      &lt;div className=<span class="hljs-string">"prose max-w-none"</span>&gt;
        &lt;MDXEditor
          ref={editorRef}
          className=<span class="hljs-string">"my-5"</span>
          markdown=<span class="hljs-string">"Hello world!"</span>
          plugins={[
            headingsPlugin(),
            linkPlugin(),
            markdownShortcutPlugin(),
            toolbarPlugin({
              toolbarContents: <span class="hljs-function">() =&gt;</span> (
                &lt;&gt;
                  {<span class="hljs-string">" "</span>}
                  &lt;UndoRedo/&gt;
                  &lt;BlockTypeSelect/&gt;
                  &lt;BoldItalicUnderlineToggles/&gt;
                &lt;/&gt;
              ),
            }),
          ]}
        /&gt;
      &lt;/div&gt;
    &lt;/&gt;
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Weve learned how to use Hashnode GraphQL API to create a custom React text editor. There are many examples on the <a target="_blank" href="https://apidocs.hashnode.com/">API Docs page</a> that you can use to extend your blogs functionality.</p>
]]></description><link>https://hashnode.com/blog/publishing-a-blog-post-to-hashnode-using-a-custom-editing-interface</link><guid isPermaLink="true">https://hashnode.com/blog/publishing-a-blog-post-to-hashnode-using-a-custom-editing-interface</guid><category><![CDATA[Beginner Developers]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[React]]></category><dc:creator><![CDATA[Ozan Akman]]></dc:creator></item><item><title><![CDATA[How to customize Hashnode Headless CMS using TailwindCSS]]></title><description><![CDATA[<p>Recently Hashnode released their <a target="_blank" href="https://hashnode.com/headless#choices">headless CMS</a> which is built specifically for running blogs.</p>
<p>It comprises their <a target="_blank" href="https://hshno.de/blog-starter-kit">Next.js Starter Kit</a> and <a target="_blank" href="https://gql.hashnode.com/">GraphQL APIs</a> to construct your blog's homepage, articles, comments, search functionality, and more.</p>
<p>In this article, lets embody the saying <em>''Hashnode's publishing power, your custom design"</em> as we customize Next.js Starter Kit blog using TailwindCSS</p>
<h2 id="heading-setup-and-installation">Setup and Installation</h2>
<p>Let start by installing the Nextjs Starter Kit locally, first head to the projects Github repository and you can either fork or clone the project.</p>
<p>In this article I will go with the cloning approach by running this command</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/Hashnode/starter-kit.git
</code></pre>
<p>The Starter Kit repository is organized as a mono-repo, housing multiple themes. To begin customization, navigate to the "packages/blog-starter-kit/themes/" directory in your local repository, where three distinct themes await: <em>enterprise, hashnode, and personal.</em></p>
<p>Choose your preferred theme and open it in your editor by either using the terminal with commands like <code>cd packages/blog-starter-kit/themes/enterprise</code> or navigating through your file explorer.</p>
<p>In this walkthrough, we'll focus on the enterprise theme, but the principles apply on all themes. Once inside your chosen theme, the folder structure becomes accessible for modification.</p>
<p>Within the theme, locate the <code>.env.example</code> file and rename it to <code>.env.local</code>. Customize the environment variables as needed for your site integration or leverage existing variables like shown in image below</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708944711104/eb344c9a-6692-4f9a-b3b0-bd504d1195e1.png" alt class="image--center mx-auto" /></p>
<p>Next, in your terminal, run the command <code>pnpm install</code> to install the required packages. Ensure that you have <code>pnpm</code> installed globally on your machine for this to work</p>
<p>Once the packages are installed, fire up the development server with <code>pnpm dev</code>. Now, you can preview it on the browser</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708947070628/5b3c930b-0f94-4a34-9b67-edbda8006d1d.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-tailwind-customizations">Tailwind Customizations</h2>
<p>By default the project comes with tailwindcss, this can be observed by the presence of <code>tailwind.config.js</code> file, so we can start customizing the project according to our likings lets start with:</p>
<ul>
<li><p><strong>Colors Customizations</strong></p>
<p>  By default the enterprise version uses blue color as the primary color as seen below in the <code>tailwind.config.js</code> file snippet</p>
<pre><code class="lang-javascript">  <span class="hljs-comment">/** <span class="hljs-doctag">@type <span class="hljs-type">{import('tailwindcss').Config}</span> </span>*/</span>
  <span class="hljs-keyword">const</span> colors = <span class="hljs-built_in">require</span>(<span class="hljs-string">'tailwindcss/colors'</span>);

  <span class="hljs-built_in">module</span>.exports = {
      <span class="hljs-attr">content</span>: [<span class="hljs-string">'./components/**/*.tsx'</span>, <span class="hljs-string">'./pages/**/*.tsx'</span>],
      <span class="hljs-attr">darkMode</span>: <span class="hljs-string">'class'</span>,
      <span class="hljs-attr">theme</span>: {
          <span class="hljs-attr">extend</span>: {
              <span class="hljs-attr">colors</span>: {
                  <span class="hljs-string">'accent-1'</span>: <span class="hljs-string">'#FAFAFA'</span>,
                  <span class="hljs-string">'accent-2'</span>: <span class="hljs-string">'#EAEAEA'</span>,
                  <span class="hljs-string">'accent-7'</span>: <span class="hljs-string">'#333'</span>,
                  <span class="hljs-attr">success</span>: <span class="hljs-string">'#0070f3'</span>,
                  <span class="hljs-attr">cyan</span>: <span class="hljs-string">'#79FFE1'</span>,
                  <span class="hljs-attr">primary</span>: colors.blue, <span class="hljs-comment">//primary color</span>
              },
  .....
  }
</code></pre>
<p>  You will also notice an import to <code>tailwindcss/colors</code> at the top of the configuration file. This enables to curate your colors from tailwind default color palette instead of defining your own custom palette.</p>
<p>  In this starter-kit you will notice <code>'primary'</code> set to inherit all blue colors from tailwind blue color palette</p>
<p>  To make your project unique, consider changing the primary color. For instance, lets switch it to <strong>red</strong> and observe the visual impact.</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709020217844/bc55611d-81e6-4969-a496-a42bbb547bcd.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Customizing UI elements</strong></p>
<p>  By using tailwind we can also customize the UI elements lets say the cards, images, fonts and other by adjusting their tailwind classes in their respective components. We can also customize the blog by creating a new components style them with tailwindcss and set them up in the UI</p>
</li>
</ul>
<h2 id="heading-theme-switcher">Theme Switcher</h2>
<p>Now, lets wrap up the customizations by building a simple theme switcher and customize it using tailwind</p>
<p>Tailwind includes a <code>dark</code> variant that lets you style your site differently when dark mode is enabled</p>
<p>The main two methods used are to achieve dark-mode in tailwind are:</p>
<ul>
<li><p><strong><em>Media strategy</em></strong></p>
<p>  The media strategy that uses <em>prefers-color-scheme</em> CSS media feature that sets dark or light mode based on system preference and this is tailwind's default strategy</p>
</li>
<li><p><strong><em>Selector strategy</em></strong></p>
<p>  The selector strategy which before <em>tailwindv3.4.1</em> was known as <code>class</code> strategy support toggling dark mode manually instead of relying on the operating system preference, now because this is not the default to use it we need to add this line in our <code>tailwind.config.js</code> file</p>
<pre><code class="lang-javascript">  <span class="hljs-comment">/** <span class="hljs-doctag">@type <span class="hljs-type">{import('tailwindcss').Config}</span> </span>*/</span>
  <span class="hljs-built_in">module</span>.exports = {
    <span class="hljs-attr">darkMode</span>: <span class="hljs-string">'selector'</span>,<span class="hljs-comment">// for v3.4.1 and above</span>
    <span class="hljs-attr">darkMode</span>: <span class="hljs-string">'class'</span> <span class="hljs-comment">// for version less than 3.4.1</span>
    <span class="hljs-comment">// ...</span>
  }
</code></pre>
</li>
</ul>
<p>Because our project as the time of this writing uses tailwind v3.3.3 you will observe it uses the <code>class</code> strategy in the <code>tailwind.config.js</code> file instead of the newer selector <code>strategy</code> (a possible pull request).</p>
<p>Now that we have understood the different strategies used to achieve dark-mode in tailwind lets proceed by installing a package that will enable as to achieve theme switching easily in Next.js called next-themes</p>
<p>Lets install it using the command</p>
<pre><code class="lang-bash">pnpm install next-themes
</code></pre>
<p>Then we can create a <code>ThemeProvider</code> on the <code>pages/_app.tsx</code> file like shown below</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// pages/_app.tsx</span>
<span class="hljs-keyword">import</span> { AppProps } <span class="hljs-keyword">from</span> <span class="hljs-string">'next/app'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'../styles/index.css'</span>;
<span class="hljs-keyword">import</span> { ThemeProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">'next-themes'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyApp</span>(<span class="hljs-params">{ Component, pageProps }: AppProps</span>) </span>{
        <span class="hljs-keyword">return</span> (
        &lt;ThemeProvider attribute=<span class="hljs-string">"class"</span>&gt;
            &lt;Component {...pageProps} /&gt;
        &lt;/ThemeProvider&gt;
    );
}
</code></pre>
<p>The <code>ThemeProvider</code> attribute prop is set to value <em>class</em> because our Nextjs application uses tailwind <code>class</code> strategy to achieve dark-mode.</p>
<p>Now our provider is set lets add the required components to toggle the theme</p>
<p>Inside the root directory navigate to <code>components\icons\svgs</code> .Inside the directory we are going to create two more SVG icons the <strong>Moon</strong>(<code>MoonSVG.js</code>) and <strong>Sun</strong>( <code>SunSVG.js</code>) icons.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//SunSVG.js</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SunSVG</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> </span>{
    render() {
        <span class="hljs-keyword">return</span> (
            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">svg</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">{this.props.className}</span>
                <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 15 15"</span>
                <span class="hljs-attr">fill</span>=<span class="hljs-string">"none"</span>
                <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://www.w3.org/2000/svg"</span>
            &gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">path</span>
                    <span class="hljs-attr">d</span>=<span class="hljs-string">"M7.5 0C7.77614 0 8 0.223858 8 0.5V2.5C8 2.77614 7.77614 3 7.5 3C7.22386 3 7 2.77614 7 2.5V0.5C7 0.223858 7.22386 0 7.5 0ZM2.1967 2.1967C2.39196 2.00144 2.70854 2.00144 2.90381 2.1967L4.31802 3.61091C4.51328 3.80617 4.51328 4.12276 4.31802 4.31802C4.12276 4.51328 3.80617 4.51328 3.61091 4.31802L2.1967 2.90381C2.00144 2.70854 2.00144 2.39196 2.1967 2.1967ZM0.5 7C0.223858 7 0 7.22386 0 7.5C0 7.77614 0.223858 8 0.5 8H2.5C2.77614 8 3 7.77614 3 7.5C3 7.22386 2.77614 7 2.5 7H0.5ZM2.1967 12.8033C2.00144 12.608 2.00144 12.2915 2.1967 12.0962L3.61091 10.682C3.80617 10.4867 4.12276 10.4867 4.31802 10.682C4.51328 10.8772 4.51328 11.1938 4.31802 11.3891L2.90381 12.8033C2.70854 12.9986 2.39196 12.9986 2.1967 12.8033ZM12.5 7C12.2239 7 12 7.22386 12 7.5C12 7.77614 12.2239 8 12.5 8H14.5C14.7761 8 15 7.77614 15 7.5C15 7.22386 14.7761 7 14.5 7H12.5ZM10.682 4.31802C10.4867 4.12276 10.4867 3.80617 10.682 3.61091L12.0962 2.1967C12.2915 2.00144 12.608 2.00144 12.8033 2.1967C12.9986 2.39196 12.9986 2.70854 12.8033 2.90381L11.3891 4.31802C11.1938 4.51328 10.8772 4.51328 10.682 4.31802ZM8 12.5C8 12.2239 7.77614 12 7.5 12C7.22386 12 7 12.2239 7 12.5V14.5C7 14.7761 7.22386 15 7.5 15C7.77614 15 8 14.7761 8 14.5V12.5ZM10.682 10.682C10.8772 10.4867 11.1938 10.4867 11.3891 10.682L12.8033 12.0962C12.9986 12.2915 12.9986 12.608 12.8033 12.8033C12.608 12.9986 12.2915 12.9986 12.0962 12.8033L10.682 11.3891C10.4867 11.1938 10.4867 10.8772 10.682 10.682ZM5.5 7.5C5.5 6.39543 6.39543 5.5 7.5 5.5C8.60457 5.5 9.5 6.39543 9.5 7.5C9.5 8.60457 8.60457 9.5 7.5 9.5C6.39543 9.5 5.5 8.60457 5.5 7.5ZM7.5 4.5C5.84315 4.5 4.5 5.84315 4.5 7.5C4.5 9.15685 5.84315 10.5 7.5 10.5C9.15685 10.5 10.5 9.15685 10.5 7.5C10.5 5.84315 9.15685 4.5 7.5 4.5Z"</span>
                    <span class="hljs-attr">fill</span>=<span class="hljs-string">"currentColor"</span>
                    <span class="hljs-attr">fill-rule</span>=<span class="hljs-string">"evenodd"</span>
                    <span class="hljs-attr">clip-rule</span>=<span class="hljs-string">"evenodd"</span>
                &gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">path</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span></span>
        );
    }
}
</code></pre>
<pre><code class="lang-javascript"><span class="hljs-comment">//MoonSVG.js</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MoonSVG</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> </span>{
    render() {
        <span class="hljs-keyword">return</span> (
            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">svg</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">{this.props.className}</span>
                <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 15 15"</span>
                <span class="hljs-attr">fill</span>=<span class="hljs-string">"none"</span>
                <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://www.w3.org/2000/svg"</span>
            &gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">path</span>
                    <span class="hljs-attr">d</span>=<span class="hljs-string">"M2.89998 0.499976C2.89998 0.279062 2.72089 0.0999756 2.49998 0.0999756C2.27906 0.0999756 2.09998 0.279062 2.09998 0.499976V1.09998H1.49998C1.27906 1.09998 1.09998 1.27906 1.09998 1.49998C1.09998 1.72089 1.27906 1.89998 1.49998 1.89998H2.09998V2.49998C2.09998 2.72089 2.27906 2.89998 2.49998 2.89998C2.72089 2.89998 2.89998 2.72089 2.89998 2.49998V1.89998H3.49998C3.72089 1.89998 3.89998 1.72089 3.89998 1.49998C3.89998 1.27906 3.72089 1.09998 3.49998 1.09998H2.89998V0.499976ZM5.89998 3.49998C5.89998 3.27906 5.72089 3.09998 5.49998 3.09998C5.27906 3.09998 5.09998 3.27906 5.09998 3.49998V4.09998H4.49998C4.27906 4.09998 4.09998 4.27906 4.09998 4.49998C4.09998 4.72089 4.27906 4.89998 4.49998 4.89998H5.09998V5.49998C5.09998 5.72089 5.27906 5.89998 5.49998 5.89998C5.72089 5.89998 5.89998 5.72089 5.89998 5.49998V4.89998H6.49998C6.72089 4.89998 6.89998 4.72089 6.89998 4.49998C6.89998 4.27906 6.72089 4.09998 6.49998 4.09998H5.89998V3.49998ZM1.89998 6.49998C1.89998 6.27906 1.72089 6.09998 1.49998 6.09998C1.27906 6.09998 1.09998 6.27906 1.09998 6.49998V7.09998H0.499976C0.279062 7.09998 0.0999756 7.27906 0.0999756 7.49998C0.0999756 7.72089 0.279062 7.89998 0.499976 7.89998H1.09998V8.49998C1.09998 8.72089 1.27906 8.89997 1.49998 8.89997C1.72089 8.89997 1.89998 8.72089 1.89998 8.49998V7.89998H2.49998C2.72089 7.89998 2.89998 7.72089 2.89998 7.49998C2.89998 7.27906 2.72089 7.09998 2.49998 7.09998H1.89998V6.49998ZM8.54406 0.98184L8.24618 0.941586C8.03275 0.917676 7.90692 1.1655 8.02936 1.34194C8.17013 1.54479 8.29981 1.75592 8.41754 1.97445C8.91878 2.90485 9.20322 3.96932 9.20322 5.10022C9.20322 8.37201 6.82247 11.0878 3.69887 11.6097C3.45736 11.65 3.20988 11.6772 2.96008 11.6906C2.74563 11.702 2.62729 11.9535 2.77721 12.1072C2.84551 12.1773 2.91535 12.2458 2.98667 12.3128L3.05883 12.3795L3.31883 12.6045L3.50684 12.7532L3.62796 12.8433L3.81491 12.9742L3.99079 13.089C4.11175 13.1651 4.23536 13.2375 4.36157 13.3059L4.62496 13.4412L4.88553 13.5607L5.18837 13.6828L5.43169 13.7686C5.56564 13.8128 5.70149 13.8529 5.83857 13.8885C5.94262 13.9155 6.04767 13.9401 6.15405 13.9622C6.27993 13.9883 6.40713 14.0109 6.53544 14.0298L6.85241 14.0685L7.11934 14.0892C7.24637 14.0965 7.37436 14.1002 7.50322 14.1002C11.1483 14.1002 14.1032 11.1453 14.1032 7.50023C14.1032 7.25044 14.0893 7.00389 14.0623 6.76131L14.0255 6.48407C13.991 6.26083 13.9453 6.04129 13.8891 5.82642C13.8213 5.56709 13.7382 5.31398 13.6409 5.06881L13.5279 4.80132L13.4507 4.63542L13.3766 4.48666C13.2178 4.17773 13.0353 3.88295 12.8312 3.60423L12.6782 3.40352L12.4793 3.16432L12.3157 2.98361L12.1961 2.85951L12.0355 2.70246L11.8134 2.50184L11.4925 2.24191L11.2483 2.06498L10.9562 1.87446L10.6346 1.68894L10.3073 1.52378L10.1938 1.47176L9.95488 1.3706L9.67791 1.2669L9.42566 1.1846L9.10075 1.09489L8.83599 1.03486L8.54406 0.98184ZM10.4032 5.30023C10.4032 4.27588 10.2002 3.29829 9.83244 2.40604C11.7623 3.28995 13.1032 5.23862 13.1032 7.50023C13.1032 10.593 10.596 13.1002 7.50322 13.1002C6.63646 13.1002 5.81597 12.9036 5.08355 12.5522C6.5419 12.0941 7.81081 11.2082 8.74322 10.0416C8.87963 10.2284 9.10028 10.3497 9.34928 10.3497C9.76349 10.3497 10.0993 10.0139 10.0993 9.59971C10.0993 9.24256 9.84965 8.94373 9.51535 8.86816C9.57741 8.75165 9.63653 8.63334 9.6926 8.51332C9.88358 8.63163 10.1088 8.69993 10.35 8.69993C11.0403 8.69993 11.6 8.14028 11.6 7.44993C11.6 6.75976 11.0406 6.20024 10.3505 6.19993C10.3853 5.90487 10.4032 5.60464 10.4032 5.30023Z"</span>
                    <span class="hljs-attr">fill</span>=<span class="hljs-string">"currentColor"</span>
                    <span class="hljs-attr">fill-rule</span>=<span class="hljs-string">"evenodd"</span>
                    <span class="hljs-attr">clip-rule</span>=<span class="hljs-string">"evenodd"</span>
                &gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">path</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span></span>
        );
    }
}
</code></pre>
<p>Now we can create a component to render the Icons conditionally: Sun icon when its dark mode and Moon Icon when it is light mode.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//components/theme-switcher.tsx</span>
<span class="hljs-keyword">import</span> { useTheme } <span class="hljs-keyword">from</span> <span class="hljs-string">'next-themes'</span>;
<span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">import</span> MoonSVG <span class="hljs-keyword">from</span> <span class="hljs-string">'./icons/svgs/MoonSVG'</span>;
<span class="hljs-keyword">import</span> SunSVG <span class="hljs-keyword">from</span> <span class="hljs-string">'./icons/svgs/SunSVG'</span>;

<span class="hljs-keyword">const</span> ThemeSwitch = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [mounted, setMounted] = useState(<span class="hljs-literal">false</span>);
    <span class="hljs-keyword">const</span> { theme, setTheme } = useTheme();

    useEffect(<span class="hljs-function">() =&gt;</span> {
        setMounted(<span class="hljs-literal">true</span>);
    }, []);

    <span class="hljs-keyword">if</span> (!mounted) {
        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
    }

    <span class="hljs-keyword">return</span> (
     <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">button</span> 
          <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setTheme(theme === 'light' ? 'dark' : 'light')}&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">SunSVG</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"h-[1.5rem] w-[1.3rem] dark:hidden"</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">MoonSVG</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"hidden h-5 w-5 dark:block"</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"sr-only"</span>&gt;</span>Toggle theme<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
     <span class="hljs-tag">&lt;/&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ThemeSwitch;
</code></pre>
<p>In the code snippet above, we are using the <code>useTheme</code> hook to get the current theme (<code>theme</code>) and the function to set the theme (<code>setTheme</code>).</p>
<p>The <code>useEffect</code> hook is used to set <code>mounted</code> to <code>true</code> after the initial render. This ensures that the component is mounted before attempting to render the theme switch button.</p>
<p>The <code>onClick</code> event of the button triggers a function that toggles the theme between 'light' and 'dark'.</p>
<p>The visibility of these icons is controlled based on the current theme. The <code>dark:hidden</code> and <code>dark:block</code> classes are used to show/hide the icons based on whether the dark theme is active or not.</p>
<p>We can now add our <code>ThemeSwitch</code> component to the <code>header</code> component.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//components/header.tsx</span>

<span class="hljs-comment">//other imports</span>
<span class="hljs-keyword">import</span> ThemeSwitch <span class="hljs-keyword">from</span> <span class="hljs-string">'./theme-switcher'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> Header = <span class="hljs-function">() =&gt;</span> {
<span class="hljs-comment">// other code   </span>
    <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"border-b bg-slate-950 py-10 dark:border-neutral-800 dark:bg-neutral-900"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"col-span-2 flex flex-row items-center justify-end gap-5 text-slate-300 lg:col-span-3"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"hidden lg:block"</span>&gt;</span>{navList}<span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">href</span>=<span class="hljs-string">{baseUrl}</span> <span class="hljs-attr">as</span>=<span class="hljs-string">"a"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"primary"</span> <span class="hljs-attr">label</span>=<span class="hljs-string">"Book a demo"</span> /&gt;</span>
            <span class="hljs-comment">&lt;!--Add theme-switch component here--&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">ThemeSwitch</span>/&gt;</span> 
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span></span>
    );
};
</code></pre>
<p>By doing just that we have successfully implemented the Theme Switcher functionality.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709106046850/d1b43b8b-62d6-4c5b-9e8c-0481df748f2e.avif" alt class="image--center mx-auto" /></p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>In summary, Tailwind CSS allows us to quickly and easily change the look of our blog. We can tweak things like card layouts, fonts, colors, and more using simple classes. Feel free to play around with it! If you have any questions or ideas, drop them in the comments, and I'll be happy to help. Happy coding!</p>
]]></description><link>https://hashnode.com/blog/how-to-customize-hashnode-headless-cms-using-tailwindcss</link><guid isPermaLink="true">https://hashnode.com/blog/how-to-customize-hashnode-headless-cms-using-tailwindcss</guid><category><![CDATA[Tailwind CSS]]></category><category><![CDATA[Hashnode]]></category><dc:creator><![CDATA[Albert Sigsbert]]></dc:creator></item><item><title><![CDATA[Integrating Hashnode Headless CMS With Ecommerce Platforms for Content-Driven Commerce]]></title><description><![CDATA[<p>Over the years, e-commerce has evolved from the times of marketplaces like Froogle (Google Shopping), Amazon, eBay, Etsy, and AliExpress to the rise of modern e-commerce platforms like Shopify, WooCommerce, Magento, Commerce Layer, etc. These platforms allow entrepreneurs and businesses to sell products in a marketplace or use their platform to build e-commerce stores. In both ways, businesses are able to maintain an inventory of products, and customers can purchase them from a storefront. Over time, content emerged as a pivotal force for driving consumer engagement, brand loyalty, and sales. It's become evident that delivering valuable, informative, and entertaining content to potential customers is vital for the success of e-commerce business, which is why the Ads industry thrives. But to convert new customers from either Ads or organic SEO, you need to lead them to a place where they can find enough information to decide on purchasing. By seamlessly integrating engaging content with product data and vice versa, businesses can offer customers an immersive shopping experience that not only showcases their products but also educates and entertains customers.</p>
<p>In this tutorial, I will show you how to use the content-driven commerce approach to improve your top-of-funnel (TOF) and middle-of-funnel (MOF) marketing goals by creating a business blog. More importantly, I will show you why you should integrate <a target="_blank" href="https://hashnode.com/headless">Hashnode Headless CMS</a> with your ecommerce store. We'll explore how this integration can revolutionize your approach to content-driven commerce, enabling you to deliver compelling experiences that drive brand awareness, conversions, and foster long-term customer relationships.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708528341473/TS2oSvbC4.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To get the best out of this tutorial, you need to have the following:</p>
<ul>
<li><p>An existing Hashnode account (you can create one <a target="_blank" href="https://hashnode.com">here</a>).</p>
</li>
<li><p>An existing ecommerce store built using any platform (I will also show you one).</p>
</li>
<li><p>The ability to navigate through a web browser, IDE, and terminal on your computer.</p>
</li>
<li><p>A smile on your face :).</p>
</li>
</ul>
<h2 id="heading-the-state-of-content-driven-commerce">The State of Content-Driven Commerce</h2>
<p>Usually, brands build their e-commerce stores with a monolith, headless, or composable architecture (don't panic, these are just expensive words that explains how the ingredients that make up an e-commerce store are used to actually cook the store 😅). They handle the commerce logic with a custom implementation or use platforms like Shopify, Magento, etc. and product content using dedicated CMSs like Contentful, Sanity, etc.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708672184914/F4L2eKcjY.png" alt class="image--center mx-auto" /></p>
<p>After sorting the technical details, what comes next is how to generate revenue with that beautiful ecommerce website. According to <a target="_blank" href="https://insiderintelligence.com/content/ecommerce-growth-worldwide-will-pick-up-before-tapering-off">Insider Intelligence</a>, we expect global e-commerce sales to hit $6.3 trillion worldwide in 2024 with 2.71 billion people shopping online. This rise will lead to increased demand and competition, forcing businesses to find innovative ways to find potential customers wherever they are and convert them. One of such ways is <strong>content</strong>!</p>
<p>In today's competitive age, more than simply having a storefront is required to win customers' hearts. Customers expect more than just a list of products and categories; they want a curated experience that guides them through their purchasing journey. Content-driven commerce allows businesses to integrate engaging content with their e-commerce product data to deliver an attractive shopping experience. This usually includes product images and videos on a product page, but it shouldn't stop there. As an e-commerce business owner or a marketing specialist working for an e-commerce business, you need to leverage other content commerce activities in your marketing funnel activities. These activities can include:</p>
<ul>
<li><p>Writing about new product launches, product news, targeted articles, buyer guides, hot and trending highlights, product comparisons, etc.</p>
</li>
<li><p>Announcing new discounts, giveaways, sales events, or special promo offers.</p>
</li>
<li><p>Curating gift guides for different seasons, holidays, and personas.</p>
</li>
<li><p>Collaborating with brand ambassadors or influencers to create promotional content, product guides, product tips, etc., featuring your products.</p>
</li>
<li><p>Telling customer stories and highlighting exceptional customer reviews to build trust and credibility like <a target="_blank" href="https://nike.com/stories">Nike</a> and <a target="_blank" href="https://www.adidas.com/us/blog">Adidas</a> does.</p>
</li>
<li><p>And many more!</p>
</li>
</ul>
<p>With this approach, you can also make your blog a marketplace where customers can directly shop from by promoting your brand and products or curating catalogs arranged by tags and categories. A good example is <a target="_blank" href="https://nymag.com/strategist">The Strategist</a>, a site for helping people shop smartly with different curated products packaged with good storytelling. These types of SEO-optimized content will bring more inbound traffic and potential customers to your store. Imagine a customer searching for the query <em>"What can I buy for my wife who loves running?"</em> and the search engine recommends a content piece from your store's blog that suggests different sportswear products and enough information to make the reader decide to purchase on your store 🤯.</p>
<p>All the content ideas above suggest that you need a <strong>blog</strong>! Somewhere, you can write and publish different articles, arrange them together, and deliver them on the internet. When you add a business blog to your e-commerce store, you can use these content pieces to improve the SEO/SEM of your e-commerce business, drive sales, and increase retention. While there are so many ways you might want to do this, I'd like to introduce you to <a target="_blank" href="https://hashnode.com/headless">Hashnode Headless CMS</a>, a powerful CMS optimized for building blogs for independent publishers and brands.</p>
<h2 id="heading-hashnode-for-ecommerce-brands">Hashnode for Ecommerce Brands</h2>
<p>Hashnode was built to provide a hassle-free blogging platform for <a target="_blank" href="https://hashnode.com">developers</a> and <a target="_blank" href="https://hashnode.com/teams">engineering teams</a>. One of the key selling features is the great editor, the ability to set up a custom domain easily, and an API you can use to fetch your posts anywhere else you want. Recently, Hashnode <a target="_blank" href="https://twitter.com/hashnode/status/1714273198127436163">announced a new product</a> that extends the capabilities of their API, offering more customization for blog owners. You now get the option to use their upgraded GraphQL APIs to build your blog's UI using any tech stack of your choosing or use their superb <a target="_blank" href="https://github.com/Hashnode/starter-kit">Next.js starter kit</a>. Now, e-commerce businesses like yours can create a team blog and customize it to match the styling of your e-commerce store!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708526503209/gFrSaqGoy.png" alt class="image--center mx-auto" /></p>
<p>As discussed earlier, having a blog is key for e-commerce businesses wanting to win. You can create one using all the traditional existing platforms or even an actual headless CMS, but Hashnode offers even more benefits than those. Most traditional CMSs lack an editorial content review process and are not cost-efficient, amongst other key issues, unlike Hashnode, which is optimized for blogging from the roots (including SEO, unique features, editor, etc.). Using Hashnode Headless CMS will offer you the following:</p>
<ul>
<li><p><strong>A powerful editor</strong>: With both a WYSIWYG and markdown editor, you can structure your text, add callouts, widgets, embeds (including product videos and direct links to purchase or checkout products!), etc. There are also AI features you can use to generate outlines, optimize your content for SEO, etc.</p>
</li>
<li><p><strong>A seamless content review process</strong>: You can create a team blog and add multiple employees with different permissions. Each staff member can submit their article drafts, and the editors can review them before publishing.</p>
</li>
<li><p><strong>In-built analytics dashboard</strong>: You view the data (views, unique visitors, demographics, device details, etc.) in the Hashnode dashboard or the advanced public analytics dashboard <a target="_blank" href="https://stats.hashnode.com/share/hOHGRKQT/b4fcceb4-5d97-4379-9ee5-b68cc11e098d">like this one</a>.</p>
</li>
<li><p><strong>Tags and series</strong>: You can add multiple tags to blog posts, making it easier for your readers to filter posts. In the demo blog, I have created (which I will show you soon), you can see this in action with the <a target="_blank" href="https://hh-store.vercel.app/blog/tag/new-products">#product-releases</a> tag. You can also create series, add multiple posts to them, and pin them on your blog's navbar <a target="_blank" href="https://hh-store.vercel.app/blog/series/new-releases">like this one</a>!</p>
</li>
<li><p><strong>Webhooks</strong>: You can set up a webhook integration to trigger some external automation (with platforms like Zapier, n8n, etc.) when certain events occur (like a published blog post). You can use this to make an automated social media post or send notifications to unique customers in your loyalty program.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710252308489/c0462dbe-c102-43e7-ba24-2d31036c2315.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708529814205/BKjLvG7f8.png" alt class="image--center mx-auto" /></p>
<p>There are just so many more features you can access right on the spot once you create a blog with Headless Hashnode CMS. You can utilize all these features to supercharge your e-commerce business at a low cost and with little to no technical knowledge. All you need is to have one of your tech support staff (or do it yourself if you have the experience) set up the blog, and your content team can click around in the dashboard to set up the blog as you desire and publish new posts! Even better, if your e-commerce store sells products for developers like mechanical keyboards, blue-light glasses, electronics, etc., you can list your blog posts on the <a target="_blank" href="https://hashnode.com">Hashnode community feed</a>, which is viewed by thousands of developers like me.</p>
<h2 id="heading-integrating-hashnode-with-an-ecommerce-store">Integrating Hashnode with an Ecommerce Store</h2>
<p>Now that you're familiar with the numerous benefits of Headless Hashnode let's create one from scratch and sync it with the ecommerce store. There are different ways you can use Headless Hashnode; you can:</p>
<ol>
<li><p>Use the GraphQL API to build a custom blog using any tech stack you want (there's <a target="_blank" href="https://apidocs.hashnode.com">documentation</a> you can read to do this) and deploy anywhere.</p>
</li>
<li><p>Use the pre-built <a target="_blank" href="https://github.com/Hashnode/starter-kit">Next.js Starter Kit</a> that comes with all the UI components you need and deploy anywhere. You can also extend the UI and add further features you need. This will save you all the development time and enable you to ship your blog before you need to drink another cup of water :).</p>
</li>
</ol>
<p>For this tutorial, we will use the Starter Kit approach and set up a blog on a sub-path like <code>yourdomain.com/blog</code>, but you can also use a subdomain like <code>blog.yourdomain.com</code>. You can even go for non-traditional names like <code>/articles</code>, <code>/hub</code>, <code>/stories</code>, etc. 🙂. This way, your customers can find your blog from the store and vice versa.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708672526807/ghbPjUTc4.png" alt /></p>
<h3 id="heading-building-a-demo-ecommerce-store">Building a Demo Ecommerce Store</h3>
<p>To show you the power of Headless Hashnode coupled with an e-commerce store, I have built a demo international e-commerce store using the <a target="_blank" href="https://github.com/commercelayer/commercelayer-sanity-template">commercelayer-sanity-template</a> and deployed it with Vercel on the <code>https://hh-store.vercel.app</code> domain. This store comes with:</p>
<ul>
<li><p>A user-friendly and performant storefront (with products, categories, i18n, cart, checkout, demo data, etc.) built with TypeScript, React18, Nextjs, Commerce Layer React Components library, and Tailwind CSS.</p>
</li>
<li><p>International transactional functionalities powered by Commerce Layer API.</p>
</li>
<li><p>Structured content and a customizable Sanity CMS authoring environment (including demo data), accessible on <code>&lt;domain&gt;/studio</code>.</p>
</li>
<li><p>PSD2-compliant and production-ready checkout functionality powered by Commerce Layer React Checkout application.</p>
</li>
<li><p>Localization support (including Italian and French translations).</p>
</li>
</ul>
<p>You can create your store using any tech stack or even platform of your choosing, like Shopify, WooCommerce, Medusa, Wix, Swell, Magento, etc. The image below shows what the deployed version looks like (you can also test it live <a target="_blank" href="https://hh-store.vercel.app">here</a>):</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708437600182/TLI6u_yC8.png" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708438528274/h290d5VvM.png" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708438679284/yNZYF2Rap.png" alt /></p>
<p>To learn how to build the e-commerce store in detail, I advise you to read <a target="_blank" href="https://github.com/commercelayer/commercelayer-sanity-template/blob/main/README.md">this comprehensive documentation</a>. But here's a quick guide on what you need to do.</p>
<p><strong>1.</strong> Create a free Commerce Layer and Sanity CMS account. With Commerce Layer, you will create your inventory (markets, SKUs, prices, stock locations, stock items, etc.), and in Sanity, you will add all the product content (text, images, etc.). This is because some ecommerce platforms separate transactional logic from content for <a target="_blank" href="https://commercefordevs.org/content-is-not-commerce">many reasons and benefits</a>. For this tutorial, there will be seed data to import.</p>
<p><strong>2.</strong> Clone or fork the template (<a target="_blank" href="https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository">learn how to do this</a>).</p>
<p><strong>3.</strong> Rename the <code>/env.local.example</code> file to <code>.env.local</code> and add the following required credentials:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Variable</strong></td><td><strong>Description</strong></td></tr>
</thead>
<tbody>
<tr>
<td><code>BUILD_LANGUAGES</code></td><td>The supported locales (the default is <code>en-US, it-IT, fr-FR</code>).</td></tr>
<tr>
<td><code>NEXT_PUBLIC_CL_CLIENT_ID</code></td><td>Your Commerce Layer sales channels application client ID (you can create this automatically by following this <a target="_blank" href="https://docs.commercelayer.io/developers">onboarding guide</a> or manually on the dashboard.</td></tr>
<tr>
<td><code>NEXT_PUBLIC_CL_ENDPOINT</code></td><td>Your Commerce Layer organization's base endpoint (you can copy this on the dashboard.</td></tr>
<tr>
<td><code>NEXT_PUBLIC_SANITY_PROJECT_ID</code></td><td>Sanity project ID (you can get this from <a target="_blank" href="https://sanity.io/manage">sanity.io/manage</a> after creating a new project with the <code>npm -y create sanity@latest</code> CLI command or this <a target="_blank" href="https://sanity.io/get-started">quick start wizard</a>.</td></tr>
<tr>
<td><code>NEXT_PUBLIC_SANITY_DATASET</code></td><td>Sanity dataset (you can get this from the dashboard.</td></tr>
<tr>
<td><code>NEXT_PUBLIC_SANITY_API_VERSION</code></td><td>Sanity API version in the ISO date format, e.g <code>2022-02-15</code> (you can learn more about this in <a target="_blank" href="https://www.sanity.io/help/js-client-api-version">this documentation</a>).</td></tr>
<tr>
<td><code>NEXT_PUBLIC_SANITY_TOKEN</code></td><td>Sanity API token (you can get this from the dashboard.</td></tr>
</tbody>
</table>
</div><p><strong>4.</strong> Install the required dependencies with the command below:</p>
<pre><code class="lang-bash">pnpm install
</code></pre>
<p><strong>5.</strong> Start the development server with the command below:</p>
<pre><code class="lang-bash">pnpm run dev
</code></pre>
<p>The store should start running now on <code>localhost:3000</code>. As mentioned earlier, kindly read <a target="_blank" href="https://github.com/commercelayer/commercelayer-sanity-template/blob/main/README.md">the documentation</a> to learn more (including how to import the seed data for both the transactional commerce data and product content data). We won't cover all of these since it's out of scope for this tutorial. If you're reading this tutorial, I'd assume you already have your sleek ecommerce store set up somewhere using your chosen e-commerce platform :).</p>
<h3 id="heading-building-the-blog-with-hashnode-headless-cms">Building the Blog with Hashnode Headless CMS</h3>
<p>Now that we have an e-commerce store running, let's set up a new Headless Hashnode Blog using the Starter Kit! First, ensure you have created a <a target="_blank" href="https://hashnode.com/signup">Hashnode account</a> and a <a target="_blank" href="https://support.hashnode.com/en/articles/6420120-creating-a-team-blog-on-hashnode">Team Blog</a>. You can use Headless Hashnode with the <a target="_blank" href="https://support.hashnode.com/en/articles/6420128-creating-a-personal-blog-on-hashnode">Personal Blog</a> too, but the Team Blog offers more features suitable for an ecommerce business. Headless Hashnode for team blogs is currently in beta, but you can <a target="_blank" href="https://forms.hashnode.com/headless-hashnode-teams">fill out this form</a> to inquire about pricing and additional details.</p>
<p>Once your blog is up and running, head to the <strong>"Advanced"</strong> tab (just at the left-bottom section of the page) in the dashboard and toggle the <strong>"Enable Headless Mode"</strong> option. This will let Hashnode know that you intend to host your blog yourself, and you can provide the base URL. In this case, my store is deployed on <code>https://hh-store.vercel.app</code>, and I intend to host the blog on the <code>https://hh-store.vercel.app/blog</code> subpath.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708535844152/yoxD3PVxh.png" alt /></p>
<p>Now that we have this configured follow the steps below to get your blog shipped:</p>
<p><strong>1.</strong> Head to the open-sourced <a target="_blank" href="https://github.com/Hashnode/starter-kit">GitHub repository</a> and fork the Starket Kit into your personal or organization account. The project comes with different themes in a monorepo, which you can find in the <code>packages/blog-starter-kit/themes</code> directory. For this tutorial, we will use the <code>enterprise</code> theme.</p>
<p><strong>2.</strong> Now, you will deploy your fork of the repository to <a target="_blank" href="https://vercel.com">Vercel</a>, a cloud hosting platform. Once you're signed in, click on the <strong>"Add New"</strong> button at the top right section of the page and select <strong>"Project"</strong>. You will then be redirected to a new page.</p>
<p><strong>3.</strong> In the new page, choose the repository you want to import (the same one you forked earlier).</p>
<p><strong>4.</strong> Select <code>packages/blog-starter-kit/themes/enterprise</code> as the Root Directory and Next.js as the Framework Preset, and then enter the environmental variables seen below.</p>
<pre><code class="lang-plaintext">NEXT_PUBLIC_HASHNODE_GQL_ENDPOINT=https://gql.hashnode.com
NEXT_PUBLIC_HASHNODE_PUBLICATION_HOST=hh-store.hashnode.dev
NEXT_PUBLIC_BASE_URL=/blog
NEXT_PUBLIC_MODE=production
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708592916198/vX3CB3GLt.gif" alt /></p>
<p><code>NEXT_PUBLIC_HASHNODE_PUBLICATION_HOST</code> should contain your Hashnode blog's default URL (yourhandle.hashnode.dev), and <code>NEXT_PUBLIC_BASE_URL</code> is the subpath you want to deploy the blog on. If you're deploying on a subdomain, you can exclude this variable, proceed to deploy the project, and then <a target="_blank" href="https://vercel.com/docs/projects/domains/add-a-domain">connect the custom domain in Vercel</a>. The same process will apply if you're using any other cloud hosting platform.</p>
<p>With this process, I have deployed the blog on a new domain: <code>https://hh-store-blog.vercel.app</code> (you can choose any name you want here). But since we chose the subpath method, we need to add rewrites to the deployed ecommerce store. Since the store is also built with Nextjs, we can update the <a target="_blank" href="https://github.com/BolajiAyodeji/hh-store/blob/main/packages/ecommerce-store/next.config.mjs"><code>next.config.js</code></a> file like so:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> nextConfig = {
  <span class="hljs-keyword">async</span> rewrites() {
    <span class="hljs-keyword">return</span> [
      {
        <span class="hljs-attr">source</span>: <span class="hljs-string">"/blog"</span>,
        <span class="hljs-attr">destination</span>: <span class="hljs-string">"https://hh-store-blog.vercel.app/blog"</span>
      },
      {
        <span class="hljs-attr">source</span>: <span class="hljs-string">"/blog/:path*"</span>,
        <span class="hljs-attr">destination</span>: <span class="hljs-string">"https://hh-store-blog.vercel.app/blog/:path*"</span>
      }
    ];
  }
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> nextConfig;
</code></pre>
<p><a target="_blank" href="https://nextjs.org/docs/pages/api-reference/next-config-js/rewrites">Nextjs Rewrites</a> allow us to map an incoming request path to a different destination path. So when a user goes to <code>https://hh-store.vercel.app</code> (the store) and clicks a link to the <code>/blog</code> subpath, it will render the project in <code>https://hh-store-blog.vercel.app/blog</code> (the blog) on the same subpath. And that's about it!</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">If your store is deployed somewhere else, you just have to figure out how to add rewrites from it to your new blog's domain (this is usually described in their documentation). As mentioned earlier, you can do this directly on a subdomain without worrying about rewrites.</div>
</div>

<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://hh-store.vercel.app/blog">https://hh-store.vercel.app/blog</a></div>
<p> </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You will agree with me now that Headless Hashnode is more suited for your next blog. You can even create an independent business from this, like <a target="_blank" href="https://nymag.com/strategist">The Strategist</a>, without owning an e-commerce business and leveraging the content-driven approach to offer value to e-commerce brands and customers. I look forward to seeing the ideas you will bring to life from this; please let us know whenever you do :).</p>
<p>For the purpose of this tutorial, I have consolidated both the code for the ecommerce store and blog in this <a target="_blank" href="https://github.com/BolajiAyodeji/hh-store">GitHub repository</a>, just in case you want to explore all the customizations I have done. It's not a monorepo, and both projects are currently not sharing any data. I only extracted the <code>enterprise</code> theme from the starterkit and pulled in the ecommerce store. But for your case, you might want to share some UI between your store and blog (like header and footer), so you might consider going this route then. That said, you can now customize the blog as you desire and start publishing engaging content for your brand and customers.</p>
<p>As <em>Guillermo Rauch</em> <a target="_blank" href="https://twitter.com/rauchg/status/1434228987979460616">said</a>, Hashnode reminds us of what Substack did for journalists; but now, Hashnode is doing something for enterprise teams, e-commerce entrepreneurs, and businesses. I hope you enjoyed reading this tutorial and learned something new. You should also read <a target="_blank" href="https://hashnode.com/blog/the-ideal-headless-cms-for-blogs">this one</a> to learn more about how Headless Hashnode offers more benefits than the traditional CMS platforms.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/Hashnode/starter-kit">https://github.com/Hashnode/starter-kit</a></div>
]]></description><link>https://hashnode.com/blog/integrating-hashnode-headless-cms-with-ecommerce-platforms-for-content-driven-commerce</link><guid isPermaLink="true">https://hashnode.com/blog/integrating-hashnode-headless-cms-with-ecommerce-platforms-for-content-driven-commerce</guid><category><![CDATA[headless cms]]></category><category><![CDATA[HeadlessHashnode]]></category><category><![CDATA[ecommerce]]></category><category><![CDATA[Blogging]]></category><category><![CDATA[business]]></category><category><![CDATA[#content marketing]]></category><category><![CDATA[GraphQL]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[Headless Commerce]]></category><category><![CDATA[headless]]></category><category><![CDATA[Hashnode]]></category><dc:creator><![CDATA[Bolaji Ayodeji]]></dc:creator></item></channel></rss>