<?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: Liandanxia</title>
    <description>The latest articles on DEV Community by Liandanxia (@liandanxiaai).</description>
    <link>https://dev.to/liandanxiaai</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%2F3905276%2F401f5587-bd49-4842-a0e4-19e724bc11f0.jpg</url>
      <title>DEV Community: Liandanxia</title>
      <link>https://dev.to/liandanxiaai</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/liandanxiaai"/>
    <language>en</language>
    <item>
      <title>The best way to use AI, you should know...</title>
      <dc:creator>Liandanxia</dc:creator>
      <pubDate>Tue, 14 Jul 2026 06:41:29 +0000</pubDate>
      <link>https://dev.to/liandanxiaai/the-best-way-to-use-ai-you-should-know-116h</link>
      <guid>https://dev.to/liandanxiaai/the-best-way-to-use-ai-you-should-know-116h</guid>
      <description>&lt;h1&gt;
  
  
  Why AI Agents Often Work Better When They Plan First and Execute Once
&lt;/h1&gt;

&lt;p&gt;AI systems are no longer limited to answering questions. They can open websites, organize files, run code, and carry out complete workflows. An AI system that can use tools and take a sequence of actions toward a goal is commonly called an &lt;strong&gt;AI agent&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Giving an AI access to tools, however, does not automatically make it efficient.&lt;/p&gt;

&lt;p&gt;Two agents may complete the same task in very different ways. One may perform a single action, stop to inspect the result, and then decide what to do next. Another may plan the entire workflow first and execute it as one complete program. Both approaches can work, but their speed, cost, and reliability may differ significantly.&lt;/p&gt;

&lt;p&gt;This article explains why, for many tasks, asking an AI agent to submit a complete workflow at once is more efficient than having it interact with tools one small step at a time.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. How Does an AI Agent Use Tools?
&lt;/h2&gt;

&lt;p&gt;Imagine asking an AI agent to complete a simple task:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Open a webpage, find its main heading, and tell me what the heading says.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One common execution pattern looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The AI sends an instruction to open the webpage.&lt;/li&gt;
&lt;li&gt;A browser tool opens the page and returns the result.&lt;/li&gt;
&lt;li&gt;The AI reads that result and sends another instruction to find the heading.&lt;/li&gt;
&lt;li&gt;The tool locates the heading and returns more information.&lt;/li&gt;
&lt;li&gt;The AI sends a final instruction to read the heading text.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This resembles an inexperienced cook asking for guidance after every tiny action:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“I took out the pan. What should I do next?”&lt;br&gt;&lt;br&gt;
“I added the oil. What should I do now?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The approach is flexible, but the AI must repeatedly read the latest result, reconsider the task, and generate the next instruction. The longer the workflow becomes, the more back-and-forth communication it requires.&lt;/p&gt;

&lt;p&gt;There is another option: the AI can write the complete procedure first and submit it to the execution environment in a single step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Open the target webpage&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;openPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Find the main heading on the page&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;heading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;findMainHeading&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Print the heading text&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;heading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is more like giving a cook the entire recipe. The cook follows the instructions and brings back the finished dish without asking for approval after slicing every ingredient.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The Real Difference Between the Two Approaches
&lt;/h2&gt;

&lt;p&gt;In technical discussions, these patterns are often described as &lt;strong&gt;interactive execution&lt;/strong&gt; and &lt;strong&gt;one-shot script execution&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interactive execution
&lt;/h3&gt;

&lt;p&gt;With interactive execution, the AI runs a small operation, observes the result, and then decides what to do next.&lt;/p&gt;

&lt;p&gt;This approach is useful when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The AI cannot predict what it will encounter.&lt;/li&gt;
&lt;li&gt;Each result may change the direction of the task.&lt;/li&gt;
&lt;li&gt;The AI is debugging a problem through repeated experiments.&lt;/li&gt;
&lt;li&gt;Initializing the environment is expensive, so preserving a long-running session is valuable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Its main disadvantage is that it can create a large number of round trips between the AI and its tools. Each round trip may add waiting time, model calls, and context-processing costs.&lt;/p&gt;

&lt;h3&gt;
  
  
  One-shot script execution
&lt;/h3&gt;

&lt;p&gt;With one-shot execution, the AI organizes the loops, filters, decisions, and calculations into a complete program before handing it to a local runtime.&lt;/p&gt;

&lt;p&gt;This approach works particularly well when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The required steps are reasonably clear.&lt;/li&gt;
&lt;li&gt;A large amount of data must be processed in batches.&lt;/li&gt;
&lt;li&gt;The intermediate steps do not require continuous AI involvement.&lt;/li&gt;
&lt;li&gt;Reducing latency, tool calls, and cost is important.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One-shot execution does not mean that the AI can only submit a single command. It also does not mean the program must ignore unexpected situations. A complete script can still include conditions, retries, validation, and error handling.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;downloadPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&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="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Failed to process page: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the local program visits the URLs, checks for a keyword, and handles failures. The AI does not need to reconsider the entire task after every page.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Why Can One-Shot Execution Cost Less?
&lt;/h2&gt;

&lt;p&gt;Running ordinary code on a computer is usually inexpensive. Asking a large AI model to repeatedly inspect results and make new decisions is often the costly part.&lt;/p&gt;

&lt;p&gt;Suppose we need to find every page containing a particular keyword across 100 websites.&lt;/p&gt;

&lt;p&gt;If the AI handles each page interactively, the workflow may look 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;Open page 1 → AI evaluates it → Open page 2 → AI evaluates it → repeat until page 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That process can generate many model interactions and tool calls.&lt;/p&gt;

&lt;p&gt;A more efficient workflow would be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use ordinary code to download all the pages.&lt;/li&gt;
&lt;li&gt;Clean and filter the content locally.&lt;/li&gt;
&lt;li&gt;Send only the most relevant results to the AI.&lt;/li&gt;
&lt;li&gt;Let the AI interpret, compare, and summarize the selected information.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is similar to assigning work inside a company:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Software handles repetitive, predictable, and measurable tasks.&lt;/li&gt;
&lt;li&gt;The AI handles tasks that require understanding, reasoning, or judgment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Making the AI participate in every mechanical action is like asking a department manager to photocopy every document personally. The work may still get done, but it is not a sensible use of an expensive resource.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. How Should “Large Intelligence” and “Small Intelligence” Work Together?
&lt;/h2&gt;

