<?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: bigben qin</title>
    <description>The latest articles on DEV Community by bigben qin (@bigben_qin_53328bc8e6cc0e).</description>
    <link>https://dev.to/bigben_qin_53328bc8e6cc0e</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%2F3716331%2F738a7d0f-bea1-4d93-bec9-a094ae57b781.png</url>
      <title>DEV Community: bigben qin</title>
      <link>https://dev.to/bigben_qin_53328bc8e6cc0e</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bigben_qin_53328bc8e6cc0e"/>
    <language>en</language>
    <item>
      <title>I built an AI hairstyle try-on tool because haircut regret is expensive</title>
      <dc:creator>bigben qin</dc:creator>
      <pubDate>Thu, 12 Mar 2026 07:43:25 +0000</pubDate>
      <link>https://dev.to/bigben_qin_53328bc8e6cc0e/i-built-an-ai-hairstyle-try-on-tool-because-haircut-regret-is-expensive-4d18</link>
      <guid>https://dev.to/bigben_qin_53328bc8e6cc0e/i-built-an-ai-hairstyle-try-on-tool-because-haircut-regret-is-expensive-4d18</guid>
      <description>&lt;p&gt;A bad haircut is annoying because you live with it for weeks, not minutes. I wanted a way to sanity-check a new look before booking anything, so I built AI Hairstyle Changer.&lt;/p&gt;

&lt;p&gt;It is simple on purpose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;upload a selfie&lt;/li&gt;
&lt;li&gt;pick a preset style or describe one&lt;/li&gt;
&lt;li&gt;generate a preview in a few seconds&lt;/li&gt;
&lt;li&gt;try hair color too if you want&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few things I learned while building it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Most people do not want a blank prompt box first. They want a few good starting options.&lt;/li&gt;
&lt;li&gt;"Does this suit my face?" matters more than perfect image sharpness.&lt;/li&gt;
&lt;li&gt;Privacy defaults matter a lot.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want to try it, it is here:&lt;br&gt;
&lt;a href="https://hairstyleaichanger.com" rel="noopener noreferrer"&gt;https://hairstyleaichanger.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am still tuning prompt quality and hairstyle presets, so I would love blunt feedback:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;which styles are missing&lt;/li&gt;
&lt;li&gt;what makes a result feel fake&lt;/li&gt;
&lt;li&gt;whether you would trust a tool like this before a real haircut&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>showdev</category>
      <category>ai</category>
      <category>webdev</category>
      <category>startup</category>
    </item>
    <item>
      <title>Building an AI Hairstyle Try-On App with Next.js</title>
      <dc:creator>bigben qin</dc:creator>
      <pubDate>Sat, 17 Jan 2026 10:45:29 +0000</pubDate>
      <link>https://dev.to/bigben_qin_53328bc8e6cc0e/building-an-ai-hairstyle-try-on-app-with-nextjs-18pb</link>
      <guid>https://dev.to/bigben_qin_53328bc8e6cc0e/building-an-ai-hairstyle-try-on-app-with-nextjs-18pb</guid>
      <description>&lt;p&gt;I recently launched &lt;strong&gt;AI Hairstyle Changer&lt;/strong&gt;—a web application that lets you&lt;/p&gt;

&lt;p&gt;preview a new hairstyle on your own photo before deciding on a haircut.&lt;/p&gt;

&lt;p&gt;👉 Online Demo: &lt;a href="https://hairstyleaichanger.com/" rel="noopener noreferrer"&gt;https://hairstyleaichanger.com/&lt;/a&gt;&lt;/p&gt;

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

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;The core workflow is simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Upload a selfie (front-facing photos are best).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose a hairstyle (or enter a suggestion).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generate a result image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Save to history (and optionally request publication).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I intentionally designed the user experience with a "prompt-first" approach: users should always see the prompts they are using.&lt;/p&gt;

&lt;p&gt;This prevents confusion between the "category" and&lt;/p&gt;

&lt;p&gt;the actual instructions to the model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Product Constraints I Consider "Non-Negotiationable"
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1) No Changing the Person
&lt;/h3&gt;

&lt;p&gt;If a user uploads their own face, the output must maintain the same identity.&lt;/p&gt;

