<?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: Vincent</title>
    <description>The latest articles on DEV Community by Vincent (@mandarinclips).</description>
    <link>https://dev.to/mandarinclips</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4037181%2F1398a0a9-4430-4970-bf1c-49fd7d937e65.png</url>
      <title>DEV Community: Vincent</title>
      <link>https://dev.to/mandarinclips</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mandarinclips"/>
    <language>en</language>
    <item>
      <title>“I Like It Very Much”: Why We Built MandarinClips</title>
      <dc:creator>Vincent</dc:creator>
      <pubDate>Mon, 19 Oct 2026 08:45:12 +0000</pubDate>
      <link>https://dev.to/mandarinclips/i-like-it-very-much-why-we-built-mandarinclips-eeg</link>
      <guid>https://dev.to/mandarinclips/i-like-it-very-much-why-we-built-mandarinclips-eeg</guid>
      <description>&lt;h2&gt;
  
  
  1. The Moment My Brain Froze for Five Seconds
&lt;/h2&gt;

&lt;p&gt;A few years ago, on my first overseas business trip, I walked up to a local bank teller to withdraw cash. What followed was an excruciating linguistic freeze that remains etched into my memory.&lt;/p&gt;

&lt;p&gt;I had studied English in China for well over a decade. I aced standardized tests and assumed routine daily interactions would be effortless. &lt;/p&gt;

&lt;p&gt;After processing my paperwork, the teller looked up, smiled, and asked:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“How do you like your money?”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I froze. A sudden ringing filled my ears. Instinctively, I blurted out: “Pardon?”&lt;br&gt;&lt;br&gt;
Assuming I hadn't heard clearly, she slowed down and enunciated every syllable:&lt;br&gt;&lt;br&gt;
&lt;em&gt;“How... do you like your money?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;My brain shut down completely for five agonizing seconds: &lt;em&gt;“Do I like my money? What kind of philosophical question is this? Does anyone on earth dislike their own money?”&lt;/em&gt;&lt;br&gt;&lt;br&gt;
Under her expectant gaze, I panicked and forced out an answer that deserves a place in the hall of shame:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“I... I like it very much!”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The air in the room instantly turned to stone. Holding back a smirk, she gently explained what she actually meant: &lt;strong&gt;“What denominations would you prefer? Hundreds, twenties, or small bills?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I walked out of that bank drenched in cold sweat. That absurd exchange shattered my confidence: &lt;strong&gt;we spend years memorizing thousands of lexical items and grammatical paradigms in sterile ivory towers, yet the moment we step into native reality, our very first sentence reduces us to square one.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  2. "Sterilized Chinese" vs. The Living World
&lt;/h2&gt;

&lt;p&gt;When we look at Chinese language education, international learners face the exact same farce.&lt;/p&gt;