&lt;p&gt;For a simple mental model, we can divide the abilities required by an agent into two categories.&lt;/p&gt;

&lt;h3&gt;
  
  
  Large intelligence: understanding and decision-making
&lt;/h3&gt;

&lt;p&gt;These tasks usually benefit from an AI model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understanding what the user actually wants.&lt;/li&gt;
&lt;li&gt;Deciding whether a passage answers a question.&lt;/li&gt;
&lt;li&gt;Comparing the strengths and weaknesses of different options.&lt;/li&gt;
&lt;li&gt;Extracting ideas from ambiguous or unstructured material.&lt;/li&gt;
&lt;li&gt;Producing a clear and natural final explanation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Small intelligence: deterministic operations
&lt;/h3&gt;

&lt;p&gt;These tasks can usually be performed efficiently with ordinary code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visiting and downloading webpages.&lt;/li&gt;
&lt;li&gt;Removing HTML tags.&lt;/li&gt;
&lt;li&gt;Filtering content by keywords.&lt;/li&gt;
&lt;li&gt;Sorting and calculating numerical data.&lt;/li&gt;
&lt;li&gt;Converting file formats.&lt;/li&gt;
&lt;li&gt;Filling fields according to fixed rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A well-designed AI agent should not send every operation to a large language model. It should not depend exclusively on rigid automation scripts either. A better system allows the two forms of intelligence to cooperate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The user describes a goal
          ↓
The AI understands the request and creates a plan
          ↓
Local code performs repetitive and batch operations
          ↓
Questions requiring interpretation are sent to the AI
          ↓
The program continues with the remaining workflow
          ↓
The AI organizes and presents the final result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a hybrid workflow. The AI acts less like a worker who performs every action manually and more like a coordinator who assigns each part of the task to the most suitable tool.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. One-Shot Execution Is Not Always the Best Choice
&lt;/h2&gt;

&lt;p&gt;Although a complete script is often more efficient, it is not the right answer for every task.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tasks well suited to one-shot execution
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Organizing files in batches.&lt;/li&gt;
&lt;li&gt;Collecting and cleaning data.&lt;/li&gt;
&lt;li&gt;Filtering information according to clear conditions.&lt;/li&gt;
&lt;li&gt;Filling out many forms with the same structure.&lt;/li&gt;
&lt;li&gt;Performing a stable sequence of browser actions.&lt;/li&gt;
&lt;li&gt;Generating reports and calculating statistics.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tasks well suited to interactive execution
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Debugging a program with an unknown failure.&lt;/li&gt;
&lt;li&gt;Exploring a website with an unfamiliar structure.&lt;/li&gt;
&lt;li&gt;Handling workflows in which every step can create a new branch.&lt;/li&gt;
&lt;li&gt;Performing high-risk actions that require human confirmation.&lt;/li&gt;
&lt;li&gt;Working inside a complex environment whose state must be preserved for a long time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, when an AI enters an unfamiliar administration dashboard for the first time, it may need to inspect the interface before deciding what to click. Step-by-step exploration is safer in that situation.&lt;/p&gt;

&lt;p&gt;Once the AI understands the page structure, it can turn the repeated part of the task into a complete script and process the remaining work in a batch.&lt;/p&gt;

&lt;p&gt;In practice, one of the most effective patterns is therefore:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Explore interactively first, then execute the repeatable work as a complete program.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  6. What Does This Mean for Everyday Users?
&lt;/h2&gt;

&lt;p&gt;You do not need to write code to benefit from this idea. The same principle can improve the way you give instructions to an AI assistant.&lt;/p&gt;

&lt;p&gt;Instead of sending a series of fragmented requests:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Open this file.&lt;br&gt;&lt;br&gt;
Tell me what is inside.&lt;br&gt;&lt;br&gt;
Find the numbers.&lt;br&gt;&lt;br&gt;
Now sort them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can describe the complete goal and expected output from the beginning:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Read this file and extract every product name and price. Remove records without a price, sort the remaining products from lowest to highest price, and present the result as a Markdown table. Do not stop to ask about each intermediate step. Ask me only when the data is genuinely ambiguous.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This kind of instruction helps the AI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand the full objective earlier.&lt;/li&gt;
&lt;li&gt;Avoid unnecessary confirmation loops.&lt;/li&gt;
&lt;li&gt;Plan the workflow before acting.&lt;/li&gt;
&lt;li&gt;Use code for repetitive processing.&lt;/li&gt;
&lt;li&gt;Produce a more consistent final result.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Actions involving payment, data deletion, publishing, or sending messages still deserve special caution. For operations that can affect external systems or other people, the AI should pause for confirmation immediately before the consequential step.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Conclusion
&lt;/h2&gt;

&lt;p&gt;The efficiency of an AI agent depends not only on how capable its model is, but also on how the agent communicates with tools.&lt;/p&gt;

&lt;p&gt;When a task has clear steps and involves a large amount of repetitive work, asking the AI to organize the complete workflow and submit it to a local runtime can reduce waiting time, tool calls, and model costs.&lt;/p&gt;

&lt;p&gt;When the task contains many unknowns and the next action depends heavily on the latest result, interactive execution remains extremely valuable.&lt;/p&gt;

&lt;p&gt;The most effective systems do not commit permanently to either approach. They switch according to the nature of the task:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Let AI handle uncertainty and let code handle certainty. Explore first, automate the repeatable work second. Let the model think, and let the program run.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That may be one of the most useful principles for both everyday users and developers working with modern AI agents.&lt;/p&gt;

</description>
      <category>ai</category>
    </item>
    <item>
      <title>Do we really need Fable 5?</title>
      <dc:creator>Liandanxia</dc:creator>
      <pubDate>Wed, 08 Jul 2026 03:02:11 +0000</pubDate>
      <link>https://dev.to/liandanxiaai/do-we-really-need-fable-5-1fd9</link>
      <guid>https://dev.to/liandanxiaai/do-we-really-need-fable-5-1fd9</guid>
      <description>&lt;p&gt;To be honest, whether large language models reach the level of Fable 5 is not especially meaningful to most people doing actual work. It is not going to leave everyone dizzy and collapsing into their chairs as though they had just witnessed an atomic bomb detonation. Whether you can make use of Fable 5-level capabilities depends, in practice, on how you code.&lt;/p&gt;

