<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Danny Chen</title>
    <description>The latest articles on DEV Community by Danny Chen (@danny_chen).</description>
    <link>https://dev.to/danny_chen</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2649629%2Fd41ba7de-1229-43c7-9039-2d0bc4046e88.png</url>
      <title>DEV Community: Danny Chen</title>
      <link>https://dev.to/danny_chen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/danny_chen"/>
    <language>en</language>
    <item>
      <title>UX Engineering: From the Eyes of a Field Pioneer (2026 Edition)</title>
      <dc:creator>Danny Chen</dc:creator>
      <pubDate>Tue, 07 Oct 2025 06:30:14 +0000</pubDate>
      <link>https://dev.to/danny_chen/ux-engineering-from-the-eyes-of-a-field-pioneer-1ehe</link>
      <guid>https://dev.to/danny_chen/ux-engineering-from-the-eyes-of-a-field-pioneer-1ehe</guid>
      <description>&lt;h2&gt;
  
  
  What is UX Engineering?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;UX Engineering&lt;/strong&gt; is the technical discipline of building and validating a product's user interface with a primary focus on the &lt;strong&gt;quality of the user's experience&lt;/strong&gt;. It is the crucial architectural practice that serves as the &lt;strong&gt;binding agent between the worlds of design and backend engineering&lt;/strong&gt;. More than just an &lt;strong&gt;evolution&lt;/strong&gt; of the traditional front-end developer role, UX Engineering represents a fundamental shift in responsibility—from simply implementing a design to becoming the &lt;strong&gt;steward and hands-on builder of the final, interactive user experience&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Architect and Gatekeeper
&lt;/h3&gt;

&lt;p&gt;At its core, a UX Engineer operates like a building architect. They are the master translators, fluent in both the language of design intent and the language of technical feasibility. They don't just receive a design blueprint; they act as a critical &lt;strong&gt;"checkpoint"&lt;/strong&gt; or &lt;strong&gt;"gatekeeper"&lt;/strong&gt;, providing essential &lt;strong&gt;validation&lt;/strong&gt; to ensure that the vision is not only beautiful but also technically sound, scalable, and capable of integrating smoothly with backend systems.&lt;/p&gt;

&lt;p&gt;This central role allows them to bridge the classic communication gap where designers and backend engineers often struggle to connect, preventing costly rework and ensuring the final product remains true to its intended user experience.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;The Three-Layer Model&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In a modern product team, the UX Engineer sits as the essential middle layer, connecting the other two:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;UX/UI Designers:&lt;/strong&gt; Who define the product's vision, feel, and user journey.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UX/Design Engineers:&lt;/strong&gt; Who translate that vision into a high-fidelity, interactive, and technically validated reality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend Engineers:&lt;/strong&gt; Who build the foundational logic and data systems that power the experience.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Without the UX Engineer, a critical gap exists. With them, the entire development process becomes more integrated, efficient, and de-risked from the start.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Your Team Needs a UX Engineer?
&lt;/h2&gt;

&lt;p&gt;Let's talk about the most common point of failure in modern product development: the expensive and ever-widening gap between your design vision and your final, shipped product.&lt;/p&gt;

&lt;p&gt;Every team in this industry experiences the same friction. Your talented UX designers create intuitive, user-centric visions. Your skilled backend engineers build powerful, robust systems. And in between, there's a chasm. This is where projects go to die. It's where timelines get bloated with endless rework cycles, where your final product becomes a compromised version of the original idea, and where your investment in a great user experience evaporates during a painful implementation phase.&lt;/p&gt;

&lt;p&gt;For years, we've tried to patch this gap with more meetings, more documentation, and more project managers. But you can't patch a foundational problem. You need a bridge.&lt;/p&gt;

&lt;p&gt;That bridge is the &lt;strong&gt;UX Engineer&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  It’s an Evolution, Not Just Another Role
&lt;/h3&gt;

&lt;p&gt;This isn't about adding another headcount to the roster; it's about a strategic &lt;strong&gt;evolution of your front-end capability&lt;/strong&gt;. A traditional front-end developer is often tasked with simply implementing a design. A UX Engineer is tasked with being the &lt;strong&gt;steward of the user's experience&lt;/strong&gt; at the most critical junction—where design and code become one. They are the hands-on architects who ensure the product you envisioned is the product your users actually get.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Strategic Value of a UX Engineer
&lt;/h3&gt;

&lt;p&gt;Here is the tangible impact they will have on your team and your product from day one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;They De-Risk Your Investment Before a Line of Code is Written.&lt;/strong&gt; A UX Engineer acts as a critical &lt;strong&gt;"gatekeeper"&lt;/strong&gt;, validating designs for technical feasibility from the very beginning. This proactive step alone eliminates the most common cause of rework, saving you countless hours of wasted engineering and design time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;They Build a Scalable Foundation for Future Growth.&lt;/strong&gt; Their primary output is often a robust &lt;strong&gt;Design System&lt;/strong&gt;. This isn't just a style guide; it's a library of pre-built, reusable, and experience-tested components. It's a force multiplier that makes all future development faster, more consistent, and cheaper.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;They Engineer a Superior 'Feel' for Your Product.&lt;/strong&gt; In a competitive market, how a product &lt;em&gt;feels&lt;/em&gt; is a key differentiator. A UX Engineer is a specialist in &lt;strong&gt;Interaction Design &amp;amp; Development (IxD)&lt;/strong&gt;. They engineer the fluid animations, transitions, and micro-interactions that make a product feel intuitive and delightful, not just functional.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;They Create a More Efficient Engineering Workflow.&lt;/strong&gt; By defining the &lt;strong&gt;API requirements&lt;/strong&gt; for the front-end &lt;em&gt;before&lt;/em&gt; the backend team begins their work, the UX Engineer removes the classic bottleneck where the front-end is forced to wait or work around a backend that wasn't built with their needs in mind.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, a UX Engineer doesn't just write code. They align your teams, eliminate friction, and ensure that the quality of your user experience is a foundational part of your engineering culture, not an afterthought.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is a UX Engineer?
&lt;/h2&gt;

&lt;p&gt;A UX Engineer is a hands-on technical leader and specialist who operates at the precise intersection of design and engineering. Their primary responsibility is to ensure the user's experience is flawlessly translated from a conceptual design into a high-quality, interactive, and technically sound product. They are not passive implementers; they are proactive architects and stewards of the front-end experience.&lt;/p&gt;




&lt;h3&gt;
  
  
  Core Competencies &amp;amp; Skillset
&lt;/h3&gt;

&lt;p&gt;A UX Engineer possesses a unique, niche skillset that allows them to bridge the gap between design and engineering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High-Fidelity, Interactive Prototyping:&lt;/strong&gt; They are masters of engineer-focused prototyping tools (like UXPin) that allow them to build more than just static images. They create functional blueprints that simulate complex interactions and states, validating the user experience before development begins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mastery of Front-End Frameworks:&lt;/strong&gt; First and foremost, they are expert engineers with a deep command of modern front-end frameworks and technologies. This is the foundation upon which all their other skills are built.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deep Familiarity with Design Systems:&lt;/strong&gt; They are both students and creators of design systems. They have an expert understanding of established systems like Material Design and Apple's Human Interface Guidelines, allowing them to build upon best practices and maintain consistency.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Key Responsibilities &amp;amp; Activities
&lt;/h3&gt;

&lt;p&gt;On any given project, a UX Engineer's time is focused on these four critical, value-driving activities:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Design Validation &amp;amp; Feasibility Analysis:&lt;/strong&gt; Acting as a critical &lt;strong&gt;"checkpoint"&lt;/strong&gt; or &lt;strong&gt;"gatekeeper,"&lt;/strong&gt; the UX Engineer partners with designers early in the process. They assess technical constraints, validate the feasibility of interaction concepts, and ensure the final design is buildable without compromising the integrity of the user experience or the stability of the underlying system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design System Engineering &amp;amp; Maintenance:&lt;/strong&gt; A primary responsibility is the architecture, construction, and maintenance of the product's Design System. They build the library of robust, reusable, and accessible UI components that serve as the single source of truth for both designers and other engineers, accelerating development and ensuring product-wide consistency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interaction Design (IxD) &amp;amp; Development:&lt;/strong&gt; The UX Engineer is responsible for bringing the interface to life. They engineer the fluid animations, state transitions, and micro-interactions that define the product's "feel." This focus on IxD is what elevates an interface from merely functional to truly intuitive and delightful.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Front-End API &amp;amp; Data Contract Definition:&lt;/strong&gt; Working proactively, the UX Engineer analyzes the needs of the validated user interface and communicates the specific data requirements to the backend team &lt;strong&gt;before&lt;/strong&gt; they begin development. This ensures the backend is built to serve the user experience from day one, eliminating bottlenecks and preventing the front-end from being constrained by a misaligned data structure.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>ux</category>
      <category>uxdesign</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Here's Why I Have Chosen to Leave the Design Industry in Singapore</title>
      <dc:creator>Danny Chen</dc:creator>
      <pubDate>Thu, 21 Aug 2025 04:49:26 +0000</pubDate>
      <link>https://dev.to/danny_chen/heres-why-i-have-chosen-to-leave-the-design-industry-in-singapore-294</link>
      <guid>https://dev.to/danny_chen/heres-why-i-have-chosen-to-leave-the-design-industry-in-singapore-294</guid>
      <description>&lt;p&gt;Hey everyone! I suppose you can say that this article has been in the works since 2016. Yeah, I began noticing those early signs and patterns in the industry years ago, but it seemed like at that time, no one in the design industry was ready to listen or hear what I have to say yet (even as a certified Thought Leader 🤦‍♂️🤷‍♂️). And so, I continued to remain in the shadow for the years to come, quietly making notes and observations about where the wind was going to blow 🌬.&lt;/p&gt;

&lt;p&gt;Now, almost a decade later, I am ready to draw some conclusions. I believe the timing is also right. I believe this is perhaps the time that the design industry is &lt;strong&gt;READY&lt;/strong&gt; to sit up and finally listen.&lt;/p&gt;

&lt;p&gt;I've spent nearly 20 years of my career in Singapore. I've always considered it a privilege that I was born here and have remained here for most of my life. We have amazing government leaders and systems that are considered to be the best in the world. In fact, I am proud to call myself a Singaporean for many of those reasons. But that doesn't mean that everything about us, as a country or society, is great. And that is especially true when it comes to our design industry.&lt;/p&gt;

&lt;h2&gt;
  
  
  Singapore's Design Industry has Lost Its Edge
&lt;/h2&gt;

&lt;p&gt;Here's the reality that we often don't want to face or admit to. Forget about the media for a moment and consider the facts on the ground. For years, we have enjoyed relative success and have earned the prestigious title of being called the "Innovation Hub" of the world. When it comes to the design industry, man, we are at the very top of the world. Okay, may not always, but consistently, Singapore's design industry has always been among the top in the world.&lt;/p&gt;

&lt;p&gt;We might not have natural resources, but the one thing we've always had, was the pool of TOP Design Talents. The reason why so many businesses and companies want to invest here isn't just because of our stability as a nation, but because of the talent pool that we provide. If we took the world's combined top design talents (not wealth, but knowledge and skills), Singapore would be among the top 1% of the world. Well, at least that is what it used to be. That has stopped being true for a few years now. Signs that we are already slipping.&lt;/p&gt;

&lt;p&gt;And it's true. We've enjoyed that success for some time now. But sadly, it is also true that we are quickly losing our edge. In fact, we might've already lost it for a while and we just didn't want to face that reality. It's almost like living in &lt;strong&gt;self-denial&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Going From a Talent Destination to a Waystation
&lt;/h2&gt;

&lt;p&gt;In the past decade or so, I have witnessed and observed our tiny, little prosperous nation go from being a talent destination to a waystation. Most of the Top Design Talents I know aren't interested in staying anymore. They see Singapore as the place to grow, to learn, to discover their fullest potential. And once they have gotten what they needed, they would leave. The same is also true for a lot of our local top design talents.&lt;/p&gt;

&lt;p&gt;After nearly a decade of observing those patterns and trends, I'm here to give the Singapore Design industry a warning message:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"If we do not change course and make the necessary adjustments soon, by 2030, Singapore will experience a 60% turnover rate of our top design talents (both local and foreign)."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Time to Welcome the Top Emerging Markets in Digital &amp;amp; Product Design
&lt;/h2&gt;

&lt;p&gt;For the past decade or so, I have been seeing the early signs of design communities around the world picking up pace. While Singapore was leading, it was getting complacent at the top and slowing down. But for these other markets, they are much hungrier, and have the kind of drive that we, Singapore's design industry has lost along the way.&lt;/p&gt;

&lt;p&gt;That is also why I've chosen to focus the next stage of my life's work on these emerging markets from &lt;strong&gt;Sao Paulo&lt;/strong&gt;, Brazil, all the way to &lt;strong&gt;Lagos&lt;/strong&gt;, Nigeria. It is NOT a matter of IF, they will exceed Singapore's design industry in innovation and new design ideas, it is only a matter of WHEN. And from what I can tell, that can happen very soon. All they needed is a &lt;strong&gt;BOOST&lt;/strong&gt;. Frankly, since I'm no longer needed here as much, it seemed like the right time to finally shift my focus elsewhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  No. 1 Sao Paulo, Brazil 🇧🇷
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fewcspqoj27g23r52kfsh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fewcspqoj27g23r52kfsh.jpg" alt="Sao Paulo currently has the greatest promise in terms of where it's design industry is heading." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For years, I have been closely watching and observing some of the global trends and industry shifts happening. And one thing that is becoming extremely clear now is that São Paulo's design industry is ripe for that push. With San Francisco's digital scene fading into oblivion and Singapore's design industry reaching a stagnation, the industry's top spot has become vacant, leaving the doors wide open for São Paulo to become the next design/innovation capital of the world.&lt;/p&gt;