&lt;p&gt;A "cool hairstyle" is meaningless if it looks like someone else's.&lt;/p&gt;

&lt;p&gt;Therefore, I made "maintaining identity" a hard rule: system prompts will add&lt;/p&gt;

&lt;p&gt;strict constraints, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Only&lt;/strong&gt; change hairstyle&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep face/facial features/skin tone/expression/pose/background&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;unchanged&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid using beauty filters, facial retouching, face swapping, changing gender/age, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These restrictions are enforced on the server side, so the client cannot bypass them.&lt;/p&gt;

&lt;h3&gt;
  
  
  2) Cost Control and Anti-Abuse
&lt;/h3&gt;

&lt;p&gt;Image editing is costly. I designed a simple free policy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Login required&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Logged-in users receive &lt;strong&gt;3 free trials&lt;/strong&gt;, after which a paid trial is required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While not perfect, it significantly reduces anonymous abuse and allows&lt;/p&gt;

&lt;p&gt;real users to quickly gain an "aha" moment.&lt;/p&gt;

&lt;h3&gt;
  
  
  3) Maintain SEO friendliness and avoid over-design
&lt;/h3&gt;

&lt;p&gt;I created a &lt;code&gt;/ideas&lt;/code&gt; directory containing hairstyle pages for search intent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/ideas&lt;/code&gt; for browsing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/ideas/{slug}&lt;/code&gt; for specific hairstyle themes&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I maintain consistency in canonical URLs and avoid indexing filter/search result pages.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Technology Stack
&lt;/h2&gt;

&lt;p&gt;I initially used &lt;strong&gt;ShipAny&lt;/strong&gt; (an AI SaaS template based on Next.js), and then did extensive customization:&lt;/p&gt;

&lt;p&gt;Including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Next.js application routing (React 19)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;next-intl for internationalization (i18n)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Drizzle ORM + Postgres&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cloudflare R2 for storing generated images&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;FAL (image editing) for changing hairstyles&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creem for payments (subscription + one-time package)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Vercel for deployment&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture (Overview)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Client uploads image → Backend stores it in R2&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Client sends "hairstyle + hint" → Server merges according to strict&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;identity constraints&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Server calls image model&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Server stores generated image in R2&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Save generation history (for history and administrator review)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For free users, I add a watermark upon upload so paid users get a clean&lt;/p&gt;

&lt;p&gt;result.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Surprised Me
&lt;/h2&gt;

&lt;h3&gt;
  
  
  "Hint Presets" Need to Be Very Specific
&lt;/h3&gt;

&lt;p&gt;If two hairstyle hints are too vague in their description of the hair, the result will look&lt;/p&gt;

&lt;p&gt;almost identical. Even if the model is technically feasible, users will feel the product is "unprofessional."&lt;/p&gt;

&lt;p&gt;My Solution: Treat each hairstyle preset as a "specification":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Length + Parting + Bangs + Volume + Outline&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Explicitly add "Avoid…" to exclude similar styles&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  Some Small SEO and Sharing Details Matter
&lt;/h3&gt;

&lt;p&gt;Some catalogs scrape Open Graph tags. If your &lt;code&gt;og:image&lt;/code&gt; is still&lt;/p&gt;

&lt;p&gt;a template preview image, the product looks incomplete.&lt;/p&gt;

&lt;p&gt;I replaced the default OG preview image and added a version number (&lt;code&gt;?v=2&lt;/code&gt;) to force&lt;/p&gt;

&lt;p&gt;the scraper to refresh the cached preview image.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A more comprehensive hairstyle library (more choices, less duplication)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Favorites and collections&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Improved backend user content moderation tools&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Performance optimization (mobile LCP optimization)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support for more languages ​​(besides English and Chinese)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are developing an AI consumer application, my most important advice is: **When designing,&lt;/p&gt;

&lt;p&gt;first and foremost, earn the user's trust.** If the model's output changes the user,&lt;/p&gt;

&lt;p&gt;then the product will immediately lose credibility.&lt;/p&gt;

&lt;p&gt;Thank you for reading—feel free to ask questions.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>saas</category>
      <category>nextjs</category>
      <category>product</category>
    </item>
  </channel>
</rss>