&lt;p&gt;There are many degrees of agentic coding.&lt;/p&gt;

&lt;p&gt;First, there are the fundamentalist Vibe coders. These people unwaveringly follow the Andrej Karpathy path and remain committed to using AI throughout the entire programming process. At this point, they have essentially undergone mechanical ascension. The code they produce can be compared to humanity in the Warhammer 40K universe relative to real-world humans—in simple terms, they are no longer human.&lt;/p&gt;

&lt;p&gt;Generally speaking, this group has an extremely high ceiling and an equally low floor.&lt;/p&gt;

&lt;p&gt;Reaching the ceiling requires becoming the god of prompt engineering while simultaneously using harness prompts to condition the AI into a sex slave. The floor consists of people who cannot articulate what they want at all. The archetypal example is the client who asks for “colorful black,” after which the system produces nothing but indescribable, Cthulhu-like creatures.&lt;/p&gt;

&lt;p&gt;Next come the heavy users who treat AI as a cybernetic implant. The stronger people in this group do not let AI write everything. They first prepare the design documents and architecture documents themselves. Some go even further by implementing the critical sections personally, leaving placeholder functions everywhere else, and writing detailed comments beside them. The AI is only responsible for filling in the blanks.&lt;/p&gt;

&lt;p&gt;This means they can get their work done with relatively small, low-parameter LLMs, which none of the other groups can reliably do. The weaker members of this group may write worse code than the AI, but at least the AI provides a safety net. Their basic logic can still be made to run.&lt;/p&gt;

&lt;p&gt;Finally, there are light AI users. They occasionally use AI to build an MVP and minimally validate an idea, or ask it to fix a bug they cannot solve themselves. Most of their code is still written by hand, so whether AI exists makes relatively little difference to them.&lt;/p&gt;

&lt;p&gt;Some people lump all of these groups together under the label “Vibe Coding.” I do not think that is appropriate. A Guangdong man with twin-tails and Hatsune Miku may both have twin-tails, but you cannot classify both of them as virtual singers. So I will not go further into that discussion.&lt;/p&gt;

&lt;p&gt;So, which kinds of people are suited to which kinds of models?&lt;/p&gt;

&lt;p&gt;Let us divide model capabilities into six categories: coding ability, tool use, instruction following, long-context reasoning, the boundary of academic knowledge—in other words, world knowledge—and factual reliability.&lt;/p&gt;

&lt;p&gt;On top of those, I would add three secondary reference dimensions: multimodal capability, cost-effectiveness, and output speed.&lt;/p&gt;

&lt;p&gt;For fundamentalist Vibe coders, certain model capabilities must be extremely strong, because the model is the primary producer of the output. This requires strong coding ability and strong tool-use capability. At present, models in this category include the Claude 4.6 family—Opus and Sonnet—as well as GPT-5.5.&lt;/p&gt;

&lt;p&gt;For people who use AI as a cybernetic implant, the AI is purely a fill-in-the-blanks tool. The human is still primarily responsible for writing the code. Such users need a model with strong coding ability, followed by strong instruction adherence.&lt;/p&gt;

&lt;p&gt;Models that currently meet these requirements include DeepSeek V4 Pro and Flash, Qwen 3.7 Max, GLM 5.1 and above, as well as the two model families mentioned earlier. For this use case, I recommend Chinese models. When you are only using the model to fill in blanks, paying that much money to A\ and CloseAI is not especially sensible.&lt;/p&gt;

&lt;p&gt;There is another group that uses AI for refactoring. These people need exceptionally strong long-context reasoning and coding ability. Among Chinese models, only GLM 5.2 and Qwen 3.7 Max are particularly suitable for this kind of work.&lt;/p&gt;

&lt;p&gt;If you do not want your project to be “fixed” into complete ruin, you may simply have to grit your teeth and choose Claude or GPT.&lt;/p&gt;

&lt;p&gt;People who use AI to learn things need tool-use capability—because they need web search—along with world knowledge and factual reliability. The Gemini family and DeepSeek V4 Pro are the most suitable for them.&lt;/p&gt;

&lt;p&gt;Just remember: do not choose Gemini 3.5 Flash. Otherwise, you really will turn into a hissing kitten, glaring at the model and going “hsssss.”&lt;/p&gt;

&lt;p&gt;Some people even use AI to assist their thinking. I would not do that myself, but I respect, understand, and bless their choice.&lt;/p&gt;

&lt;p&gt;These users need models with strong long-context reasoning, extensive world knowledge, and high factual reliability. Uncle Liang’s DeepSeek V4 Pro and Google’s Gemini 3.1 Pro are the best choices for them.&lt;/p&gt;

&lt;p&gt;As for the absolute beasts who merely use AI as a wrench and could still tighten the nut by hand without it, model strength is largely irrelevant. They can apparently use something like MiniMax M2.5—what, that puny thing?!—to perform feasibility validation.&lt;/p&gt;

&lt;p&gt;Then there is multimodal capability. For coding, it should only be treated as a bonus. It is mainly during debugging that you will say, “Oh, this is good. This is really good,” with genuine appreciation. It should not be a deciding factor.&lt;/p&gt;

&lt;p&gt;For everyday use, however, multimodal capability is still quite helpful.&lt;/p&gt;

&lt;p&gt;Finally, I have to explain why I am not choosing MiniMax M3 or MiMo 2.5 Pro.&lt;/p&gt;

&lt;p&gt;Their output speed is just so damn slow!!!!&lt;/p&gt;

&lt;p&gt;Someone using DeepSeek V4 Flash will already have completed several rounds of debugging while you are still slowly polishing every detail—yes, I am specifically calling out M3. Some models even manage to produce bad work despite taking their sweet time—MiMo, I am looking at you. It is genuinely impossible to keep a straight face.&lt;/p&gt;