&lt;p&gt;More and more of the next-generation design ideas are now coming out of São Paulo, and I'm honestly very excited to see where that will lead in the next 5 years.&lt;/p&gt;

&lt;h3&gt;
  
  
  No. 2 Shenzhen, China 🇨🇳
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp29330w6366fri1w46nv.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp29330w6366fri1w46nv.jpeg" alt="Shenzhen may have been better known for it's semiconductor boom in recent years, but it's design industry is also fast catching on." width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the last decade or so, Shenzhen has become this semiconductor/electronics capital of the world. Far exceeding many of the other countries from around the world. But the one industry that nobody would've thought to pay attention to, was their digital &amp;amp; product design industry. They have been like an underdog in this story, and for years, quietly building themselves up to a point where they can start to compete with the rest of the market. By 2024, nearly 30% of the world's top design talents are now coming out of China. That says a lot about where the country is heading when it comes to the digital &amp;amp; product design market.&lt;/p&gt;

&lt;h3&gt;
  
  
  No. 3 Riga, Latvia 🇱🇻
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdkg76g3whsz4t6ryp2f5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdkg76g3whsz4t6ryp2f5.png" alt="In EU itself, Riga's design community might seem small in comparison, but it's never always about the size of the community." width="800" height="599"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've had my share of interacting, mentoring and guiding some of the designers within the Riga design community over the years. If there is one thing I can say about their community, it is that they have this passion that I haven't seen in a long time from my own design community here in Singapore. I feel like we've lost that passion somewhere along the way. We've stopped taking risks because we're afraid of what it might mean when we fail. Maybe it is time we learn something from our friends in the Riga design community.&lt;/p&gt;

&lt;h3&gt;
  
  
  No. 4 Lima, Peru 🇵🇪
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjevro6bosz62fsyg7cwy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjevro6bosz62fsyg7cwy.jpg" alt="Lima, Peru features one of the fastest growing digital &amp;amp; product design communities in South America" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's often a misconception to look at the biggest cities and most technologically advanced nations and cities and think that that is where you will find the best designers and engineers. But in my experience, sometimes, the most promising talents tend to come from the least expected places on earth. And Lima (Peru) has that. They might be small in size when compared to the rest of the world, but they have been steadily expanding over the years. Here's what I like about the design community in Lima, being a small community, they aren't afraid to try new things. That's the thing about being a small community, you know where you stand on the world stage, and you don't feel that need to constantly prove yourself. Instead, it is much easier to channel all that energy into creating new and often interesting ideas. You can't be afraid to fail and to try again. That is how we can keep innovating.&lt;/p&gt;

&lt;h3&gt;
  
  
  No. 5 Lagos, Nigeria 🇳🇬
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx8lj3hp0980yo35mxm1k.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx8lj3hp0980yo35mxm1k.jpg" alt="2nd only to Sao Paulo, Lagos features a community of digital &amp;amp; product designers that are perhaps more hungry to learn and grow than any other place on the planet" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In recent years, I have been seeing a steady uptick of designers and engineers from Lagos, Nigeria, reaching out over LinkedIn. Many of them are not afraid to ask questions. There is something truly refreshing about their deep hunger to learn. There is no such thing as a stupid question because when we ask, we learn from it. Second to a city like São Paulo, the design community in Lagos is perhaps one of the hungriest communities in the world. And I see that as an amazing attribute. It is also one of the things that I think my local Singaporean design community has lost as well. We're not as hungry as we once were. And that is sad to watch.&lt;/p&gt;




&lt;h2&gt;
  
  
  Beginning My Lifelong Work of Lifting Other Design Communities Up
&lt;/h2&gt;

&lt;p&gt;And so this is where I am today. I'm beginning to look out into the world around me, and I'm seeing many of our sisters and brothers in the design communities looking for that opportunity to learn and to keep growing. A boost that would help push them over the edge into the leading pole position.&lt;/p&gt;

&lt;p&gt;Where Singapore's design industry has lost its hunger, passion and willingness to learn and take risks, I see all of these other design communities around the world picking up the precise qualities that we have lost along the way.&lt;/p&gt;

&lt;p&gt;And I know that this has presented an opportunity for a real industry shake-up. I will say this one thing: Within the next 3 to 5 years, Singapore will &lt;strong&gt;NO LONGER&lt;/strong&gt; be the leader when it comes to design and innovation.&lt;/p&gt;

&lt;p&gt;The only real question we must ask ourselves now is, &lt;em&gt;"How long will it take before we finally wake up?"&lt;/em&gt;, &lt;em&gt;"How far behind do we want to be when the time comes that we are no longer leading the industry, but just a follower?"&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ux</category>
      <category>inclusion</category>
      <category>frontend</category>
      <category>career</category>
    </item>
    <item>
      <title>We are here to announce officially that our pronouns are now "we/us", "they/them". We are a collective of FIVE DISTINCT brothers. We are done hiding ourselves from the world. #comingout🏳️‍🌈 #we #us</title>
      <dc:creator>Danny Chen</dc:creator>
      <pubDate>Wed, 06 Aug 2025 09:28:36 +0000</pubDate>
      <link>https://dev.to/danny_chen/we-are-here-to-announce-officially-that-our-pronouns-are-now-weus-theythem-we-are-a-1lff</link>
      <guid>https://dev.to/danny_chen/we-are-here-to-announce-officially-that-our-pronouns-are-now-weus-theythem-we-are-a-1lff</guid>
      <description></description>
      <category>lgbtq</category>
      <category>representation</category>
      <category>devpride</category>
      <category>announcement</category>
    </item>
    <item>
      <title>Let Me Tell You a Story About the Origins of the Humble Breadcrumb and Visual Indicators as We Know It Today</title>
      <dc:creator>Danny Chen</dc:creator>
      <pubDate>Sun, 03 Aug 2025 13:44:45 +0000</pubDate>
      <link>https://dev.to/danny_chen/let-me-tell-you-a-story-about-the-origins-of-the-humble-breadcrumb-and-visual-indicators-as-we-know-3bjf</link>
      <guid>https://dev.to/danny_chen/let-me-tell-you-a-story-about-the-origins-of-the-humble-breadcrumb-and-visual-indicators-as-we-know-3bjf</guid>
      <description>&lt;p&gt;Let me start by first asking you a question, &lt;em&gt;"What do you know about the origins of the humble breadcrumb visual indicator?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I am pretty sure that by now, I would've gotten like a thousand different answers 😂.&lt;/p&gt;

&lt;p&gt;But let me tell you the real story of how Mr Breadcrumb first came about.&lt;/p&gt;

&lt;h2&gt;
  
  
  "I want my customers to know where they are on the website as they are browsing it."
&lt;/h2&gt;

&lt;p&gt;The origin stories of the humble breadcrumb wasn't what you would imagine. It wasn't born in a multi-million dollar lab, or some university dorm room. Instead, it was born from something rather...ordinary. Something that you might not have even expected to look.&lt;/p&gt;

&lt;p&gt;Back in 2006, I was working on an eCommerce website project for a client. And during the testing stages, she told me that she wanted her customers to have a sense of knowing where they are as they are browsing through her website. Now, back then, there wasn't such a thing as a breadcrumb link yet.&lt;/p&gt;

&lt;p&gt;So, I accepted the feedback, and went home to crack my brain 🧠 over how to help make that a reality. One night, I was going to the fridge to grab an ice cream 🍨 and as I was closing the fridge door, I noticed the sticker label that was still stuck to the door. You know how when you buy a new fridge and they would come with all these shiny little stickers??? Yeah, that one.&lt;/p&gt;

&lt;p&gt;Right there, right at the bottom, I saw a row of arrow-like progress indicator. They were trying to use it to describe the different modes, or different features, honestly, I don't remember that part well, I do remember seeing an arrow indicator that ran from the left-to-right. And it has slightly different colours, but used the same colour tone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mr Breadcrumb was Born
&lt;/h2&gt;

&lt;p&gt;And just like that, a light bulb went off inside my head. And when I finally got back to my desk with my ice cream and extreme excitement, I began sketching what would become the very first Breadcrumb visual indicator in the world. And well, everywhere that I look, I see him everywhere. Honestly, I am the proudest parent knowing that my little design inspiration is now being used by billions of people all over the world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Here Comes the Wizard 🪄
&lt;/h2&gt;

&lt;p&gt;In the following year of 2007, I had a chance to work on an online student registration form. Now you must bear in mind that back then, these forms are looooonnnnnggg...sorry, I had to add that for dramatic effect 😅&lt;/p&gt;

&lt;p&gt;Point being, these registration pages can span multiple pages and God were there many fields!!! Seriously..one page takes a student 10..maybe 15 minutes to finishing filling up. Anybody remember that experience in the early to mid-2000s???&lt;/p&gt;