&lt;p&gt;Open almost any standard beginner-to-intermediate textbook, and the dialogue inevitably reads like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“你好，你去不去食堂？” (&lt;em&gt;Hello, are you going to the cafeteria?&lt;/em&gt;)&lt;br&gt;&lt;br&gt;
“我不去食堂，我去图书馆。” (&lt;em&gt;I am not going to the cafeteria; I am going to the library.&lt;/em&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Syntactically immaculate. Lexically pristine. Utterly lifeless.&lt;br&gt;&lt;br&gt;
In an actual Chinese office, apartment complex, or dinner table, native speakers almost never communicate like this.&lt;/p&gt;

&lt;p&gt;A real interaction looks more like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“中午一起吃个便饭？” (&lt;em&gt;Grab a quick lunch together?&lt;/em&gt;)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;“改天吧，今天手头实在有点紧。”&lt;/strong&gt; (&lt;em&gt;Another day—my hands are completely tied today.&lt;/em&gt;)&lt;br&gt;&lt;br&gt;
Or:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;“我还是算了吧，你们去。”&lt;/strong&gt; (&lt;em&gt;I'd rather pass—you guys go ahead.&lt;/em&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Native speakers rarely fling a blunt, chilling “我不去” (&lt;em&gt;I am not going&lt;/em&gt;) into someone's face. We deploy &lt;strong&gt;“改天吧”&lt;/strong&gt; (&lt;em&gt;another day&lt;/em&gt;) to preserve face; we use &lt;strong&gt;“算了吧”&lt;/strong&gt; (&lt;em&gt;let's drop it&lt;/em&gt;) to lower expectations; we lean on &lt;strong&gt;“老实说”&lt;/strong&gt; (&lt;em&gt;honestly speaking&lt;/em&gt;) to pivot toward candid pushback; and we drop &lt;strong&gt;“别提了”&lt;/strong&gt; (&lt;em&gt;don't get me started&lt;/em&gt;) to cut off a frustrating tangent.&lt;/p&gt;

&lt;p&gt;These discourse markers, pragmatic softeners, and micro-tonal hesitations constitute the living soul of actual communication. To standardize instruction, conventional curricula filter out these vibrant pragmatic nuances, leaving behind nothing but a hollow, sterilized syntactic skeleton.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. My Sister’s Desk and the "Lesson Prep Torment"
&lt;/h2&gt;

&lt;p&gt;If learners are suffering through artificial language, teachers on the other side of the podium endure an entirely different kind of torture.&lt;/p&gt;

&lt;p&gt;My sister is a university English professor, and my brother-in-law is a university lecturer as well. To outsiders, academia looks pristine and comfortable. But whenever I looked at her desk late at night, I saw the endless, manual exhaustion that went into crafting engaging lessons.&lt;/p&gt;

&lt;p&gt;To bring a classroom to life and demonstrate how an expression actually functions in authentic contexts, she needed film dialogue snippets.&lt;br&gt;&lt;br&gt;
Yet locating a single, five-second usable video clip required:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Digging through mental archives to remember which show or film featured that exact phrase;&lt;/li&gt;
&lt;li&gt;Opening a media player and scrubbing the timeline back and forth blindly across two hours of video;&lt;/li&gt;
&lt;li&gt;Once found, manually screen-recording, exporting audio, transcribing dialogue, and double-checking context.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Sourcing three authentic, high-quality examples routinely burned two to three hours of her evening.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Watching her drag media scrubbers frame by frame late at night for tomorrow's slide deck, it hit me:&lt;br&gt;&lt;br&gt;
Whether teaching English or Chinese, &lt;strong&gt;language educators everywhere are bogged down by grueling manual material collection, while learners are starved for living language.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Why not engineer an industrial solution to eliminate this friction entirely?&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Building MandarinClips: Grounding Language in Empirical Context
&lt;/h2&gt;

&lt;p&gt;As a software engineer accustomed to building high-throughput systems, my immediate intuition was clear: this shouldn't be an endless manual sinkhole. It is a structured corpus engineering problem.&lt;/p&gt;

&lt;p&gt;If we could segment every conversational turn across classic cinema into atomic audiovisual units, and index them across &lt;strong&gt;Pragmatic Function (How to say)&lt;/strong&gt;, &lt;strong&gt;Syntactic Frames (How to construct)&lt;/strong&gt;, and &lt;strong&gt;Social Scenarios (When to say)&lt;/strong&gt;, the landscape changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;For Educators&lt;/strong&gt;: Preparing a module on &lt;em&gt;pragmatic softeners&lt;/em&gt; or &lt;em&gt;colloquial '把' variations&lt;/em&gt; no longer takes hours. Enter a keyword, and within three seconds retrieve 50 authentic clips equipped with precise timestamps, source attribution, preceding conversational turns, and aligned translations. Lesson prep shrinks from hours to seconds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;For Learners&lt;/strong&gt;: No more "I like it very much" linguistic paralysis. Search an expression and witness real human beings navigating hesitation, nuance, irony, and warmth on screen, instantly grasping the pragmatic subtext.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This realization forms the bedrock of &lt;strong&gt;MandarinClips&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. A Living Discovery Map, Not a Video Platform
&lt;/h2&gt;

&lt;p&gt;Today, MandarinClips indexes &lt;strong&gt;over 180,000 real-world cinema dialogue snippets&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We skipped social feeds, gamified flashcard streaks, and disruptive autoplay loops. We focused entirely on building an intuitive, deterministic discovery map for spoken Chinese:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Expression Index (&lt;code&gt;/expressions&lt;/code&gt;)&lt;/strong&gt;: Discover how native speakers convey reluctance, validation, dismissal, and casual rapport.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grammar Index (&lt;code&gt;/grammar&lt;/code&gt;)&lt;/strong&gt;: Observe how core syntactic frames naturally compress, invert, and omit elements in spontaneous speech.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scene Index (&lt;code&gt;/scenes&lt;/code&gt;)&lt;/strong&gt;: Master social distance and interpersonal boundaries across workplace requests, family conflicts, and social banter.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Language lives in the messy, nuanced reality of human interaction. MandarinClips exists to lift the burden of lesson prep off tired teachers, and to help dedicated learners finally understand the unspoken subtext behind what native speakers say.&lt;/p&gt;

</description>
      <category>pragmatics</category>
    </item>
    <item>
      <title>I Built an Open-Source SEO Indexing Infrastructure with Rust</title>
      <dc:creator>Vincent</dc:creator>
      <pubDate>Fri, 28 Aug 2026 02:37:38 +0000</pubDate>
      <link>https://dev.to/mandarinclips/i-built-an-open-source-seo-indexing-infrastructure-with-rust-3fld</link>
      <guid>https://dev.to/mandarinclips/i-built-an-open-source-seo-indexing-infrastructure-with-rust-3fld</guid>
      <description>&lt;h2&gt;
  
  
  A website being online does not mean search engines understand it
&lt;/h2&gt;

&lt;p&gt;As developers, we usually think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If my website is deployed and users can access it, the job is done.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But after building content-heavy websites, I realized there is another layer that developers often overlook:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do search engines discover, crawl, and understand my website?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After deployment, many invisible problems can appear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are pages returning the correct HTTP status codes?&lt;/li&gt;
&lt;li&gt;Is the sitemap valid?&lt;/li&gt;
&lt;li&gt;Are URLs structured correctly?&lt;/li&gt;
&lt;li&gt;Are there unexpected 404 pages?&lt;/li&gt;
&lt;li&gt;Are search engines still crawling the website?&lt;/li&gt;
&lt;li&gt;Which URLs are indexed and which are not?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These problems usually do not appear during local development.&lt;/p&gt;

&lt;p&gt;They only appear after your website is live.&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem I experienced
&lt;/h2&gt;

&lt;p&gt;While building my own content website, I encountered unexpected indexing issues.&lt;/p&gt;

&lt;p&gt;At first, everything seemed fine.&lt;/p&gt;

&lt;p&gt;The website was running.&lt;br&gt;
The pages were accessible.&lt;br&gt;
The application worked.&lt;/p&gt;

&lt;p&gt;However, search engine crawling behavior changed after some deployment and website structure changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lesson 1: Infrastructure stability affects search engine crawling
&lt;/h2&gt;

&lt;p&gt;The website was initially deployed on Cloudflare Workers.&lt;/p&gt;

&lt;p&gt;Because of runtime limitations, some requests occasionally resulted in 5xx errors.&lt;/p&gt;

&lt;p&gt;For normal users, an occasional failure may only be a small inconvenience.&lt;/p&gt;

&lt;p&gt;But for search engines, repeated failures can affect how they evaluate a website.&lt;/p&gt;

&lt;p&gt;A website that frequently fails to respond correctly is harder for search engines to crawl reliably.&lt;/p&gt;

&lt;p&gt;Eventually, I noticed that search engine crawling activity decreased significantly.&lt;/p&gt;

&lt;p&gt;This made me realize:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Website reliability is not only a user experience problem. It is also a search engine visibility problem.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Lesson 2: URL changes are more dangerous than they look
&lt;/h2&gt;

&lt;p&gt;Later, I changed parts of my URL structure to make it cleaner and more SEO-friendly.&lt;/p&gt;

&lt;p&gt;However, changing URLs is not just a simple string replacement.&lt;/p&gt;

&lt;p&gt;It affects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;redirects&lt;/li&gt;
&lt;li&gt;sitemap generation&lt;/li&gt;
&lt;li&gt;URL discovery&lt;/li&gt;
&lt;li&gt;indexing status&lt;/li&gt;
&lt;li&gt;search engine understanding&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without proper monitoring, it is difficult to know whether these changes are helping or hurting.&lt;/p&gt;




&lt;h2&gt;
  
  
  SEO starts before keywords
&lt;/h2&gt;

&lt;p&gt;When people talk about SEO, they often think about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;keyword research&lt;/li&gt;
&lt;li&gt;ranking optimization&lt;/li&gt;
&lt;li&gt;backlinks&lt;/li&gt;
&lt;li&gt;content strategy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are important.&lt;/p&gt;

&lt;p&gt;But for developers, there is a more fundamental question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can search engines correctly access and understand my website?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before optimizing keywords, we should make sure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pages are accessible&lt;/li&gt;
&lt;li&gt;URLs can be discovered&lt;/li&gt;
&lt;li&gt;technical SEO issues are detected&lt;/li&gt;
&lt;li&gt;website structure is healthy&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Building IndexFlow
&lt;/h2&gt;

&lt;p&gt;This experience led me to build &lt;strong&gt;IndexFlow-core&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;IndexFlow-core is an open-source search engine indexing infrastructure designed for developers.&lt;/p&gt;

&lt;p&gt;The goal is not to replace SEO professionals.&lt;/p&gt;

&lt;p&gt;Instead, it focuses on the technical foundation between websites and search engines.&lt;/p&gt;

&lt;p&gt;Current focus areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sitemap management&lt;/li&gt;
&lt;li&gt;URL discovery&lt;/li&gt;
&lt;li&gt;SEO quality checks&lt;/li&gt;
&lt;li&gt;Indexing workflow management&lt;/li&gt;
&lt;li&gt;Search engine submission infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/IndexFlowing/IndexFlow-core" rel="noopener noreferrer"&gt;https://github.com/IndexFlowing/IndexFlow-core&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Website:&lt;/p&gt;

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




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

&lt;p&gt;I wanted IndexFlow to be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lightweight&lt;/li&gt;
&lt;li&gt;self-hostable&lt;/li&gt;
&lt;li&gt;reliable&lt;/li&gt;
&lt;li&gt;suitable for long-running services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rust fits this kind of infrastructure project very well.&lt;/p&gt;

&lt;p&gt;During development, I also extracted some reusable components into standalone Rust libraries.&lt;/p&gt;

&lt;p&gt;The idea is simple:&lt;/p&gt;

&lt;p&gt;If a component can be useful outside IndexFlow, it should not be locked inside the project.&lt;/p&gt;




&lt;h2&gt;
  
  
  Open-source direction
&lt;/h2&gt;

&lt;p&gt;IndexFlow-core is moving toward an open-source search engine indexing infrastructure.&lt;/p&gt;

&lt;p&gt;The long-term vision is to provide developers with better tools for managing the relationship between their websites and search engines.&lt;/p&gt;

&lt;p&gt;Future improvements include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;better SEO quality gates&lt;/li&gt;
&lt;li&gt;smarter URL scheduling&lt;/li&gt;
&lt;li&gt;multi-site management&lt;/li&gt;
&lt;li&gt;improved indexing monitoring&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;IndexFlow was not created because I wanted to build another SEO tool.&lt;/p&gt;

&lt;p&gt;It started because I encountered a real problem while building websites.&lt;/p&gt;

&lt;p&gt;Deployment issues, URL changes, and indexing problems made me realize:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Search engine visibility also needs infrastructure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is why I started building IndexFlow.&lt;/p&gt;

&lt;p&gt;If you are interested in technical SEO, Rust, or open-source infrastructure, I would love to hear your feedback.&lt;/p&gt;

&lt;p&gt;Thanks for reading.&lt;/p&gt;

</description>
      <category>infrastructure</category>
      <category>opensource</category>
      <category>rust</category>
      <category>seo</category>
    </item>
    <item>
      <title>How I built a high-performance Chinese learning platform with 100k+ TV clips using Rust and Next.js 15</title>
      <dc:creator>Vincent</dc:creator>
      <pubDate>Mon, 20 Jul 2026 02:44:30 +0000</pubDate>
      <link>https://dev.to/mandarinclips/how-i-built-a-high-performance-chinese-learning-platform-with-100k-tv-clips-using-rust-and-nextjs-2a81</link>
      <guid>https://dev.to/mandarinclips/how-i-built-a-high-performance-chinese-learning-platform-with-100k-tv-clips-using-rust-and-nextjs-2a81</guid>
      <description>&lt;p&gt;Hi dev.to community! 👋&lt;/p&gt;

&lt;p&gt;Today, I’m incredibly excited to share &lt;strong&gt;MandarinClips&lt;/strong&gt;, a side project I’ve been pouring my soul into. It's a high-performance language learning platform that indexes and organizes sentence-sized dialogue segments from authentic Chinese movies and TV series to help language learners transition from sterile textbooks to real-world immersion.&lt;/p&gt;

&lt;p&gt;👉 Check it out here: &lt;a href="https://www.mandarinclips.com" rel="noopener noreferrer"&gt;MandarinClips.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a deep dive into the engineering decisions, performance bottlenecks, and the technical architecture that powers the platform under the hood.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏗️ The High-Level Architecture
&lt;/h2&gt;

&lt;p&gt;I wanted the platform to be blindingly fast, cost-effective, and highly available. Here is the stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: Next.js 15 (React 19) + Tailwind CSS + next-intl (for multilingual support).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: Rust (Axum framework) + Tokio async runtime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database&lt;/strong&gt;: PostgreSQL with &lt;code&gt;pg_trgm&lt;/code&gt; (trigram) extension.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage &amp;amp; CDN&lt;/strong&gt;: Backblaze B2 proxied through Cloudflare CDN (S3 API compatible, 0-cost egress).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚡ Backend: Why Rust &amp;amp; Axum?
&lt;/h2&gt;

&lt;p&gt;The backend is responsible for high-frequency search requests, serving sitemaps, and tracking user quota usage. &lt;/p&gt;

&lt;p&gt;Using &lt;strong&gt;Rust&lt;/strong&gt; was a no-brainer for several reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Safety &amp;amp; Zero-Cost Abstractions&lt;/strong&gt;: No garbage collection means zero GC pauses, resulting in extremely predictable latency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Axum &amp;amp; Tokio&lt;/strong&gt;: Axum is a highly ergonomic, thin routing wrapper on top of Tokio. It handles asynchronous tasks with minimal CPU overhead, allowing our single 2-core VPS to handle thousands of concurrent queries without breaking a sweat.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🗄️ Database: Sub-millisecond Fuzzy Search with PG GIN Indexes
&lt;/h2&gt;

&lt;p&gt;With over 100,000 video clips and subtitles indexed, a standard &lt;code&gt;ILIKE '%query%'&lt;/code&gt; search would quickly degrade and result in full table scans, locking up the CPU under high traffic.&lt;/p&gt;

&lt;p&gt;To solve this, we utilized the PostgreSQL &lt;strong&gt;&lt;code&gt;pg_trgm&lt;/code&gt;&lt;/strong&gt; (trigram) extension to build &lt;strong&gt;GIN (Generalized Inverted Index)&lt;/strong&gt; on both Chinese characters and no-tone pinyin strings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;EXTENSION&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;pg_trgm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;idx_clips_text_zh_trgm&lt;/span&gt; 
&lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;clips&lt;/span&gt; &lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;GIN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text_zh&lt;/span&gt; &lt;span class="n"&gt;gin_trgm_ops&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;idx_clips_pinyin_search_trgm&lt;/span&gt; 
&lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;clips&lt;/span&gt; &lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;GIN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pinyin_search&lt;/span&gt; &lt;span class="n"&gt;gin_trgm_ops&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By querying against these indices, fuzzy matches for queries like "ni hao" or "明天见" take under 1 millisecond locally. We achieve pure O(1) list scans.&lt;br&gt;
🎥 Media Delivery: 0-Cost Egress with Backblaze B2 &amp;amp; Cloudflare&lt;br&gt;
Hosting over 100,000 MP4 video clips can quickly become a bandwidth billing nightmare on standard cloud providers.&lt;br&gt;
We solved this by storing all .mp4 video files and .jpg posters in Backblaze B2, which is part of the Cloudflare Bandwidth Alliance. By proxying the B2 bucket through Cloudflare's global edge network:&lt;br&gt;
All public egress bandwidth is $0.&lt;br&gt;
We configured aggressive Cloudflare Cache Rules (using Cache-Control: public, max-age=86400, s-maxage=604800 headers) so that sitemaps and video assets are served straight from Cloudflare's edge memory, dropping origin VPS bandwidth and IOPS to near-zero.&lt;br&gt;
🌐 Frontend: Next.js 15 &amp;amp; Native 308 Permanent Redirections&lt;br&gt;
For the frontend, we used Next.js 15. One of our recent refactoring milestones was migrating legacy URLs from underscores (_) to SEO-friendly dashes (-).&lt;br&gt;
To preserve SEO link juice, we avoided heavy JS-based Edge middleware and leveraged Next.js's native redirects config in next.config.ts to issue 308 Permanent Redirects at the router level:&lt;br&gt;
// next.config.ts&lt;br&gt;
async redirects() {&lt;br&gt;
  return [&lt;br&gt;
    {&lt;br&gt;
      source: '/sitemap.xml',&lt;br&gt;
      destination: '&lt;a href="https://www.mandarinclips.com/sitemaps/sitemap.xml" rel="noopener noreferrer"&gt;https://www.mandarinclips.com/sitemaps/sitemap.xml&lt;/a&gt;',&lt;br&gt;
      permanent: true,&lt;br&gt;
    }&lt;br&gt;
  ];&lt;br&gt;
}&lt;br&gt;
This is processed natively before any middleware execution, ensuring zero-latency transitions for Googlebot.&lt;br&gt;
🎁 Wrapping Up &amp;amp; Feedback&lt;br&gt;
Building MandarinClips has been an incredible full-stack journey.&lt;br&gt;
I’d love to hear your feedback on the architecture, the Rust Axum setup, or the database indexing! If you're currently learning Chinese (or are just curious about the UI), please check out MandarinClips and let me know your thoughts in the comments below!&lt;br&gt;
Happy hacking! 🚀&lt;/p&gt;

</description>
      <category>rust</category>
      <category>nextjs</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