&lt;p&gt;There is, however, one extreme case when it comes to output speed: MiMo 2.5 Pro UltraSpeed.&lt;/p&gt;

&lt;p&gt;That is right. The fastest and the slowest are both made by Xiaomi.&lt;/p&gt;

&lt;p&gt;More than 1,000 tokens per second. Brute force works miracles. It does not matter if the code is bad. In the time it takes you to write one version, I can write one, then debug it several times over.&lt;/p&gt;

&lt;p&gt;That said, this thing is not currently part of the evaluation framework, because it is almost impossible to get access to.&lt;/p&gt;

&lt;p&gt;So, do you see the point?&lt;/p&gt;

&lt;p&gt;Very few people can meaningfully use the full capabilities of Fable 5. Unless you are Vibe Coding an entire project from scratch, Opus 4.6, GPT-5.5, or GLM 5.2 will be sufficient in the overwhelming majority of cases.&lt;/p&gt;

&lt;p&gt;The people selling anxiety about model capability are either shills for LLM providers and API resellers, or adorable little victims who have already fallen for the marketing.&lt;/p&gt;

&lt;p&gt;So why should we continue developing domestic Chinese large models?&lt;/p&gt;

&lt;p&gt;I do not want to imitate certain smartphone manufacturers or A:divide: by invoking some grand national narrative, so I will mention only one important reason:&lt;/p&gt;

&lt;p&gt;Exploring new and more efficient large-model architectures helps make affordable, high-performance AI available to everyone.&lt;/p&gt;

&lt;p&gt;Once stronger models exist, their more efficient architectures will gradually trickle down. Smaller models will gain higher intelligence, on-device AI will continue improving, and costs will keep falling.&lt;/p&gt;

&lt;p&gt;Eventually, everyone will be able to run a relatively small model with at least Opus 4.6-level capability on their own phone, computer, or workstation.&lt;/p&gt;

&lt;p&gt;That is how technological progress advances equality of access to AI.&lt;/p&gt;

&lt;p&gt;But Anthropic certainly does not see it that way. Your Uncle Dario still plans to spend the rest of his life piling parameters onto low-end models and squeezing out incremental upgrades like toothpaste. Even when Fable 5 arrives, it will merely be another instrument for extracting money.&lt;/p&gt;

&lt;p&gt;As for when that architecture will finally trickle down to Sonnet- and Haiku-class models, we may have to wait until the seas dry up and the rocks crumble.&lt;br&gt;
Want to read more perspectives? Visit &lt;a href="https://liandanxia.io" rel="noopener noreferrer"&gt;https://liandanxia.io&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>programming</category>
    </item>
    <item>
      <title>What Is an AI API Gateway? A Simple Guide for Developers</title>
      <dc:creator>Liandanxia</dc:creator>
      <pubDate>Tue, 30 Jun 2026 08:15:55 +0000</pubDate>
      <link>https://dev.to/liandanxiaai/what-is-an-ai-api-gateway-a-simple-guide-for-developers-42g1</link>
      <guid>https://dev.to/liandanxiaai/what-is-an-ai-api-gateway-a-simple-guide-for-developers-42g1</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;AI is no longer a one-model world. Developers now build with Claude, GPT, Gemini, DeepSeek, GLM, Mistral, and other models, each with its own API format, authentication flow, rate limits, pricing model, and documentation.&lt;/p&gt;

&lt;p&gt;That creates a practical problem. The more models you want to use, the more integration work you take on. You need to manage multiple API keys, normalize different request formats, handle provider-specific errors, watch separate usage dashboards, and rebuild fallback logic every time a provider changes something.&lt;/p&gt;

&lt;p&gt;This is where an AI API gateway becomes useful.&lt;/p&gt;

&lt;p&gt;An AI API gateway gives developers one layer between their application and multiple model providers. Instead of integrating every model API directly, you send requests through a unified endpoint and let the gateway route, normalize, and manage the traffic.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is an AI API Gateway?
&lt;/h2&gt;

&lt;p&gt;An AI API gateway is a unified access layer that lets developers connect to multiple AI models through one API endpoint, one authentication system, and one consistent request format.&lt;/p&gt;

&lt;p&gt;In simple terms, it sits between your app and the model providers you want to use.&lt;/p&gt;

&lt;p&gt;Instead of building separate integrations for Claude, DeepSeek, GLM, GPT, and Gemini, your application sends requests to the gateway. The gateway then forwards those requests to the right provider and returns the result in a standardized format.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7r76bl7ve4pjzsjcm6vd.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7r76bl7ve4pjzsjcm6vd.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How an AI API Gateway Works
&lt;/h2&gt;

&lt;p&gt;From the perspective of an AI API gateway, its operating logic can be understood as follows:&lt;/p&gt;

&lt;p&gt;① Acquiring model channels → ② Connecting them to a relay platform → ③ Providing access to users or downstream relay platforms&lt;/p&gt;

&lt;p&gt;First, let’s look at model channel acquisition. There are generally two ways to obtain access: legitimate channels and illegitimate channels.&lt;/p&gt;

&lt;p&gt;Legitimate channels refer to commercial negotiations between large companies and model providers. By making large-volume purchases, these companies can obtain certain discounts. Apart from using these resources internally, the remaining capacity can be redistributed through relay platforms. The pricing of these models is usually lower than official API pricing, but still higher than models obtained through illegitimate channels.&lt;/p&gt;

&lt;p&gt;Illegitimate channels refer to acquiring model access through reverse-engineering methods. A well-known example is the Claude Code $200-per-month coding plan. For a single user, if they fully use up every 5-hour limit and weekly limit, the amount of usage consumed would be far greater than $200 if calculated at API pricing. This creates an opportunity for illegitimate channels. Through reverse-engineering methods, they intercept requests from Claude Code, Codex, and similar services, then wrap and disguise those requests as normal traffic. In this way, they can allow ten users to share the quota of a single account without being detected. This is also the lowest-priced approach currently seen in the market.&lt;/p&gt;

&lt;p&gt;The second part is connecting these channels to a relay platform. After obtaining model access through either reverse-engineered or legitimate methods, the next step is to deploy open-source projects such as New API or sub2api. Inside relay platforms like New API or sub2api, operators can directly fill in the upstream base URL, API key, and other configuration details to call upstream models. Once the integration is successful, the relay platform can begin offering services externally.&lt;/p&gt;