&lt;p&gt;Anyway, after the truly successful delivery of the project (we got very positive reviews and feedbacks from the client FYI...no errors, no bugs...they couldn't find a single one). And even during the live registration period, the portal never crashed either. NOT EVEN ONCE.&lt;/p&gt;

&lt;p&gt;But that is not what I really wanted to tell you... 😅 (Sorry, blame it on my ADHD)&lt;/p&gt;

&lt;h2&gt;
  
  
  From Breadcrumbs to Form Wizards
&lt;/h2&gt;

&lt;p&gt;Having had some successful deployments under my belt and having had some practice of implementing the breadcrumb indicator across several web projects, I felt it was time to test my limits and abilities. So thinking about that recent online registration form project, I wanted to take it and experiment with an idea. And I thought 💭 to myself, &lt;em&gt;"What if we can shorten the length of those forms/pages and then split it into steps?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So, I began to test the idea out and it looks alright at first. But then I noticed something similar, the student wouldn't know where or which part/section of the form they are filling up. So, I added section headers, and step indicators. And now, 20 years later, I see my work literally everywhere! I see them in checkout pages, I see them in flight booking pages, I see them in...oh yeah, Accordions, ever wondered how they started?? It's right above.&lt;/p&gt;

&lt;h2&gt;
  
  
  True Innovation Can Be Found in Everyday Ordinary Things..Like That Sticker on the Fridge
&lt;/h2&gt;

&lt;p&gt;And here's where I really want to end my NUCLEAR TRUTH BOMB 💣 tonight. Most of the time, designers and engineers think that in order to create a groundbreaking, or revolutionary idea, they have to experiment for months and years, or even thinking that it might require some expensive equipment, hardware, or a lab.&lt;/p&gt;

&lt;p&gt;Come on! Just look at our humble little Mr. Breadcrumb. HE CAME FROM A FRIDGE STICKER. 😏😏😏😏😏&lt;/p&gt;

&lt;p&gt;And from there, we have our...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Form Wizards&lt;/li&gt;
&lt;li&gt;Step Indicators&lt;/li&gt;
&lt;li&gt;Flow/Process Charts&lt;/li&gt;
&lt;li&gt;Accordions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes, all you really need is one fridge sticker to change the world.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>mobile</category>
      <category>ux</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Thank you to the DEV Community team &amp; the whole community itself for allowing folks like me to have a way to share my voice. Today, I just got featured among the "Top Voices in the UX Industry" by Dan Maccarone of UX Collective.</title>
      <dc:creator>Danny Chen</dc:creator>
      <pubDate>Wed, 30 Jul 2025 09:30:02 +0000</pubDate>
      <link>https://dev.to/danny_chen/thank-you-to-the-dev-community-team-the-whole-community-itself-for-allowing-folks-like-me-to-have-4563</link>
      <guid>https://dev.to/danny_chen/thank-you-to-the-dev-community-team-the-whole-community-itself-for-allowing-folks-like-me-to-have-4563</guid>
      <description></description>
      <category>webdev</category>
      <category>frontend</category>
      <category>ux</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Production-Ready? Really?? Or Just Copious Amounts of Glue &amp; Duct-Tape? | The Lovable Reality Check</title>
      <dc:creator>Danny Chen</dc:creator>
      <pubDate>Thu, 24 Jul 2025 01:35:00 +0000</pubDate>
      <link>https://dev.to/danny_chen/production-ready-really-or-just-copious-amounts-of-glue-duct-tape-the-lovable-reality-check-2d99</link>
      <guid>https://dev.to/danny_chen/production-ready-really-or-just-copious-amounts-of-glue-duct-tape-the-lovable-reality-check-2d99</guid>
      <description>&lt;p&gt;Scene: Monday morning. A parent tries to book their child into &lt;strong&gt;“Math Excellence Tuition Centre.”&lt;/strong&gt; The new website was built and shipped last week—Lovable AI, of course.&lt;/p&gt;

&lt;p&gt;Parent: &lt;em&gt;“Hi, I tried booking my son for Friday’s class, but the website says he’s already attended... next month?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Center Admin (scrolling dashboard): &lt;em&gt;“Oh, uh, sometimes it does that. The AI is ‘future-predictive’. Try refreshing the page?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Parent: &lt;em&gt;“Now it says there are 3 seats left, then 15, then negative 2. Also, my payment just went through twice.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Center Admin: &lt;em&gt;“Great! That means the payment API integration is working—twice as fast as before.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Parent: &lt;em&gt;“There’s no confirmation email, and I can’t find the ‘undo’ button. Also, the app logged me out, but the booking still shows as ‘pending’. Should I try again?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Center Admin (smiling nervously): &lt;em&gt;“Uh... Let me ask our product manager.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Product Manager (appears, carrying laptop and coffee): &lt;em&gt;“That’s just the AI learning. Our team shipped this in 2 days! Lovable even said it was production-ready. Ignore the warnings—most users don’t see those anyway. And if it really breaks, just email us. We’re fastest to $100M, you know.”&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  All Aboard the Hyper-Train: The Lovable Illusion
&lt;/h2&gt;

&lt;p&gt;Speed sells. That’s why every other LinkedIn post is flexing on &lt;em&gt;“shipping in a weekend,”&lt;/em&gt; &lt;em&gt;“10x productivity,”&lt;/em&gt; or being &lt;em&gt;“the fastest to $100M.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Lovable and similar tools want you to believe that the only thing between you and success is how quickly you can ship.&lt;/p&gt;

&lt;p&gt;But let’s be honest: &lt;strong&gt;Speed without substance is just a train to nowhere.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Recently, I saw someone compare &lt;em&gt;“vibe coding”&lt;/em&gt; to gambling—and it’s not far off. You throw some AI code at a wall, spin the roulette wheel, and hope you land on &lt;em&gt;“production-ready.”&lt;/em&gt; Sometimes it works, sometimes it doesn’t. But is that how you want to run your business? In the real world, that’s like playing Russian roulette—with a loaded revolver pointed at the temple of your business. Are you really ready to spin and pull that trigger?&lt;/p&gt;

&lt;p&gt;Tools like Lovable can absolutely help you ship something faster than ever before. Heck, even I was impressed when I first tried using it to experiment with some ideas 💡 that I had.&lt;/p&gt;

&lt;p&gt;But what they can’t do—and what most users never stop to ask—is the most important question of all:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;“Why are we building this?”&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No AI tool can answer that for you. And when you’re riding the hyper-train, it’s dangerously easy to forget.&lt;/p&gt;

&lt;h2&gt;
  
  
  What “Production-Ready” Actually Means (Hint: It’s Not Just a Demo or a Working Prototype either)
&lt;/h2&gt;

&lt;p&gt;When I first played with Lovable, I was blown away. I pitched it a Pomodoro-inspired app idea, and—like magic—there it was: a working app, spun up in an afternoon.&lt;/p&gt;

&lt;p&gt;A few tweaks, some feedback loops, and it did exactly what it said on the tin: it shipped &lt;em&gt;something&lt;/em&gt; fast.&lt;/p&gt;

&lt;p&gt;But then the illusion cracked.&lt;/p&gt;

&lt;p&gt;What I had wasn’t &lt;em&gt;“production-ready”&lt;/em&gt;. Heck, it wasn’t even something I’d trust myself (or anyone else) to use past that initial wow moment.&lt;/p&gt;

&lt;p&gt;The MVP worked, sure. But MVP isn’t even a full prototype, let alone an app I’d stake my reputation on.&lt;/p&gt;

&lt;p&gt;Second attempt: same story. I tried to build something closer to my real ambitions. Lovable got me an MVP...and then it could not progress further.&lt;/p&gt;

&lt;p&gt;No auth, no proper error handling, no battle-tested backend.&lt;br&gt;
It’s a cool trick for demos, but &lt;em&gt;“production-ready”&lt;/em&gt;? Not by a long shot.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Tools: Where They Shine, Where They Absolutely Don’t
&lt;/h2&gt;

&lt;p&gt;Here’s the truth: if it weren’t for AI, I wouldn’t have shipped my last project in five weeks. It would’ve taken me three months, maybe more.&lt;/p&gt;

&lt;p&gt;Tools like GPT-4.1 (and yes, even Lovable and its cousins) are incredible for turning ideas into something tangible.&lt;/p&gt;

&lt;p&gt;They’re the perfect platforms for rapid prototyping, ideation, and that first dopamine hit of seeing your vision take shape.&lt;/p&gt;

&lt;p&gt;Honestly? You don’t need a CS degree, or even much coding knowledge, to get a “working” demo out the door now.&lt;/p&gt;

&lt;p&gt;Things I spent 15–20 years learning, these tools can now do it in seconds. That’s powerful. That’s &lt;em&gt;democratizing&lt;/em&gt;. I salute that.&lt;/p&gt;

&lt;p&gt;But let’s not kid ourselves: what’s impressive for a hackathon or side project is not what you want holding up your actual business when real users (and real money/investments) are on the line.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Day in the Life: When the Glue Starts to Melt
&lt;/h2&gt;

&lt;p&gt;Take my own &lt;a href="https://dev.to/d2d_weizhi/from-user-to-builder-how-i-built-a-pagebuilder-in-5-weeks-2oif"&gt;PageBuilder project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Week one, with GPT-4.1 as my co-pilot, I whipped up a demo so fast 💨 it felt like cheating. Drag-and-drop worked. Editing flowed. UI looked shiny.&lt;/p&gt;

&lt;p&gt;I was riding the hyper-train, smiling all the way.&lt;/p&gt;

&lt;p&gt;Then I started testing.&lt;/p&gt;

&lt;p&gt;Suddenly, the wheels came off.&lt;/p&gt;

&lt;p&gt;Weird bugs, edge cases, subtle UI breakage, data vanishing when you least expect it.&lt;/p&gt;

&lt;p&gt;The demo that looked &lt;em&gt;“production-ready”&lt;/em&gt; for next Monday? By Saturday, it was a haunted house of quirks. In fact, my client and I had to agree that the project needed more time to be built properly [better].&lt;/p&gt;

&lt;p&gt;This is the &lt;strong&gt;trap&lt;/strong&gt;: trusting the illusion that the tool can do it all for you.&lt;/p&gt;

&lt;p&gt;It’s like building your dream house on clay. Sure, it looks fine until the first big storm.&lt;/p&gt;

&lt;p&gt;And there will be storms 🌪️ 🌀 🌊.&lt;/p&gt;

&lt;p&gt;No matter how good the AI, &lt;strong&gt;the human factor still matters&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You need to know when to question, when to stress-test, and when to say, &lt;em&gt;“This isn’t ready—yet.”&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The “Production-Ready” Checklist (for Real Businesses, Not Just Investors)
&lt;/h2&gt;

&lt;p&gt;Speaking as a seasoned UX engineer and front-end developer for over 20 years, I can tell you: there’s so much more to building a production-level app or website than just patching together code with glue and scissors ✂️. Even if you slap on a mountain of duct tape, you’re still left with something fragile—something that’s bound to fall apart when the first real storm hits.&lt;/p&gt;

&lt;p&gt;We all saw this during the pandemic. Businesses everywhere scrambled to go online overnight. The result? Too many platforms and tools rushed to market, not properly tested or built, and it led to a tidal wave of bad customer experiences, and, in many cases, real business pain.&lt;/p&gt;

&lt;p&gt;So before you trust your business (or reputation) to the next &lt;em&gt;“production-ready”&lt;/em&gt; app, here’s a simple checklist to measure if it’s truly up to the task:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Category&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;What It Really Means&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Does Your App Pass?&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Auth/Security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Secure logins, no obvious XSS/injection holes, permissions handled cleanly&lt;/td&gt;
&lt;td&gt;☐ Yes ☐ No ☐ “Soon…”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;App doesn’t crash, users get clear error messages and can recover&lt;/td&gt;
&lt;td&gt;☐ Yes ☐ No ☐ “Kinda…”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Integrity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No lost data, no “ghost” entries, proper validation on inputs&lt;/td&gt;
&lt;td&gt;☐ Yes ☐ No ☐ “Mostly?”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;API Integration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Real APIs, not just dummy or static data; robust fallback on failure&lt;/td&gt;
&lt;td&gt;☐ Yes ☐ No ☐ “Well…”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Responsive UI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Works across devices, not just desktop Chrome&lt;/td&gt;
&lt;td&gt;☐ Yes ☐ No ☐ “Maybe?”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Accessibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Navigable with keyboard, readable by screenreader, color contrast is legit&lt;/td&gt;
&lt;td&gt;☐ Yes ☐ No ☐ “Oops…”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Undo/Redo/History&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Users can undo mistakes or roll back changes&lt;/td&gt;
&lt;td&gt;☐ Yes ☐ No ☐ “Coming soon”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;State Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;App recovers gracefully from refreshes, accidental closes, or back/forward&lt;/td&gt;
&lt;td&gt;☐ Yes ☐ No ☐ “???”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Export/Import&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Users can export/import data in standard formats (CSV, JSON, etc.)&lt;/td&gt;
&lt;td&gt;☐ Yes ☐ No ☐ “Next sprint”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Loads quickly, no timeouts or infinite spinners as usage grows&lt;/td&gt;
&lt;td&gt;☐ Yes ☐ No ☐ “It’s… fine?”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Docs/Onboarding&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A new dev (or even you) can understand/extend the codebase in a week&lt;/td&gt;
&lt;td&gt;☐ Yes ☐ No ☐ “Just ChatGPT it”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hosting/DevOps&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Versioned deploys, reliable uptime, easy rollback if shit hits the fan&lt;/td&gt;
&lt;td&gt;☐ Yes ☐ No ☐ “Pray”&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Issuing the Challenge: “Lovable Production Community Challenge”
&lt;/h2&gt;

&lt;p&gt;So here’s my offer, and my challenge, to the Lovable community.&lt;/p&gt;

&lt;p&gt;Starting today, I’m launching a new article series: &lt;strong&gt;Lovable Production Community Challenge.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In each article, I’ll review selected apps submitted by community members, built using Lovable, shipped and live in the wild. You’ll get a public, honest, and (most importantly) fair critique. I won’t sugarcoat my professional opinions, but I will provide constructive feedback and suggestions for improvement.&lt;/p&gt;

&lt;p&gt;My goal isn’t to shame. Instead, it’s to help you get your ideas and visions closer to the real results you want. If your app passes the production-ready checklist, I’ll give you a shoutout 📣 here. If not? At least you’ll walk away with clear, actionable steps to raise your game.&lt;/p&gt;

&lt;p&gt;But here’s the real challenge. And this one’s for Lovable as a company:&lt;/p&gt;

&lt;p&gt;Are you ready to put your platform to the test?&lt;/p&gt;

&lt;p&gt;If you’re not, then please, stop using words like &lt;em&gt;“shipping”&lt;/em&gt; and &lt;em&gt;“production-ready”&lt;/em&gt; in your advertising and marketing. Because once users break through the illusion, it’s only a matter of time before that loaded revolver comes full circle, and you discover there’s a real cost to overhyping what you can’t deliver.&lt;/p&gt;

&lt;p&gt;Reputation is everything in tech. Once lost, it’s almost impossible to get back.&lt;/p&gt;

&lt;p&gt;🎤 (mic drop)&lt;/p&gt;

</description>
      <category>lovable</category>
      <category>ai</category>
      <category>webdev</category>
      <category>mobile</category>
    </item>
    <item>
      <title>From User to Builder: How I Built a PageBuilder in 5 Weeks</title>
      <dc:creator>Danny Chen</dc:creator>
      <pubDate>Sat, 19 Jul 2025 05:03:42 +0000</pubDate>
      <link>https://dev.to/danny_chen/from-user-to-builder-how-i-built-a-pagebuilder-in-5-weeks-2oif</link>
      <guid>https://dev.to/danny_chen/from-user-to-builder-how-i-built-a-pagebuilder-in-5-weeks-2oif</guid>
      <description>&lt;h2&gt;
  
  
  Personal Note &amp;amp; Opening
&lt;/h2&gt;

&lt;p&gt;Hey guys, it has truly been a minute since I've actually truly written something on this platform. And I don't just mean coming here for a quick post and checking in with the rest of the dev community. I mean, having something substantive to share and write about.&lt;/p&gt;

&lt;p&gt;Some time ago, I also wrote something brief about how I wanted to take a step back from posting/sharing stuff online so that I could really focus on doing the actual work. The truth is, I've always felt more comfortable doing the work and then allowing the end results of that work to speak for me. I've never really been comfortable with the idea of self-promotion and self-advertising.&lt;/p&gt;

&lt;p&gt;After weeks of not sharing much, I'm happy to be back this weekend to discuss a recent freelance project I've been working on. As part of an inspiration, I've also decided to title my project as &lt;strong&gt;"Satori PageBuilder"&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you truly want to know why I chose that word "Satori", well, then I suppose you'd have to follow me here and stay tuned for my future posts when I'm finally ready to debut and share my custom collection of "Satori UI". It is still a work-in-progress, so I don't think I am fully ready to showcase the suite of UI components just yet.&lt;/p&gt;

&lt;p&gt;In a nutshell, "Satori" is a Japanese word that also means &lt;em&gt;"enlightened"&lt;/em&gt; or &lt;em&gt;"to be enlightened"&lt;/em&gt;. It also means &lt;em&gt;"understanding"&lt;/em&gt;. It is a word that resonated deeply with everything that I have experienced in my nearly 20 years as a freelancer.&lt;/p&gt;

&lt;p&gt;Alright, my goal for today is not to dive into that topic, so we'll have plenty of time in the near future to discuss more about that. For now, let's just focus on my recent developer experience when it comes to building my first ever PageBuilder (and crafting a better drag-and-drop UX)&lt;/p&gt;

&lt;h2&gt;
  
  
  A Blogger’s Perspective
&lt;/h2&gt;

&lt;p&gt;Before I even wrote a single line of code for the Satori PageBuilder, I have considered myself to be a Power User of the web. For as long as I could remember, I have been using platforms like blogger.com, myspace, WordPress (currently still), Weebly, WIX, Facebook's Notes, LinkedIn's article publisher, and so many more. I've quite literally tried everything there is on the web, trying to find not only the most comprehensive page-building tool available, but also one that would provide the kind of smooth UX that content creators like myself needed. At my height as a featured technical writer, I even paid for premium page-building plugins/tools. But I was never truly impressed by any single one of them. For the longest time, it always seemed like they all had their strengths, but there is still something missing in terms of the UX that they could provide.&lt;/p&gt;

&lt;p&gt;Even though I could've tried to build my own PageBuilder, I never really saw the need, or felt the incentive to want to build something from scratch. Not when there are readily available tools and plugins to choose from. Sure, maybe paying $75 a year or $200+ a year for a top plugin might seem a little much at times, I just never really felt the need to do it.&lt;/p&gt;

&lt;p&gt;At least not until my freelance client approached me about 5 weeks ago.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Build a PageBuilder?
&lt;/h2&gt;

&lt;p&gt;When my client first approached me with this idea that he had about wanting to build a PageBuilder for their current Software-as-a-Service (SaaS), I was honestly excited (and maybe a little intimidated) by the opportunity that it presented. You see, after spending so many years working on complex Content Management Systems (CMS), I've never had a real opportunity to build a PageBuilder of my own. I mean, you know my background by now. I've used them for a long time, but I've never actually built one.&lt;/p&gt;

&lt;p&gt;But here I am, thinking to myself, &lt;em&gt;"Hey, you know what, I've built far more complex full-scale websites that can cost up to 30K - 40K. I mean, how hard would it be to build a PageBuilder...right...?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;(Yes, go ahead and laugh. I am sure every dev has had that thought at least once. The most famous last words ever 😅🤦‍♂️)&lt;/p&gt;

&lt;p&gt;Spoiler: There’s a world of difference between using something and building it. We, as users, only see what the creators want us to see. The real complexity lurks beneath the surface. I mean, I've been pursuing and practising UX and front-end development for close to two decades, and I already know this. &lt;/p&gt;

&lt;p&gt;To my client’s credit, he trusted me even after I told him I had never built one before. I think that mutual honesty and trust are what got this project off the ground; that, and a shared drive to make something better than just &lt;em&gt;“good enough.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzk04nwyzf6ofihsuc37g.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzk04nwyzf6ofihsuc37g.jpg" alt="This is the little Pi that could. I lost count of how many times it froze, but with a mix of stubbornness, perseverance, and a lot of grit, 70% of Satori PageBuilder's v1.0 was built on it." width="800" height="1062"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sidebar: &lt;em&gt;For context, I was juggling this with a post-diploma course, a final school project, and working off a Raspberry Pi 4B with 8GB of RAM (yes, really). Oh, and the project started just as my ADHD brain 🧠 was hitting peak summer chaos. If not for AI tools like ChatGPT (shoutout 📣 to GPT-4.1), I honestly don’t think I’d have gotten to v1.0 in five weeks. Five years ago, this would have been a two- or three-month job, easy.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There’s something funny about building modern software on much less capable hardware. While you’re waiting for your little Pi to catch up (or unfreeze, again), you start to appreciate every edge you can get. For me, that secret weapon turned out to be AI and not just for writing code.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Real Workflow: Human × AI
&lt;/h2&gt;

&lt;p&gt;If you’d told me a year ago that I’d be pair-programming with an AI every day, I probably would’ve laughed. I was a late adopter, not because I doubted the tech, but because I was honestly worried I’d become too dependent, or maybe lose some of that &lt;em&gt;“scrappy problem solver”&lt;/em&gt; instinct.&lt;/p&gt;

&lt;p&gt;But it wasn’t until my Raspberry Pi kept freezing, and I found myself facing problem after problem with limited hardware, that I truly began to appreciate just how powerful an AI companion could be.&lt;/p&gt;

&lt;p&gt;What surprised me most is that GPT-4.1 became more than just a coding assistant. It was there for my morning routine, regularly helping me plan my day, break down sprint goals, and brainstorm solutions before I even wrote a single line of code. (I’ve even got a photo of my “morning mission brief” routine with my tablet and a cup of ginger tea — that’s how real it became!)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Favqiqch7d4p25nzyq1ze.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Favqiqch7d4p25nzyq1ze.jpg" alt="My morning routine for the last few weeks" width="800" height="602"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Without a laptop or a MacBook, every morning I’d wake up early, grab my tablet, and spend 1.5 to 2 hours working through tasks with GPT-4.1. That meant I could clear up to 10–20% of my daily workload before breakfast. Add that up, and in a typical week, it’s like gaining a whole extra day of progress — all because of a smart workflow and a bit of AI magic.&lt;/p&gt;

&lt;p&gt;AI wasn’t just there for code. It was my brainstorming partner, my sounding board, and, honestly, my best teammate &amp;amp; development buddy during the solo grind.&lt;/p&gt;

&lt;p&gt;Frankly, there were days when the stress from personal challenges and my chronic anxiety disorder felt overwhelming. On those days, this “AI tool” became something more. It helped me to maintain my sanity, gave me a sense of momentum, and let me fight that much harder to maintain the highest possible quality in my work, even when everything else felt shaky and uncertain.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI Can’t Ship v1.0: Only You Can
&lt;/h3&gt;

&lt;p&gt;There was a moment, right in the middle of this journey, that really stuck with me. I had just finished my first working version of the drag-and-drop feature—the part that lets you move content around visually. Before diving into the next part of the project that also required a similar drag-and-drop experience, I decided to stop for a second and take a breath.&lt;/p&gt;

&lt;p&gt;Up until then, I’ll be honest: I had gotten pretty good at searching for code snippets, leaning on GPT-4.1 for “how-to” solutions, and pasting fixes directly into my files. But it was in that in-between moment, code working but not understood, that it hit me:&lt;/p&gt;

&lt;p&gt;I was operating on blind faith. The code worked, but I couldn’t really tell you why it worked. That was a humbling self-realisation.&lt;/p&gt;

&lt;p&gt;So I did something that’s easy to skip when you’re in a rush: &lt;strong&gt;I stepped back&lt;/strong&gt;. I made myself pause and dive into how the critical parts of &lt;code&gt;react-dnd&lt;/code&gt; actually functioned, beyond the tutorials and the AI’s step-by-step instructions.&lt;/p&gt;

&lt;p&gt;Don’t get me wrong: GPT-4.1 was incredible at unblocking me, showing me solutions, and helping me debug when I was stuck. But the “aha” moments, the true leaps in UX, only happened when I put in the effort to &lt;em&gt;understand&lt;/em&gt; what I was building. It was on me to bring the critical thinking, the problem-solving, and the empathy to craft a drag-and-drop experience that felt good to real users.&lt;/p&gt;

&lt;p&gt;AI can help you get there faster, but it can’t make those calls for you. The &lt;em&gt;craft&lt;/em&gt; still has to come from you.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Craftsman’s Approach, Even in 2025
&lt;/h2&gt;

&lt;p&gt;One of the biggest lessons I’ve learned, especially when you’re doing your best to build something truly meaningful on modest hardware, is that speed isn’t everything. The most rewarding (and honestly, the best) work happened when I permitted myself to slow down.&lt;/p&gt;

&lt;p&gt;It’s easy to get caught up chasing velocity—cranking out features as fast as possible, especially when everything around you is moving at startup pace. But there’s something deeply satisfying about slow, thoughtful, and deliberate development. That’s when real progress happens. Sometimes, top, premium quality work requires us to take a more &lt;em&gt;“surgical approach”&lt;/em&gt; rather than speed.&lt;/p&gt;

&lt;p&gt;Over time, I found myself naturally settling into a set of philosophies: a kind of personal development manifesto. Here are a few that guided me through this project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Go slow to go far.&lt;/strong&gt; Sometimes the fastest way to finish is to resist the urge to rush.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Embrace “surgical” work.&lt;/strong&gt; When you can’t brute-force your way through, you learn to make every move count.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Patterns are your friend, but not your prison.&lt;/strong&gt; Find workflows and rituals that work for you, but don’t be afraid to evolve them as the project changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reflect often.&lt;/strong&gt; The best ideas come when you pause to ask, &lt;em&gt;“Is this still the right [best] way?”&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;(Right around Sprint 3.6.*, I had discovered a workflow that was working extremely well for me, so I decided to note it down in Notion)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;### Dev Workflow&lt;/span&gt;

With the assistance of ChatGPT 4.1 these last few days, we have 
managed to developed a proven workflow when working on this Sprint.
&lt;span class="p"&gt;
1.&lt;/span&gt; Refer to Unlayer
&lt;span class="p"&gt;2.&lt;/span&gt; Add relevant properties to &lt;span class="sb"&gt;`blockData`&lt;/span&gt;.
&lt;span class="p"&gt;3.&lt;/span&gt; Create default values under &lt;span class="sb"&gt;`block-factory.tsx`&lt;/span&gt;
&lt;span class="p"&gt;4.&lt;/span&gt; Pass properties from &lt;span class="sb"&gt;`renderContentBlock`&lt;/span&gt;
&lt;span class="p"&gt;5.&lt;/span&gt; Set global state in block’s &lt;span class="sb"&gt;`onClick`&lt;/span&gt; handler.
&lt;span class="p"&gt;6.&lt;/span&gt; Update content blocks with style generation.
&lt;span class="p"&gt;7.&lt;/span&gt; Add &lt;span class="sb"&gt;`set[Content]Config`&lt;/span&gt; to &lt;span class="sb"&gt;`contentManager`&lt;/span&gt;.
&lt;span class="p"&gt;8.&lt;/span&gt; Create &lt;span class="sb"&gt;`[Content]Styles`&lt;/span&gt; or &lt;span class="sb"&gt;`[Content]Options`&lt;/span&gt; section.
&lt;span class="p"&gt;9.&lt;/span&gt; Add conditional rendering to &lt;span class="sb"&gt;`sidebar-panel.tsx`&lt;/span&gt;
&lt;span class="p"&gt;10.&lt;/span&gt; Add serialization function to export to &lt;span class="sb"&gt;`cssContent`&lt;/span&gt; 
    format/structure.
&lt;span class="p"&gt;11.&lt;/span&gt; Add the selector value to raw HTML.
&lt;span class="p"&gt;12.&lt;/span&gt; Pass/extract &lt;span class="sb"&gt;`blockData`&lt;/span&gt; values for JSON export/import (not 
    styles, but options, configurations).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;But here’s the real talk: there were plenty of days when I was seriously tempted to rush. Financial pressures were very real because this was my main source of income, and I genuinely needed more work. Some days, I felt desperate for that next gig. And yet, as tempting as it was to sprint toward that “finish line”, I made myself slow down and focus on doing the job right, not just fast.&lt;/p&gt;

&lt;p&gt;That doesn’t mean my output was perfect. I still got feedback. I still had to make corrections and improvements. But here’s what stood out: &lt;strong&gt;I spent absolutely ZERO time on rework.&lt;/strong&gt; In five weeks, there were hardly any moments where I had to tear things down and start over. That wasn’t luck, it was the direct result of taking my time, thinking things through, and not cutting corners.&lt;/p&gt;

&lt;p&gt;If there’s one ethos that I kept coming back to, it’s this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Building something fast doesn’t make you the best. Building it once and building it well almost guarantees you’ll be faster than the next guy, who’s stuck redoing their work again and again to get it right."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Reality of Crafting a (Not Just Using) Drag-and-Drop UX
&lt;/h2&gt;

&lt;p&gt;Most of us have used drag-and-drop before. Making it feel good as a builder? That’s a whole different challenge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visualizing Drag-and-Drop: My “Mail Sorting Warehouse” Moment
&lt;/h3&gt;

&lt;p&gt;I remember one day, sketching out a mail-sorting warehouse as a metaphor for how blocks should move around in a page builder. Every block is a package, every drop area is a sorting bin, and my job was to make sure each package landed in the right place, in the right order—every time. (I’ve included the photo of that sketch below. Trust me, sometimes the most “developer” thing you can do is grab a pen and draw it out.)&lt;/p&gt;

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

&lt;h3&gt;
  
  
  The Building Blocks: &lt;code&gt;useDrag&lt;/code&gt; vs. &lt;code&gt;useDrop&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;If you’re new to building drag-and-drop UIs, there are two key concepts:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drag sources&lt;/strong&gt; (&lt;code&gt;useDrag&lt;/code&gt;): &lt;/p&gt;

&lt;p&gt;These are the things you pick up and move (like a package on the warehouse floor).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="nx"&gt;isDragging&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;dragRef&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDrag&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BLOCK_TYPE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// e.g., "CARD", "BLOCK", etc.&lt;/span&gt;
  &lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Info about what's being dragged (its "passport")&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;uniqueBlockId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BLOCK_TYPE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;yourBlockData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;monitor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;isDragging&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;monitor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isDragging&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Then attach dragRef to the element you want to be draggable&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dragRef&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ...content... */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Drop targets&lt;/strong&gt; (&lt;code&gt;useDrop&lt;/code&gt;): &lt;/p&gt;

&lt;p&gt;These are the places you can drop those things.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="nx"&gt;isOver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;canDrop&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;dropRef&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDrop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BLOCK_TYPE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// What kinds of items this drop area accepts&lt;/span&gt;
  &lt;span class="na"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;monitor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// What happens when something is dropped here&lt;/span&gt;
    &lt;span class="nf"&gt;handleDrop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;monitor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;isOver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;monitor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isOver&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;canDrop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;monitor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;canDrop&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Attach dropRef to your drop area&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dropRef&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ...drop area... */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You don’t always have to pick just one. Sometimes, the same component needs to be both a drag source and a drop target. (Though, heads up: combining them isn’t always the most performant move—found that out the hard way.) But it’s possible, and sometimes necessary.&lt;/p&gt;

&lt;h3&gt;
  
  
  What’s in a Payload? (Or: Don’t Travel Without Your Documents)
&lt;/h3&gt;

&lt;p&gt;Every time you pick up a block and move it, there’s an invisible “travel document” (aka: payload) that tells the system what you’re holding. It’s like crossing borders—you need the right paperwork.&lt;/p&gt;

&lt;p&gt;Here’s a (simplified) pseudocode version of the kind of “passport” I used for each drag action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;BlockPayload&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// If moving between columns, reference the other column's block ID&lt;/span&gt;
  &lt;span class="nl"&gt;otherColumnBlockId&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// The type of block (e.g., "TEXT", "IMAGE", or a custom type)&lt;/span&gt;
  &lt;span class="nl"&gt;blockType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Unique ID for the specific block being moved&lt;/span&gt;
  &lt;span class="nl"&gt;designBlockId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Optional: reference to the DOM element (for focus, toolbars, etc.)&lt;/span&gt;
  &lt;span class="nl"&gt;blockRef&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;RefObject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// The main content data (think: the package you’re delivering)&lt;/span&gt;
  &lt;span class="nl"&gt;contentBlock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ContentBlock&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This payload acts as a contract between every drag-and-drop operation. If your travel document has missing information, you’re not getting through airport security.&lt;/p&gt;

&lt;h3&gt;
  
  
  Drop Areas vs. Drop Zones: Designing the “Where” of Drag-and-Drop
&lt;/h3&gt;

&lt;p&gt;When you’re building a drag-and-drop interface, not every drop area is created equal. There’s a difference between a general drop area (like an entire canvas or a column) and a drop zone (those specific, often highlighted spots that say, “Drop right here!”).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drop Areas:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;Here’s a look at one of my early drop areas: the &lt;code&gt;ColumnCell&lt;/code&gt;. Notice how the whole area gets a highlight when you’re hovering a block over it. This is a “general” drop area—it covers the entire cell, and it’s great for quickly tossing blocks into columns without worrying about the exact position.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Designated DropZones:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;Now, compare that with a drop zone: here, you see a custom button block drag preview hovering over a very specific, thin &lt;code&gt;DesignDropZone&lt;/code&gt;. These are the little hot spots between blocks that let you insert content precisely where you want it, not just &lt;em&gt;“somewhere in the column.”&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Behind the Scenes: The Code
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;General drop areas&lt;/strong&gt; (like the canvas or a whole column) use &lt;code&gt;useDrop()&lt;/code&gt; hooks that accept almost any block, and typically just “append” or “insert” at the end or into an empty space.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Designated drop zones&lt;/strong&gt; are more targeted: each one is paired with a specific spot in your content structure (e.g., “insert between block A and block B”). The code calls a specialised &lt;code&gt;handleDrop()&lt;/code&gt; function that knows exactly where in the array/tree to insert the new block.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why does this matter?
&lt;/h4&gt;

&lt;p&gt;Because, as a user, you want control: sometimes “just drop it anywhere” is fine, and sometimes you need pixel-perfect precision. As a builder, you have to design for both.&lt;/p&gt;

&lt;h4&gt;
  
  
  What I Learned:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;General drop areas are great for speed and simplicity, but they don’t give users fine-grained control.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Designated drop zones take more work to implement, but they deliver a much better experience when it comes to reordering and inserting content “just so.”&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Visually, it helps to make drop zones bold and obvious when they’re active, so users know exactly where their block will land.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; &lt;em&gt;The best UIs often blend both: use general drop areas for new users or “quick add,” and designated drop zones for power users who care about details.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Inspiration: Why I Built My Own &lt;code&gt;designTree&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;It was around late June, specifically during &lt;strong&gt;Session 3.5.4: Cross-Canvas Block Management &amp;amp; UX Finalization&lt;/strong&gt; (17th–20th June, according to my now-priceless dev logs), that I hit a key insight:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I needed a reliable, centralised way to track every block’s state, position, and relationships in my PageBuilder.&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  The Problem
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Most UI builders rely on deeply nested arrays/objects to model layouts. That works, but it can get messy, especially when you want to move blocks around, sync between canvas and columns, or just find a block quickly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I realised what I needed was a “single source of truth” for everything in the design view. In the same way a browser uses a &lt;strong&gt;DOM tree&lt;/strong&gt; to keep track of every node, I needed a &lt;strong&gt;design tree&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  The Solution: Enter &lt;code&gt;designTree&lt;/code&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I decided to use a flat &lt;code&gt;Map&amp;lt;contentBlockId, DesignTreeEntry&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fast lookups&lt;/strong&gt;: Find any block instantly—no recursion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy updates&lt;/strong&gt;: When a block moves, update its entry. No headaches.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Syncable&lt;/strong&gt;: It’s easy to sort and sync the tree with your visual content, so what you see is always what’s really there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single-level&lt;/strong&gt;: No complex nesting—every block is a top-level entry, with metadata about its current “location” (canvas vs columns).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  Pseudocode: What’s in a &lt;code&gt;DesignTreeEntry&lt;/code&gt;?
&lt;/h4&gt;

&lt;p&gt;Here’s a simplified, commented version of the interface I designed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;DesignTreeEntry&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Unique ID for the content block (stays the same, no matter where you move it)&lt;/span&gt;
  &lt;span class="nl"&gt;contentBlockId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// The ID for the design wrapper (can change if you move it between places)&lt;/span&gt;
  &lt;span class="nl"&gt;designBlockId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Ref to the outer block (used for drag, hover, focus, etc.)&lt;/span&gt;
  &lt;span class="nl"&gt;designBlockRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RefObject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLDivElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Ref to the actual content (like the text or image component)&lt;/span&gt;
  &lt;span class="nl"&gt;contentBlockRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RefObject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// What kind of content block is this? ("heading", "columns", etc.)&lt;/span&gt;
  &lt;span class="nl"&gt;contentBlockType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Where is this block right now? ("canvas" or "columns")&lt;/span&gt;
  &lt;span class="nl"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;columns&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// If inside columns, what is the column index? (optional)&lt;/span&gt;
  &lt;span class="nl"&gt;colIndex&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Think of it as the "address book" for every block in my builder. At any time, I can open the &lt;code&gt;designTree&lt;/code&gt;, find a block by its unique content ID, and know exactly where it is, what it is, and how to interact with it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Why It Matters
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;No matter how complex the UI or how many blocks you drag around, everything stays in sync and easy to debug.&lt;/li&gt;
&lt;li&gt;Whenever content is saved, deleted, or modified, the &lt;code&gt;designTree&lt;/code&gt; ensures that the visual state matches the data model, hence no “ghost blocks,” no lost content.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro tip&lt;/strong&gt;: &lt;em&gt;If you’re ever struggling with managing complex layouts, try a flat map/tree approach. It might just save your sanity (and your sprint deadlines).&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Lessons Learned (and Why I Log Everything Now)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Slow Is Not Lazy. It’s Precision!
&lt;/h3&gt;

&lt;p&gt;In a world that prizes speed, taking things slow can feel almost rebellious. But here’s what I learned:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Slow” isn’t lazy, and it isn’t “whatever happens, happens.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s about being deliberate. Methodical. Surgical.&lt;/p&gt;

&lt;p&gt;It's about moving with intention, purpose, not just momentum.&lt;/p&gt;

&lt;p&gt;Some of my most valuable progress came when I forced myself to slow down, step back, and really think about what I was building, not just rushing to check an item on the list.&lt;/p&gt;

&lt;p&gt;Slow is how you avoid avoidable mistakes, reduce rework, and create something you can be truly proud of.&lt;/p&gt;

&lt;h3&gt;
  
  
  Our Circumstances Don’t Define Us. Our Work Does.
&lt;/h3&gt;

&lt;p&gt;It’s tempting to let our circumstances or limitations (hardware, health, life stress, whatever) become part of our professional identity. I’ll admit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building a production-ready PageBuilder on a Raspberry Pi wasn’t glamorous.&lt;/li&gt;
&lt;li&gt;Balancing freelance stress with personal challenges was hard.&lt;/li&gt;
&lt;li&gt;There were days I felt like an underdog, or even an impostor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But I also learned something important:&lt;br&gt;
None of those things define who you are or how your work will be remembered.&lt;/p&gt;

&lt;p&gt;What does matter is what you create, the value you deliver, and the quality you stand behind.&lt;/p&gt;

&lt;p&gt;Let your results speak for you, not your gear, your LinkedIn profile, or your backstory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dev Logs: The Game-Changer I Didn’t See Coming
&lt;/h3&gt;

&lt;p&gt;Here’s a confession:&lt;/p&gt;

&lt;p&gt;For most of my freelance career (even during my best, highest-paid years), I never kept a dev log.&lt;/p&gt;

&lt;p&gt;Not once. It just never seemed necessary, or I convinced myself I’d remember everything.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;I was wrong.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fts03e8npm4vmxgnwwfvg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fts03e8npm4vmxgnwwfvg.png" alt="Part One: My detailed dev log, and this is only for one sprint session." width="800" height="803"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Keeping detailed, daily dev logs on this project changed everything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It kept me organised and honest.&lt;/li&gt;
&lt;li&gt;It made handover and debugging a breeze.&lt;/li&gt;
&lt;li&gt;It let me track my growth, spot patterns, and catch recurring pain points before they became real problems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fflat5dmi54hw36gi7ljp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fflat5dmi54hw36gi7ljp.png" alt="Part One: My detailed dev log, and this is only for one sprint session." width="800" height="819"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;(Fun fact: When I tried to upload a screenshot of my dev log, dev.to told me the image was too big. Had to split it in half. Turns out, documenting everything means you sometimes outgrow the platform’s limits. Worth it!)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Honestly? I wish I’d started doing this years ago.&lt;/p&gt;

&lt;p&gt;(And yes, while I’m happy to share more snippets or screenshots, I’ll probably keep the full logs private for now — there’s something powerful about having a “for your eyes only” record of the real process.)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;: &lt;em&gt;Even if you’re not a “journaling” type, try it for one project. You might be surprised by how much clarity and momentum it brings.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  AI &amp;amp; The Truth About “Vibe Coding” vs. Real Development
&lt;/h2&gt;

&lt;p&gt;There’s a lot of hype, memes, and honestly, a fair bit of panic lately about the rise of “vibe coding”. There is this idea that you can just vibe with an AI and crank out production apps without understanding a thing. Some folks claim that developers are becoming obsolete, or that tools like Lovable (or the latest “no-code” darling) can do it all for you.&lt;/p&gt;

&lt;p&gt;Let’s get real for a second.&lt;/p&gt;

&lt;p&gt;As someone who’s worked through every line of my own PageBuilder—on a Raspberry Pi, no less—I can tell you one thing that is true:&lt;/p&gt;

&lt;p&gt;AI is an incredible partner. It accelerates your workflow, offers new perspectives, and lets you clear roadblocks faster than ever.&lt;/p&gt;

&lt;p&gt;But &lt;strong&gt;AI is not a replacement for craft, judgment, or actual experience&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vibe Coding vs. AI-Accelerated Development: What’s the Difference?
&lt;/h3&gt;

&lt;p&gt;The difference is &lt;em&gt;human guardrails&lt;/em&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Vibe Coding:
&lt;/h4&gt;

&lt;p&gt;This is when you blindly trust the AI to generate code, solutions, or even whole apps, without really understanding or questioning what’s happening. It can feel like magic…until you hit a wall, or something breaks in production, and you have no clue why.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It’s tempting, especially when you’re tired or in a hurry.&lt;/li&gt;
&lt;li&gt;I’ve fallen into this myself; earlier in this very project, when I realised I didn’t truly understand what I was building until I hit pause and dug in.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  AI-Accelerated Development:
&lt;/h4&gt;

&lt;p&gt;This is about &lt;em&gt;collaboration&lt;/em&gt;, using AI as a partner, but bringing your own experience, curiosity, and care to the process.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You sanity-check every step.&lt;/li&gt;
&lt;li&gt;You ask “why,” not just “how.”&lt;/li&gt;
&lt;li&gt;You add empathy, judgment, and the willingness to slow down, refactor, or rethink a feature when it matters.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my experience, even with all the power of GPT-4.1 and similar tools, building something real, something you’d actually hand over to a client or deploy in production, remains a &lt;em&gt;shared effort&lt;/em&gt;. At best, it’s a 50/50 split:&lt;/p&gt;

&lt;p&gt;AI brings speed and breadth, but you bring depth, vision, and the responsibility to make it &lt;em&gt;right&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Bottom line:&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;You can’t vibe your way to excellence. Tools are just tools. It’s the human in the loop, the builder, the craftsperson, the one who cares, that makes the difference between shipping an app and shipping something that lasts.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What Makes a True UX Artisan in 2025?
&lt;/h2&gt;

&lt;p&gt;If there’s one thing I’ve learned: over all these years, in all these projects, it’s that the best builders are not just coders, or even designers. They’re &lt;em&gt;artisans&lt;/em&gt;. And the defining trait of a true UX artisan? &lt;strong&gt;Relentlessly thinking like the end user.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It’s a bit like a carpenter shaping a bespoke bench. He doesn’t just carve and assemble the wood—he sits on it, tests how it feels, then carves and sands some more. He keeps returning, tweaking, and reworking, not stopping until that bench isn’t just beautiful, but &lt;em&gt;comfortable&lt;/em&gt;, &lt;em&gt;usable&lt;/em&gt;, and &lt;em&gt;right&lt;/em&gt; for whoever sits down.&lt;/p&gt;

&lt;p&gt;Every meaningful UX I’ve helped to build started with that same quiet habit:&lt;/p&gt;

&lt;p&gt;I would put myself in the user’s shoes before writing a single line of code, and &lt;em&gt;again&lt;/em&gt; after every new feature.&lt;/p&gt;

&lt;p&gt;A UX artisan isn’t just a designer. We are the builders who take a vision or an idea and turn it into something better, layer by layer, always testing, always refining.&lt;/p&gt;

&lt;p&gt;When my freelance client came to me and said, &lt;em&gt;“I want something like Unlayer,”&lt;/em&gt; I didn’t just hear &lt;em&gt;“copy this.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I heard, &lt;em&gt;“Let’s craft the ideal PageBuilder, one that users will truly love.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So I drew on my past as a creator and a power user, asking,&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"What would make this the most comfortable, powerful, and joyful tool it could be?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And then, like that careful carpenter, I built, tested, refined, and rebuilt—until it didn’t just work, &lt;em&gt;it felt right&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A UX artisan isn’t satisfied with “it works.”&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;We keep shaping, testing, and caring, until it feels like it was made just for you.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Final Thoughts &amp;amp; An Invitation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  For Potential Clients &amp;amp; Collaborators
&lt;/h3&gt;

&lt;p&gt;My next big goal, a proper portfolio showcase (v2.0), is still on the horizon. I’m in no rush. When it’s ready, it’ll be something I can be truly proud of, not just something to tick a box.&lt;/p&gt;

&lt;p&gt;But this article?&lt;/p&gt;

&lt;p&gt;This was never meant as a detailed technical manual. It’s an inside look at how I work, think, and what I care about: my approach, my philosophy, my struggles, and what I’ve learned along the way.&lt;/p&gt;

&lt;p&gt;If you’re reading this as a founder, business owner, or potential collaborator:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I won’t pretend I can work for free right now. Life’s real, and I need the income.&lt;/li&gt;
&lt;li&gt;But I’m not only here for a paycheck. Some of my most meaningful collaborations have come from clients who paid less, but valued trust, transparency, and a shared mission.&lt;/li&gt;
&lt;li&gt;Yes, I hope to land those S$10K–S$20K projects one day soon. But I’m just as open to working with those who have tight budgets, if we’re aligned in vision and values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So if you’re looking for someone who cares as much about the journey as the result, someone who wants to build things that matter, let’s connect.&lt;/p&gt;

&lt;p&gt;You can always drop me an email if you have a project idea that you want to turn into reality, and we can discuss how to proceed. &lt;/p&gt;

&lt;p&gt;Reach me at &lt;a href="mailto:d2d.weizhi@gmail.com"&gt;d2d.weizhi@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  To My Fellow Developers, Makers, and Builders
&lt;/h3&gt;

&lt;p&gt;I want to leave you with this:&lt;/p&gt;

&lt;p&gt;You don’t need to be loud to shine.&lt;/p&gt;

&lt;p&gt;You don’t have to self-promote, boast, or go viral to prove your value. Sometimes, the most powerful thing you can do is focus on your craft, care deeply about your work, and let the results speak for themselves.&lt;/p&gt;

&lt;p&gt;Resilience, grit, and passion matter, especially when things are hard or when you’re building on a shoestring budget (or a Raspberry Pi!).&lt;/p&gt;

&lt;p&gt;If you ever feel like you’re struggling to stand out, or worried you’re not being noticed, remember:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Your best work will find its audience.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Focus on creating something real and meaningful.&lt;/p&gt;

&lt;p&gt;Let your craft speak for you. That’s how I’ve always tried to do it, and eventually, it'll speak louder than you ever could.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>frontend</category>
      <category>freelance</category>
    </item>
    <item>
      <title>Satori UI | PageBuilder v1.0 - Development Done</title>
      <dc:creator>Danny Chen</dc:creator>
      <pubDate>Sun, 06 Jul 2025 23:44:06 +0000</pubDate>
      <link>https://dev.to/danny_chen/satori-ui-pagebuilder-v10-development-done-3cnc</link>
      <guid>https://dev.to/danny_chen/satori-ui-pagebuilder-v10-development-done-3cnc</guid>
      <description>&lt;p&gt;Hey everyone! I want to apologise for my most recent disappearance and silence. Let's just say that the last 3-4 weeks of my life has been extremely crazy when it comes to managing my final school assignment as well as my first freelance project since making my official return to the industry in 2022.&lt;/p&gt;

&lt;p&gt;For this very first freelance project, I was determined to succeed where I had failed in the past. I wanted to leave nothing but the best possible impression with my now client (a former part-time employer). Over the past few weeks, I constantly reminded myself that as tempting as it was to want to rush/speed up towards the finish line, I have a stronger, deeper mandate to do this project well. By doing it well, it would help to protect the trust that my client already has in me. It would protect my own credibility/reputation. Most importantly, it would also help me to secure a pipeline of freelance work that could come from this one freelance client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Satori UI v1.0
&lt;/h2&gt;

&lt;p&gt;Satori is the name that I've decided on when it comes to curating and building my very own suite of custom UI components. For the first 10-15 years of my career, I did something similar and I named that collection of over 100 different UI components, "Blaze UI". Back then, I saw great UX as speed, performance and efficiency. So technically speaking, that usually means responsiveness, lazy loading of large datasets, and UI performance.&lt;/p&gt;

&lt;p&gt;But as I got older, and most certainly wiser, I've come to learn that speed is but an illusion. Sometimes you can appear to be traveling very fast, but if you are not heading in the right direction, you'll still end up ofcourse long before you realize what just happened. So, after nearly two decades of grit, perseverance and lessons, I chose "Satori", which in Japanese also means "enlightened", "understanding. Words that truly resemble everything that I believe in today.&lt;/p&gt;

&lt;p&gt;Satori UI is all about having this seamless, smooth flow. When a user interacts with Satori UI components, it makes them happy using them because it always feels like the UI is flowing with them, and not getting in the way. As someone that loved a minimalist-design, I chose to use a slightly non-flat/gradient background, coupled with a less obvious gray for my borders and then a tint of blue for the highlights/active areas. This helps to ensure that the UI components doesn't steal away the attention/focus of the user using the component. The main focus is always the content themselves.&lt;/p&gt;

&lt;p&gt;I will share a more detailed article about how I built a version 2 ("Satori") of my custom UI components collection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Satori PageBuilder v1.0
&lt;/h2&gt;

&lt;p&gt;When my freelancer client came to me recently expressing his interests to build a custom PageBuilder to the likes of Unlayer, I was truly excited by the prospect and possibilities. Considering my vast experiences as a front-end developer and UX engineer, I actually never had the opportunity to work on a PageBuilder-like project before. It's something I had always wanted to do, I just never got the opportunity. Until now.&lt;/p&gt;

&lt;p&gt;As with any new project, it is really important that as freelancers, we acknowledge that sometimes despite our best judgement and past experience, it can be tricky trying to accurately estimate the effort and time needed to work on something that we have no experience working with.&lt;/p&gt;

&lt;p&gt;So, I ended up needing to extending the project deadline twice. But that extension was totally worth it. It allowed me the time and space to do a much better job. At times, as tempted as I was to speed things through, I had to constantly remind myself that by speeding through, I run the risk of missing something, and that could be the one thing the client discovers during their own testing, and it would've ruined my reputation and credibility.&lt;/p&gt;

&lt;p&gt;So, I decided to instead slow down. I took my time (so to speak) to focus on doing what I do best.&lt;/p&gt;

&lt;p&gt;Even though the PageBuilder v1.0 is not perfect now. I would say that it no longer looks or feel like an MVP. In spite of it's quirks, this is finally a production-ready PageBuilder.&lt;/p&gt;

&lt;p&gt;All that is left is for me to preparing the documentations, do more testing, improvements/tweaks and ensure that I provide the best-in-class handover experience for the client's dev team. I'm only saying that because I've been doing this a long, long time. And I know that I am capable of doing something at that level. All I really needed was an opportunity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing - Open to Top-Tier Freelance Work
&lt;/h2&gt;

&lt;p&gt;Recently, with the ending of my part-time post-diploma course in UX Design &amp;amp; Management, I made a conscious decision in my mind that I was going to focus my time and energy full-time as a freelancer. Sure, it would be nice if a company would offer me a role in something permanent/full-time. But I won't sit around and hoping/wishing/chasing after something that has no guarantee. What is now guaranteed is that with my client's trust secured, I know I have secured a new pipeline of freelance work.&lt;/p&gt;

&lt;p&gt;On top of that, because I want to do this full-time, it also means that I will have more time and energy to work on other projects in parallel. Now, it also depends on how much I can handle full-time, but if I want to maintain that same highest-level quality/standards, I'm going to limit myself to working on just two projects at any one time. Anything more than two and I know my quality will start to suffer.&lt;/p&gt;

&lt;p&gt;If you are looking for a global freelance to work on a mobile/web project (web preferred for now), you can reach out to me at &lt;a href="mailto:%20d2d.weizhi@gmail.com"&gt;d2d.weizhi@gmail.com&lt;/a&gt;. Typical responses are usually within 24-48 hours.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>freelance</category>
      <category>portfolio</category>
      <category>react</category>
    </item>
    <item>
      <title>3 Reasons Why I Stuck with Progress Telerik for 19 Years</title>
      <dc:creator>Danny Chen</dc:creator>
      <pubDate>Tue, 27 May 2025 12:03:47 +0000</pubDate>
      <link>https://dev.to/danny_chen/3-reasons-why-i-stuck-with-progress-telerik-for-19-years-5gei</link>
      <guid>https://dev.to/danny_chen/3-reasons-why-i-stuck-with-progress-telerik-for-19-years-5gei</guid>
      <description>&lt;p&gt;Hey guys, so my Award as a Telerik Champion has finally arrived today. While this is my second year as a Progress Telerik Champion, it is my 10th year of collaborating with the company as an influencer and technical writer. More importantly, at the time of posting this, I'm officially 19 years and 5 months into advocating for and supporting Telerik's products.&lt;/p&gt;

&lt;p&gt;Without diving into my entire journey, I want to focus on &lt;strong&gt;THREE&lt;/strong&gt; reasons why I stuck with Progress Telerik for the past 19 years.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Developer Experience
&lt;/h2&gt;

&lt;p&gt;I have been using Telerik UI since 2006. One of my early impressions of using the UI components is that they are effortless to implement. I still recall their former slogan, &lt;em&gt;"For Developers, By Developers."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Long before the industry acknowledged the importance of UX and CX, Telerik, as a company (before Progress acquired it), was already focused on ensuring that its products were developer-centric. As a result, everything that they have created since then has become the de facto standard for other UI component libraries. They understood one of the most fundamental principles - &lt;strong&gt;by making the lives of developers easier, more efficient at work, then the product would be able to sell itself&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdnulcw5ml5cgajw0jkrv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdnulcw5ml5cgajw0jkrv.png" alt="After 19 years, they still manage to provide the best developer experience on the market." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Gold Standard for Online Technical Resources
&lt;/h2&gt;

&lt;p&gt;Does anyone still remember the early days of online technical resources and documentation? Do you still remember how it felt when some documentation was seriously lacking? Like the company creating the product didn't bother to invest the time and effort to explain how to properly and effectively use their products?&lt;/p&gt;

&lt;p&gt;I do. I still remember all those nights when I would be "forced" to support and use certain products that the company felt were necessary, but then it turned out to be very difficult to implement. To make matters worse, the product lacked well-written documentation, an API, and tutorials. I can't tell you how much time I wasted just trying to figure out the code and how it's supposed to work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8xbas6qzpktvvofvvx9s.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8xbas6qzpktvvofvvx9s.jpeg" alt="Everything you ever need to know to make the most of the UI components can be found in their online resources." width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But that never happened with Telerik. For as long as I have been using and supporting Telerik's products, their documentation and online resources have been the most comprehensive ones I have found among their competitors. &lt;/p&gt;

&lt;p&gt;To make things even better, their online demos and code samples are THE BEST on the market! I mean, seriously, just take a look at their &lt;strong&gt;"DOCS &amp;amp; DEMOs"&lt;/strong&gt; section and you'll quickly understand what I mean.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Best UI Component Suite for FEDs to Fast-track Their UX Skills
&lt;/h2&gt;

&lt;p&gt;One of the primary reasons I discovered and later stuck with Telerik is its strong connection to UX/UI design principles. Again, this was in 2006 when I first began discovering my own interests and passion for usability design. This was also at a time in the industry where most companies felt that a good usability design (UX) was just a "nice-to-have" thing. For me, I know almost immediately that what the folks at Telerik were doing then was on the right track. They were creating their UI components with UX in mind.&lt;/p&gt;

&lt;p&gt;As a front-end developer, I also recognised the value of utilising their UI suite in real-world projects. Since I began using and supporting their products, I have managed to implement Telerik UI components in more than 100 different projects, ranging from web, desktop to mobile apps (yes, they did support mobile UI components at one time). In every single one of those instances, clients were always delighted because their customers were happy.&lt;/p&gt;

&lt;p&gt;From the perspective of a UX Engineer today, I'd say that Progress Telerik's products are the ultimate gateway to fast-tracking UX skills and understanding for any front-end developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;By continuing to provide unwavering support for Progress Telerik's products, I hope to demonstrate that their UI suite will continue to remain the industry standard. One that other brands, like SyncFusion and DevExpress, will have to follow if they wish to achieve the same level of success and provide a much higher level of developer experience.&lt;/p&gt;

</description>
      <category>telerik</category>
      <category>frontend</category>
      <category>devrel</category>
    </item>
    <item>
      <title>I'm currently taking an Intermission/break from posting and sharing so that I can focus more on my work and studies. My part-time studies is in the final stretch, so I need to give it my full attention. #takingabreak</title>
      <dc:creator>Danny Chen</dc:creator>
      <pubDate>Tue, 20 May 2025 01:12:53 +0000</pubDate>
      <link>https://dev.to/danny_chen/im-currently-taking-an-intermissionbreak-from-posting-and-sharing-so-that-i-can-focus-more-on-my-4ijk</link>
      <guid>https://dev.to/danny_chen/im-currently-taking-an-intermissionbreak-from-posting-and-sharing-so-that-i-can-focus-more-on-my-4ijk</guid>
      <description></description>
      <category>productivity</category>
      <category>career</category>
    </item>
    <item>
      <title>The Power of Thinking..."I CAN"</title>
      <dc:creator>Danny Chen</dc:creator>
      <pubDate>Fri, 16 May 2025 07:45:20 +0000</pubDate>
      <link>https://dev.to/danny_chen/the-power-of-thinkingi-can-gbb</link>
      <guid>https://dev.to/danny_chen/the-power-of-thinkingi-can-gbb</guid>
      <description>&lt;p&gt;First off, I need to admit that despite my years of experience working on so many projects, there is one hurdle that I never quite got over - creating my own Chat UI. I've tried doing it several times in the past (mostly in my private tinkering). I sometimes thought, &lt;em&gt;"I think this is this, this weekend, I'm going to crack this and get it looking right."&lt;/em&gt; But no matter what, this is one of those UI features I could never get right.&lt;/p&gt;

&lt;p&gt;After years of attempting it, I eventually began to think to myself that maybe I'd never be able to crack this thing. So, I began to abandon that attempt...until today.&lt;/p&gt;




&lt;h2&gt;
  
  
  Adding a Group Discussion Feature to AceIt's Assignment Details page
&lt;/h2&gt;

&lt;p&gt;The first thing I really want to conquer was getting those chat bubbles right. So I started with the chat bubbles from the other senders in the Group Discussion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{/* Outermost layout will have a left align by default */}
&amp;lt;div className="flex-grow flex-col p-4 overflow-y-auto"&amp;gt;
  {/* Chat bubble from other senders */}
  &amp;lt;div className="flex mb-4"&amp;gt;
    &amp;lt;div className="flex items-start mr-4"&amp;gt; 
      {/* The contents of the chat bubble */} 
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The best way to look at this layout is that the outermost container is an entire row stretched across the group chat area.&lt;/p&gt;

&lt;p&gt;Like with most chatroom UIs, incoming messages will always start from the left of the UI. And when it comes to the contents of our chat bubbles, we want to ensure that everything is aligned to the top, so we use &lt;code&gt;items-start&lt;/code&gt; here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Contents to our Chat Bubble
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{/* Outermost layout will have a left align by default */}
&amp;lt;div className="flex-grow flex-col p-4 overflow-y-auto"&amp;gt;
  {/* Chat bubble from other senders */}
  &amp;lt;div className="flex mb-4"&amp;gt;
    &amp;lt;div className="flex items-start mr-4"&amp;gt; 
      {/* Next, we add our profile image. */}
      &amp;lt;div className="w-8 h-8 rounded-full overflow-hidden mr-2"&amp;gt;
        &amp;lt;Image 
          src="/female-student-chinese.jpg" 
          alt="Profile Picture" 
          width={50} 
          height={50} 
          className="object-cover" 
        /&amp;gt;
      &amp;lt;/div&amp;gt; 
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next thing we want is to include the user's profile image. This one here is quite straightforward. We want a fully rounded profile image, and it will be positioned to the start/left of the chat bubble.&lt;/p&gt;

&lt;p&gt;Next, we will add our message contents.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{/* Outermost layout will have a left align by default */}
&amp;lt;div className="flex-grow flex-col p-4 overflow-y-auto"&amp;gt;
  {/* Chat bubble from other senders */}
  &amp;lt;div className="flex mb-4"&amp;gt;
    &amp;lt;div className="flex items-start mr-4"&amp;gt; 
      {/* Profile Image here. */}

      &amp;lt;div className="bg-gray-200 rounded-lg p-3 max-w-xs"&amp;gt;
        &amp;lt;p className="text-xs font-medium text-gray-800"&amp;gt;Agnes Yeo&amp;lt;/p&amp;gt; 
        &amp;lt;p className="text-sm"&amp;gt;Hey everyone, just wanted to check in and see how the project's coming along!&amp;lt;/p&amp;gt;
        &amp;lt;span className="text-xs text-gray-500"&amp;gt;Tue 10:15 am&amp;lt;/span&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What About the User's Message Bubble?
&lt;/h3&gt;

&lt;p&gt;That is quite simple; we just need to make a few changes. Like most familial chat apps, as the sender/user, we don't need to display a profile image. So it will be just the message content itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="flex justify-end mb-4"&amp;gt;
  &amp;lt;div className="bg-blue-500 text-white rounded-lg p-3 max-w-xs ml-4"&amp;gt; 
    &amp;lt;p className="text-sm"&amp;gt;Hey Agnes! I'm making good progress on the research. How's the mood board coming along?&amp;lt;/p&amp;gt;
    &amp;lt;span className="text-xs text-gray-100"&amp;gt;Tue 10:45 am&amp;lt;/span&amp;gt; 
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Our Textarea for Typing, Sending and Attaching Stuff
&lt;/h3&gt;

&lt;p&gt;The most essential feature of any Chat UI is having the ability to type a message, hit Send, right? So we can't do without that functionality here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{/* Message Input Area */}
&amp;lt;div className="border-t border-gray-300 p-4 bg-white"&amp;gt; 
  {/* Use flex-col for vertical layout */}
  &amp;lt;div className="flex flex-col justify-start"&amp;gt;
    {/* Container for textarea and send button */}
    &amp;lt;div className="flex"&amp;gt; 
      &amp;lt;textarea 
        className="flex-grow resize-none border border-gray-400 rounded-md p-2 mr-2 focus:outline-none focus:ring focus:ring-blue-300 bg-gray-100" 
        placeholder="Type your message..."
      &amp;gt;&amp;lt;/textarea&amp;gt;
      &amp;lt;button className="flex bg-blue-500 text-white px-4 py-2 rounded-md self-start items-center justify-center ml-2"&amp;gt; 
        Send &amp;lt;SendHorizonal width={20} height={20} className="ml-1" /&amp;gt;
      &amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
    {/* Attachment button below */}
    &amp;lt;button className="bg-gray-300 rounded-md py-2 px-4 mt-2 flex items-center justify-center w-max"&amp;gt; 
      &amp;lt;Paperclip width={16} height={16} className="mr-1"/&amp;gt; Add Attachments
    &amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What is important here is that I've chosen to place the attachment in a separate flex row (layout-wise). The initial idea of placing it inside the textarea didn't work out very well. Plus I wanted to keep things simple and not overcomplicate things. So, this seems like the easiest solution.&lt;/p&gt;

&lt;p&gt;Once I get to the logic implementation stages, I'll add in a context menu for the Button. So it will present the student with a few options like attaching Images, Videos, Files and Links.&lt;/p&gt;

&lt;p&gt;At this point, I'm already feeling pretty confident and honestly quite pleased with myself. But I also felt something's still missing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Image Attachments and Modal Overlays...so, Let's Add Some!!
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="flex justify-end mb-4"&amp;gt;
  &amp;lt;div className="bg-blue-500 text-white rounded-lg p-3 max-w-xs ml-4"&amp;gt; 
    {/* Our message content remains here. */}

    {/* Container for attachment previews */}
    &amp;lt;div className="flex flex-row gap-x-2 mt-2"&amp;gt; 
      &amp;lt;div className="w-1/2 relative"&amp;gt; 
        {/* Add "relative" for image overlay */}
        &amp;lt;div className="relative aspect-square overflow-hidden rounded-md"&amp;gt;
          &amp;lt;Image 
            src="/sample-wireframes-01.jpg"
            fill={true}
            quality={90}
            alt="Mobile friendly wireframes" 
            className="object-cover w-1/2 aspect-square" 
          /&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div className="absolute inset-0 flex items-center justify-center opacity-0 hover:opacity-50 bg-gray-900 rounded-md transition duration-300"&amp;gt;
          {/* Expand icon */}
          &amp;lt;Expand className="text-white" size={32} /&amp;gt; 
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div className="w-1/2 relative"&amp;gt;
        &amp;lt;div className="relative aspect-square overflow-hidden rounded-md"&amp;gt; 
          {/* Image 2 */}
          &amp;lt;Image 
            src="/sample-wireframes-02.jpg"
            alt="Mobile friendly wireframes"
            quality={90}
            fill={true}
            className="object-cover w-1/2 aspect-square" 
          /&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div className="absolute inset-0 flex items-center justify-center opacity-0 hover:opacity-50 bg-gray-900 rounded-md transition duration-300"&amp;gt;
          {/* Expand icon */}
          &amp;lt;Expand className="text-white" size={32} /&amp;gt; 
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;span className="text-xs text-gray-100"&amp;gt;Thu 2:15 pm&amp;lt;/span&amp;gt; 
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've removed the &lt;code&gt;onClick&lt;/code&gt; event handler from the code snippet for now. The most important aspect is how I've laid out the attached images to the bottom of the message. I've ensured they each share half the width while filling out a square shape. Think of it like thumbnails.&lt;/p&gt;

&lt;p&gt;I've also included the &lt;code&gt;&amp;lt;Expand /&amp;gt;&lt;/code&gt; Lucide icons. They worked perfectly with the layout. The overlay will show nicely when a user mouseovers the images on a desktop browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up our Modal Overlay
&lt;/h3&gt;

&lt;p&gt;At first, I tried to place this overlay layout at the bottom of the section, but that somehow didn't quite work properly. So I decided to move it all the way to the top of the right panel. And now, it works perfectly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{/* Image Modal Overlay */}
{isShowImageModal &amp;amp;&amp;amp; (
  &amp;lt;div className="absolute left-0 top-0 w-full h-full z-40 items-center justify-center"
    style={{
      backgroundColor: "#000000AA"
    }}
  &amp;gt;
    {/* Container for image and controls */}
    &amp;lt;div className="relative"&amp;gt;  
      {/* Close button */}
      &amp;lt;button className="absolute top-4 right-4 z-50 text-white"&amp;gt; 
        &amp;lt;X size={32} onClick={() =&amp;gt; setIsShowImageModal(false)} /&amp;gt; 
      &amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;div className="w-[90%] h-[90%] opacity-100"&amp;gt;
      {/* Left Chevron button */}
      {currModalImage.includes("02") &amp;amp;&amp;amp; (
        &amp;lt;button 
          className="absolute top-[50%] left-5 z-50 text-white"
          onClick={() =&amp;gt; {
            if (currModalImage.includes("02")) {
              setCurrModalImage("/sample-wireframes-01.jpg");
            }
          }}
        &amp;gt; 
          &amp;lt;ChevronLeft 
            size={48} 
          /&amp;gt; 
        &amp;lt;/button&amp;gt;
      )}

      &amp;lt;Image src={currModalImage} alt="attachment image" fill style={{ objectFit: "contain" }} className="aspect-auto" /&amp;gt;

      {/* Right Chevron button */}      
      {currModalImage.includes("01") &amp;amp;&amp;amp; (
        &amp;lt;button 
          className="absolute top-[50%] right-5 z-50 text-white"
          onClick={() =&amp;gt; {
            if (currModalImage.includes("01")) {
              setCurrModalImage("/sample-wireframes-02.jpg");
            }
          }}
        &amp;gt; 
          &amp;lt;ChevronRight size={48} /&amp;gt;
        &amp;lt;/button&amp;gt;
      )}
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
)}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the overlay done, the next thing I needed to do was to add the Image to the overlay:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Image 
  src={currModalImage} 
  alt="attachment image" 
  fill 
  style={{ objectFit: "contain" }} 
  className="aspect-auto" 
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The props &lt;code&gt;fill&lt;/code&gt;, &lt;code&gt;style={{ objectFit: "contain" }}&lt;/code&gt; and &lt;code&gt;className="aspect-auto"&lt;/code&gt; helped to ensure that regardless of whether the photo/image is in a portrait or landscape mode, it would still fit nicely within the overlay's area.&lt;/p&gt;

&lt;p&gt;Next, we need to add our Chevrons (Left/Right) so that the user can easily navigate between the available images. For our UI prototype, we will go straight ahead and hard-code the values. But ofcourse, when it comes time to work on the logic, we will need a more dynamic way to handle this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{/* Left Chevron button */}
{currModalImage.includes("02") &amp;amp;&amp;amp; (
  &amp;lt;button 
    className="absolute top-[50%] left-5 z-50 text-white"
    onClick={() =&amp;gt; {
      if (currModalImage.includes("02")) {
        setCurrModalImage("/sample-wireframes-01.jpg");
      }
    }}
  &amp;gt; 
    &amp;lt;ChevronLeft 
      size={48} 
    /&amp;gt; 
  &amp;lt;/button&amp;gt;
)}

&amp;lt;Image src={currModalImage} alt="attachment image" fill style={{ objectFit: "contain" }} className="aspect-auto" /&amp;gt;

{/* Right Chevron button */}
{currModalImage.includes("01") &amp;amp;&amp;amp; (
  &amp;lt;button 
    className="absolute top-[50%] right-5 z-50 text-white"
    onClick={() =&amp;gt; {
      if (currModalImage.includes("01")) {
        setCurrModalImage("/sample-wireframes-02.jpg");
      }
    }}
  &amp;gt; 
    &amp;lt;ChevronRight size={48} /&amp;gt;
  &amp;lt;/button&amp;gt;
)}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The position of the Chevrons is worth highlighting/noting. Now, this is what I can think of using tailwindcss. Perhaps there might be a more effective way to do it. Gemini kind of broke down around this time (actually before I implemented them). I actually did this whole portion by myself without any help from Gemini, so I'm feeling pretty good about myself.&lt;/p&gt;

&lt;p&gt;Since I've added the conditional checks before rendering the Chevron buttons, I can simplify the internal logic by self-checking my own UI logic. So the final UI Chevron button should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{/* Right Chevron button */}
{currModalImage.includes("01") &amp;amp;&amp;amp; (
  &amp;lt;button 
    className="absolute top-[50%] right-5 z-50 text-white"
    onClick={() =&amp;gt; setCurrModalImage("/sample-wireframes-02.jpg")}
  &amp;gt; 
    &amp;lt;ChevronRight size={48} /&amp;gt;
  &amp;lt;/button&amp;gt;
)}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final Thoughts &amp;amp; Ideas
&lt;/h2&gt;

&lt;p&gt;So, guys, that's it for my Group Discussion section UI prototype. Frankly, I am pretty happy with how it all turned out. I am sure we can make more tweaks to enhance the UI further. Still, before I overcomplicate everything, the key objective at this stage of the project is to assess and identify any position UI issues before making the UI slightly more dynamic.&lt;/p&gt;

&lt;p&gt;A couple of ideas/next-steps on my mind:&lt;/p&gt;

&lt;p&gt;👨‍💻 I could eventually refactor the message bubbles and turn them into reusable components.&lt;/p&gt;

&lt;p&gt;👨‍💻 Once I get to the application logic, I will add the attachments selection.&lt;/p&gt;

&lt;p&gt;👨‍💻 Auto-scroll down to the latest message.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>react</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>How I (Almost) Outsourced My Brain to Gemini Pro</title>
      <dc:creator>Danny Chen</dc:creator>
      <pubDate>Wed, 14 May 2025 13:18:56 +0000</pubDate>
      <link>https://dev.to/danny_chen/how-i-almost-outsourced-my-brain-to-gemini-pro-430n</link>
      <guid>https://dev.to/danny_chen/how-i-almost-outsourced-my-brain-to-gemini-pro-430n</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;"Have you ever been so reliant on a tool that you forgot how to function without it?  Yeah, me neither... until I met Gemini."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Okay, so, recently, I think some of you might have experienced something quite similar - there is some kind of issue regarding the clipboard functionality of Gemini Pro. I must admit that Gemini/ChatGPT has become a deeply integrated part of my life so much so that I stopped working on my current showcase project when the copy-and-paste feature wasn't working. I felt...stuck. Yeah, I know it sounds silly now when I say it out loud, but for a few days, I didn't touch the coding (plus, I was also dealing with something on the personal front).&lt;/p&gt;

&lt;p&gt;My point is that this was one of those examples of what I want to discuss today—our overreliance on specific tools to the point that we can no longer do what we're supposed to know how to do when we didn't have those tools. Do you remember a time before we had Gemini? Or Lovable? Or Firebase Studio? I do.&lt;/p&gt;

&lt;h2&gt;
  
  
  The StackOverflow Copy-and-Paste Era
&lt;/h2&gt;

&lt;p&gt;Remember those days when we'd frantically Google coding solutions, praying for a Stack Overflow answer that would magically fix everything? Yeah, those were the days... or were they?  I'll admit, I've been guilty of blindly copying and pasting code snippets more times than I'd like to admit. There was this one time I was wrestling with a particularly nasty JavaScript bug... like the early days of trying to customise a JS DatePicker so that it would display as "dd/MM/YYYY" when the only JS DatePicker was based on the US formatting of "MM/dd/yyyy". Let's just say it involved a lot of head-scratching, a few choice curse words, and a renewed appreciation for the importance of reading documentation.&lt;/p&gt;

&lt;p&gt;The thing is, readily available solutions can be a double-edged sword. On one hand, they're incredibly helpful for saving time and learning from others. But on the other hand, they can lull us into a false sense of security. It's easy to think, &lt;em&gt;"Someone else has already solved this, so I don't need to strain my brain cells."&lt;/em&gt; Add to that the rise of "vibe coding" – where the focus is on flow state and coding to chill beats – and it's no wonder some of us might be tempted to take the easy way out.&lt;/p&gt;

&lt;p&gt;Don't get me wrong, I'm all for finding a groove and enjoying the process!  But even in a state of blissful coding zen, we can't forget that AI tools – powerful as they may be – are still tools.  They're extensions of our intentions, not replacements for them.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI and Devs: The Ultimate Coding Power Couple (Think Mulder and Scully, But With Less Aliens)
&lt;/h2&gt;

&lt;p&gt;Think of it like this: you wouldn't walk into a restaurant and say, "Bring me food!" and expect a perfectly prepared, five-course meal tailored to your exact tastes, would you? (Okay, maybe some of us would, but you get the point!).  It's the same with AI coding assistants. If we're not clear about what we want, down to the specific ingredients, flavours, and presentation, we can't expect the AI to conjure up our ideal solution magically. &lt;/p&gt;

&lt;p&gt;Take the other day, for example. I was trying to build out the Stats view for my AceIt dashboard and asked Gemini (my official AI best buddy, by the way!) for some help. But I was slightly distracted and kept leaving some minor details out. We ended up going back and forth for almost four hours, and I still couldn't solve the problem. But as soon as I figured out what was missing, the solution immediately became simple.&lt;/p&gt;

&lt;p&gt;This recent experience reminded me that, at the end of the day, a developer still has to understand not just the problem and the solution but also how to get there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flexing My Tailwind CSS Prowess: Why Sometimes the Best Code is the Code You Write Yourself
&lt;/h2&gt;

&lt;p&gt;While working on the Assignments Listing view today, I could've relied upon Gemini to help generate the entire piece of code. If time were of the essence, I probably would've gotten Gemini's help for sure.&lt;/p&gt;

&lt;p&gt;But nope! I wanted to take this opportunity to challenge myself. I've been aiming to deepen my skills in &lt;a href="https://tailwindcss.com/docs/flex" rel="noopener noreferrer"&gt;tailwindcss&lt;/a&gt; for some time. And there is no better time than right now. So I spent a few hours writing the UI's code, line-by-line on my own.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div
  className="flex items-center w-full section-header-wrapper"
  onClick={() =&amp;gt; setIsOngoingExpanded(!isOngoingExpanded)}
&amp;gt;
  &amp;lt;div className="flex flex-col justify-center items-center w-5 aspect-square transition-transform duration-250 ease-in-out"&amp;gt;
    &amp;lt;ChevronRight
      className={`h-4 w-4 ${isOngoingExpanded &amp;amp;&amp;amp; "rotate-90"}`}
    /&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;div className="flex-1 flex-col justify-start items-center"&amp;gt;
    &amp;lt;h2 className="section-header"&amp;gt;On-going Assignments:&amp;lt;/h2&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;

{isOngoingExpanded ? (
  &amp;lt;div className={`flex items-center w-full h-max mb-16`}&amp;gt;  
    {/* Ongoing Assignments Section starts here. */}
    &amp;lt;ListView 
      data={assignmentsData.filter(a =&amp;gt; a.status === "ongoing")} 
      item={assignmentsRender} 
      style={{ width: '100%', height: (assignmentsData.filter(a =&amp;gt; a.status === "ongoing").length * 110) + 2 }} 
    /&amp;gt;
    {/* Ongoing Assignments Section ends here. */}
  &amp;lt;/div&amp;gt;
) : (&amp;lt;div className="flex h-16 w-full" /&amp;gt;)}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The part of the UI that I am most pleased with is the ListView item render function. While working on the first sub-section of the UI, I had this inspiration and idea to make use of the &lt;code&gt;.filter()&lt;/code&gt; method to pass only the relevant records to the &lt;code&gt;assignmentsRender()&lt;/code&gt; function. That way, I won't have to write multiple render functions for each sub-section of the Assignments Listing view.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const assignmentsRender = (props: ListViewItemProps) =&amp;gt; {
  const item = props.dataItem;

  return (
    &amp;lt;ListViewItemWrapper
      className="p-8 h-[100px]"
      style={{ borderBottom: "1px solid lightgrey" }}
    &amp;gt;
      &amp;lt;div className="flex flex-row w-full h-[80px] mt-[10px] mb-[10px]"&amp;gt;
        &amp;lt;div className="flex flex-col items-center justify-start w-[68%] h-full"&amp;gt;
          &amp;lt;div className="flex-1 text-2xl font-bold w-full items-center"&amp;gt;
            {item.assignmentTitle}
          &amp;lt;/div&amp;gt;
          &amp;lt;div className="flex text-md font-normal w-full h-max items-center"&amp;gt;
            Next Milestone: {item.milestone.title} ({item.milestone.date})
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div className="flex flex-col w-[32%] items-center justify-end h-full"&amp;gt;
          {item.status === "ongoing" || item.status === "submitted" 
            ? (
              &amp;lt;div className="flex text-lg font-normal w-full items-center justify-end pr-4 h-1/2"&amp;gt;
                &amp;lt;div className="mr-2 w-16"&amp;gt;
                  &amp;lt;ProgressBar 
                    value={item.progressPercent * 100} 
                    labelVisible={false} 
                    min={0} 
                    max={100} 
                    progressStyle={{ borderRadius: "2px" }}
                    style={{
                      borderRadius: "2px"
                    }}
                  /&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;div className="w-8 justify-end pr-4"&amp;gt;
                  {Math.round(item.progressPercent * 100)}%
                &amp;lt;/div&amp;gt;
              &amp;lt;/div&amp;gt;
            ) : (
              &amp;lt;div className="flex text-xl font-semibold text-green-800 w-full items-center justify-end pr-2 h-1/2"&amp;gt;
                COMPLETED
              &amp;lt;/div&amp;gt;
            )
          }

          &amp;lt;div className="flex text-lg font-normal w-full items-center justify-end pr-2 h-1/2"&amp;gt;
            &amp;lt;ChipList
              selection={'single'}
              defaultData={item.tags}
              chip={(props: ChipProps) =&amp;gt; {
                const { dataItem } = props;
                return (
                  &amp;lt;Chip
                    text={dataItem.tagTitle}
                    value={dataItem.id}
                    style={{
                      backgroundColor: "#e51a5f",
                      color: "#efefef"
                    }}
                  /&amp;gt;
                );
              }}
            /&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/ListViewItemWrapper&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While the UI doesn't look perfect [yet], I walked away from this experience with a new sense of confidence in my skills as a front-end engineer. I am glad that I didn't take the easy way out today. I could've, but I didn't. And that is also precisely the same reason that enabled me to become the world's top front-end developer.&lt;/p&gt;

&lt;p&gt;While others had relied on solutions and ideas that have been pre-generated, I've always sought to break those solutions and ideas down into smaller parts so that I could figure out how they came up with the solution/answers. Sometimes, I would even take things a step further, create a better solution, and repost what I've learned/created.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some Final Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;I love AI tools. I love Gemini Pro. They are the best creations ever made for devs because now, we can automate a lot of the repetitive coding that we used to have to write by hand. Thank God for that.&lt;/p&gt;

&lt;p&gt;But I will still find the greatest fulfilment when writing my code, especially when it comes to creating something a little more complex, or customized.&lt;/p&gt;

&lt;p&gt;So, the next time you're tempted to hit the "Generate Code" button, take a moment to consider the alternative.  Challenge yourself. Embrace the struggle. You might be surprised by what you can achieve and the confidence you'll gain.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>tailwindcss</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