&lt;p&gt;The third part is providing model access to users or downstream relay platforms. Similar to the second step, if a downstream relay platform wants to connect to your relay platform, you only need to create an API key for them and provide your base URL. This forms a chain-like structure, similar to a snake passing access from one segment to the next, with the end user at the very end.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvd0m4u15p8ogtv9ekmfy.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvd0m4u15p8ogtv9ekmfy.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Developers Use AI API Gateways
&lt;/h2&gt;

&lt;p&gt;1.One API for Multiple Models&lt;/p&gt;

&lt;p&gt;A gateway makes it possible to access multiple models through one interface. That matters when your product uses Claude for long-context reasoning, DeepSeek for cost-efficient coding tasks, GLM for certain multilingual scenarios, and GPT or Gemini for other workloads.&lt;/p&gt;

&lt;p&gt;2.Easier Model Switching&lt;/p&gt;

&lt;p&gt;Model preferences change fast. Pricing changes. Latency changes. A provider may add a better model, deprecate an older one, or enforce new limits. A gateway reduces switching cost because your application does not need to be tightly coupled to every provider-specific API.&lt;/p&gt;

&lt;p&gt;3.Lower Infrastructure Complexity&lt;/p&gt;

&lt;p&gt;Without a gateway, your team has to maintain multiple SDK integrations, auth flows, retries, observability pipelines, and error mappings. A gateway centralizes that operational work.&lt;/p&gt;

&lt;p&gt;4.Better Reliability Through Fallbacks&lt;/p&gt;

&lt;p&gt;If one model times out or becomes unavailable, a gateway can retry or reroute traffic to another model. That kind of fallback logic is painful to maintain separately in every application.&lt;/p&gt;

&lt;p&gt;5.Better Cost Control&lt;/p&gt;

&lt;p&gt;Not every request needs your most expensive model. A gateway can help you route simple tasks to lower-cost models while keeping higher-end models for complex reasoning or high-value interactions.&lt;/p&gt;

&lt;p&gt;6.Cleaner Usage Tracking&lt;/p&gt;

&lt;p&gt;Developers and product teams often want one place to see request volume, model usage, failure rates, latency, and spend. A gateway makes that much easier than checking several provider dashboards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Use Cases
&lt;/h2&gt;

&lt;p&gt;AI API gateways are especially useful in products that depend on more than one model or need production-grade control.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI chat applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A chatbot may use one model for fast replies and another for more difficult reasoning tasks.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Coding assistants&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A development tool may use Claude for high-quality code reasoning, DeepSeek for lower-cost generation, and another model as a fallback.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI agents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agents often need different models for planning, tool use, summarization, and verification. A gateway helps manage that complexity.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SaaS products with embedded AI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your product serves many users, you may want routing rules based on user tier, geography, cost, latency, or provider availability.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Internal AI infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Companies building internal AI tooling often use a gateway to create a stable interface for many teams, even while the underlying model stack evolves.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Look for in an AI API Gateway
&lt;/h2&gt;

&lt;p&gt;Not all gateways are equally useful. If you are choosing one, look for these capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Support for the models your team actually wants to use&lt;/li&gt;
&lt;li&gt;A unified and well-documented API format&lt;/li&gt;
&lt;li&gt;OpenAI-compatible endpoints if your stack already uses the OpenAI SDK&lt;/li&gt;
&lt;li&gt;Clear pricing and transparent billing&lt;/li&gt;
&lt;li&gt;Good uptime and fast response times&lt;/li&gt;
&lt;li&gt;Fallback and retry support&lt;/li&gt;
&lt;li&gt;Usage analytics and cost visibility&lt;/li&gt;
&lt;li&gt;Secure API key handling&lt;/li&gt;
&lt;li&gt;Stable versioning and developer-friendly documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best gateway is not just the one with the most models. It is the one that reduces engineering friction while giving you control over routing, spend, and reliability. Platforms such as &lt;a href="https://liandanxia.io" rel="noopener noreferrer"&gt;https://liandanxia.io&lt;/a&gt; and OpenRouter are often evaluated by developers looking for a unified way to access multiple AI models.&lt;/p&gt;

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

&lt;p&gt;As the AI ecosystem becomes more fragmented, the real challenge is no longer just getting access to models. It is managing differences across providers without turning your product into a maze of separate integrations.&lt;/p&gt;

&lt;p&gt;That is why AI API gateways matter. They give developers a practical way to unify access, simplify integration, and keep their model strategy flexible as pricing, performance, and provider availability continue to change.&lt;/p&gt;

&lt;p&gt;For teams working with multiple models, an AI API gateway is not just a convenience layer. It becomes an operational layer for routing, standardization, monitoring, and controlled distribution. Instead of rebuilding your application every time the model landscape shifts, you can rely on one stable interface and adapt behind the scenes.&lt;/p&gt;

&lt;p&gt;In that sense, an AI API gateway is not only about connecting to models. It is about turning a fragmented upstream market into a simpler and more usable developer experience.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>apigateway</category>
    </item>
    <item>
      <title>How to Use DeepSeek in Claude Code and OpenCode</title>
      <dc:creator>Liandanxia</dc:creator>
      <pubDate>Tue, 09 Jun 2026 02:29:29 +0000</pubDate>
      <link>https://dev.to/liandanxiaai/how-to-use-deepseek-in-claude-code-and-opencode-db7</link>
      <guid>https://dev.to/liandanxiaai/how-to-use-deepseek-in-claude-code-and-opencode-db7</guid>
      <description>&lt;h1&gt;
  
  
  How to Use Liandanxia DeepSeek Models in Claude Code and OpenCode
&lt;/h1&gt;

&lt;p&gt;This guide explains how to connect Liandanxia's DeepSeek models to Claude Code and OpenCode.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Register a Liandanxia Account and Create an API Key
&lt;/h2&gt;

&lt;p&gt;First, sign up for a Liandanxia account and create an API key from your account dashboard.&lt;/p&gt;

&lt;p&gt;Keep your API key secure. It should look similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sk-your_api_key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Install Claude Code or OpenCode
&lt;/h2&gt;

&lt;p&gt;You can use Liandanxia models with either Claude Code or OpenCode.&lt;/p&gt;




&lt;h2&gt;
  
  
  Claude Code
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Install Claude Code on Windows
&lt;/h3&gt;

&lt;p&gt;Open a &lt;code&gt;cmd&lt;/code&gt; window and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -fsSL https://claude.ai/install.cmd -o install.cmd &amp;amp;&amp;amp; install.cmd &amp;amp;&amp;amp; del install.cmd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait for the installation to complete.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure Environment Variables
&lt;/h3&gt;

&lt;p&gt;Claude Code can be pointed to Liandanxia's API endpoint by setting the following environment variables.&lt;/p&gt;

&lt;h4&gt;
  
  
  Windows CMD
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setx ANTHROPIC_BASE_URL "https://api.liandanxia.io"
setx ANTHROPIC_AUTH_TOKEN "sk-your_api_key"
setx ANTHROPIC_MODEL "deepseek-v4-pro"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running these commands, close the current terminal window and open a new one for the changes to take effect.&lt;/p&gt;

&lt;p&gt;Then start Claude Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  macOS / Linux / Git Bash
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://api.liandanxia.io"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_AUTH_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"sk-your_api_key"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"deepseek-v4-pro"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Code should now use the Liandanxia DeepSeek model.&lt;/p&gt;




&lt;h2&gt;
  
  
  OpenCode
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Install OpenCode
&lt;/h3&gt;

&lt;p&gt;On macOS, Linux, WSL, or Git Bash, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://opencode.ai/install | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are using Windows CMD, consider running this command inside Git Bash or WSL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure OpenCode
&lt;/h3&gt;

&lt;p&gt;OpenCode uses the &lt;code&gt;provider&lt;/code&gt; config key, not &lt;code&gt;providers&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Create or update an &lt;code&gt;opencode.json&lt;/code&gt; file in your project root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://opencode.ai/config.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ldx/deepseek-v4-pro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ldx"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"npm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@ai-sdk/openai-compatible"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"LDX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"baseURL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.liandanxia.io/v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"apiKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sk-your_api_key"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"models"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"deepseek-v4-pro"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"deepseek-v4-flash"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After saving the file, run OpenCode from your project directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;opencode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Recommended: Use an Environment Variable for Your API Key
&lt;/h2&gt;

&lt;p&gt;To avoid storing your API key directly in your project configuration, use an environment variable instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  macOS / Linux / Git Bash
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LDX_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"sk-your_api_key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Windows CMD
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setx LDX_API_KEY "sk-your_api_key"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After using &lt;code&gt;setx&lt;/code&gt;, restart your terminal.&lt;/p&gt;

&lt;p&gt;Then update your &lt;code&gt;opencode.json&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://opencode.ai/config.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ldx/deepseek-v4-pro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ldx"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"npm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@ai-sdk/openai-compatible"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"LDX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"baseURL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.liandanxia.io/v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"apiKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{env:LDX_API_KEY}"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"models"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"deepseek-v4-pro"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"deepseek-v4-flash"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now OpenCode will read your Liandanxia API key from the &lt;code&gt;LDX_API_KEY&lt;/code&gt; environment variable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Model Options
&lt;/h2&gt;

&lt;p&gt;You can switch models by changing the &lt;code&gt;model&lt;/code&gt; field in &lt;code&gt;opencode.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ldx/deepseek-v4-pro"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ldx/deepseek-v4-flash"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;code&gt;deepseek-v4-pro&lt;/code&gt; when you need stronger reasoning and higher-quality coding performance. Use &lt;code&gt;deepseek-v4-flash&lt;/code&gt; when you want faster responses and lower cost.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Claude Code configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;ANTHROPIC_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://api.liandanxia.io
&lt;span class="nv"&gt;ANTHROPIC_AUTH_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sk-your_api_key
&lt;span class="nv"&gt;ANTHROPIC_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;deepseek-v4-pro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OpenCode configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ldx/deepseek-v4-pro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ldx"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"npm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@ai-sdk/openai-compatible"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"baseURL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.liandanxia.io/v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"apiKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{env:LDX_API_KEY}"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"models"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"deepseek-v4-pro"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"deepseek-v4-flash"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once configured, you can use Liandanxia's DeepSeek models directly inside Claude Code or OpenCode.&lt;/p&gt;

</description>
      <category>deepseek</category>
      <category>claudecode</category>
      <category>opencode</category>
    </item>
    <item>
      <title>I Reverse Engineered a Nuxt 3 Login Flow and Got Fooled by an MD5 Magic Number</title>
      <dc:creator>Liandanxia</dc:creator>
      <pubDate>Mon, 01 Jun 2026 05:56:14 +0000</pubDate>
      <link>https://dev.to/liandanxiaai/i-reverse-engineered-a-nuxt-3-login-flow-and-got-fooled-by-an-md5-magic-number-1dei</link>
      <guid>https://dev.to/liandanxiaai/i-reverse-engineered-a-nuxt-3-login-flow-and-got-fooled-by-an-md5-magic-number-1dei</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is not a guide about bypassing login.&lt;/p&gt;

&lt;p&gt;It is a reverse engineering write-up: how I started from an ordinary login page, followed the frontend bundles to the API call chain, made a wrong assumption about a hash function, and eventually confirmed the answer by reading a few very familiar magic numbers.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Before We Start
&lt;/h2&gt;

&lt;p&gt;One day, I opened &lt;code&gt;liandanxia.io&lt;/code&gt; and wanted to answer a simple question:&lt;/p&gt;

&lt;p&gt;What actually happens behind the login button of a modern frontend application?&lt;/p&gt;

&lt;p&gt;The page itself did not look unusual. It had email/password login, phone login, GitHub OAuth, and Google OAuth. A pretty standard authentication setup.&lt;/p&gt;

&lt;p&gt;But the more ordinary the page looked, the more curious I became about the implementation behind it.&lt;/p&gt;

&lt;p&gt;So I set a very small scope for myself:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do not touch accounts I do not own. Do not bypass captchas. Do not brute force anything. Only analyze the login flow exposed through publicly accessible frontend resources.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The toolset was simple:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Browser source / page fetching&lt;/td&gt;
&lt;td&gt;Inspect what the homepage and login page expose&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PowerShell / curl&lt;/td&gt;
&lt;td&gt;Perform a small number of API checks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Select-String / grep&lt;/td&gt;
&lt;td&gt;Search inside compressed frontend bundles&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek&lt;/td&gt;
&lt;td&gt;Help read and reason about minified JavaScript&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The interesting part was not finding an API endpoint.&lt;/p&gt;

&lt;p&gt;The interesting part was the hash function I almost misidentified.&lt;/p&gt;




&lt;h2&gt;
  
  
  First Clue: The API Base Was in the Nuxt Config
&lt;/h2&gt;

&lt;p&gt;I started by fetching the homepage.&lt;/p&gt;

&lt;p&gt;The response quickly revealed an important detail: this was a Nuxt 3 single-page application.&lt;/p&gt;

&lt;p&gt;Inside the page source, I found a runtime config similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__NUXT__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;public&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;apiBase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.liandanxia.io/silver&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&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;There was nothing magical about this.&lt;/p&gt;

&lt;p&gt;Many Nuxt, Vite, and Next-style applications expose public runtime configuration in the HTML. If the browser needs to call an API, the frontend must eventually know where that API lives.&lt;/p&gt;

&lt;p&gt;So the first clue was clear:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API Base = https://api.liandanxia.io/silver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But knowing the API base was not enough.&lt;/p&gt;

&lt;p&gt;The real questions were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which function does the login button call?&lt;/li&gt;
&lt;li&gt;Is the password transformed before submission?&lt;/li&gt;
&lt;li&gt;Where does the token come back?&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Second Clue: The Login Page Exposed the Bundles
&lt;/h2&gt;

&lt;p&gt;Next, I opened the login page.&lt;/p&gt;

&lt;p&gt;The login page was client-side rendered, so the raw HTML did not contain the actual form logic. But it did expose a list of Nuxt-generated JavaScript bundles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"modulepreload"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/_nuxt/j-XipXza.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"modulepreload"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/_nuxt/HKoFWgYB.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"modulepreload"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/_nuxt/c8TO03ko.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"modulepreload"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/_nuxt/P1PMQwvn.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These filenames are content hashes, so they may change after every deployment. The names themselves are not stable clues. The useful approach is to follow whatever the current page actually loads.&lt;/p&gt;

&lt;p&gt;After downloading a few candidate bundles, I found what looked like the login component.&lt;/p&gt;

&lt;p&gt;The code was minified, and meaningful names had been replaced by short identifiers such as &lt;code&gt;Le&lt;/code&gt;, &lt;code&gt;Je&lt;/code&gt;, and &lt;code&gt;Qe&lt;/code&gt;. Still, the Vue component structure was recognizable.&lt;/p&gt;

&lt;p&gt;One part of the logic could be roughly reconstructed as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Validate email and password&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;loginWithEmail&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&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;The minified version was obviously less friendly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nc"&gt;Le&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part was not the name &lt;code&gt;Le&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The important part was that &lt;code&gt;Le&lt;/code&gt; came from the main entry bundle.&lt;/p&gt;

&lt;p&gt;In other words, the login component was only the doorway. The real API implementation was hidden in the main bundle.&lt;/p&gt;




&lt;h2&gt;
  
  
  Third Clue: From Short Function Names to Real API Calls
&lt;/h2&gt;

&lt;p&gt;The main bundle was a few hundred kilobytes, mostly compressed into a very long line of JavaScript.&lt;/p&gt;

&lt;p&gt;This is not the kind of file you read from top to bottom.&lt;/p&gt;

&lt;p&gt;You search it.&lt;/p&gt;

&lt;p&gt;I started with obvious path patterns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Get-Content&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;bundle.js&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Raw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-split&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;';'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;Where-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'/api/user'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That quickly revealed the rough shape of the authentication-related endpoints.&lt;/p&gt;

&lt;p&gt;I could see that login, registration, user info, OAuth, and verification flows were all close to the same authentication call chain.&lt;/p&gt;

&lt;p&gt;But I still could not jump to a conclusion, because the login flow had one critical detail:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The frontend did not send the raw password directly. It hashed the password before submitting it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That was where the story became much more interesting.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Trap: I Thought It Was SHA-256
&lt;/h2&gt;

&lt;p&gt;I kept tracing the login function.&lt;/p&gt;

&lt;p&gt;In the minified code, the logic was roughly equivalent to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hashedPassword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;encryptPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;requestLogin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;hashedPassword&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;So I followed &lt;code&gt;encryptPassword&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Eventually, it pointed to a hash library wrapper with byte conversion, array handling, and hex output logic.&lt;/p&gt;

&lt;p&gt;At that moment, I saw structures like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My first reaction was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is probably SHA-256.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Looking back, that was too quick.&lt;/p&gt;

&lt;p&gt;But it was an easy mistake to make. In many modern projects, if developers hash something client-side, SHA-256 is often the first algorithm that comes to mind. The compressed code also looked like a generic hash wrapper, so I wrote a quick SHA-256 version and tested it.&lt;/p&gt;

&lt;p&gt;The result was immediate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Incorrect account or password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That meant at least one assumption was wrong.&lt;/p&gt;

&lt;p&gt;Maybe the algorithm was wrong.&lt;/p&gt;

&lt;p&gt;Maybe the encoding was wrong.&lt;/p&gt;

&lt;p&gt;Maybe there was a salt.&lt;/p&gt;

&lt;p&gt;Or maybe I had followed the wrong call chain.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Funniest Part: MD5 Had Already Worked
&lt;/h2&gt;

&lt;p&gt;Next, I did something boring but effective: I tested several common hashing schemes.&lt;/p&gt;

&lt;p&gt;SHA-256, SHA-512, SHA-1, MD5, email-plus-password combinations, double hashing. I checked them in a small and controlled way.&lt;/p&gt;

&lt;p&gt;One result stood out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MD5 hex -&amp;gt; code 200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That should have been the answer.&lt;/p&gt;

&lt;p&gt;But my test script had a bug.&lt;/p&gt;

&lt;p&gt;It only looked for the token in one fixed location, while the real response nested the token under &lt;code&gt;data&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So the request had succeeded, but my script failed to extract the token.&lt;/p&gt;

&lt;p&gt;I looked at the "no token found" output and mistakenly concluded that MD5 was also wrong.&lt;/p&gt;

&lt;p&gt;That was the most dramatic moment of the whole analysis:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The correct answer had already peeked through the door, and I closed the door on it because my own validation logic was broken.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When I looked back at this step later, I felt it was more valuable than simply finding the endpoint.&lt;/p&gt;

&lt;p&gt;In reverse engineering, the most dangerous thing is not ignorance.&lt;/p&gt;

&lt;p&gt;It is thinking you already know.&lt;/p&gt;




&lt;h2&gt;
  
  
  Back to the Source: The Magic Numbers Gave It Away
&lt;/h2&gt;

&lt;p&gt;At that point, I decided to stop guessing.&lt;/p&gt;

&lt;p&gt;I went back into the bundle and continued tracing deeper into the hash function. This time, I did not look at the shape of the wrapper. I looked for algorithm constants.&lt;/p&gt;

&lt;p&gt;Then I saw these numbers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;680876936&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;389564586&lt;/span&gt;
&lt;span class="mi"&gt;606105819&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And these rotations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have ever read an MD5 implementation, these should look very familiar.&lt;/p&gt;

&lt;p&gt;They match the classic constants and rotation schedule used in the MD5 round functions.&lt;/p&gt;

&lt;p&gt;At that moment, the answer was finally clear:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The password was transformed into a standard MD5 hex digest before submission.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This became the main lesson of the whole exercise:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do not identify an algorithm only by surface-level patterns like &lt;code&gt;Uint8Array&lt;/code&gt;, &lt;code&gt;hash&lt;/code&gt;, or &lt;code&gt;digest&lt;/code&gt;.&lt;br&gt;
Stronger evidence comes from constants, round functions, output behavior, and verification results all pointing to the same conclusion.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Another Reminder: Rate Limiting Was Real
&lt;/h2&gt;

&lt;p&gt;During verification, I also triggered login rate limiting.&lt;/p&gt;

&lt;p&gt;After several failed attempts, the API started returning remaining-attempt messages. After more failures, it reported that login was too frequent.&lt;/p&gt;

&lt;p&gt;That means the endpoint was not completely unprotected. At minimum, it had basic protection against repeated failed login attempts.&lt;/p&gt;

&lt;p&gt;It was also a reminder to keep this kind of research controlled:&lt;/p&gt;

&lt;p&gt;Only test with an account you own. Keep the number of requests small. Do not turn the process into brute forcing, credential stuffing, automated registration, or captcha bypassing.&lt;/p&gt;

&lt;p&gt;That would no longer be a technical write-up.&lt;/p&gt;

&lt;p&gt;That would be crossing a line.&lt;/p&gt;




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

&lt;p&gt;By the end of the analysis, I had confirmed a few things:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Finding&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Frontend framework&lt;/td&gt;
&lt;td&gt;Nuxt 3 / Vite build&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API base&lt;/td&gt;
&lt;td&gt;Exposed through Nuxt public runtime config&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Login call chain&lt;/td&gt;
&lt;td&gt;Login component calls authentication helpers from the main bundle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Password handling&lt;/td&gt;
&lt;td&gt;Password is hashed as an MD5 hex digest before submission&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Token location&lt;/td&gt;
&lt;td&gt;Token is returned inside the login response data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Token type&lt;/td&gt;
&lt;td&gt;JWT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Protection&lt;/td&gt;
&lt;td&gt;Failed login rate limiting exists&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Three Lessons I Took Away
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Public frontend assets often contain enough clues
&lt;/h3&gt;

&lt;p&gt;SPA bundles can contain a surprising amount of runtime information.&lt;/p&gt;

&lt;p&gt;API bases, endpoint paths, status-code handling, token storage keys, and third-party login entry points often do not require any "cracking" to discover. They are already loaded by the browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Guessing algorithms is risky
&lt;/h3&gt;

&lt;p&gt;When I first saw the hash wrapper, I assumed it was SHA-256.&lt;/p&gt;

&lt;p&gt;That assumption was too fast.&lt;/p&gt;

&lt;p&gt;Compressed hash implementations often look similar. A more reliable approach is to go back to the algorithm itself: constants, round functions, output length, and verification behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Test scripts can mislead you too
&lt;/h3&gt;

&lt;p&gt;When MD5 first returned &lt;code&gt;code 200&lt;/code&gt;, it had already pointed in the right direction.&lt;/p&gt;

&lt;p&gt;But my script parsed the response incorrectly, so I misread a successful result as a failed one.&lt;/p&gt;

&lt;p&gt;That kind of bug is subtle because it disguises a validation problem as a reverse engineering conclusion.&lt;/p&gt;




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

&lt;p&gt;The most interesting part of this analysis was not finding an endpoint or writing a snippet of code.&lt;/p&gt;

&lt;p&gt;It was being reminded again that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Reverse engineering is rarely a straight line.&lt;/p&gt;

&lt;p&gt;It feels more like walking through fog. You find clues, make assumptions, take wrong turns, and then suddenly stop in front of a tiny constant that tells you the answer had been there all along.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The next time I see a similar frontend login flow, I will probably slow down before naming the algorithm.&lt;/p&gt;

&lt;p&gt;Do not rush to say, "This is probably SHA-256."&lt;/p&gt;

&lt;p&gt;Find the magic numbers first.&lt;/p&gt;

&lt;p&gt;I also put the full notes and supporting files in this GitHub repo if you want to take a closer look:&lt;br&gt;
&lt;a href="https://github.com/liandanxiaAI/reverse-engineering-daily/tree/main/liandanxia-login-analysis" rel="noopener noreferrer"&gt;https://github.com/liandanxiaAI/reverse-engineering-daily/tree/main/liandanxia-login-analysis&lt;/a&gt;&lt;/p&gt;

</description>
      <category>reverseengineering</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>security</category>
    </item>
  </channel>
</rss>
